diff options
author | rob <rob@robwu.nl> | 2015-04-04 03:42:58 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-04 10:43:23 +0000 |
commit | 6e3c0446a84339e95996e9cafd6e5e72c0698827 (patch) | |
tree | a78a653149da09c553d998bb317877eb6bf1ba56 /extensions/renderer/resources | |
parent | bc9022cfedb422ee2e18421cd5b8d79281dd7d84 (diff) | |
download | chromium_src-6e3c0446a84339e95996e9cafd6e5e72c0698827.zip chromium_src-6e3c0446a84339e95996e9cafd6e5e72c0698827.tar.gz chromium_src-6e3c0446a84339e95996e9cafd6e5e72c0698827.tar.bz2 |
Merge custom bindings for context menus
De-duplicated the logic for contextMenus custom bindings.
And changed the contextMenus.update method, so that calling it with
"onclick: null" will remove the onclick handler.
BUG=461869
TEST=browser_tests ExtensionContextMenuBrowserTest.UpdateOnclick
Review URL: https://codereview.chromium.org/948243005
Cr-Commit-Position: refs/heads/master@{#323880}
Diffstat (limited to 'extensions/renderer/resources')
3 files changed, 149 insertions, 102 deletions
diff --git a/extensions/renderer/resources/context_menus_custom_bindings.js b/extensions/renderer/resources/context_menus_custom_bindings.js index 0e82711b5..fe5cec9 100644 --- a/extensions/renderer/resources/context_menus_custom_bindings.js +++ b/extensions/renderer/resources/context_menus_custom_bindings.js @@ -5,117 +5,22 @@ // Custom binding for the contextMenus API. var binding = require('binding').Binding.create('contextMenus'); - -var contextMenuNatives = requireNative('context_menus'); -var sendRequest = require('sendRequest').sendRequest; -var Event = require('event_bindings').Event; -var lastError = require('lastError'); +var contextMenusHandlers = require('contextMenusHandlers'); binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; - var contextMenus = {}; - contextMenus.generatedIdHandlers = {}; - contextMenus.stringIdHandlers = {}; - var eventName = 'contextMenus'; - contextMenus.event = new Event(eventName); - contextMenus.getIdFromCreateProperties = function(prop) { - if (typeof(prop.id) !== 'undefined') - return prop.id; - return prop.generatedId; - }; - contextMenus.handlersForId = function(id) { - if (typeof(id) === 'number') - return contextMenus.generatedIdHandlers; - return contextMenus.stringIdHandlers; - }; - contextMenus.ensureListenerSetup = function() { - if (contextMenus.listening) { - return; - } - contextMenus.listening = true; - contextMenus.event.addListener(function() { - // An extension context menu item has been clicked on - fire the onclick - // if there is one. - var id = arguments[0].menuItemId; - var onclick = contextMenus.handlersForId(id)[id]; - if (onclick) { - $Function.apply(onclick, null, arguments); - } - }); - }; - - apiFunctions.setHandleRequest('create', function() { - var args = arguments; - var id = contextMenuNatives.GetNextContextMenuId(); - args[0].generatedId = id; - var optArgs = { - customCallback: this.customCallback, - }; - sendRequest(this.name, args, this.definition.parameters, optArgs); - return contextMenus.getIdFromCreateProperties(args[0]); - }); - - apiFunctions.setCustomCallback('create', - function(name, request, callback, response) { - if (lastError.hasError(chrome)) { - if (callback) - callback(); - return; - } + var handlers = contextMenusHandlers.create(false /* isWebview */); - var id = contextMenus.getIdFromCreateProperties(request.args[0]); + apiFunctions.setHandleRequest('create', handlers.requestHandlers.create); - // Set up the onclick handler if we were passed one in the request. - var onclick = request.args.length ? request.args[0].onclick : null; - if (onclick) { - contextMenus.ensureListenerSetup(); - contextMenus.handlersForId(id)[id] = onclick; - } - if (callback) - callback(); - }); + apiFunctions.setCustomCallback('create', handlers.callbacks.create); - apiFunctions.setCustomCallback('remove', - function(name, request, callback, response) { - if (lastError.hasError(chrome)) { - if (callback) - callback(); - return; - } - var id = request.args[0]; - delete contextMenus.handlersForId(id)[id]; - if (callback) - callback(); - }); + apiFunctions.setCustomCallback('remove', handlers.callbacks.remove); - apiFunctions.setCustomCallback('update', - function(name, request, callback, response) { - if (lastError.hasError(chrome)) { - if (callback) - callback(); - return; - } - var id = request.args[0]; - if (request.args[1].onclick) { - contextMenus.handlersForId(id)[id] = request.args[1].onclick; - } - if (callback) - callback(); - }); + apiFunctions.setCustomCallback('update', handlers.callbacks.update); - apiFunctions.setCustomCallback('removeAll', - function(name, request, callback, response) { - if (lastError.hasError(chrome)) { - if (callback) - callback(); - return; - } - contextMenus.generatedIdHandlers = {}; - contextMenus.stringIdHandlers = {}; - if (callback) - callback(); - }); + apiFunctions.setCustomCallback('removeAll', handlers.callbacks.removeAll); }); exports.binding = binding.generate(); diff --git a/extensions/renderer/resources/context_menus_handlers.js b/extensions/renderer/resources/context_menus_handlers.js new file mode 100644 index 0000000..b334900 --- /dev/null +++ b/extensions/renderer/resources/context_menus_handlers.js @@ -0,0 +1,141 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Implementation of custom bindings for the contextMenus API. +// This is used to implement the contextMenus API for extensions and for the +// <webview> tag (see chrome_web_view_experimental.js). + +var contextMenuNatives = requireNative('context_menus'); +var sendRequest = require('sendRequest').sendRequest; +var Event = require('event_bindings').Event; +var lastError = require('lastError'); + +// Add the bindings to the contextMenus API. +function createContextMenusHandlers(isWebview) { + var eventName = isWebview ? 'webViewInternal.contextMenus' : 'contextMenus'; + // Some dummy value for chrome.contextMenus instances. + // Webviews use positive integers, and 0 to denote an invalid webview ID. + // The following constant is -1 to avoid any conflicts between webview IDs and + // extensions. + var INSTANCEID_NON_WEBVIEW = -1; + + // Generates a customCallback for a given method. |handleCallback| will be + // invoked with |request.args| as parameters. + function createCustomCallback(handleCallback) { + return function(name, request, callback) { + if (lastError.hasError(chrome)) { + if (callback) + callback(); + return; + } + var args = request.args; + if (!isWebview) { + // <webview>s have an extra item in front of the parameter list, which + // specifies the viewInstanceId of the webview. This is used to hide + // context menu events in one webview from another. + // The non-webview chrome.contextMenus API is not called with such an + // ID, so we prepend an ID to match the function signature. + args = $Array.concat([INSTANCEID_NON_WEBVIEW], args); + } + $Function.apply(handleCallback, null, args); + if (callback) + callback(); + }; + } + + var contextMenus = {}; + contextMenus.handlers = {}; + contextMenus.event = new Event(eventName); + + contextMenus.getIdFromCreateProperties = function(createProperties) { + if (typeof createProperties.id !== 'undefined') + return createProperties.id; + return createProperties.generatedId; + }; + + contextMenus.handlersForId = function(instanceId, id) { + if (!contextMenus.handlers[instanceId]) { + contextMenus.handlers[instanceId] = { + generated: {}, + string: {} + }; + } + if (typeof id === 'number') + return contextMenus.handlers[instanceId].generated; + return contextMenus.handlers[instanceId].string; + }; + + contextMenus.ensureListenerSetup = function() { + if (contextMenus.listening) { + return; + } + contextMenus.listening = true; + contextMenus.event.addListener(function(info) { + var instanceId = INSTANCEID_NON_WEBVIEW; + if (isWebview) { + instanceId = info.webviewInstanceId; + // Don't expose |webviewInstanceId| via the public API. + delete info.webviewInstanceId; + } + + var id = info.menuItemId; + var onclick = contextMenus.handlersForId(instanceId, id)[id]; + if (onclick) { + $Function.apply(onclick, null, arguments); + } + }); + }; + + // To be used with apiFunctions.setHandleRequest + var requestHandlers = {}; + // To be used with apiFunctions.setCustomCallback + var callbacks = {}; + + requestHandlers.create = function() { + var createProperties = isWebview ? arguments[1] : arguments[0]; + createProperties.generatedId = contextMenuNatives.GetNextContextMenuId(); + var optArgs = { + customCallback: this.customCallback, + }; + sendRequest(this.name, arguments, this.definition.parameters, optArgs); + return contextMenus.getIdFromCreateProperties(createProperties); + }; + + callbacks.create = + createCustomCallback(function(instanceId, createProperties) { + var id = contextMenus.getIdFromCreateProperties(createProperties); + var onclick = createProperties.onclick; + if (onclick) { + contextMenus.ensureListenerSetup(); + contextMenus.handlersForId(instanceId, id)[id] = onclick; + } + }); + + callbacks.remove = createCustomCallback(function(instanceId, id) { + delete contextMenus.handlersForId(instanceId, id)[id]; + }); + + callbacks.update = + createCustomCallback(function(instanceId, id, updateProperties) { + var onclick = updateProperties.onclick; + if (onclick) { + contextMenus.ensureListenerSetup(); + contextMenus.handlersForId(instanceId, id)[id] = onclick; + } else if (onclick === null) { + // When onclick is explicitly set to null, remove the event listener. + delete contextMenus.handlersForId(instanceId, id)[id]; + } + }); + + callbacks.removeAll = createCustomCallback(function(instanceId) { + delete contextMenus.handlers[instanceId]; + }); + + return { + requestHandlers: requestHandlers, + callbacks: callbacks + }; +} + +exports.create = createContextMenusHandlers; diff --git a/extensions/renderer/resources/extensions_renderer_resources.grd b/extensions/renderer/resources/extensions_renderer_resources.grd index d5c1d67..c9c6299 100644 --- a/extensions/renderer/resources/extensions_renderer_resources.grd +++ b/extensions/renderer/resources/extensions_renderer_resources.grd @@ -69,6 +69,7 @@ <include name="IDR_APP_WINDOW_CUSTOM_BINDINGS_JS" file="app_window_custom_bindings.js" type="BINDATA" /> <include name="IDR_BINDING_JS" file="binding.js" type="BINDATA" /> <include name="IDR_CONTEXT_MENUS_CUSTOM_BINDINGS_JS" file="context_menus_custom_bindings.js" type="BINDATA" /> + <include name="IDR_CONTEXT_MENUS_HANDLERS_JS" file="context_menus_handlers.js" type="BINDATA" /> <include name="IDR_DECLARATIVE_WEBREQUEST_CUSTOM_BINDINGS_JS" file="declarative_webrequest_custom_bindings.js" type="BINDATA" /> <include name="IDR_EXTENSION_CUSTOM_BINDINGS_JS" file="extension_custom_bindings.js" type="BINDATA" /> <include name="IDR_GREASEMONKEY_API_JS" file="greasemonkey_api.js" type="BINDATA" /> |