Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1756)

Unified Diff: chrome/renderer/resources/extensions/web_view/chrome_web_view.js

Issue 1004233002: Moved the contextmenu webview API to stable, and removed the experimental API infrastructure. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/renderer/resources/extensions/web_view/chrome_web_view.js
diff --git a/chrome/renderer/resources/extensions/web_view/chrome_web_view.js b/chrome/renderer/resources/extensions/web_view/chrome_web_view.js
index 14eca5be49ab88a9f1aab0dae8b64685c5cff4d4..a91a239c79133d234774fe7759f4cc421a044458 100644
--- a/chrome/renderer/resources/extensions/web_view/chrome_web_view.js
+++ b/chrome/renderer/resources/extensions/web_view/chrome_web_view.js
@@ -3,11 +3,17 @@
// found in the LICENSE file.
// This module implements chrome-specific <webview> API.
+// See web_view_api_methods.js for details.
var ChromeWebView = require('chromeWebViewInternal').ChromeWebView;
+var ChromeWebViewSchema =
+ requireNative('schema_registry').GetSchema('chromeWebViewInternal');
var CreateEvent = require('guestViewEvents').CreateEvent;
var EventBindings = require('event_bindings');
+var idGeneratorNatives = requireNative('id_generator');
+var Utils = require('utils');
var WebViewEvents = require('webViewEvents').WebViewEvents;
+var WebViewImpl = require('webView').WebViewImpl;
var CHROME_WEB_VIEW_EVENTS = {
'contextmenushown': {
@@ -18,20 +24,161 @@ var CHROME_WEB_VIEW_EVENTS = {
}
};
-/**
- * Calls to show contextmenu right away instead of dispatching a 'contextmenu'
- * event.
- * This will be overridden in chrome_web_view_experimental.js to implement
- * contextmenu API.
- */
-WebViewEvents.prototype.handleContextMenu = function(event) {
+// This is the only "webViewInternal.onClicked" named event for this renderer.
+//
+// Since we need an event per <webview>, we define events with suffix
+// (subEventName) in each of the <webview>. Behind the scenes, this event is
+// registered as a ContextMenusEvent, with filter set to the webview's
+// |viewInstanceId|. Any time a ContextMenusEvent is dispatched, we re-dispatch
+// it to the subEvent's listeners. This way
+// <webview>.contextMenus.onClicked behave as a regular chrome Event type.
+var ContextMenusEvent = CreateEvent('chromeWebViewInternal.onClicked');
+
+// -----------------------------------------------------------------------------
+// ContextMenusOnClickedEvent object.
+
+// This event is exposed as <webview>.contextMenus.onClicked.
+function ContextMenusOnClickedEvent(opt_eventName,
+ opt_argSchemas,
+ opt_eventOptions,
+ opt_webViewInstanceId) {
+ var subEventName = GetUniqueSubEventName(opt_eventName);
+ EventBindings.Event.call(this,
+ subEventName,
+ opt_argSchemas,
+ opt_eventOptions,
+ opt_webViewInstanceId);
+
+ // TODO(lazyboy): When do we dispose this listener?
+ ContextMenusEvent.addListener(function() {
+ // Re-dispatch to subEvent's listeners.
+ $Function.apply(this.dispatch, this, $Array.slice(arguments));
+ }.bind(this), {instanceId: opt_webViewInstanceId || 0});
+}
+
+ContextMenusOnClickedEvent.prototype.__proto__ = EventBindings.Event.prototype;
+
+// -----------------------------------------------------------------------------
+// WebViewContextMenusImpl object.
+
+// An instance of this class is exposed as <webview>.contextMenus.
+function WebViewContextMenusImpl(viewInstanceId) {
+ this.viewInstanceId_ = viewInstanceId;
+}
+
+WebViewContextMenusImpl.prototype.create = function() {
+ var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
+ return $Function.apply(ChromeWebView.contextMenusCreate, null, args);
+};
+
+WebViewContextMenusImpl.prototype.remove = function() {
+ var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
+ return $Function.apply(ChromeWebView.contextMenusRemove, null, args);
+};
+
+WebViewContextMenusImpl.prototype.removeAll = function() {
+ var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
+ return $Function.apply(ChromeWebView.contextMenusRemoveAll, null, args);
+};
+
+WebViewContextMenusImpl.prototype.update = function() {
+ var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
+ return $Function.apply(ChromeWebView.contextMenusUpdate, null, args);
+};
+
+var WebViewContextMenus = Utils.expose(
+ 'WebViewContextMenus', WebViewContextMenusImpl,
+ { functions: ['create', 'remove', 'removeAll', 'update'] });
+
+// -----------------------------------------------------------------------------
+
+WebViewImpl.prototype.maybeSetupContextMenus = function() {
+ var createContextMenus = function() {
+ return function() {
+ if (this.contextMenus_) {
+ return this.contextMenus_;
+ }
+
+ this.contextMenus_ = new WebViewContextMenus(this.viewInstanceId);
+
+ // Define 'onClicked' event property on |this.contextMenus_|.
+ var getOnClickedEvent = function() {
+ return function() {
+ if (!this.contextMenusOnClickedEvent_) {
+ var eventName = 'chromeWebViewInternal.onClicked';
+ // TODO(lazyboy): Find event by name instead of events[0].
+ var eventSchema = ChromeWebViewSchema.events[0];
+ var eventOptions = {supportsListeners: true};
+ var onClickedEvent = new ContextMenusOnClickedEvent(
+ eventName, eventSchema, eventOptions, this.viewInstanceId);
+ this.contextMenusOnClickedEvent_ = onClickedEvent;
+ return onClickedEvent;
+ }
+ return this.contextMenusOnClickedEvent_;
+ }.bind(this);
+ }.bind(this);
+ Object.defineProperty(
+ this.contextMenus_,
+ 'onClicked',
+ {get: getOnClickedEvent(), enumerable: true});
+
+ return this.contextMenus_;
+ }.bind(this);
+ }.bind(this);
+
+ // Expose <webview>.contextMenus object.
+ Object.defineProperty(
+ this.element,
+ 'contextMenus',
+ {
+ get: createContextMenus(),
+ enumerable: true
+ });
+};
+
+WebViewEvents.prototype.handleContextMenu = function(event, eventName) {
+ var webViewEvent = this.makeDomEvent(event, eventName);
var requestId = event.requestId;
- // Setting |params| = undefined will show the context menu unmodified, hence
- // the 'contextmenu' API is disabled for stable channel.
- var params = undefined;
- ChromeWebView.showContextMenu(this.view.guest.getId(), requestId, params);
+ // Construct the event.menu object.
+ var actionTaken = false;
+ var validateCall = function() {
+ var ERROR_MSG_CONTEXT_MENU_ACTION_ALREADY_TAKEN = '<webview>: ' +
+ 'An action has already been taken for this "contextmenu" event.';
+
+ if (actionTaken) {
+ throw new Error(ERROR_MSG_CONTEXT_MENU_ACTION_ALREADY_TAKEN);
+ }
+ actionTaken = true;
+ };
+ var menu = {
+ show: function(items) {
+ validateCall();
+ // TODO(lazyboy): WebViewShowContextFunction doesn't do anything useful
+ // with |items|, implement.
+ ChromeWebView.showContextMenu(this.view.guest.getId(), requestId, items);
+ }.bind(this)
+ };
+ webViewEvent.menu = menu;
+ var element = this.view.element;
+ var defaultPrevented = !element.dispatchEvent(webViewEvent);
+ if (actionTaken) {
+ return;
+ }
+ if (!defaultPrevented) {
+ actionTaken = true;
+ // The default action is equivalent to just showing the context menu as is.
+ ChromeWebView.showContextMenu(
+ this.view.guest.getId(), requestId, undefined);
+
+ // TODO(lazyboy): Figure out a way to show warning message only when
+ // listeners are registered for this event.
+ } // else we will ignore showing the context menu completely.
};
+function GetUniqueSubEventName(eventName) {
+ return eventName + '/' + idGeneratorNatives.GetNextId();
+}
+
// Exposes |CHROME_WEB_VIEW_EVENTS| when the ChromeWebView API is available.
(function() {
for (var eventName in CHROME_WEB_VIEW_EVENTS) {

Powered by Google App Engine
This is Rietveld 408576698