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 webRequestEvent = require('webRequest').webRequestEvent; | |
11 | |
10 var watchForTag = require("tagWatcher").watchForTag; | 12 var watchForTag = require("tagWatcher").watchForTag; |
11 | 13 |
12 var WEB_VIEW_ATTRIBUTES = ['name', 'src', 'partition', 'autosize', 'minheight', | 14 var WEB_VIEW_ATTRIBUTES = ['name', 'src', 'partition', 'autosize', 'minheight', |
13 'minwidth', 'maxheight', 'maxwidth']; | 15 'minwidth', 'maxheight', 'maxwidth']; |
14 | 16 |
15 // All exposed api methods for <webview>, these are forwarded to the browser | 17 // All exposed api methods for <webview>, these are forwarded to the browser |
16 // plugin. | 18 // plugin. |
17 var WEB_VIEW_API_METHODS = [ | 19 var WEB_VIEW_API_METHODS = [ |
18 'back', | 20 'back', |
19 'canGoBack', | 21 'canGoBack', |
20 'canGoForward', | 22 'canGoForward', |
21 'forward', | 23 'forward', |
22 'getProcessId', | 24 'getProcessId', |
23 'go', | 25 'go', |
24 'reload', | 26 'reload', |
25 'stop', | 27 'stop', |
26 'terminate' | 28 'terminate' |
27 ]; | 29 ]; |
28 | 30 |
29 var WEB_VIEW_EVENTS = { | 31 var WEB_VIEW_EVENTS = { |
30 'exit' : ['processId', 'reason'], | 32 'exit' : ['processId', 'reason'], |
31 'loadabort' : ['url', 'isTopLevel', 'reason'], | 33 'loadabort' : ['url', 'isTopLevel', 'reason'], |
32 'loadcommit' : ['url', 'isTopLevel'], | 34 'loadcommit' : ['url', 'isTopLevel'], |
33 'loadredirect' : ['oldUrl', 'newUrl', 'isTopLevel'], | 35 'loadredirect' : ['oldUrl', 'newUrl', 'isTopLevel'], |
34 'loadstart' : ['url', 'isTopLevel'], | 36 'loadstart' : ['url', 'isTopLevel'], |
35 'loadstop' : [], | 37 'loadstop' : [], |
36 'sizechanged': ['oldHeight', 'oldWidth', 'newHeight', 'newWidth'], | 38 'sizechanged': ['oldHeight', 'oldWidth', 'newHeight', 'newWidth'], |
37 }; | 39 }; |
38 | 40 |
41 var WEB_REQUEST_EVENTS = [ | |
42 'onBeforeRequest', | |
43 'onBeforeSendHeaders', | |
44 'onSendHeaders', | |
45 'onHeadersReceived', | |
46 'onAuthRequired', | |
47 'onBeforeRedirect', | |
48 'onResponseStarted', | |
49 'onCompleted', | |
50 'onErrorOccurred' | |
51 ]; | |
52 | |
39 window.addEventListener('DOMContentLoaded', function() { | 53 window.addEventListener('DOMContentLoaded', function() { |
40 watchForTag('WEBVIEW', function(addedNode) { new WebView(addedNode); }); | 54 watchForTag('WEBVIEW', function(addedNode) { new WebView(addedNode); }); |
41 }); | 55 }); |
42 | 56 |
43 /** | 57 /** |
44 * @constructor | 58 * @constructor |
45 */ | 59 */ |
46 function WebView(node) { | 60 function WebView(node) { |
47 this.node_ = node; | 61 this.node_ = node; |
48 var shadowRoot = node.webkitCreateShadowRoot(); | 62 var shadowRoot = node.webkitCreateShadowRoot(); |
49 | 63 |
50 this.objectNode_ = document.createElement('object'); | 64 this.objectNode_ = document.createElement('object'); |
51 this.objectNode_.type = 'application/browser-plugin'; | 65 this.objectNode_.type = 'application/browser-plugin'; |
52 // The <object> node fills in the <webview> container. | 66 // The <object> node fills in the <webview> container. |
53 this.objectNode_.style.width = '100%'; | 67 this.objectNode_.style.width = '100%'; |
54 this.objectNode_.style.height = '100%'; | 68 this.objectNode_.style.height = '100%'; |
55 WEB_VIEW_ATTRIBUTES.forEach(function(attributeName) { | 69 WEB_VIEW_ATTRIBUTES.forEach(function(attributeName) { |
56 // Only copy attributes that have been assigned values, rather than copying | 70 // Only copy attributes that have been assigned values, rather than copying |
57 // a series of undefined attributes to BrowserPlugin. | 71 // a series of undefined attributes to BrowserPlugin. |
58 if (this.node_.hasAttribute(attributeName)) { | 72 if (this.node_.hasAttribute(attributeName)) { |
59 this.objectNode_.setAttribute( | 73 this.objectNode_.setAttribute( |
60 attributeName, this.node_.getAttribute(attributeName)); | 74 attributeName, this.node_.getAttribute(attributeName)); |
61 } | 75 } |
62 }, this); | 76 }, this); |
77 this.onBeforeRequest_ = null; | |
63 | 78 |
64 shadowRoot.appendChild(this.objectNode_); | 79 shadowRoot.appendChild(this.objectNode_); |
65 | 80 |
66 // this.objectNode_[apiMethod] are not necessarily defined immediately after | 81 // this.objectNode_[apiMethod] are not necessarily defined immediately after |
67 // the shadow object is appended to the shadow root. | 82 // the shadow object is appended to the shadow root. |
68 var self = this; | 83 var self = this; |
69 WEB_VIEW_API_METHODS.forEach(function(apiMethod) { | 84 WEB_VIEW_API_METHODS.forEach(function(apiMethod) { |
70 node[apiMethod] = function(var_args) { | 85 node[apiMethod] = function(var_args) { |
71 return self.objectNode_[apiMethod].apply(self.objectNode_, arguments); | 86 return self.objectNode_[apiMethod].apply(self.objectNode_, arguments); |
72 }; | 87 }; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 }, | 121 }, |
107 set: function(value) { | 122 set: function(value) { |
108 objectNode[attributeName] = value; | 123 objectNode[attributeName] = value; |
109 }, | 124 }, |
110 enumerable: true | 125 enumerable: true |
111 }); | 126 }); |
112 }, this); | 127 }, this); |
113 | 128 |
114 // We cannot use {writable: true} property descriptor because we want dynamic | 129 // We cannot use {writable: true} property descriptor because we want dynamic |
115 // getter value. | 130 // getter value. |
131 WEB_REQUEST_EVENTS.forEach(function(eventName) { | |
132 Object.defineProperty(this.node_, eventName, { | |
133 get: function() { | |
134 if (!self[eventName + '_']) { | |
135 self[eventName + '_'] = | |
136 new webRequestEvent( | |
137 'webRequest.' + eventName, null, {}, null, | |
Matt Perry
2013/02/05 00:47:25
right here, you could use a different prefix for t
| |
138 self.objectNode_.getProcessId(), | |
139 self.objectNode_.getRouteId()); | |
140 } | |
141 return self[eventName + '_']; | |
142 }, | |
143 // No setter. | |
144 enumerable: true | |
145 }); | |
146 }, this); | |
147 | |
116 Object.defineProperty(this.node_, 'contentWindow', { | 148 Object.defineProperty(this.node_, 'contentWindow', { |
117 get: function() { | 149 get: function() { |
118 // TODO(fsamuel): This is a workaround to enable | 150 // TODO(fsamuel): This is a workaround to enable |
119 // contentWindow.postMessage until http://crbug.com/152006 is fixed. | 151 // contentWindow.postMessage until http://crbug.com/152006 is fixed. |
120 if (objectNode.contentWindow) | 152 if (objectNode.contentWindow) |
121 return objectNode.contentWindow.self; | 153 return objectNode.contentWindow.self; |
122 console.error('contentWindow is not available at this time. ' + | 154 console.error('contentWindow is not available at this time. ' + |
123 'It will become available when the page has finished loading.'); | 155 'It will become available when the page has finished loading.'); |
124 }, | 156 }, |
125 // No setter. | 157 // No setter. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 var node = this.node_; | 200 var node = this.node_; |
169 this.objectNode_.addEventListener('-internal-' + eventname, function(e) { | 201 this.objectNode_.addEventListener('-internal-' + eventname, function(e) { |
170 var evt = new Event(eventname, { bubbles: true }); | 202 var evt = new Event(eventname, { bubbles: true }); |
171 var detail = e.detail ? JSON.parse(e.detail) : {}; | 203 var detail = e.detail ? JSON.parse(e.detail) : {}; |
172 attribs.forEach(function(attribName) { | 204 attribs.forEach(function(attribName) { |
173 evt[attribName] = detail[attribName]; | 205 evt[attribName] = detail[attribName]; |
174 }); | 206 }); |
175 node.dispatchEvent(evt); | 207 node.dispatchEvent(evt); |
176 }); | 208 }); |
177 } | 209 } |
OLD | NEW |