| 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 |