Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / renderer / resources / extensions / web_view_experimental.js
blob11cfd8c9973584381658f62d8e5e4698990b81ae
1 // Copyright 2013 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 // This module implements experimental API for <webview>.
6 // See web_view.js for details.
7 //
8 // <webview> Experimental API is only available on canary and dev channels of
9 // Chrome.
11 var ContextMenusSchema =
12     requireNative('schema_registry').GetSchema('contextMenus');
13 var CreateEvent = require('webView').CreateEvent;
14 var EventBindings = require('event_bindings');
15 var MessagingNatives = requireNative('messaging_natives');
16 var WebView = require('webView').WebView;
17 var WebViewInternal = require('webView').WebViewInternal;
18 var WebViewSchema = requireNative('schema_registry').GetSchema('webview');
19 var idGeneratorNatives = requireNative('id_generator');
20 var utils = require('utils');
22 // WEB_VIEW_EXPERIMENTAL_EVENTS is a map of experimental <webview> DOM event
23 //     names to their associated extension event descriptor objects.
24 // An event listener will be attached to the extension event |evt| specified in
25 //     the descriptor.
26 // |fields| specifies the public-facing fields in the DOM event that are
27 //     accessible to <webview> developers.
28 // |customHandler| allows a handler function to be called each time an extension
29 //     event is caught by its event listener. The DOM event should be dispatched
30 //     within this handler function. With no handler function, the DOM event
31 //     will be dispatched by default each time the extension event is caught.
32 // |cancelable| (default: false) specifies whether the event's default
33 //     behavior can be canceled. If the default action associated with the event
34 //     is prevented, then its dispatch function will return false in its event
35 //     handler. The event must have a custom handler for this to be meaningful.
36 var WEB_VIEW_EXPERIMENTAL_EVENTS = {
37   'contextmenu': {
38     evt: CreateEvent('webview.contextmenu'),
39     cancelable: true,
40     customHandler: function(webViewInternal, event, webViewEvent) {
41       webViewInternal.handleContextMenu(event, webViewEvent);
42     },
43     fields: ['items']
44   },
45   'findupdate': {
46     evt: CreateEvent('webview.onFindReply'),
47     fields: [
48       'searchText',
49       'numberOfMatches',
50       'activeMatchOrdinal',
51       'selectionRect',
52       'canceled',
53       'finalUpdate'
54     ]
55   },
56   'zoomchange': {
57     evt: CreateEvent('webview.onZoomChange'),
58     fields: ['oldZoomFactor', 'newZoomFactor']
59   }
62 function GetUniqueSubEventName(eventName) {
63   return eventName + "/" + idGeneratorNatives.GetNextId();
66 // This is the only "webview.onClicked" named event for this renderer.
68 // Since we need an event per <webview>, we define events with suffix
69 // (subEventName) in each of the <webview>. Behind the scenes, this event is
70 // registered as a ContextMenusEvent, with filter set to the webview's
71 // |viewInstanceId|. Any time a ContextMenusEvent is dispatched, we re-dispatch
72 // it to the subEvent's listeners. This way
73 // <webview>.contextMenus.onClicked behave as a regular chrome Event type.
74 var ContextMenusEvent = CreateEvent('webview.onClicked');
76 /**
77  * This event is exposed as <webview>.contextMenus.onClicked.
78  *
79  * @constructor
80  */
81 function ContextMenusOnClickedEvent(opt_eventName,
82                                     opt_argSchemas,
83                                     opt_eventOptions,
84                                     opt_webViewInstanceId) {
85   var subEventName = GetUniqueSubEventName(opt_eventName);
86   EventBindings.Event.call(this, subEventName, opt_argSchemas, opt_eventOptions,
87       opt_webViewInstanceId);
89   var self = this;
90   // TODO(lazyboy): When do we dispose this listener?
91   ContextMenusEvent.addListener(function() {
92     // Re-dispatch to subEvent's listeners.
93     $Function.apply(self.dispatch, self, $Array.slice(arguments));
94   }, {instanceId: opt_webViewInstanceId || 0});
97 ContextMenusOnClickedEvent.prototype = {
98   __proto__: EventBindings.Event.prototype
102  * An instance of this class is exposed as <webview>.contextMenus.
103  * @constructor
104  */
105 function WebViewContextMenusImpl(viewInstanceId) {
106   this.viewInstanceId_ = viewInstanceId;
109 WebViewContextMenusImpl.prototype.create = function() {
110   var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
111   return $Function.apply(WebView.contextMenusCreate, null, args);
114 WebViewContextMenusImpl.prototype.remove = function() {
115   var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
116   return $Function.apply(WebView.contextMenusRemove, null, args);
119 WebViewContextMenusImpl.prototype.removeAll = function() {
120   var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
121   return $Function.apply(WebView.contextMenusRemoveAll, null, args);
124 WebViewContextMenusImpl.prototype.update = function() {
125   var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
126   return $Function.apply(WebView.contextMenusUpdate, null, args);
129 var WebViewContextMenus = utils.expose(
130     'WebViewContextMenus', WebViewContextMenusImpl,
131     { functions: ['create', 'remove', 'removeAll', 'update'] });
134  * @private
135  */
136 WebViewInternal.prototype.maybeAttachWebRequestEventToObject =
137     function(obj, eventName, webRequestEvent) {
138   Object.defineProperty(
139       obj,
140       eventName,
141       {
142         get: webRequestEvent,
143         enumerable: true
144       }
145   );
148 /** @private */
149 WebViewInternal.prototype.handleContextMenu = function(e, webViewEvent) {
150   var requestId = e.requestId;
151   var self = this;
152   // Construct the event.menu object.
153   var menu = {
154     show: function(items) {
155       // TODO(lazyboy): Implement.
156       window.console.log('menu.show() Not implemented yet');
157     }
158   };
159   webViewEvent.menu = menu;
160   var webviewNode = this.webviewNode;
161   webviewNode.dispatchEvent(webViewEvent);
165  * @private
166  */
167 WebViewInternal.prototype.setZoom = function(zoomFactor) {
168   if (!this.instanceId) {
169     return;
170   }
171   WebView.setZoom(this.instanceId, zoomFactor);
174 WebViewInternal.prototype.maybeGetExperimentalEvents = function() {
175   return WEB_VIEW_EXPERIMENTAL_EVENTS;
178 /** @private */
179 WebViewInternal.prototype.maybeGetExperimentalPermissions = function() {
180   return [];
183 /** @private */
184 WebViewInternal.prototype.maybeSetCurrentZoomFactor =
185     function(zoomFactor) {
186   this.currentZoomFactor = zoomFactor;
189 /** @private */
190 WebViewInternal.prototype.setZoom = function(zoomFactor, callback) {
191   if (!this.instanceId) {
192     return;
193   }
194   WebView.setZoom(this.instanceId, zoomFactor, callback);
197 WebViewInternal.prototype.getZoom = function(callback) {
198   if (!this.instanceId) {
199     return;
200   }
201   WebView.getZoom(this.instanceId, callback);
204 /** @private */
205 WebViewInternal.prototype.captureVisibleRegion = function(spec, callback) {
206   WebView.captureVisibleRegion(this.instanceId, spec, callback);
209 /** @private */
210 WebViewInternal.prototype.find = function(search_text, options, callback) {
211   if (!this.instanceId) {
212     return;
213   }
214   WebView.find(this.instanceId, search_text, options, callback);
217 /** @private */
218 WebViewInternal.prototype.stopFinding = function(action) {
219   if (!this.instanceId) {
220     return;
221   }
222   WebView.stopFinding(this.instanceId, action);
225 WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {
226   proto.setZoom = function(zoomFactor, callback) {
227     privates(this).internal.setZoom(zoomFactor, callback);
228   };
230   proto.getZoom = function(callback) {
231     return privates(this).internal.getZoom(callback);
232   };
234   proto.captureVisibleRegion = function(spec, callback) {
235     privates(this).internal.captureVisibleRegion(spec, callback);
236   };
238   proto.find = function(search_text, options, callback) {
239     privates(this).internal.find(search_text, options, callback);
240   };
242   proto.stopFinding = function(action) {
243     privates(this).internal.stopFinding(action);
244   };
247 /** @private */
248 WebViewInternal.prototype.setupExperimentalContextMenus_ = function() {
249   var self = this;
250   var createContextMenus = function() {
251     return function() {
252       if (self.contextMenus_) {
253         return self.contextMenus_;
254       }
256       self.contextMenus_ = new WebViewContextMenus(self.viewInstanceId);
258       // Define 'onClicked' event property on |self.contextMenus_|.
259       var getOnClickedEvent = function() {
260         return function() {
261           if (!self.contextMenusOnClickedEvent_) {
262             var eventName = 'webview.onClicked';
263             // TODO(lazyboy): Find event by name instead of events[0].
264             var eventSchema = WebViewSchema.events[0];
265             var eventOptions = {supportsListeners: true};
266             var onClickedEvent = new ContextMenusOnClickedEvent(
267                 eventName, eventSchema, eventOptions, self.viewInstanceId);
268             self.contextMenusOnClickedEvent_ = onClickedEvent;
269             return onClickedEvent;
270           }
271           return self.contextMenusOnClickedEvent_;
272         }
273       };
274       Object.defineProperty(
275           self.contextMenus_,
276           'onClicked',
277           {get: getOnClickedEvent(), enumerable: true});
279       return self.contextMenus_;
280     };
281   };
283   // Expose <webview>.contextMenus object.
284   Object.defineProperty(
285       this.webviewNode,
286       'contextMenus',
287       {
288         get: createContextMenus(),
289         enumerable: true
290       });