OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // Shim that simulates a <webview> tag via Mutation Observers. | 5 // Shim that simulates a <webview> tag via Mutation Observers. |
6 // | 6 // |
7 // The actual tag is implemented via the browser plugin. The internals of this | 7 // The actual tag is implemented via the browser plugin. The internals of this |
8 // are hidden via Shadow DOM. | 8 // are hidden via Shadow DOM. |
9 | 9 |
10 var addTagWatcher = require('tagWatcher').addTagWatcher; | 10 var addTagWatcher = require('tagWatcher').addTagWatcher; |
(...skipping 18 matching lines...) Expand all Loading... | |
29 fields: [] | 29 fields: [] |
30 }, | 30 }, |
31 'consolemessage': { | 31 'consolemessage': { |
32 evt: createEvent('webview.onConsoleMessage'), | 32 evt: createEvent('webview.onConsoleMessage'), |
33 fields: ['level', 'message', 'line', 'sourceId'] | 33 fields: ['level', 'message', 'line', 'sourceId'] |
34 }, | 34 }, |
35 'contentload': { | 35 'contentload': { |
36 evt: createEvent('webview.onContentLoad'), | 36 evt: createEvent('webview.onContentLoad'), |
37 fields: [] | 37 fields: [] |
38 }, | 38 }, |
39 'dialog': { | |
lazyboy
2013/08/05 09:26:58
mixing this up with stable here seems a bit unclea
Fady Samuel
2013/08/06 07:14:40
Done.
| |
40 cancelable: true, | |
41 customHandler: function(webview, event, webviewEvent) { | |
42 webview.maybeSetupExtDialogEvent_(event, webviewEvent); | |
43 }, | |
44 evt: createEvent('webview.onDialog'), | |
45 fields: ['defaultPromptText', 'messageText', 'messageType', 'url'] | |
46 }, | |
39 'exit': { | 47 'exit': { |
40 evt: createEvent('webview.onExit'), | 48 evt: createEvent('webview.onExit'), |
41 fields: ['processId', 'reason'] | 49 fields: ['processId', 'reason'] |
42 }, | 50 }, |
43 'loadabort': { | 51 'loadabort': { |
44 evt: createEvent('webview.onLoadAbort'), | 52 evt: createEvent('webview.onLoadAbort'), |
45 fields: ['url', 'isTopLevel', 'reason'] | 53 fields: ['url', 'isTopLevel', 'reason'] |
46 }, | 54 }, |
47 'loadcommit': { | 55 'loadcommit': { |
48 customHandler: function(webview, event) { | 56 customHandler: function(webview, event, webviewEvent) { |
49 webview.currentEntryIndex_ = event.currentEntryIndex; | 57 webview.currentEntryIndex_ = event.currentEntryIndex; |
50 webview.entryCount_ = event.entryCount; | 58 webview.entryCount_ = event.entryCount; |
51 webview.processId_ = event.processId; | 59 webview.processId_ = event.processId; |
52 if (event.isTopLevel) { | 60 if (event.isTopLevel) { |
53 webview.browserPluginNode_.setAttribute('src', event.url); | 61 webview.browserPluginNode_.setAttribute('src', event.url); |
54 } | 62 } |
63 webview.webviewNode_.dispatchEvent(webviewEvent); | |
55 }, | 64 }, |
56 evt: createEvent('webview.onLoadCommit'), | 65 evt: createEvent('webview.onLoadCommit'), |
57 fields: ['url', 'isTopLevel'] | 66 fields: ['url', 'isTopLevel'] |
58 }, | 67 }, |
59 'loadredirect': { | 68 'loadredirect': { |
60 evt: createEvent('webview.onLoadRedirect'), | 69 evt: createEvent('webview.onLoadRedirect'), |
61 fields: ['isTopLevel', 'oldUrl', 'newUrl'] | 70 fields: ['isTopLevel', 'oldUrl', 'newUrl'] |
62 }, | 71 }, |
63 'loadstart': { | 72 'loadstart': { |
64 evt: createEvent('webview.onLoadStart'), | 73 evt: createEvent('webview.onLoadStart'), |
65 fields: ['url', 'isTopLevel'] | 74 fields: ['url', 'isTopLevel'] |
66 }, | 75 }, |
67 'loadstop': { | 76 'loadstop': { |
68 evt: createEvent('webview.onLoadStop'), | 77 evt: createEvent('webview.onLoadStop'), |
69 fields: [] | 78 fields: [] |
70 }, | 79 }, |
80 'newwindow': { | |
81 cancelable: true, | |
82 customHandler: function(webview, event, webviewEvent) { | |
83 webview.setupExtNewWindowEvent_(event, webviewEvent); | |
84 }, | |
85 evt: createEvent('webview.onNewWindow'), | |
86 fields: ['initialHeight', 'initialWidth', 'targetUrl', | |
lazyboy
2013/08/05 09:26:58
nit: here and below, since these don't fit in one
Fady Samuel
2013/08/06 07:14:40
Done.
| |
87 'windowOpenDisposition', 'name'] | |
88 }, | |
89 'permissionrequest': { | |
90 cancelable: true, | |
91 customHandler: function(webview, event, webviewEvent) { | |
92 webview.setupExtPermissionEvent_(event, webviewEvent); | |
93 }, | |
94 evt: createEvent('webview.onPermissionRequest'), | |
95 fields: ['lastUnlockedBySelf', 'permission', 'requestMethod', 'url', | |
96 'userGesture'] | |
97 }, | |
71 'responsive': { | 98 'responsive': { |
72 evt: createEvent('webview.onResponsive'), | 99 evt: createEvent('webview.onResponsive'), |
73 fields: ['processId'] | 100 fields: ['processId'] |
74 }, | 101 }, |
75 'unresponsive': { | 102 'unresponsive': { |
76 evt: createEvent('webview.onUnresponsive'), | 103 evt: createEvent('webview.onUnresponsive'), |
77 fields: ['processId'] | 104 fields: ['processId'] |
78 } | 105 } |
79 }; | 106 }; |
80 | 107 |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
354 for (var eventName in WEB_VIEW_EXT_EVENTS) { | 381 for (var eventName in WEB_VIEW_EXT_EVENTS) { |
355 self.setupExtEvent_(eventName, WEB_VIEW_EXT_EVENTS[eventName]); | 382 self.setupExtEvent_(eventName, WEB_VIEW_EXT_EVENTS[eventName]); |
356 } | 383 } |
357 }; | 384 }; |
358 this.browserPluginNode_.addEventListener('-internal-instanceid-allocated', | 385 this.browserPluginNode_.addEventListener('-internal-instanceid-allocated', |
359 onInstanceIdAllocated); | 386 onInstanceIdAllocated); |
360 | 387 |
361 for (var eventName in WEB_VIEW_EVENTS) { | 388 for (var eventName in WEB_VIEW_EVENTS) { |
362 this.setupEvent_(eventName, WEB_VIEW_EVENTS[eventName]); | 389 this.setupEvent_(eventName, WEB_VIEW_EVENTS[eventName]); |
363 } | 390 } |
364 this.setupNewWindowEvent_(); | |
365 this.setupPermissionEvent_(); | |
366 }; | 391 }; |
367 | 392 |
368 /** | 393 /** |
369 * @private | 394 * @private |
370 */ | 395 */ |
371 WebView.prototype.setupExtEvent_ = function(eventName, eventInfo) { | 396 WebView.prototype.setupExtEvent_ = function(eventName, eventInfo) { |
372 var self = this; | 397 var self = this; |
373 var webviewNode = this.webviewNode_; | 398 var webviewNode = this.webviewNode_; |
374 eventInfo.evt.addListener(function(event) { | 399 eventInfo.evt.addListener(function(event) { |
375 var webviewEvent = new Event(eventName, {bubbles: true}); | 400 var details = {bubbles:true}; |
401 if (eventInfo.cancelable) | |
402 details.cancelable = true; | |
403 var webviewEvent = new Event(eventName, details); | |
376 $Array.forEach(eventInfo.fields, function(field) { | 404 $Array.forEach(eventInfo.fields, function(field) { |
377 webviewEvent[field] = event[field]; | 405 if (event[field] != undefined) { |
lazyboy
2013/08/05 09:26:58
use !== undefined
Fady Samuel
2013/08/06 07:14:40
Done.
| |
406 webviewEvent[field] = event[field]; | |
407 } | |
378 }); | 408 }); |
379 if (eventInfo.customHandler) { | 409 if (eventInfo.customHandler) { |
380 eventInfo.customHandler(self, event); | 410 eventInfo.customHandler(self, event, webviewEvent); |
411 return; | |
381 } | 412 } |
382 webviewNode.dispatchEvent(webviewEvent); | 413 webviewNode.dispatchEvent(webviewEvent); |
383 }, {instanceId: self.instanceId_}); | 414 }, {instanceId: self.instanceId_}); |
384 }; | 415 }; |
385 | 416 |
386 /** | 417 /** |
387 * @private | 418 * @private |
388 */ | 419 */ |
389 WebView.prototype.setupEvent_ = function(eventName, attribs) { | 420 WebView.prototype.setupEvent_ = function(eventName, attribs) { |
390 var webviewNode = this.webviewNode_; | 421 var webviewNode = this.webviewNode_; |
391 var internalname = '-internal-' + eventName; | 422 var internalname = '-internal-' + eventName; |
392 this.browserPluginNode_.addEventListener(internalname, function(e) { | 423 this.browserPluginNode_.addEventListener(internalname, function(e) { |
393 var evt = new Event(eventName, { bubbles: true }); | 424 var evt = new Event(eventName, { bubbles: true }); |
394 var detail = e.detail ? JSON.parse(e.detail) : {}; | 425 var detail = e.detail ? JSON.parse(e.detail) : {}; |
395 $Array.forEach(attribs, function(attribName) { | 426 $Array.forEach(attribs, function(attribName) { |
396 evt[attribName] = detail[attribName]; | 427 evt[attribName] = detail[attribName]; |
397 }); | 428 }); |
398 webviewNode.dispatchEvent(evt); | 429 webviewNode.dispatchEvent(evt); |
399 }); | 430 }); |
400 }; | 431 }; |
401 | 432 |
402 /** | 433 /** |
403 * @private | 434 * @private |
404 */ | 435 */ |
405 WebView.prototype.setupNewWindowEvent_ = function() { | 436 WebView.prototype.setupExtNewWindowEvent_ = function(event, webviewEvent) { |
406 var ERROR_MSG_NEWWINDOW_ACTION_ALREADY_TAKEN = '<webview>: ' + | 437 var ERROR_MSG_NEWWINDOW_ACTION_ALREADY_TAKEN = '<webview>: ' + |
407 'An action has already been taken for this "newwindow" event.'; | 438 'An action has already been taken for this "newwindow" event.'; |
408 | 439 |
409 var ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH = '<webview>: ' + | 440 var ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH = '<webview>: ' + |
410 'Unable to attach the new window to the provided webview.'; | 441 'Unable to attach the new window to the provided webview.'; |
411 | 442 |
412 var ERROR_MSG_WEBVIEW_EXPECTED = '<webview> element expected.'; | 443 var ERROR_MSG_WEBVIEW_EXPECTED = '<webview> element expected.'; |
413 | 444 |
414 var showWarningMessage = function() { | 445 var showWarningMessage = function() { |
415 var WARNING_MSG_NEWWINDOW_BLOCKED = '<webview>: A new window was blocked.'; | 446 var WARNING_MSG_NEWWINDOW_BLOCKED = '<webview>: A new window was blocked.'; |
416 console.warn(WARNING_MSG_NEWWINDOW_BLOCKED); | 447 console.warn(WARNING_MSG_NEWWINDOW_BLOCKED); |
417 }; | 448 }; |
418 | 449 |
419 var NEW_WINDOW_EVENT_ATTRIBUTES = [ | 450 var self = this; |
420 'initialHeight', | 451 var browserPluginNode = this.browserPluginNode_; |
421 'initialWidth', | 452 var webviewNode = this.webviewNode_; |
422 'targetUrl', | |
423 'windowOpenDisposition', | |
424 'name' | |
425 ]; | |
426 | 453 |
427 var self = this; | 454 var requestId = event.requestId; |
428 var node = this.webviewNode_; | 455 var actionTaken = false; |
429 var browserPluginNode = this.browserPluginNode_; | |
430 | 456 |
431 var onTrackedObjectGone = function(requestId, e) { | 457 var onTrackedObjectGone = function(requestId, e) { |
432 var detail = e.detail ? JSON.parse(e.detail) : {}; | 458 var detail = e.detail ? JSON.parse(e.detail) : {}; |
433 if (detail.id != requestId) { | 459 if (detail.id != requestId) { |
434 return; | 460 return; |
435 } | 461 } |
436 // If the request was pending then show a warning indiciating that a dialog | |
437 // was blocked. | |
438 if (browserPluginNode['-internal-setPermission'](requestId, false, '')) { | |
439 showWarningMessage(); | |
440 } | |
441 }; | |
442 | 462 |
443 browserPluginNode.addEventListener('-internal-newwindow', function(e) { | 463 // Avoid showing a warning message if the decision has already been made. |
444 var evt = new Event('newwindow', { bubbles: true, cancelable: true }); | |
445 var detail = e.detail ? JSON.parse(e.detail) : {}; | |
446 | |
447 $Array.forEach(NEW_WINDOW_EVENT_ATTRIBUTES, function(attribName) { | |
448 evt[attribName] = detail[attribName]; | |
449 }); | |
450 var requestId = detail.requestId; | |
451 var actionTaken = false; | |
452 | |
453 var validateCall = function () { | |
454 if (actionTaken) { | |
455 throw new Error(ERROR_MSG_NEWWINDOW_ACTION_ALREADY_TAKEN); | |
456 } | |
457 actionTaken = true; | |
458 }; | |
459 | |
460 var window = { | |
461 attach: function(webview) { | |
462 validateCall(); | |
463 if (!webview) | |
464 throw new Error(ERROR_MSG_WEBVIEW_EXPECTED); | |
465 // Attach happens asynchronously to give the tagWatcher an opportunity | |
466 // to pick up the new webview before attach operates on it, if it hasn't | |
467 // been attached to the DOM already. | |
468 // Note: Any subsequent errors cannot be exceptions because they happen | |
469 // asynchronously. | |
470 setTimeout(function() { | |
471 var attached = | |
472 browserPluginNode['-internal-attachWindowTo'](webview, | |
473 detail.windowId); | |
474 if (!attached) { | |
475 console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH); | |
476 } | |
477 // If the object being passed into attach is not a valid <webview> | |
478 // then we will fail and it will be treated as if the new window | |
479 // was rejected. The permission API plumbing is used here to clean | |
480 // up the state created for the new window if attaching fails. | |
481 browserPluginNode['-internal-setPermission'](requestId, attached, ''); | |
482 }, 0); | |
483 }, | |
484 discard: function() { | |
485 validateCall(); | |
486 browserPluginNode['-internal-setPermission'](requestId, false, ''); | |
487 } | |
488 }; | |
489 evt.window = window; | |
490 | |
491 var defaultPrevented = !node.dispatchEvent(evt); | |
492 if (actionTaken) { | 464 if (actionTaken) { |
493 return; | 465 return; |
494 } | 466 } |
495 | 467 |
496 if (defaultPrevented) { | 468 chrome.webview.setPermission(self.instanceId_, requestId, false, ''); |
497 // Make browser plugin track lifetime of |window|. | 469 showWarningMessage(); |
498 var onTrackedObjectGoneWithRequestId = | 470 }; |
499 $Function.bind(onTrackedObjectGone, self, requestId); | 471 |
500 browserPluginNode.addEventListener('-internal-trackedobjectgone', | 472 |
501 onTrackedObjectGoneWithRequestId); | 473 var validateCall = function () { |
502 browserPluginNode['-internal-trackObjectLifetime'](window, requestId); | 474 if (actionTaken) { |
503 } else { | 475 throw new Error(ERROR_MSG_NEWWINDOW_ACTION_ALREADY_TAKEN); |
504 actionTaken = true; | |
505 // The default action is to discard the window. | |
506 browserPluginNode['-internal-setPermission'](requestId, false, ''); | |
507 showWarningMessage(); | |
508 } | 476 } |
477 actionTaken = true; | |
478 }; | |
509 | 479 |
510 }); | 480 var window = { |
481 attach: function(webview) { | |
482 validateCall(); | |
483 if (!webview) | |
484 throw new Error(ERROR_MSG_WEBVIEW_EXPECTED); | |
485 // Attach happens asynchronously to give the tagWatcher an opportunity | |
486 // to pick up the new webview before attach operates on it, if it hasn't | |
487 // been attached to the DOM already. | |
488 // Note: Any subsequent errors cannot be exceptions because they happen | |
489 // asynchronously. | |
490 setTimeout(function() { | |
491 var attached = | |
492 browserPluginNode['-internal-attachWindowTo'](webview, | |
493 event.windowId); | |
494 if (!attached) { | |
495 console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH); | |
496 } | |
497 // If the object being passed into attach is not a valid <webview> | |
498 // then we will fail and it will be treated as if the new window | |
499 // was rejected. The permission API plumbing is used here to clean | |
500 // up the state created for the new window if attaching fails. | |
501 chrome.webview.setPermission(self.instanceId_, requestId, attached, ''); | |
502 }, 0); | |
503 }, | |
504 discard: function() { | |
505 validateCall(); | |
506 chrome.webview.setPermission(self.instanceId_, requestId, false, ''); | |
507 } | |
508 }; | |
509 webviewEvent.window = window; | |
510 | |
511 var defaultPrevented = !webviewNode.dispatchEvent(webviewEvent); | |
512 if (actionTaken) { | |
513 return; | |
514 } | |
515 | |
516 if (defaultPrevented) { | |
517 // Make browser plugin track lifetime of |window|. | |
518 var onTrackedObjectGoneWithRequestId = | |
519 $Function.bind(onTrackedObjectGone, self, requestId); | |
520 browserPluginNode.addEventListener('-internal-trackedobjectgone', | |
521 onTrackedObjectGoneWithRequestId); | |
522 browserPluginNode['-internal-trackObjectLifetime'](window, requestId); | |
523 } else { | |
524 actionTaken = true; | |
525 // The default action is to discard the window. | |
526 chrome.webview.setPermission(self.instanceId_, requestId, false, ''); | |
527 showWarningMessage(); | |
528 } | |
511 }; | 529 }; |
512 | 530 |
513 /** | 531 /** |
514 * @private | 532 * @private |
515 */ | 533 */ |
516 WebView.prototype.setupExecuteCodeAPI_ = function() { | 534 WebView.prototype.setupExecuteCodeAPI_ = function() { |
517 var ERROR_MSG_CANNOT_INJECT_SCRIPT = '<webview>: ' + | 535 var ERROR_MSG_CANNOT_INJECT_SCRIPT = '<webview>: ' + |
518 'Script cannot be injected into content until the page has loaded.'; | 536 'Script cannot be injected into content until the page has loaded.'; |
519 | 537 |
520 var self = this; | 538 var self = this; |
(...skipping 11 matching lines...) Expand all Loading... | |
532 } | 550 } |
533 this.webviewNode_['insertCSS'] = function(var_args) { | 551 this.webviewNode_['insertCSS'] = function(var_args) { |
534 validateCall(); | 552 validateCall(); |
535 var args = $Array.concat([self.browserPluginNode_.getGuestInstanceId()], | 553 var args = $Array.concat([self.browserPluginNode_.getGuestInstanceId()], |
536 $Array.slice(arguments)); | 554 $Array.slice(arguments)); |
537 $Function.apply(chrome.webview.insertCSS, null, args); | 555 $Function.apply(chrome.webview.insertCSS, null, args); |
538 } | 556 } |
539 }; | 557 }; |
540 | 558 |
541 /** | 559 /** |
542 * @param {!Object} detail The event details, originated from <object>. | |
543 * @private | 560 * @private |
544 */ | 561 */ |
545 WebView.prototype.setupPermissionEvent_ = function() { | 562 WebView.prototype.getPermissionTypes_ = function() { |
563 return ['media', 'geolocation', 'pointerLock', 'download']; | |
564 }; | |
565 | |
566 WebView.prototype.setupExtPermissionEvent_ = function(event, webviewEvent) { | |
546 var ERROR_MSG_PERMISSION_ALREADY_DECIDED = '<webview>: ' + | 567 var ERROR_MSG_PERMISSION_ALREADY_DECIDED = '<webview>: ' + |
547 'Permission has already been decided for this "permissionrequest" event.'; | 568 'Permission has already been decided for this "permissionrequest" event.'; |
548 | 569 |
549 var showWarningMessage = function(permission) { | 570 var showWarningMessage = function(permission) { |
550 var WARNING_MSG_PERMISSION_DENIED = '<webview>: ' + | 571 var WARNING_MSG_PERMISSION_DENIED = '<webview>: ' + |
551 'The permission request for "%1" has been denied.'; | 572 'The permission request for "%1" has been denied.'; |
552 console.warn(WARNING_MSG_PERMISSION_DENIED.replace('%1', permission)); | 573 console.warn(WARNING_MSG_PERMISSION_DENIED.replace('%1', permission)); |
553 }; | 574 }; |
554 | 575 |
555 var PERMISSION_TYPES = ['media', 'geolocation', 'pointerLock', 'download']; | 576 var PERMISSION_TYPES = this.getPermissionTypes_(); |
556 | |
557 var EXPOSED_PERMISSION_EVENT_ATTRIBS = [ | |
558 'lastUnlockedBySelf', | |
559 'permission', | |
560 'requestMethod', | |
561 'url', | |
562 'userGesture' | |
563 ]; | |
564 | 577 |
565 var self = this; | 578 var self = this; |
566 var node = this.webviewNode_; | |
567 var browserPluginNode = this.browserPluginNode_; | 579 var browserPluginNode = this.browserPluginNode_; |
568 var internalevent = '-internal-permissionrequest'; | 580 var webviewNode = this.webviewNode_; |
581 | |
582 var requestId = event.requestId; | |
583 var decisionMade = false; | |
569 | 584 |
570 var onTrackedObjectGone = function(requestId, permission, e) { | 585 var onTrackedObjectGone = function(requestId, permission, e) { |
571 var detail = e.detail ? JSON.parse(e.detail) : {}; | 586 var detail = e.detail ? JSON.parse(e.detail) : {}; |
572 if (detail.id != requestId) | 587 if (detail.id != requestId) { |
573 return; | |
574 // If the request was pending then show a warning indiciating that the | |
575 // permission was denied. | |
576 if (browserPluginNode['-internal-setPermission'](requestId, false, '')) { | |
577 showWarningMessage(permission); | |
578 } | |
579 }; | |
580 | |
581 browserPluginNode.addEventListener(internalevent, function(e) { | |
582 var evt = new Event('permissionrequest', {bubbles: true, cancelable: true}); | |
583 var detail = e.detail ? JSON.parse(e.detail) : {}; | |
584 $Array.forEach(EXPOSED_PERMISSION_EVENT_ATTRIBS, function(attribName) { | |
585 if (detail[attribName] !== undefined) | |
586 evt[attribName] = detail[attribName]; | |
587 }); | |
588 var requestId = detail.requestId; | |
589 | |
590 if (detail.requestId == undefined || | |
591 PERMISSION_TYPES.indexOf(detail.permission) < 0) { | |
592 return; | 588 return; |
593 } | 589 } |
594 | 590 |
595 // TODO(lazyboy): Also fill in evt.details (see webview specs). | 591 // Avoid showing a warning message if the decision has already been made. |
596 // http://crbug.com/141197. | |
597 var decisionMade = false; | |
598 | |
599 var validateCall = function() { | |
600 if (decisionMade) { | |
601 throw new Error(ERROR_MSG_PERMISSION_ALREADY_DECIDED); | |
602 } | |
603 decisionMade = true; | |
604 }; | |
605 | |
606 // Construct the event.request object. | |
607 var request = { | |
608 allow: function() { | |
609 validateCall(); | |
610 browserPluginNode['-internal-setPermission'](requestId, true, ''); | |
611 }, | |
612 deny: function() { | |
613 validateCall(); | |
614 browserPluginNode['-internal-setPermission'](requestId, false, ''); | |
615 } | |
616 }; | |
617 evt.request = request; | |
618 | |
619 var defaultPrevented = !node.dispatchEvent(evt); | |
620 if (decisionMade) { | 592 if (decisionMade) { |
621 return; | 593 return; |
622 } | 594 } |
623 | 595 |
624 if (defaultPrevented) { | 596 chrome.webview.setPermission(self.instanceId_, requestId, false, ''); |
625 // Make browser plugin track lifetime of |request|. | 597 showWarningMessage(permission); |
626 var onTrackedObjectGoneWithRequestId = | 598 }; |
627 $Function.bind( | 599 |
628 onTrackedObjectGone, self, requestId, detail.permission); | 600 var validateCall = function() { |
629 browserPluginNode.addEventListener('-internal-trackedobjectgone', | 601 if (decisionMade) { |
630 onTrackedObjectGoneWithRequestId); | 602 throw new Error(ERROR_MSG_PERMISSION_ALREADY_DECIDED); |
631 browserPluginNode['-internal-trackObjectLifetime'](request, requestId); | |
632 } else { | |
633 decisionMade = true; | |
634 browserPluginNode['-internal-setPermission'](requestId, false, ''); | |
635 showWarningMessage(detail.permission); | |
636 } | 603 } |
637 }); | 604 decisionMade = true; |
605 }; | |
606 | |
607 // Construct the event.request object. | |
608 var request = { | |
609 allow: function() { | |
610 validateCall(); | |
611 chrome.webview.setPermission(self.instanceId_, requestId, true, ''); | |
612 }, | |
613 deny: function() { | |
614 validateCall(); | |
615 chrome.webview.setPermission(self.instanceId_, requestId, false, ''); | |
616 } | |
617 }; | |
618 webviewEvent.request = request; | |
619 | |
620 var defaultPrevented = !webviewNode.dispatchEvent(webviewEvent); | |
621 if (decisionMade) { | |
622 return; | |
623 } | |
624 | |
625 if (defaultPrevented) { | |
626 // Make browser plugin track lifetime of |request|. | |
627 var onTrackedObjectGoneWithRequestId = | |
628 $Function.bind( | |
629 onTrackedObjectGone, self, requestId, event.permission); | |
630 browserPluginNode.addEventListener('-internal-trackedobjectgone', | |
631 onTrackedObjectGoneWithRequestId); | |
632 browserPluginNode['-internal-trackObjectLifetime'](request, requestId); | |
633 } else { | |
634 decisionMade = true; | |
635 chrome.webview.setPermission(self.instanceId_, requestId, false, ''); | |
636 showWarningMessage(event.permission); | |
637 } | |
638 }; | 638 }; |
639 | 639 |
640 /** | 640 /** |
641 * Implemented when the experimental API is available. | 641 * Implemented when the experimental API is available. |
642 * @private | 642 * @private |
643 */ | 643 */ |
644 WebView.prototype.maybeSetupExperimentalAPI_ = function() {}; | 644 WebView.prototype.maybeSetupExperimentalAPI_ = function() {}; |
645 | 645 |
646 /** | |
647 * Implemented when the experimental API is available. | |
648 * @private | |
649 */ | |
650 WebView.prototype.maybeSetupExtDialogEvent_ = function() {}; | |
651 | |
646 exports.WebView = WebView; | 652 exports.WebView = WebView; |
OLD | NEW |