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 // This module implements Webview (<webview>) as a custom element that wraps a | 5 // This module implements Webview (<webview>) as a custom element that wraps a |
6 // BrowserPlugin object element. The object element is hidden within | 6 // BrowserPlugin object element. The object element is hidden within |
7 // the shadow DOM of the Webview element. | 7 // the shadow DOM of the Webview element. |
8 | 8 |
9 var DocumentNatives = requireNative('document_natives'); | 9 var DocumentNatives = requireNative('document_natives'); |
10 var EventBindings = require('event_bindings'); | 10 var EventBindings = require('event_bindings'); |
11 var IdGenerator = requireNative('id_generator'); | 11 var IdGenerator = requireNative('id_generator'); |
12 var MessagingNatives = requireNative('messaging_natives'); | 12 var MessagingNatives = requireNative('messaging_natives'); |
13 var WebRequestEvent = require('webRequestInternal').WebRequestEvent; | 13 var WebRequestEvent = require('webRequestInternal').WebRequestEvent; |
14 var WebRequestSchema = | 14 var WebRequestSchema = |
15 requireNative('schema_registry').GetSchema('webRequest'); | 15 requireNative('schema_registry').GetSchema('webRequest'); |
16 var DeclarativeWebRequestSchema = | 16 var DeclarativeWebRequestSchema = |
17 requireNative('schema_registry').GetSchema('declarativeWebRequest'); | 17 requireNative('schema_registry').GetSchema('declarativeWebRequest'); |
18 var WebView = require('webview').WebView; | 18 var WebView = require('webview').WebView; |
19 | 19 |
20 var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight'; | 20 var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight'; |
21 var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth'; | 21 var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth'; |
22 var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight'; | 22 var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight'; |
23 var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth'; | 23 var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth'; |
24 | 24 |
25 /** @type {Array.<string>} */ | 25 /** @type {Array.<string>} */ |
26 var WEB_VIEW_ATTRIBUTES = [ | 26 var WEB_VIEW_ATTRIBUTES = [ |
27 'allowtransparency', | 27 'allowtransparency', |
28 'autosize', | 28 'autosize', |
29 'name', | |
30 'partition', | 29 'partition', |
31 WEB_VIEW_ATTRIBUTE_MINHEIGHT, | 30 WEB_VIEW_ATTRIBUTE_MINHEIGHT, |
32 WEB_VIEW_ATTRIBUTE_MINWIDTH, | 31 WEB_VIEW_ATTRIBUTE_MINWIDTH, |
33 WEB_VIEW_ATTRIBUTE_MAXHEIGHT, | 32 WEB_VIEW_ATTRIBUTE_MAXHEIGHT, |
34 WEB_VIEW_ATTRIBUTE_MAXWIDTH | 33 WEB_VIEW_ATTRIBUTE_MAXWIDTH |
35 ]; | 34 ]; |
36 | 35 |
37 var CreateEvent = function(name) { | 36 var CreateEvent = function(name) { |
38 var eventOpts = {supportsListeners: true, supportsFilters: true}; | 37 var eventOpts = {supportsListeners: true, supportsFilters: true}; |
39 return new EventBindings.Event(name, undefined, eventOpts); | 38 return new EventBindings.Event(name, undefined, eventOpts); |
40 }; | 39 }; |
41 | 40 |
42 // WEB_VIEW_EVENTS is a map of stable <webview> DOM event names to their | 41 // WEB_VIEW_EVENTS is a map of stable <webview> DOM event names to their |
43 // associated extension event descriptor objects. | 42 // associated extension event descriptor objects. |
44 // An event listener will be attached to the extension event |evt| specified in | 43 // An event listener will be attached to the extension event |evt| specified in |
45 // the descriptor. | 44 // the descriptor. |
46 // |fields| specifies the public-facing fields in the DOM event that are | 45 // |fields| specifies the public-facing fields in the DOM event that are |
47 // accessible to <webview> developers. | 46 // accessible to <webview> developers. |
48 // |customHandler| allows a handler function to be called each time an extension | 47 // |customHandler| allows a handler function to be called each time an extension |
49 // event is caught by its event listener. The DOM event should be dispatched | 48 // event is caught by its event listener. The DOM event should be dispatched |
50 // within this handler function. With no handler function, the DOM event | 49 // within this handler function. With no handler function, the DOM event |
51 // will be dispatched by default each time the extension event is caught. | 50 // will be dispatched by default each time the extension event is caught. |
52 // |cancelable| (default: false) specifies whether the event's default | 51 // |cancelable| (default: false) specifies whether the event's default |
53 // behavior can be canceled. If the default action associated with the event | 52 // behavior can be canceled. If the default action associated with the event |
54 // is prevented, then its dispatch function will return false in its event | 53 // is prevented, then its dispatch function will return false in its event |
55 // handler. The event must have a custom handler for this to be meaningful. | 54 // handler. The event must have a custom handler for this to be meaningful. |
55 | |
56 var FrameNameChangedEvent = CreateEvent('webview.onFrameNameChanged'); | |
57 | |
56 var WEB_VIEW_EVENTS = { | 58 var WEB_VIEW_EVENTS = { |
57 'close': { | 59 'close': { |
58 evt: CreateEvent('webview.onClose'), | 60 evt: CreateEvent('webview.onClose'), |
59 fields: [] | 61 fields: [] |
60 }, | 62 }, |
61 'consolemessage': { | 63 'consolemessage': { |
62 evt: CreateEvent('webview.onConsoleMessage'), | 64 evt: CreateEvent('webview.onConsoleMessage'), |
63 fields: ['level', 'message', 'line', 'sourceId'] | 65 fields: ['level', 'message', 'line', 'sourceId'] |
64 }, | 66 }, |
65 'contentload': { | 67 'contentload': { |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
380 get: function() { | 382 get: function() { |
381 return self.src; | 383 return self.src; |
382 }, | 384 }, |
383 set: function(value) { | 385 set: function(value) { |
384 self.webviewNode.setAttribute('src', value); | 386 self.webviewNode.setAttribute('src', value); |
385 }, | 387 }, |
386 // No setter. | 388 // No setter. |
387 enumerable: true | 389 enumerable: true |
388 }); | 390 }); |
389 | 391 |
392 Object.defineProperty(this.webviewNode, 'name', { | |
393 get: function() { | |
394 return self.name; | |
395 }, | |
396 set: function(value) { | |
397 self.webviewNode.setAttribute('name', value); | |
398 }, | |
399 enumerable: true | |
400 }); | |
401 | |
390 // We cannot use {writable: true} property descriptor because we want a | 402 // We cannot use {writable: true} property descriptor because we want a |
391 // dynamic getter value. | 403 // dynamic getter value. |
392 Object.defineProperty(this.webviewNode, 'contentWindow', { | 404 Object.defineProperty(this.webviewNode, 'contentWindow', { |
393 get: function() { | 405 get: function() { |
394 if (browserPluginNode.contentWindow) | 406 if (browserPluginNode.contentWindow) |
395 return browserPluginNode.contentWindow; | 407 return browserPluginNode.contentWindow; |
396 window.console.error(ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE); | 408 window.console.error(ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE); |
397 }, | 409 }, |
398 // No setter. | 410 // No setter. |
399 enumerable: true | 411 enumerable: true |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
439 /** | 451 /** |
440 * @private | 452 * @private |
441 */ | 453 */ |
442 WebViewInternal.prototype.handleWebviewAttributeMutation = | 454 WebViewInternal.prototype.handleWebviewAttributeMutation = |
443 function(name, oldValue, newValue) { | 455 function(name, oldValue, newValue) { |
444 // This observer monitors mutations to attributes of the <webview> and | 456 // This observer monitors mutations to attributes of the <webview> and |
445 // updates the BrowserPlugin properties accordingly. In turn, updating | 457 // updates the BrowserPlugin properties accordingly. In turn, updating |
446 // a BrowserPlugin property will update the corresponding BrowserPlugin | 458 // a BrowserPlugin property will update the corresponding BrowserPlugin |
447 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more | 459 // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more |
448 // details. | 460 // details. |
449 if (name == 'src') { | 461 if (name == 'name') { |
450 // We treat null attribute (attribute removed) and the empty string as | 462 // We treat null attribute (attribute removed) and the empty string as |
451 // one case. | 463 // one case. |
452 oldValue = oldValue || ''; | 464 oldValue = oldValue || ''; |
465 newValue = newValue || ''; | |
466 | |
467 if (oldValue === newValue) { | |
468 return; | |
469 } | |
470 this.name = newValue; | |
471 if (!this.instanceId) { | |
472 return; | |
473 } | |
474 WebView.setName(this.instanceId, newValue); | |
475 } else if (name == 'src') { | |
476 // We treat null attribute (attribute removed) and the empty string as | |
477 // one case. | |
478 oldValue = oldValue || ''; | |
453 newValue = newValue || ''; | 479 newValue = newValue || ''; |
454 // Once we have navigated, we don't allow clearing the src attribute. | 480 // Once we have navigated, we don't allow clearing the src attribute. |
455 // Once <webview> enters a navigated state, it cannot be return back to a | 481 // Once <webview> enters a navigated state, it cannot be return back to a |
456 // placeholder state. | 482 // placeholder state. |
457 if (newValue == '' && oldValue != '') { | 483 if (newValue == '' && oldValue != '') { |
458 // src attribute changes normally initiate a navigation. We suppress | 484 // src attribute changes normally initiate a navigation. We suppress |
459 // the next src attribute handler call to avoid reloading the page | 485 // the next src attribute handler call to avoid reloading the page |
460 // on every guest-initiated navigation. | 486 // on every guest-initiated navigation. |
461 this.ignoreNextSrcAttributeChange = true; | 487 this.ignoreNextSrcAttributeChange = true; |
462 this.webviewNode.setAttribute('src', oldValue); | 488 this.webviewNode.setAttribute('src', oldValue); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 this.on = {}; | 614 this.on = {}; |
589 var events = self.getEvents(); | 615 var events = self.getEvents(); |
590 for (var eventName in events) { | 616 for (var eventName in events) { |
591 this.setupEventProperty(eventName); | 617 this.setupEventProperty(eventName); |
592 } | 618 } |
593 }; | 619 }; |
594 | 620 |
595 /** | 621 /** |
596 * @private | 622 * @private |
597 */ | 623 */ |
624 WebViewInternal.prototype.setupNameAttribute = function() { | |
625 var self = this; | |
626 FrameNameChangedEvent.addListener(function(event) { | |
627 self.name = event.name; | |
628 self.webviewNode.setAttribute('name', self.name); | |
629 }, {instanceId: self.instanceId}); | |
630 | |
lazyboy
2014/05/21 16:27:05
Remove empty line.
Fady Samuel
2014/05/21 16:56:49
Done.
| |
631 }; | |
632 | |
633 /** | |
634 * @private | |
635 */ | |
598 WebViewInternal.prototype.setupEvent = function(eventName, eventInfo) { | 636 WebViewInternal.prototype.setupEvent = function(eventName, eventInfo) { |
599 var self = this; | 637 var self = this; |
600 var webviewNode = this.webviewNode; | 638 var webviewNode = this.webviewNode; |
601 eventInfo.evt.addListener(function(event) { | 639 eventInfo.evt.addListener(function(event) { |
602 var details = {bubbles:true}; | 640 var details = {bubbles:true}; |
603 if (eventInfo.cancelable) | 641 if (eventInfo.cancelable) |
604 details.cancelable = true; | 642 details.cancelable = true; |
605 var webViewEvent = new Event(eventName, details); | 643 var webViewEvent = new Event(eventName, details); |
606 $Array.forEach(eventInfo.fields, function(field) { | 644 $Array.forEach(eventInfo.fields, function(field) { |
607 if (event[field] !== undefined) { | 645 if (event[field] !== undefined) { |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1017 return; | 1055 return; |
1018 } | 1056 } |
1019 WebView.overrideUserAgent(this.instanceId, userAgentOverride); | 1057 WebView.overrideUserAgent(this.instanceId, userAgentOverride); |
1020 }; | 1058 }; |
1021 | 1059 |
1022 /** @private */ | 1060 /** @private */ |
1023 WebViewInternal.prototype.attachWindowAndSetUpEvents = function(instanceId) { | 1061 WebViewInternal.prototype.attachWindowAndSetUpEvents = function(instanceId) { |
1024 this.instanceId = instanceId; | 1062 this.instanceId = instanceId; |
1025 var params = { | 1063 var params = { |
1026 'api': 'webview', | 1064 'api': 'webview', |
1027 'instanceId': this.viewInstanceId | 1065 'instanceId': this.viewInstanceId, |
1066 'name': this.name | |
1028 }; | 1067 }; |
1029 if (this.userAgentOverride) { | 1068 if (this.userAgentOverride) { |
1030 params['userAgentOverride'] = this.userAgentOverride; | 1069 params['userAgentOverride'] = this.userAgentOverride; |
1031 } | 1070 } |
1032 this.browserPluginNode['-internal-attach'](this.instanceId, params); | 1071 this.setupNameAttribute(); |
1033 | |
1034 var events = this.getEvents(); | 1072 var events = this.getEvents(); |
1035 for (var eventName in events) { | 1073 for (var eventName in events) { |
1036 this.setupEvent(eventName, events[eventName]); | 1074 this.setupEvent(eventName, events[eventName]); |
1037 } | 1075 } |
1076 | |
1077 this.browserPluginNode['-internal-attach'](this.instanceId, params); | |
1078 | |
1038 return true; | 1079 return true; |
1039 }; | 1080 }; |
1040 | 1081 |
1041 // Registers browser plugin <object> custom element. | 1082 // Registers browser plugin <object> custom element. |
1042 function registerBrowserPluginElement() { | 1083 function registerBrowserPluginElement() { |
1043 var proto = Object.create(HTMLObjectElement.prototype); | 1084 var proto = Object.create(HTMLObjectElement.prototype); |
1044 | 1085 |
1045 proto.createdCallback = function() { | 1086 proto.createdCallback = function() { |
1046 this.setAttribute('type', 'application/browser-plugin'); | 1087 this.setAttribute('type', 'application/browser-plugin'); |
1047 // The <object> node fills in the <webview> container. | 1088 // The <object> node fills in the <webview> container. |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1210 | 1251 |
1211 /** | 1252 /** |
1212 * Implemented when the experimental API is available. | 1253 * Implemented when the experimental API is available. |
1213 * @private | 1254 * @private |
1214 */ | 1255 */ |
1215 WebViewInternal.prototype.setupExperimentalContextMenus_ = function() {}; | 1256 WebViewInternal.prototype.setupExperimentalContextMenus_ = function() {}; |
1216 | 1257 |
1217 exports.WebView = WebView; | 1258 exports.WebView = WebView; |
1218 exports.WebViewInternal = WebViewInternal; | 1259 exports.WebViewInternal = WebViewInternal; |
1219 exports.CreateEvent = CreateEvent; | 1260 exports.CreateEvent = CreateEvent; |
OLD | NEW |