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 WEB_VIEW_ATTRIBUTES = ['src']; | 10 var WEB_VIEW_ATTRIBUTES = ['src']; |
11 | 11 |
12 var WEB_VIEW_READONLY_ATTRIBUTES = ['contentWindow']; | 12 var WEB_VIEW_READONLY_ATTRIBUTES = ['contentWindow']; |
13 | 13 |
14 // All exposed api methods for <webview>, these are forwarded to the browser | 14 // All exposed api methods for <webview>, these are forwarded to the browser |
15 // plugin. | 15 // plugin. |
16 var WEB_VIEW_API_METHODS = [ | 16 var WEB_VIEW_API_METHODS = [ |
17 'addEventListener', | 17 'back', |
18 'back', | 18 'canGoBack', |
19 'canGoBack', | 19 'canGoForward', |
20 'canGoForward', | 20 'forward', |
21 'forward', | 21 'getProcessId', |
22 'getProcessId', | 22 'go', |
23 'go', | 23 'reload', |
24 'reload', | 24 'stop', |
25 'removeEventListener', | 25 'terminate' |
26 'stop', | 26 ]; |
27 'terminate' | 27 |
28 ]; | 28 var WEB_VIEW_EVENTS = { |
| 29 'exit' : [ 'processId', 'reason' ], |
| 30 'loadabort' : [ 'url', 'isTopLevel', 'reason' ], |
| 31 'loadcommit' : [ 'url', 'isTopLevel' ], |
| 32 'loadredirect' : [ 'oldurl', 'newurl', 'isTopLevel' ], |
| 33 'loadstart' : [ 'url', 'isTopLevel' ], |
| 34 'loadstop' : [], |
| 35 }; |
29 | 36 |
30 window.addEventListener('DOMContentLoaded', function() { | 37 window.addEventListener('DOMContentLoaded', function() { |
31 // Handle <webview> tags already in the document. | 38 // Handle <webview> tags already in the document. |
32 var webViewNodes = document.body.querySelectorAll('webview'); | 39 var webViewNodes = document.body.querySelectorAll('webview'); |
33 for (var i = 0, webViewNode; webViewNode = webViewNodes[i]; i++) { | 40 for (var i = 0, webViewNode; webViewNode = webViewNodes[i]; i++) { |
34 new WebView(webViewNode); | 41 new WebView(webViewNode); |
35 } | 42 } |
36 | 43 |
37 // Handle <webview> tags added later. | 44 // Handle <webview> tags added later. |
38 var documentObserver = new WebKitMutationObserver(function(mutations) { | 45 var documentObserver = new WebKitMutationObserver(function(mutations) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 WEB_VIEW_READONLY_ATTRIBUTES.forEach(function(attributeName) { | 111 WEB_VIEW_READONLY_ATTRIBUTES.forEach(function(attributeName) { |
105 Object.defineProperty(this.node_, attributeName, { | 112 Object.defineProperty(this.node_, attributeName, { |
106 get: function() { | 113 get: function() { |
107 // Read these attributes from the plugin <object>. | 114 // Read these attributes from the plugin <object>. |
108 return objectNode[attributeName]; | 115 return objectNode[attributeName]; |
109 }, | 116 }, |
110 // No setter. | 117 // No setter. |
111 enumerable: true | 118 enumerable: true |
112 }) | 119 }) |
113 }, this); | 120 }, this); |
| 121 |
| 122 for (eventname in WEB_VIEW_EVENTS) { |
| 123 this.setupEvent_(eventname, WEB_VIEW_EVENTS[eventname]); |
| 124 } |
114 }; | 125 }; |
115 | 126 |
116 /** | 127 /** |
117 * @private | 128 * @private |
118 */ | 129 */ |
119 WebView.prototype.handleMutation_ = function(mutation) { | 130 WebView.prototype.handleMutation_ = function(mutation) { |
120 switch (mutation.attributeName) { | 131 switch (mutation.attributeName) { |
121 case 'src': | 132 case 'src': |
122 // We need to set .src directly on the shadow element so that | 133 // We need to set .src directly on the shadow element so that |
123 // BrowserPluginBindings catches this as src attribute mutation. The | 134 // BrowserPluginBindings catches this as src attribute mutation. The |
124 // bindings would catch 'SetAttribute' method call with src as argument | 135 // bindings would catch 'SetAttribute' method call with src as argument |
125 // otherwise. | 136 // otherwise. |
126 this.objectNode_.src = this.node_.getAttribute('src'); | 137 this.objectNode_.src = this.node_.getAttribute('src'); |
127 break; | 138 break; |
128 default: | 139 default: |
129 this.copyAttribute_(mutation.attributeName); | 140 this.copyAttribute_(mutation.attributeName); |
130 break; | 141 break; |
131 } | 142 } |
132 }; | 143 }; |
133 | 144 |
134 /** | 145 /** |
135 * @private | 146 * @private |
136 */ | 147 */ |
137 WebView.prototype.copyAttribute_ = function(attributeName) { | 148 WebView.prototype.copyAttribute_ = function(attributeName) { |
138 this.objectNode_.setAttribute( | 149 this.objectNode_.setAttribute( |
139 attributeName, this.node_.getAttribute(attributeName)); | 150 attributeName, this.node_.getAttribute(attributeName)); |
140 }; | 151 }; |
| 152 |
| 153 /** |
| 154 * @private |
| 155 */ |
| 156 WebView.prototype.setupEvent_ = function(eventname, attribs) { |
| 157 var node = this.node_; |
| 158 this.objectNode_.addEventListener('-internal-' + eventname, function(e) { |
| 159 var evt = new Event(eventname); |
| 160 attribs.forEach(function(attribname) { |
| 161 evt[attribname] = e.detail[attribname]; |
| 162 }); |
| 163 node.dispatchEvent(evt); |
| 164 }); |
| 165 } |
OLD | NEW |