OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Event management for WebViewInternal. | 5 // Event management for WebViewInternal. |
6 | 6 |
7 var DeclarativeWebRequestSchema = | 7 var DeclarativeWebRequestSchema = |
8 requireNative('schema_registry').GetSchema('declarativeWebRequest'); | 8 requireNative('schema_registry').GetSchema('declarativeWebRequest'); |
9 var EventBindings = require('event_bindings'); | 9 var EventBindings = require('event_bindings'); |
10 var IdGenerator = requireNative('id_generator'); | 10 var IdGenerator = requireNative('id_generator'); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 }; | 164 }; |
165 | 165 |
166 function DeclarativeWebRequestEvent(opt_eventName, | 166 function DeclarativeWebRequestEvent(opt_eventName, |
167 opt_argSchemas, | 167 opt_argSchemas, |
168 opt_eventOptions, | 168 opt_eventOptions, |
169 opt_webViewInstanceId) { | 169 opt_webViewInstanceId) { |
170 var subEventName = opt_eventName + '/' + IdGenerator.GetNextId(); | 170 var subEventName = opt_eventName + '/' + IdGenerator.GetNextId(); |
171 EventBindings.Event.call(this, subEventName, opt_argSchemas, opt_eventOptions, | 171 EventBindings.Event.call(this, subEventName, opt_argSchemas, opt_eventOptions, |
172 opt_webViewInstanceId); | 172 opt_webViewInstanceId); |
173 | 173 |
174 var self = this; | |
175 // TODO(lazyboy): When do we dispose this listener? | 174 // TODO(lazyboy): When do we dispose this listener? |
176 WebRequestMessageEvent.addListener(function() { | 175 WebRequestMessageEvent.addListener(function() { |
177 // Re-dispatch to subEvent's listeners. | 176 // Re-dispatch to subEvent's listeners. |
178 $Function.apply(self.dispatch, self, $Array.slice(arguments)); | 177 $Function.apply(this.dispatch, this, $Array.slice(arguments)); |
179 }, {instanceId: opt_webViewInstanceId || 0}); | 178 }.bind(this), {instanceId: opt_webViewInstanceId || 0}); |
180 } | 179 } |
181 | 180 |
182 DeclarativeWebRequestEvent.prototype = { | 181 DeclarativeWebRequestEvent.prototype = { |
183 __proto__: EventBindings.Event.prototype | 182 __proto__: EventBindings.Event.prototype |
184 }; | 183 }; |
185 | 184 |
186 // Constructor. | 185 // Constructor. |
187 function WebViewEvents(webViewInternal, viewInstanceId) { | 186 function WebViewEvents(webViewInternal, viewInstanceId) { |
188 this.webViewInternal = webViewInternal; | 187 this.webViewInternal = webViewInternal; |
189 this.viewInstanceId = viewInstanceId; | 188 this.viewInstanceId = viewInstanceId; |
(...skipping 19 matching lines...) Expand all Loading... |
209 }.bind(this), {instanceId: this.viewInstanceId}); | 208 }.bind(this), {instanceId: this.viewInstanceId}); |
210 }; | 209 }; |
211 | 210 |
212 WebViewEvents.prototype.setupPluginDestroyedEvent = function() { | 211 WebViewEvents.prototype.setupPluginDestroyedEvent = function() { |
213 PluginDestroyedEvent.addListener(function(e) { | 212 PluginDestroyedEvent.addListener(function(e) { |
214 this.webViewInternal.onPluginDestroyed(); | 213 this.webViewInternal.onPluginDestroyed(); |
215 }.bind(this), {instanceId: this.viewInstanceId}); | 214 }.bind(this), {instanceId: this.viewInstanceId}); |
216 }; | 215 }; |
217 | 216 |
218 WebViewEvents.prototype.setupWebRequestEvents = function() { | 217 WebViewEvents.prototype.setupWebRequestEvents = function() { |
219 var self = this; | |
220 var request = {}; | 218 var request = {}; |
221 var createWebRequestEvent = function(webRequestEvent) { | 219 var createWebRequestEvent = function(webRequestEvent) { |
222 return function() { | 220 return function() { |
223 if (!self[webRequestEvent.name]) { | 221 if (!this[webRequestEvent.name]) { |
224 self[webRequestEvent.name] = | 222 this[webRequestEvent.name] = |
225 new WebRequestEvent( | 223 new WebRequestEvent( |
226 'webViewInternal.' + webRequestEvent.name, | 224 'webViewInternal.' + webRequestEvent.name, |
227 webRequestEvent.parameters, | 225 webRequestEvent.parameters, |
228 webRequestEvent.extraParameters, webRequestEvent.options, | 226 webRequestEvent.extraParameters, webRequestEvent.options, |
229 self.viewInstanceId); | 227 this.viewInstanceId); |
230 } | 228 } |
231 return self[webRequestEvent.name]; | 229 return this[webRequestEvent.name]; |
232 }; | 230 }.bind(this); |
233 }; | 231 }.bind(this); |
234 | 232 |
235 var createDeclarativeWebRequestEvent = function(webRequestEvent) { | 233 var createDeclarativeWebRequestEvent = function(webRequestEvent) { |
236 return function() { | 234 return function() { |
237 if (!self[webRequestEvent.name]) { | 235 if (!this[webRequestEvent.name]) { |
238 // The onMessage event gets a special event type because we want | 236 // The onMessage event gets a special event type because we want |
239 // the listener to fire only for messages targeted for this particular | 237 // the listener to fire only for messages targeted for this particular |
240 // <webview>. | 238 // <webview>. |
241 var EventClass = webRequestEvent.name === 'onMessage' ? | 239 var EventClass = webRequestEvent.name === 'onMessage' ? |
242 DeclarativeWebRequestEvent : EventBindings.Event; | 240 DeclarativeWebRequestEvent : EventBindings.Event; |
243 self[webRequestEvent.name] = | 241 this[webRequestEvent.name] = |
244 new EventClass( | 242 new EventClass( |
245 'webViewInternal.' + webRequestEvent.name, | 243 'webViewInternal.' + webRequestEvent.name, |
246 webRequestEvent.parameters, | 244 webRequestEvent.parameters, |
247 webRequestEvent.options, | 245 webRequestEvent.options, |
248 self.viewInstanceId); | 246 this.viewInstanceId); |
249 } | 247 } |
250 return self[webRequestEvent.name]; | 248 return this[webRequestEvent.name]; |
251 }; | 249 }.bind(this); |
252 }; | 250 }.bind(this); |
253 | 251 |
254 for (var i = 0; i < DeclarativeWebRequestSchema.events.length; ++i) { | 252 for (var i = 0; i < DeclarativeWebRequestSchema.events.length; ++i) { |
255 var eventSchema = DeclarativeWebRequestSchema.events[i]; | 253 var eventSchema = DeclarativeWebRequestSchema.events[i]; |
256 var webRequestEvent = createDeclarativeWebRequestEvent(eventSchema); | 254 var webRequestEvent = createDeclarativeWebRequestEvent(eventSchema); |
257 Object.defineProperty( | 255 Object.defineProperty( |
258 request, | 256 request, |
259 eventSchema.name, | 257 eventSchema.name, |
260 { | 258 { |
261 get: webRequestEvent, | 259 get: webRequestEvent, |
262 enumerable: true | 260 enumerable: true |
(...skipping 19 matching lines...) Expand all Loading... |
282 | 280 |
283 WebViewEvents.prototype.getEvents = function() { | 281 WebViewEvents.prototype.getEvents = function() { |
284 var experimentalEvents = this.webViewInternal.maybeGetExperimentalEvents(); | 282 var experimentalEvents = this.webViewInternal.maybeGetExperimentalEvents(); |
285 for (var eventName in experimentalEvents) { | 283 for (var eventName in experimentalEvents) { |
286 WEB_VIEW_EVENTS[eventName] = experimentalEvents[eventName]; | 284 WEB_VIEW_EVENTS[eventName] = experimentalEvents[eventName]; |
287 } | 285 } |
288 return WEB_VIEW_EVENTS; | 286 return WEB_VIEW_EVENTS; |
289 }; | 287 }; |
290 | 288 |
291 WebViewEvents.prototype.setupEvent = function(name, info) { | 289 WebViewEvents.prototype.setupEvent = function(name, info) { |
292 var self = this; | |
293 info.evt.addListener(function(e) { | 290 info.evt.addListener(function(e) { |
294 var details = {bubbles:true}; | 291 var details = {bubbles:true}; |
295 if (info.cancelable) | 292 if (info.cancelable) { |
296 details.cancelable = true; | 293 details.cancelable = true; |
| 294 } |
297 var webViewEvent = new Event(name, details); | 295 var webViewEvent = new Event(name, details); |
298 $Array.forEach(info.fields, function(field) { | 296 $Array.forEach(info.fields, function(field) { |
299 if (e[field] !== undefined) { | 297 if (e[field] !== undefined) { |
300 webViewEvent[field] = e[field]; | 298 webViewEvent[field] = e[field]; |
301 } | 299 } |
302 }); | 300 }.bind(this)); |
303 if (info.customHandler) { | 301 if (info.customHandler) { |
304 info.customHandler(self, e, webViewEvent); | 302 info.customHandler(this, e, webViewEvent); |
305 return; | 303 return; |
306 } | 304 } |
307 self.webViewInternal.dispatchEvent(webViewEvent); | 305 this.webViewInternal.dispatchEvent(webViewEvent); |
308 }, {instanceId: self.viewInstanceId}); | 306 }.bind(this), {instanceId: this.viewInstanceId}); |
309 | 307 |
310 this.webViewInternal.setupEventProperty(name); | 308 this.webViewInternal.setupEventProperty(name); |
311 }; | 309 }; |
312 | 310 |
313 | 311 |
314 // Event handlers. | 312 // Event handlers. |
315 WebViewEvents.prototype.handleContextMenu = function(e, webViewEvent) { | 313 WebViewEvents.prototype.handleContextMenu = function(e, webViewEvent) { |
316 this.webViewInternal.maybeHandleContextMenu(e, webViewEvent); | 314 this.webViewInternal.maybeHandleContextMenu(e, webViewEvent); |
317 }; | 315 }; |
318 | 316 |
319 WebViewEvents.prototype.handleDialogEvent = function(event, webViewEvent) { | 317 WebViewEvents.prototype.handleDialogEvent = function(event, webViewEvent) { |
320 var showWarningMessage = function(dialogType) { | 318 var showWarningMessage = function(dialogType) { |
321 var VOWELS = ['a', 'e', 'i', 'o', 'u']; | 319 var VOWELS = ['a', 'e', 'i', 'o', 'u']; |
322 var WARNING_MSG_DIALOG_BLOCKED = '<webview>: %1 %2 dialog was blocked.'; | 320 var WARNING_MSG_DIALOG_BLOCKED = '<webview>: %1 %2 dialog was blocked.'; |
323 var article = (VOWELS.indexOf(dialogType.charAt(0)) >= 0) ? 'An' : 'A'; | 321 var article = (VOWELS.indexOf(dialogType.charAt(0)) >= 0) ? 'An' : 'A'; |
324 var output = WARNING_MSG_DIALOG_BLOCKED.replace('%1', article); | 322 var output = WARNING_MSG_DIALOG_BLOCKED.replace('%1', article); |
325 output = output.replace('%2', dialogType); | 323 output = output.replace('%2', dialogType); |
326 window.console.warn(output); | 324 window.console.warn(output); |
327 }; | 325 }; |
328 | 326 |
329 var self = this; | |
330 var requestId = event.requestId; | 327 var requestId = event.requestId; |
331 var actionTaken = false; | 328 var actionTaken = false; |
332 | 329 |
333 var validateCall = function() { | 330 var validateCall = function() { |
334 var ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN = '<webview>: ' + | 331 var ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN = '<webview>: ' + |
335 'An action has already been taken for this "dialog" event.'; | 332 'An action has already been taken for this "dialog" event.'; |
336 | 333 |
337 if (actionTaken) { | 334 if (actionTaken) { |
338 throw new Error(ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN); | 335 throw new Error(ERROR_MSG_DIALOG_ACTION_ALREADY_TAKEN); |
339 } | 336 } |
340 actionTaken = true; | 337 actionTaken = true; |
341 }; | 338 }; |
342 | 339 |
343 var getGuestInstanceId = function() { | 340 var getGuestInstanceId = function() { |
344 return self.webViewInternal.getGuestInstanceId(); | 341 return this.webViewInternal.getGuestInstanceId(); |
345 }; | 342 }.bind(this); |
346 | 343 |
347 var dialog = { | 344 var dialog = { |
348 ok: function(user_input) { | 345 ok: function(user_input) { |
349 validateCall(); | 346 validateCall(); |
350 user_input = user_input || ''; | 347 user_input = user_input || ''; |
351 WebView.setPermission(getGuestInstanceId(), requestId, 'allow', | 348 WebView.setPermission(getGuestInstanceId(), requestId, 'allow', |
352 user_input); | 349 user_input); |
353 }, | 350 }, |
354 cancel: function() { | 351 cancel: function() { |
355 validateCall(); | 352 validateCall(); |
356 WebView.setPermission(getGuestInstanceId(), requestId, 'deny'); | 353 WebView.setPermission(getGuestInstanceId(), requestId, 'deny'); |
357 } | 354 } |
358 }; | 355 }; |
359 webViewEvent.dialog = dialog; | 356 webViewEvent.dialog = dialog; |
360 | 357 |
361 var defaultPrevented = !self.webViewInternal.dispatchEvent(webViewEvent); | 358 var defaultPrevented = !this.webViewInternal.dispatchEvent(webViewEvent); |
362 if (actionTaken) { | 359 if (actionTaken) { |
363 return; | 360 return; |
364 } | 361 } |
365 | 362 |
366 if (defaultPrevented) { | 363 if (defaultPrevented) { |
367 // Tell the JavaScript garbage collector to track lifetime of |dialog| and | 364 // Tell the JavaScript garbage collector to track lifetime of |dialog| and |
368 // call back when the dialog object has been collected. | 365 // call back when the dialog object has been collected. |
369 MessagingNatives.BindToGC(dialog, function() { | 366 MessagingNatives.BindToGC(dialog, function() { |
370 // Avoid showing a warning message if the decision has already been made. | 367 // Avoid showing a warning message if the decision has already been made. |
371 if (actionTaken) { | 368 if (actionTaken) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 | 416 |
420 var ERROR_MSG_WEBVIEW_EXPECTED = '<webview> element expected.'; | 417 var ERROR_MSG_WEBVIEW_EXPECTED = '<webview> element expected.'; |
421 | 418 |
422 var showWarningMessage = function() { | 419 var showWarningMessage = function() { |
423 var WARNING_MSG_NEWWINDOW_BLOCKED = '<webview>: A new window was blocked.'; | 420 var WARNING_MSG_NEWWINDOW_BLOCKED = '<webview>: A new window was blocked.'; |
424 window.console.warn(WARNING_MSG_NEWWINDOW_BLOCKED); | 421 window.console.warn(WARNING_MSG_NEWWINDOW_BLOCKED); |
425 }; | 422 }; |
426 | 423 |
427 var requestId = event.requestId; | 424 var requestId = event.requestId; |
428 var actionTaken = false; | 425 var actionTaken = false; |
429 var self = this; | |
430 var getGuestInstanceId = function() { | 426 var getGuestInstanceId = function() { |
431 return self.webViewInternal.getGuestInstanceId(); | 427 return this.webViewInternal.getGuestInstanceId(); |
432 }; | 428 }.bind(this); |
433 | 429 |
434 var validateCall = function () { | 430 var validateCall = function () { |
435 if (actionTaken) { | 431 if (actionTaken) { |
436 throw new Error(ERROR_MSG_NEWWINDOW_ACTION_ALREADY_TAKEN); | 432 throw new Error(ERROR_MSG_NEWWINDOW_ACTION_ALREADY_TAKEN); |
437 } | 433 } |
438 actionTaken = true; | 434 actionTaken = true; |
439 }; | 435 }; |
440 | 436 |
441 var windowObj = { | 437 var windowObj = { |
442 attach: function(webview) { | 438 attach: function(webview) { |
(...skipping 25 matching lines...) Expand all Loading... |
468 getGuestInstanceId(), requestId, attached ? 'allow' : 'deny'); | 464 getGuestInstanceId(), requestId, attached ? 'allow' : 'deny'); |
469 }, 0); | 465 }, 0); |
470 }, | 466 }, |
471 discard: function() { | 467 discard: function() { |
472 validateCall(); | 468 validateCall(); |
473 WebView.setPermission(getGuestInstanceId(), requestId, 'deny'); | 469 WebView.setPermission(getGuestInstanceId(), requestId, 'deny'); |
474 } | 470 } |
475 }; | 471 }; |
476 webViewEvent.window = windowObj; | 472 webViewEvent.window = windowObj; |
477 | 473 |
478 var defaultPrevented = !self.webViewInternal.dispatchEvent(webViewEvent); | 474 var defaultPrevented = !this.webViewInternal.dispatchEvent(webViewEvent); |
479 if (actionTaken) { | 475 if (actionTaken) { |
480 return; | 476 return; |
481 } | 477 } |
482 | 478 |
483 if (defaultPrevented) { | 479 if (defaultPrevented) { |
484 // Make browser plugin track lifetime of |windowObj|. | 480 // Make browser plugin track lifetime of |windowObj|. |
485 MessagingNatives.BindToGC(windowObj, function() { | 481 MessagingNatives.BindToGC(windowObj, function() { |
486 // Avoid showing a warning message if the decision has already been made. | 482 // Avoid showing a warning message if the decision has already been made. |
487 if (actionTaken) { | 483 if (actionTaken) { |
488 return; | 484 return; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 'Permission has already been decided for this "permissionrequest" event.'; | 522 'Permission has already been decided for this "permissionrequest" event.'; |
527 | 523 |
528 var showWarningMessage = function(permission) { | 524 var showWarningMessage = function(permission) { |
529 var WARNING_MSG_PERMISSION_DENIED = '<webview>: ' + | 525 var WARNING_MSG_PERMISSION_DENIED = '<webview>: ' + |
530 'The permission request for "%1" has been denied.'; | 526 'The permission request for "%1" has been denied.'; |
531 window.console.warn( | 527 window.console.warn( |
532 WARNING_MSG_PERMISSION_DENIED.replace('%1', permission)); | 528 WARNING_MSG_PERMISSION_DENIED.replace('%1', permission)); |
533 }; | 529 }; |
534 | 530 |
535 var requestId = event.requestId; | 531 var requestId = event.requestId; |
536 var self = this; | |
537 var getGuestInstanceId = function() { | 532 var getGuestInstanceId = function() { |
538 return self.webViewInternal.getGuestInstanceId(); | 533 return this.webViewInternal.getGuestInstanceId(); |
539 }; | 534 }.bind(this); |
540 | 535 |
541 if (this.getPermissionTypes().indexOf(event.permission) < 0) { | 536 if (this.getPermissionTypes().indexOf(event.permission) < 0) { |
542 // The permission type is not allowed. Trigger the default response. | 537 // The permission type is not allowed. Trigger the default response. |
543 WebView.setPermission( | 538 WebView.setPermission( |
544 getGuestInstanceId(), requestId, 'default', '', function(allowed) { | 539 getGuestInstanceId(), requestId, 'default', '', function(allowed) { |
545 if (allowed) { | 540 if (allowed) { |
546 return; | 541 return; |
547 } | 542 } |
548 showWarningMessage(event.permission); | 543 showWarningMessage(event.permission); |
549 }); | 544 }); |
(...skipping 14 matching lines...) Expand all Loading... |
564 validateCall(); | 559 validateCall(); |
565 WebView.setPermission(getGuestInstanceId(), requestId, 'allow'); | 560 WebView.setPermission(getGuestInstanceId(), requestId, 'allow'); |
566 }, | 561 }, |
567 deny: function() { | 562 deny: function() { |
568 validateCall(); | 563 validateCall(); |
569 WebView.setPermission(getGuestInstanceId(), requestId, 'deny'); | 564 WebView.setPermission(getGuestInstanceId(), requestId, 'deny'); |
570 } | 565 } |
571 }; | 566 }; |
572 webViewEvent.request = request; | 567 webViewEvent.request = request; |
573 | 568 |
574 var defaultPrevented = !self.webViewInternal.dispatchEvent(webViewEvent); | 569 var defaultPrevented = !this.webViewInternal.dispatchEvent(webViewEvent); |
575 if (decisionMade) { | 570 if (decisionMade) { |
576 return; | 571 return; |
577 } | 572 } |
578 | 573 |
579 if (defaultPrevented) { | 574 if (defaultPrevented) { |
580 // Make browser plugin track lifetime of |request|. | 575 // Make browser plugin track lifetime of |request|. |
581 MessagingNatives.BindToGC(request, function() { | 576 MessagingNatives.BindToGC(request, function() { |
582 // Avoid showing a warning message if the decision has already been made. | 577 // Avoid showing a warning message if the decision has already been made. |
583 if (decisionMade) { | 578 if (decisionMade) { |
584 return; | 579 return; |
(...skipping 19 matching lines...) Expand all Loading... |
604 } | 599 } |
605 }; | 600 }; |
606 | 601 |
607 WebViewEvents.prototype.handleSizeChangedEvent = function( | 602 WebViewEvents.prototype.handleSizeChangedEvent = function( |
608 event, webViewEvent) { | 603 event, webViewEvent) { |
609 this.webViewInternal.onSizeChanged(webViewEvent); | 604 this.webViewInternal.onSizeChanged(webViewEvent); |
610 }; | 605 }; |
611 | 606 |
612 exports.WebViewEvents = WebViewEvents; | 607 exports.WebViewEvents = WebViewEvents; |
613 exports.CreateEvent = CreateEvent; | 608 exports.CreateEvent = CreateEvent; |
OLD | NEW |