| OLD | NEW |
| (Empty) |
| 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 // Event management for WebView. | |
| 6 | |
| 7 var CreateEvent = require('guestViewEvents').CreateEvent; | |
| 8 var DeclarativeWebRequestSchema = | |
| 9 requireNative('schema_registry').GetSchema('declarativeWebRequest'); | |
| 10 var EventBindings = require('event_bindings'); | |
| 11 var GuestViewEvents = require('guestViewEvents').GuestViewEvents; | |
| 12 var IdGenerator = requireNative('id_generator'); | |
| 13 var WebRequestEvent = require('webRequestInternal').WebRequestEvent; | |
| 14 var WebRequestSchema = | |
| 15 requireNative('schema_registry').GetSchema('webRequest'); | |
| 16 var WebViewActionRequests = | |
| 17 require('webViewActionRequests').WebViewActionRequests; | |
| 18 | |
| 19 var WebRequestMessageEvent = CreateEvent('webViewInternal.onMessage'); | |
| 20 | |
| 21 function WebViewEvents(webViewImpl) { | |
| 22 GuestViewEvents.call(this, webViewImpl); | |
| 23 | |
| 24 this.setupWebRequestEvents(); | |
| 25 this.view.setupExperimentalContextMenus(); | |
| 26 } | |
| 27 | |
| 28 WebViewEvents.prototype.__proto__ = GuestViewEvents.prototype; | |
| 29 | |
| 30 // A dictionary of <webview> extension events to be listened for. This | |
| 31 // dictionary augments |GuestViewEvents.EVENTS| in guest_view_events.js. See the | |
| 32 // documentation there for details. | |
| 33 WebViewEvents.EVENTS = { | |
| 34 'close': { | |
| 35 evt: CreateEvent('webViewInternal.onClose') | |
| 36 }, | |
| 37 'consolemessage': { | |
| 38 evt: CreateEvent('webViewInternal.onConsoleMessage'), | |
| 39 fields: ['level', 'message', 'line', 'sourceId'] | |
| 40 }, | |
| 41 'contentload': { | |
| 42 evt: CreateEvent('webViewInternal.onContentLoad') | |
| 43 }, | |
| 44 'dialog': { | |
| 45 cancelable: true, | |
| 46 evt: CreateEvent('webViewInternal.onDialog'), | |
| 47 fields: ['defaultPromptText', 'messageText', 'messageType', 'url'], | |
| 48 handler: 'handleDialogEvent' | |
| 49 }, | |
| 50 'droplink': { | |
| 51 evt: CreateEvent('webViewInternal.onDropLink'), | |
| 52 fields: ['url'] | |
| 53 }, | |
| 54 'exit': { | |
| 55 evt: CreateEvent('webViewInternal.onExit'), | |
| 56 fields: ['processId', 'reason'] | |
| 57 }, | |
| 58 'findupdate': { | |
| 59 evt: CreateEvent('webViewInternal.onFindReply'), | |
| 60 fields: [ | |
| 61 'searchText', | |
| 62 'numberOfMatches', | |
| 63 'activeMatchOrdinal', | |
| 64 'selectionRect', | |
| 65 'canceled', | |
| 66 'finalUpdate' | |
| 67 ] | |
| 68 }, | |
| 69 'framenamechanged': { | |
| 70 evt: CreateEvent('webViewInternal.onFrameNameChanged'), | |
| 71 handler: 'handleFrameNameChangedEvent' | |
| 72 }, | |
| 73 'loadabort': { | |
| 74 cancelable: true, | |
| 75 evt: CreateEvent('webViewInternal.onLoadAbort'), | |
| 76 fields: ['url', 'isTopLevel', 'reason'], | |
| 77 handler: 'handleLoadAbortEvent' | |
| 78 }, | |
| 79 'loadcommit': { | |
| 80 evt: CreateEvent('webViewInternal.onLoadCommit'), | |
| 81 fields: ['url', 'isTopLevel'], | |
| 82 handler: 'handleLoadCommitEvent' | |
| 83 }, | |
| 84 'loadprogress': { | |
| 85 evt: CreateEvent('webViewInternal.onLoadProgress'), | |
| 86 fields: ['url', 'progress'] | |
| 87 }, | |
| 88 'loadredirect': { | |
| 89 evt: CreateEvent('webViewInternal.onLoadRedirect'), | |
| 90 fields: ['isTopLevel', 'oldUrl', 'newUrl'] | |
| 91 }, | |
| 92 'loadstart': { | |
| 93 evt: CreateEvent('webViewInternal.onLoadStart'), | |
| 94 fields: ['url', 'isTopLevel'] | |
| 95 }, | |
| 96 'loadstop': { | |
| 97 evt: CreateEvent('webViewInternal.onLoadStop') | |
| 98 }, | |
| 99 'newwindow': { | |
| 100 cancelable: true, | |
| 101 evt: CreateEvent('webViewInternal.onNewWindow'), | |
| 102 fields: [ | |
| 103 'initialHeight', | |
| 104 'initialWidth', | |
| 105 'targetUrl', | |
| 106 'windowOpenDisposition', | |
| 107 'name' | |
| 108 ], | |
| 109 handler: 'handleNewWindowEvent' | |
| 110 }, | |
| 111 'permissionrequest': { | |
| 112 cancelable: true, | |
| 113 evt: CreateEvent('webViewInternal.onPermissionRequest'), | |
| 114 fields: [ | |
| 115 'identifier', | |
| 116 'lastUnlockedBySelf', | |
| 117 'name', | |
| 118 'permission', | |
| 119 'requestMethod', | |
| 120 'url', | |
| 121 'userGesture' | |
| 122 ], | |
| 123 handler: 'handlePermissionEvent' | |
| 124 }, | |
| 125 'responsive': { | |
| 126 evt: CreateEvent('webViewInternal.onResponsive'), | |
| 127 fields: ['processId'] | |
| 128 }, | |
| 129 'sizechanged': { | |
| 130 evt: CreateEvent('webViewInternal.onSizeChanged'), | |
| 131 fields: ['oldHeight', 'oldWidth', 'newHeight', 'newWidth'], | |
| 132 handler: 'handleSizeChangedEvent' | |
| 133 }, | |
| 134 'unresponsive': { | |
| 135 evt: CreateEvent('webViewInternal.onUnresponsive'), | |
| 136 fields: ['processId'] | |
| 137 }, | |
| 138 'zoomchange': { | |
| 139 evt: CreateEvent('webViewInternal.onZoomChange'), | |
| 140 fields: ['oldZoomFactor', 'newZoomFactor'] | |
| 141 } | |
| 142 }; | |
| 143 | |
| 144 WebViewEvents.prototype.setupWebRequestEvents = function() { | |
| 145 var request = {}; | |
| 146 var createWebRequestEvent = function(webRequestEvent) { | |
| 147 return function() { | |
| 148 if (!this[webRequestEvent.name]) { | |
| 149 this[webRequestEvent.name] = | |
| 150 new WebRequestEvent( | |
| 151 'webViewInternal.' + webRequestEvent.name, | |
| 152 webRequestEvent.parameters, | |
| 153 webRequestEvent.extraParameters, webRequestEvent.options, | |
| 154 this.view.viewInstanceId); | |
| 155 } | |
| 156 return this[webRequestEvent.name]; | |
| 157 }.bind(this); | |
| 158 }.bind(this); | |
| 159 | |
| 160 var createDeclarativeWebRequestEvent = function(webRequestEvent) { | |
| 161 return function() { | |
| 162 if (!this[webRequestEvent.name]) { | |
| 163 // The onMessage event gets a special event type because we want | |
| 164 // the listener to fire only for messages targeted for this particular | |
| 165 // <webview>. | |
| 166 var EventClass = webRequestEvent.name === 'onMessage' ? | |
| 167 DeclarativeWebRequestEvent : EventBindings.Event; | |
| 168 this[webRequestEvent.name] = | |
| 169 new EventClass( | |
| 170 'webViewInternal.declarativeWebRequest.' + webRequestEvent.name, | |
| 171 webRequestEvent.parameters, | |
| 172 webRequestEvent.options, | |
| 173 this.view.viewInstanceId); | |
| 174 } | |
| 175 return this[webRequestEvent.name]; | |
| 176 }.bind(this); | |
| 177 }.bind(this); | |
| 178 | |
| 179 for (var i = 0; i < DeclarativeWebRequestSchema.events.length; ++i) { | |
| 180 var eventSchema = DeclarativeWebRequestSchema.events[i]; | |
| 181 var webRequestEvent = createDeclarativeWebRequestEvent(eventSchema); | |
| 182 Object.defineProperty( | |
| 183 request, | |
| 184 eventSchema.name, | |
| 185 { | |
| 186 get: webRequestEvent, | |
| 187 enumerable: true | |
| 188 } | |
| 189 ); | |
| 190 } | |
| 191 | |
| 192 // Populate the WebRequest events from the API definition. | |
| 193 for (var i = 0; i < WebRequestSchema.events.length; ++i) { | |
| 194 var webRequestEvent = createWebRequestEvent(WebRequestSchema.events[i]); | |
| 195 Object.defineProperty( | |
| 196 request, | |
| 197 WebRequestSchema.events[i].name, | |
| 198 { | |
| 199 get: webRequestEvent, | |
| 200 enumerable: true | |
| 201 } | |
| 202 ); | |
| 203 } | |
| 204 | |
| 205 this.view.setRequestPropertyOnWebViewElement(request); | |
| 206 }; | |
| 207 | |
| 208 WebViewEvents.prototype.getEvents = function() { | |
| 209 return WebViewEvents.EVENTS; | |
| 210 }; | |
| 211 | |
| 212 WebViewEvents.prototype.handleDialogEvent = function(event, eventName) { | |
| 213 var webViewEvent = this.makeDomEvent(event, eventName); | |
| 214 new WebViewActionRequests.Dialog(this.view, event, webViewEvent); | |
| 215 }; | |
| 216 | |
| 217 WebViewEvents.prototype.handleFrameNameChangedEvent = function(event) { | |
| 218 this.view.onFrameNameChanged(event.name); | |
| 219 }; | |
| 220 | |
| 221 WebViewEvents.prototype.handleLoadAbortEvent = function(event, eventName) { | |
| 222 var showWarningMessage = function(reason) { | |
| 223 var WARNING_MSG_LOAD_ABORTED = '<webview>: ' + | |
| 224 'The load has aborted with reason "%1".'; | |
| 225 window.console.warn(WARNING_MSG_LOAD_ABORTED.replace('%1', reason)); | |
| 226 }; | |
| 227 var webViewEvent = this.makeDomEvent(event, eventName); | |
| 228 if (this.view.dispatchEvent(webViewEvent)) { | |
| 229 showWarningMessage(event.reason); | |
| 230 } | |
| 231 }; | |
| 232 | |
| 233 WebViewEvents.prototype.handleLoadCommitEvent = function(event, eventName) { | |
| 234 this.view.onLoadCommit(event.baseUrlForDataUrl, | |
| 235 event.currentEntryIndex, | |
| 236 event.entryCount, | |
| 237 event.processId, | |
| 238 event.url, | |
| 239 event.isTopLevel); | |
| 240 var webViewEvent = this.makeDomEvent(event, eventName); | |
| 241 this.view.dispatchEvent(webViewEvent); | |
| 242 }; | |
| 243 | |
| 244 WebViewEvents.prototype.handleNewWindowEvent = function(event, eventName) { | |
| 245 var webViewEvent = this.makeDomEvent(event, eventName); | |
| 246 new WebViewActionRequests.NewWindow(this.view, event, webViewEvent); | |
| 247 }; | |
| 248 | |
| 249 WebViewEvents.prototype.handlePermissionEvent = function(event, eventName) { | |
| 250 var webViewEvent = this.makeDomEvent(event, eventName); | |
| 251 new WebViewActionRequests.PermissionRequest(this.view, event, webViewEvent); | |
| 252 }; | |
| 253 | |
| 254 WebViewEvents.prototype.handleSizeChangedEvent = function(event, eventName) { | |
| 255 var webViewEvent = this.makeDomEvent(event, eventName); | |
| 256 this.view.onSizeChanged(webViewEvent); | |
| 257 }; | |
| 258 | |
| 259 function DeclarativeWebRequestEvent(opt_eventName, | |
| 260 opt_argSchemas, | |
| 261 opt_eventOptions, | |
| 262 opt_webViewInstanceId) { | |
| 263 var subEventName = opt_eventName + '/' + IdGenerator.GetNextId(); | |
| 264 EventBindings.Event.call(this, | |
| 265 subEventName, | |
| 266 opt_argSchemas, | |
| 267 opt_eventOptions, | |
| 268 opt_webViewInstanceId); | |
| 269 | |
| 270 // TODO(lazyboy): When do we dispose this listener? | |
| 271 WebRequestMessageEvent.addListener(function() { | |
| 272 // Re-dispatch to subEvent's listeners. | |
| 273 $Function.apply(this.dispatch, this, $Array.slice(arguments)); | |
| 274 }.bind(this), {instanceId: opt_webViewInstanceId || 0}); | |
| 275 } | |
| 276 | |
| 277 DeclarativeWebRequestEvent.prototype.__proto__ = EventBindings.Event.prototype; | |
| 278 | |
| 279 // Exports. | |
| 280 exports.WebViewEvents = WebViewEvents; | |
| OLD | NEW |