1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Implementation of custom bindings for the contextMenus API.
6 // This is used to implement the contextMenus API for extensions and for the
7 // <webview> tag (see chrome_web_view_experimental.js).
9 var contextMenuNatives
= requireNative('context_menus');
10 var sendRequest
= require('sendRequest').sendRequest
;
11 var Event
= require('event_bindings').Event
;
12 var lastError
= require('lastError');
14 // Add the bindings to the contextMenus API.
15 function createContextMenusHandlers(isWebview
) {
16 var eventName
= isWebview
? 'webViewInternal.contextMenus' : 'contextMenus';
17 // Some dummy value for chrome.contextMenus instances.
18 // Webviews use positive integers, and 0 to denote an invalid webview ID.
19 // The following constant is -1 to avoid any conflicts between webview IDs and
21 var INSTANCEID_NON_WEBVIEW
= -1;
23 // Generates a customCallback for a given method. |handleCallback| will be
24 // invoked with |request.args| as parameters.
25 function createCustomCallback(handleCallback
) {
26 return function(name
, request
, callback
) {
27 if (lastError
.hasError(chrome
)) {
32 var args
= request
.args
;
34 // <webview>s have an extra item in front of the parameter list, which
35 // specifies the viewInstanceId of the webview. This is used to hide
36 // context menu events in one webview from another.
37 // The non-webview chrome.contextMenus API is not called with such an
38 // ID, so we prepend an ID to match the function signature.
39 args
= $Array
.concat([INSTANCEID_NON_WEBVIEW
], args
);
41 $Function
.apply(handleCallback
, null, args
);
47 var contextMenus
= {};
48 contextMenus
.handlers
= {};
49 contextMenus
.event
= new Event(eventName
);
51 contextMenus
.getIdFromCreateProperties = function(createProperties
) {
52 if (typeof createProperties
.id
!== 'undefined')
53 return createProperties
.id
;
54 return createProperties
.generatedId
;
57 contextMenus
.handlersForId = function(instanceId
, id
) {
58 if (!contextMenus
.handlers
[instanceId
]) {
59 contextMenus
.handlers
[instanceId
] = {
64 if (typeof id
=== 'number')
65 return contextMenus
.handlers
[instanceId
].generated
;
66 return contextMenus
.handlers
[instanceId
].string
;
69 contextMenus
.ensureListenerSetup = function() {
70 if (contextMenus
.listening
) {
73 contextMenus
.listening
= true;
74 contextMenus
.event
.addListener(function(info
) {
75 var instanceId
= INSTANCEID_NON_WEBVIEW
;
77 instanceId
= info
.webviewInstanceId
;
78 // Don't expose |webviewInstanceId| via the public API.
79 delete info
.webviewInstanceId
;
82 var id
= info
.menuItemId
;
83 var onclick
= contextMenus
.handlersForId(instanceId
, id
)[id
];
85 $Function
.apply(onclick
, null, arguments
);
90 // To be used with apiFunctions.setHandleRequest
91 var requestHandlers
= {};
92 // To be used with apiFunctions.setCustomCallback
95 requestHandlers
.create = function() {
96 var createProperties
= isWebview
? arguments
[1] : arguments
[0];
97 createProperties
.generatedId
= contextMenuNatives
.GetNextContextMenuId();
99 customCallback
: this.customCallback
,
101 sendRequest(this.name
, arguments
, this.definition
.parameters
, optArgs
);
102 return contextMenus
.getIdFromCreateProperties(createProperties
);
106 createCustomCallback(function(instanceId
, createProperties
) {
107 var id
= contextMenus
.getIdFromCreateProperties(createProperties
);
108 var onclick
= createProperties
.onclick
;
110 contextMenus
.ensureListenerSetup();
111 contextMenus
.handlersForId(instanceId
, id
)[id
] = onclick
;
115 callbacks
.remove
= createCustomCallback(function(instanceId
, id
) {
116 delete contextMenus
.handlersForId(instanceId
, id
)[id
];
120 createCustomCallback(function(instanceId
, id
, updateProperties
) {
121 var onclick
= updateProperties
.onclick
;
123 contextMenus
.ensureListenerSetup();
124 contextMenus
.handlersForId(instanceId
, id
)[id
] = onclick
;
125 } else if (onclick
=== null) {
126 // When onclick is explicitly set to null, remove the event listener.
127 delete contextMenus
.handlersForId(instanceId
, id
)[id
];
131 callbacks
.removeAll
= createCustomCallback(function(instanceId
) {
132 delete contextMenus
.handlers
[instanceId
];
136 requestHandlers
: requestHandlers
,
141 exports
.create
= createContextMenusHandlers
;