123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // 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');
- // 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 the same arguments this function is called with.
- function getCallback(handleCallback) {
- return function() {
- var extensionCallback = arguments[arguments.length - 1];
- if (bindingUtil.hasLastError()) {
- if (extensionCallback)
- extensionCallback();
- return;
- }
- $Function.apply(handleCallback, null, arguments);
- if (extensionCallback)
- extensionCallback();
- };
- }
- // Shift off the instanceId from the arguments for webviews.
- function getInstanceId(args) {
- if (isWebview)
- return $Array.shift(args); // This modifies the array in-place.
- return INSTANCEID_NON_WEBVIEW;
- }
- var contextMenus = { __proto__: null };
- contextMenus.handlers = { __proto__: null };
- var supportsLazyListeners = !isWebview;
- var supportsFilters = false;
- contextMenus.event = bindingUtil.createCustomEvent(
- eventName, supportsFilters, supportsLazyListeners);
- 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 = { __proto__: null };
- function createCallback(instanceId, id, onclick) {
- if (onclick) {
- contextMenus.ensureListenerSetup();
- contextMenus.handlersForId(instanceId, id)[id] = onclick;
- }
- }
- requestHandlers.create = function() {
- var args = $Array.from(arguments);
- var instanceId = getInstanceId(args);
- var createProperties = args[0];
- var callback = args[1];
- createProperties.generatedId = contextMenuNatives.GetNextContextMenuId();
- var id = contextMenus.getIdFromCreateProperties(createProperties);
- var onclick = createProperties.onclick;
- var optArgs = {
- __proto__: null,
- customCallback: getCallback($Function.bind(createCallback, null,
- instanceId, id, onclick)),
- };
- if (isWebview) {
- bindingUtil.sendRequest(
- 'chromeWebViewInternal.contextMenusCreate',
- [instanceId, createProperties, callback], optArgs);
- } else {
- bindingUtil.sendRequest(
- 'contextMenus.create', [createProperties, callback], optArgs);
- }
- return id;
- };
- function removeCallback(instanceId, id) {
- delete contextMenus.handlersForId(instanceId, id)[id];
- }
- requestHandlers.remove = function() {
- var args = $Array.from(arguments);
- var instanceId = getInstanceId(args);
- var id = args[0];
- var callback = args[1];
- var optArgs = {
- __proto__: null,
- customCallback: getCallback($Function.bind(removeCallback, null,
- instanceId, id)),
- };
- if (isWebview) {
- bindingUtil.sendRequest(
- 'chromeWebViewInternal.contextMenusRemove',
- [instanceId, id, callback], optArgs);
- } else {
- bindingUtil.sendRequest('contextMenus.remove', [id, callback], optArgs);
- }
- };
- function updateCallback(instanceId, id, 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];
- }
- }
- requestHandlers.update = function() {
- var args = $Array.from(arguments);
- var instanceId = getInstanceId(args);
- var id = args[0];
- var updateProperties = args[1];
- var callback = args[2];
- var onclick = updateProperties.onclick;
- var optArgs = {
- __proto__: null,
- customCallback: getCallback($Function.bind(updateCallback, null,
- instanceId, id, onclick)),
- };
- if (isWebview) {
- bindingUtil.sendRequest(
- 'chromeWebViewInternal.contextMenusUpdate',
- [instanceId, id, updateProperties, callback], optArgs);
- } else {
- bindingUtil.sendRequest(
- 'contextMenus.update', [id, updateProperties, callback], optArgs);
- }
- };
- function removeAllCallback(instanceId) {
- delete contextMenus.handlers[instanceId];
- }
- requestHandlers.removeAll = function() {
- var args = $Array.from(arguments);
- var instanceId = getInstanceId(args);
- var callback = args[0];
- var optArgs = {
- __proto__: null,
- customCallback: getCallback($Function.bind(removeAllCallback, null,
- instanceId)),
- };
- if (isWebview) {
- bindingUtil.sendRequest(
- 'chromeWebViewInternal.contextMenusRemoveAll', [instanceId, callback],
- optArgs);
- } else {
- bindingUtil.sendRequest('contextMenus.removeAll', [callback], optArgs);
- }
- };
- return {
- requestHandlers: requestHandlers,
- };
- }
- exports.$set('create', createContextMenusHandlers);
|