12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This module implements experimental API for <webview>.
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// See web_view.js for details.
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// <webview> Experimental API is only available on canary and dev channels of
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Chrome.
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)var ContextMenusSchema =
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    requireNative('schema_registry').GetSchema('contextMenus');
136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)var CreateEvent = require('webViewEvents').CreateEvent;
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)var EventBindings = require('event_bindings');
15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)var MessagingNatives = requireNative('messaging_natives');
16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)var WebView = require('webView').WebView;
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)var WebViewInternal = require('webView').WebViewInternal;
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)var WebViewSchema = requireNative('schema_registry').GetSchema('webview');
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)var idGeneratorNatives = requireNative('id_generator');
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)var utils = require('utils');
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// WEB_VIEW_EXPERIMENTAL_EVENTS is a map of experimental <webview> DOM event
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     names to their associated extension event descriptor objects.
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// An event listener will be attached to the extension event |evt| specified in
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     the descriptor.
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// |fields| specifies the public-facing fields in the DOM event that are
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     accessible to <webview> developers.
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// |customHandler| allows a handler function to be called each time an extension
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     event is caught by its event listener. The DOM event should be dispatched
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     within this handler function. With no handler function, the DOM event
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     will be dispatched by default each time the extension event is caught.
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// |cancelable| (default: false) specifies whether the event's default
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     behavior can be canceled. If the default action associated with the event
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     is prevented, then its dispatch function will return false in its event
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//     handler. The event must have a custom handler for this to be meaningful.
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)var WEB_VIEW_EXPERIMENTAL_EVENTS = {
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  'findupdate': {
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    evt: CreateEvent('webview.onFindReply'),
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    fields: [
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      'searchText',
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      'numberOfMatches',
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      'activeMatchOrdinal',
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      'selectionRect',
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      'canceled',
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      'finalUpdate'
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ]
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  },
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  'zoomchange': {
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    evt: CreateEvent('webview.onZoomChange'),
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    fields: ['oldZoomFactor', 'newZoomFactor']
51c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  }
52c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch};
53c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)function GetUniqueSubEventName(eventName) {
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return eventName + "/" + idGeneratorNatives.GetNextId();
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This is the only "webview.onClicked" named event for this renderer.
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Since we need an event per <webview>, we define events with suffix
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// (subEventName) in each of the <webview>. Behind the scenes, this event is
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// registered as a ContextMenusEvent, with filter set to the webview's
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |viewInstanceId|. Any time a ContextMenusEvent is dispatched, we re-dispatch
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// it to the subEvent's listeners. This way
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// <webview>.contextMenus.onClicked behave as a regular chrome Event type.
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)var ContextMenusEvent = CreateEvent('webview.onClicked');
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/**
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * This event is exposed as <webview>.contextMenus.onClicked.
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @constructor
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) */
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)function ContextMenusOnClickedEvent(opt_eventName,
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    opt_argSchemas,
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    opt_eventOptions,
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    opt_webViewInstanceId) {
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  var subEventName = GetUniqueSubEventName(opt_eventName);
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EventBindings.Event.call(this, subEventName, opt_argSchemas, opt_eventOptions,
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      opt_webViewInstanceId);
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  var self = this;
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(lazyboy): When do we dispose this listener?
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ContextMenusEvent.addListener(function() {
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Re-dispatch to subEvent's listeners.
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    $Function.apply(self.dispatch, self, $Array.slice(arguments));
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }, {instanceId: opt_webViewInstanceId || 0});
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ContextMenusOnClickedEvent.prototype = {
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  __proto__: EventBindings.Event.prototype
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/**
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * An instance of this class is exposed as <webview>.contextMenus.
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @constructor
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) */
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)function WebViewContextMenusImpl(viewInstanceId) {
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  this.viewInstanceId_ = viewInstanceId;
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WebViewContextMenusImpl.prototype.create = function() {
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return $Function.apply(WebView.contextMenusCreate, null, args);
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WebViewContextMenusImpl.prototype.remove = function() {
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return $Function.apply(WebView.contextMenusRemove, null, args);
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WebViewContextMenusImpl.prototype.removeAll = function() {
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return $Function.apply(WebView.contextMenusRemoveAll, null, args);
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WebViewContextMenusImpl.prototype.update = function() {
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments));
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return $Function.apply(WebView.contextMenusUpdate, null, args);
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)var WebViewContextMenus = utils.expose(
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    'WebViewContextMenus', WebViewContextMenusImpl,
1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    { functions: ['create', 'remove', 'removeAll', 'update'] });
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)/** @private */
126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)WebViewInternal.prototype.maybeHandleContextMenu = function(e, webViewEvent) {
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  var requestId = e.requestId;
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  var self = this;
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Construct the event.menu object.
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  var actionTaken = false;
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  var validateCall = function() {
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    var ERROR_MSG_CONTEXT_MENU_ACTION_ALREADY_TAKEN = '<webview>: ' +
133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        'An action has already been taken for this "contextmenu" event.';
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (actionTaken) {
136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      throw new Error(ERROR_MSG_CONTEXT_MENU_ACTION_ALREADY_TAKEN);
137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    actionTaken = true;
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  };
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  var menu = {
141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    show: function(items) {
142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      validateCall();
143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // TODO(lazyboy): WebViewShowContextFunction doesn't do anything useful
144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // with |items|, implement.
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      WebView.showContextMenu(self.instanceId, requestId, items);
146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  };
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  webViewEvent.menu = menu;
149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  var webviewNode = this.webviewNode;
150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  var defaultPrevented = !webviewNode.dispatchEvent(webViewEvent);
151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (actionTaken) {
152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!defaultPrevented) {
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    actionTaken = true;
156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // The default action is equivalent to just showing the context menu as is.
157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    WebView.showContextMenu(self.instanceId, requestId, undefined);
158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // TODO(lazyboy): Figure out a way to show warning message only when
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // listeners are registered for this event.
161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } //  else we will ignore showing the context menu completely.
162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)};
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
164a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch/**
165a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch * @private
166a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch */
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebViewInternal.prototype.setZoom = function(zoomFactor) {
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!this.instanceId) {
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebView.setZoom(this.instanceId, zoomFactor);
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebViewInternal.prototype.maybeGetExperimentalEvents = function() {
175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return WEB_VIEW_EXPERIMENTAL_EVENTS;
176a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch};
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/** @private */
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebViewInternal.prototype.maybeGetExperimentalPermissions = function() {
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return [];
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/** @private */
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebViewInternal.prototype.maybeSetCurrentZoomFactor =
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    function(zoomFactor) {
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  this.currentZoomFactor = zoomFactor;
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/** @private */
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebViewInternal.prototype.setZoom = function(zoomFactor, callback) {
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!this.instanceId) {
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebView.setZoom(this.instanceId, zoomFactor, callback);
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebViewInternal.prototype.getZoom = function(callback) {
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!this.instanceId) {
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebView.getZoom(this.instanceId, callback);
20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/** @private */
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebViewInternal.prototype.captureVisibleRegion = function(spec, callback) {
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebView.captureVisibleRegion(this.instanceId, spec, callback);
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/** @private */
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WebViewInternal.prototype.find = function(search_text, options, callback) {
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!this.instanceId) {
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WebView.find(this.instanceId, search_text, options, callback);
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/** @private */
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WebViewInternal.prototype.stopFinding = function(action) {
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!this.instanceId) {
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WebView.stopFinding(this.instanceId, action);
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  proto.setZoom = function(zoomFactor, callback) {
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    privates(this).internal.setZoom(zoomFactor, callback);
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  };
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  proto.getZoom = function(callback) {
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return privates(this).internal.getZoom(callback);
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  };
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  proto.captureVisibleRegion = function(spec, callback) {
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    privates(this).internal.captureVisibleRegion(spec, callback);
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  };
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  proto.find = function(search_text, options, callback) {
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    privates(this).internal.find(search_text, options, callback);
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  proto.stopFinding = function(action) {
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    privates(this).internal.stopFinding(action);
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/** @private */
2486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)WebViewInternal.prototype.setupExperimentalContextMenus = function() {
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  var self = this;
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  var createContextMenus = function() {
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return function() {
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (self.contextMenus_) {
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return self.contextMenus_;
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      self.contextMenus_ = new WebViewContextMenus(self.viewInstanceId);
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Define 'onClicked' event property on |self.contextMenus_|.
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      var getOnClickedEvent = function() {
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return function() {
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          if (!self.contextMenusOnClickedEvent_) {
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            var eventName = 'webview.onClicked';
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            // TODO(lazyboy): Find event by name instead of events[0].
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            var eventSchema = WebViewSchema.events[0];
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            var eventOptions = {supportsListeners: true};
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            var onClickedEvent = new ContextMenusOnClickedEvent(
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                eventName, eventSchema, eventOptions, self.viewInstanceId);
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            self.contextMenusOnClickedEvent_ = onClickedEvent;
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            return onClickedEvent;
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          }
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          return self.contextMenusOnClickedEvent_;
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      };
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Object.defineProperty(
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          self.contextMenus_,
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          'onClicked',
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          {get: getOnClickedEvent(), enumerable: true});
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return self.contextMenus_;
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    };
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Expose <webview>.contextMenus object.
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Object.defineProperty(
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      this.webviewNode,
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      'contextMenus',
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      {
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        get: createContextMenus(),
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        enumerable: true
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      });
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
292