1 // Copyright 2014 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. 4 5 // This module implements chrome-specific <webview> API. 6 7 var ChromeWebView = require('chromeWebViewInternal').ChromeWebView; 8 var CreateEvent = require('webViewEvents').CreateEvent; 9 var DeclarativeWebRequestSchema = 10 requireNative('schema_registry').GetSchema('declarativeWebRequest'); 11 var EventBindings = require('event_bindings'); 12 var IdGenerator = requireNative('id_generator'); 13 var WebRequestEvent = require('webRequestInternal').WebRequestEvent; 14 var WebRequestSchema = 15 requireNative('schema_registry').GetSchema('webRequest'); 16 var WebViewInternal = require('webView').WebViewInternal 17 18 var WebRequestMessageEvent = CreateEvent('webViewInternal.onMessage'); 19 20 var CHROME_WEB_VIEW_EVENTS = { 21 'contextmenu': { 22 evt: CreateEvent('chromeWebViewInternal.contextmenu'), 23 cancelable: true, 24 customHandler: function(handler, event, webViewEvent) { 25 handler.webViewInternal.maybeHandleContextMenu(event, webViewEvent); 26 }, 27 fields: ['items'] 28 } 29 }; 30 31 function DeclarativeWebRequestEvent(opt_eventName, 32 opt_argSchemas, 33 opt_eventOptions, 34 opt_webViewInstanceId) { 35 var subEventName = opt_eventName + '/' + IdGenerator.GetNextId(); 36 EventBindings.Event.call(this, subEventName, opt_argSchemas, opt_eventOptions, 37 opt_webViewInstanceId); 38 39 // TODO(lazyboy): When do we dispose this listener? 40 WebRequestMessageEvent.addListener(function() { 41 // Re-dispatch to subEvent's listeners. 42 $Function.apply(this.dispatch, this, $Array.slice(arguments)); 43 }.bind(this), {instanceId: opt_webViewInstanceId || 0}); 44 } 45 46 DeclarativeWebRequestEvent.prototype = { 47 __proto__: EventBindings.Event.prototype 48 }; 49 50 /** 51 * Implemented when the ChromeWebView API is available. 52 * @private 53 */ 54 WebViewInternal.prototype.maybeGetChromeWebViewEvents = function() { 55 return CHROME_WEB_VIEW_EVENTS; 56 }; 57 58 /** 59 * Calls to show contextmenu right away instead of dispatching a 'contextmenu' 60 * event. 61 * This will be overridden in chrome_web_view_experimental.js to implement 62 * contextmenu API. 63 */ 64 WebViewInternal.prototype.maybeHandleContextMenu = function(e, webViewEvent) { 65 var requestId = e.requestId; 66 // Setting |params| = undefined will show the context menu unmodified, hence 67 // the 'contextmenu' API is disabled for stable channel. 68 var params = undefined; 69 ChromeWebView.showContextMenu(this.guestInstanceId, requestId, params); 70 }; 71 72 WebViewInternal.prototype.maybeSetupChromeWebViewEvents = function() { 73 var request = {}; 74 var createWebRequestEvent = function(webRequestEvent) { 75 return function() { 76 if (!this[webRequestEvent.name]) { 77 this[webRequestEvent.name] = 78 new WebRequestEvent( 79 'webViewInternal.' + webRequestEvent.name, 80 webRequestEvent.parameters, 81 webRequestEvent.extraParameters, webRequestEvent.options, 82 this.viewInstanceId); 83 } 84 return this[webRequestEvent.name]; 85 }.bind(this); 86 }.bind(this); 87 88 var createDeclarativeWebRequestEvent = function(webRequestEvent) { 89 return function() { 90 if (!this[webRequestEvent.name]) { 91 // The onMessage event gets a special event type because we want 92 // the listener to fire only for messages targeted for this particular 93 // <webview>. 94 var EventClass = webRequestEvent.name === 'onMessage' ? 95 DeclarativeWebRequestEvent : EventBindings.Event; 96 this[webRequestEvent.name] = 97 new EventClass( 98 'webViewInternal.' + webRequestEvent.name, 99 webRequestEvent.parameters, 100 webRequestEvent.options, 101 this.viewInstanceId); 102 } 103 return this[webRequestEvent.name]; 104 }.bind(this); 105 }.bind(this); 106 107 for (var i = 0; i < DeclarativeWebRequestSchema.events.length; ++i) { 108 var eventSchema = DeclarativeWebRequestSchema.events[i]; 109 var webRequestEvent = createDeclarativeWebRequestEvent(eventSchema); 110 Object.defineProperty( 111 request, 112 eventSchema.name, 113 { 114 get: webRequestEvent, 115 enumerable: true 116 } 117 ); 118 } 119 120 // Populate the WebRequest events from the API definition. 121 for (var i = 0; i < WebRequestSchema.events.length; ++i) { 122 var webRequestEvent = createWebRequestEvent(WebRequestSchema.events[i]); 123 Object.defineProperty( 124 request, 125 WebRequestSchema.events[i].name, 126 { 127 get: webRequestEvent, 128 enumerable: true 129 } 130 ); 131 } 132 133 this.setRequestPropertyOnWebViewNode(request); 134 }; 135