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 // This module implements the attributes of the <webview> tag. | 5 // This module implements the attributes of the <webview> tag. |
6 | 6 |
7 var GuestViewInternal = | 7 var GuestViewInternal = |
8 require('binding').Binding.create('guestViewInternal').generate(); | 8 require('binding').Binding.create('guestViewInternal').generate(); |
9 var WebViewImpl = require('webView').WebViewImpl; | 9 var WebViewImpl = require('webView').WebViewImpl; |
10 var WebViewConstants = require('webViewConstants').WebViewConstants; | 10 var WebViewConstants = require('webViewConstants').WebViewConstants; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 if (this.ignoreMutation) { | 57 if (this.ignoreMutation) { |
58 return; | 58 return; |
59 } | 59 } |
60 | 60 |
61 this.handleMutation(oldValue, newValue); | 61 this.handleMutation(oldValue, newValue); |
62 }; | 62 }; |
63 | 63 |
64 // Called when a change that isn't ignored occurs to the attribute's value. | 64 // Called when a change that isn't ignored occurs to the attribute's value. |
65 WebViewAttribute.prototype.handleMutation = function(oldValue, newValue) {}; | 65 WebViewAttribute.prototype.handleMutation = function(oldValue, newValue) {}; |
66 | 66 |
| 67 // Called when the <webview> element is attached to the DOM tree. |
| 68 WebViewAttribute.prototype.attach = function() {}; |
| 69 |
67 // Called when the <webview> element is detached from the DOM tree. | 70 // Called when the <webview> element is detached from the DOM tree. |
68 WebViewAttribute.prototype.reset = function() {}; | 71 WebViewAttribute.prototype.detach = function() {}; |
69 | 72 |
70 // An attribute that is treated as a Boolean. | 73 // An attribute that is treated as a Boolean. |
71 function BooleanAttribute(name, webViewImpl) { | 74 function BooleanAttribute(name, webViewImpl) { |
72 WebViewAttribute.call(this, name, webViewImpl); | 75 WebViewAttribute.call(this, name, webViewImpl); |
73 } | 76 } |
74 | 77 |
75 BooleanAttribute.prototype.__proto__ = WebViewAttribute.prototype; | 78 BooleanAttribute.prototype.__proto__ = WebViewAttribute.prototype; |
76 | 79 |
77 BooleanAttribute.prototype.getValue = function() { | 80 BooleanAttribute.prototype.getValue = function() { |
78 return this.webViewImpl.element.hasAttribute(this.name); | 81 return this.webViewImpl.element.hasAttribute(this.name); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 return parseInt(this.webViewImpl.element.getAttribute(this.name)) || 0; | 136 return parseInt(this.webViewImpl.element.getAttribute(this.name)) || 0; |
134 }; | 137 }; |
135 | 138 |
136 AutosizeDimensionAttribute.prototype.handleMutation = function( | 139 AutosizeDimensionAttribute.prototype.handleMutation = function( |
137 oldValue, newValue) { | 140 oldValue, newValue) { |
138 if (!this.webViewImpl.guest.getId()) { | 141 if (!this.webViewImpl.guest.getId()) { |
139 return; | 142 return; |
140 } | 143 } |
141 this.webViewImpl.guest.setSize({ | 144 this.webViewImpl.guest.setSize({ |
142 'enableAutoSize': this.webViewImpl.attributes[ | 145 'enableAutoSize': this.webViewImpl.attributes[ |
143 WebViewConstants.ATTRIBUTE_AUTOSIZE].getValue(), | 146 WebViewConstants.ATTRIBUTE_AUTOSIZE].getValue(), |
144 'min': { | 147 'min': { |
145 'width': this.webViewImpl.attributes[ | 148 'width': this.webViewImpl.attributes[ |
146 WebViewConstants.ATTRIBUTE_MINWIDTH].getValue(), | 149 WebViewConstants.ATTRIBUTE_MINWIDTH].getValue(), |
147 'height': this.webViewImpl.attributes[ | 150 'height': this.webViewImpl.attributes[ |
148 WebViewConstants.ATTRIBUTE_MINHEIGHT].getValue() | 151 WebViewConstants.ATTRIBUTE_MINHEIGHT].getValue() |
149 }, | 152 }, |
150 'max': { | 153 'max': { |
151 'width': this.webViewImpl.attributes[ | 154 'width': this.webViewImpl.attributes[ |
152 WebViewConstants.ATTRIBUTE_MAXWIDTH].getValue(), | 155 WebViewConstants.ATTRIBUTE_MAXWIDTH].getValue(), |
153 'height': this.webViewImpl.attributes[ | 156 'height': this.webViewImpl.attributes[ |
154 WebViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() | 157 WebViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() |
155 } | 158 } |
156 }); | 159 }); |
157 return; | 160 return; |
158 }; | 161 }; |
159 | 162 |
160 // Attribute that specifies whether the webview should be autosized. | 163 // Attribute that specifies whether the webview should be autosized. |
161 function AutosizeAttribute(webViewImpl) { | 164 function AutosizeAttribute(webViewImpl) { |
162 BooleanAttribute.call(this, WebViewConstants.ATTRIBUTE_AUTOSIZE, webViewImpl); | 165 BooleanAttribute.call(this, WebViewConstants.ATTRIBUTE_AUTOSIZE, webViewImpl); |
163 } | 166 } |
164 | 167 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 this.validPartitionId = true; | 203 this.validPartitionId = true; |
201 } | 204 } |
202 | 205 |
203 PartitionAttribute.prototype.__proto__ = WebViewAttribute.prototype; | 206 PartitionAttribute.prototype.__proto__ = WebViewAttribute.prototype; |
204 | 207 |
205 PartitionAttribute.prototype.handleMutation = function(oldValue, newValue) { | 208 PartitionAttribute.prototype.handleMutation = function(oldValue, newValue) { |
206 newValue = newValue || ''; | 209 newValue = newValue || ''; |
207 | 210 |
208 // The partition cannot change if the webview has already navigated. | 211 // The partition cannot change if the webview has already navigated. |
209 if (!this.webViewImpl.attributes[ | 212 if (!this.webViewImpl.attributes[ |
210 WebViewConstants.ATTRIBUTE_SRC].beforeFirstNavigation) { | 213 WebViewConstants.ATTRIBUTE_SRC].beforeFirstNavigation) { |
211 window.console.error(WebViewConstants.ERROR_MSG_ALREADY_NAVIGATED); | 214 window.console.error(WebViewConstants.ERROR_MSG_ALREADY_NAVIGATED); |
212 this.setValueIgnoreMutation(oldValue); | 215 this.setValueIgnoreMutation(oldValue); |
213 return; | 216 return; |
214 } | 217 } |
215 if (newValue == 'persist:') { | 218 if (newValue == 'persist:') { |
216 this.validPartitionId = false; | 219 this.validPartitionId = false; |
217 window.console.error( | 220 window.console.error( |
218 WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE); | 221 WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE); |
219 } | 222 } |
220 }; | 223 }; |
221 | 224 |
222 PartitionAttribute.prototype.reset = function() { | 225 PartitionAttribute.prototype.detach = function() { |
223 this.validPartitionId = true; | 226 this.validPartitionId = true; |
224 }; | 227 }; |
225 | 228 |
226 // Attribute that handles the location and navigation of the webview. | 229 // Attribute that handles the location and navigation of the webview. |
227 function SrcAttribute(webViewImpl) { | 230 function SrcAttribute(webViewImpl) { |
228 WebViewAttribute.call(this, WebViewConstants.ATTRIBUTE_SRC, webViewImpl); | 231 WebViewAttribute.call(this, WebViewConstants.ATTRIBUTE_SRC, webViewImpl); |
229 this.setupMutationObserver(); | 232 this.setupMutationObserver(); |
230 this.beforeFirstNavigation = true; | 233 this.beforeFirstNavigation = true; |
| 234 this.elementAttached = false; |
231 } | 235 } |
232 | 236 |
233 SrcAttribute.prototype.__proto__ = WebViewAttribute.prototype; | 237 SrcAttribute.prototype.__proto__ = WebViewAttribute.prototype; |
234 | 238 |
235 SrcAttribute.prototype.setValueIgnoreMutation = function(value) { | 239 SrcAttribute.prototype.setValueIgnoreMutation = function(value) { |
236 WebViewAttribute.prototype.setValueIgnoreMutation.call(this, value); | 240 WebViewAttribute.prototype.setValueIgnoreMutation.call(this, value); |
237 // takeRecords() is needed to clear queued up src mutations. Without it, it is | 241 // takeRecords() is needed to clear queued up src mutations. Without it, it is |
238 // possible for this change to get picked up asyncronously by src's mutation | 242 // possible for this change to get picked up asyncronously by src's mutation |
239 // observer |observer|, and then get handled even though we do not want to | 243 // observer |observer|, and then get handled even though we do not want to |
240 // handle this mutation. | 244 // handle this mutation. |
241 this.observer.takeRecords(); | 245 this.observer.takeRecords(); |
242 } | 246 } |
243 | 247 |
244 SrcAttribute.prototype.handleMutation = function(oldValue, newValue) { | 248 SrcAttribute.prototype.handleMutation = function(oldValue, newValue) { |
245 // Once we have navigated, we don't allow clearing the src attribute. | 249 // Once we have navigated, we don't allow clearing the src attribute. |
246 // Once <webview> enters a navigated state, it cannot return to a | 250 // Once <webview> enters a navigated state, it cannot return to a |
247 // placeholder state. | 251 // placeholder state. |
248 if (!newValue && oldValue) { | 252 if (!newValue && oldValue) { |
249 // src attribute changes normally initiate a navigation. We suppress | 253 // src attribute changes normally initiate a navigation. We suppress |
250 // the next src attribute handler call to avoid reloading the page | 254 // the next src attribute handler call to avoid reloading the page |
251 // on every guest-initiated navigation. | 255 // on every guest-initiated navigation. |
252 this.setValueIgnoreMutation(oldValue); | 256 this.setValueIgnoreMutation(oldValue); |
253 return; | 257 return; |
254 } | 258 } |
255 this.parse(); | 259 this.parse(); |
256 }; | 260 }; |
257 | 261 |
258 SrcAttribute.prototype.reset = function() { | 262 SrcAttribute.prototype.attach = function() { |
| 263 this.elementAttached = true; |
| 264 this.parse(); |
| 265 }; |
| 266 |
| 267 SrcAttribute.prototype.detach = function() { |
259 this.beforeFirstNavigation = true; | 268 this.beforeFirstNavigation = true; |
| 269 this.elementAttached = false; |
260 }; | 270 }; |
261 | 271 |
262 // The purpose of this mutation observer is to catch assignment to the src | 272 // The purpose of this mutation observer is to catch assignment to the src |
263 // attribute without any changes to its value. This is useful in the case | 273 // attribute without any changes to its value. This is useful in the case |
264 // where the webview guest has crashed and navigating to the same address | 274 // where the webview guest has crashed and navigating to the same address |
265 // spawns off a new process. | 275 // spawns off a new process. |
266 SrcAttribute.prototype.setupMutationObserver = | 276 SrcAttribute.prototype.setupMutationObserver = |
267 function() { | 277 function() { |
268 this.observer = new MutationObserver(function(mutations) { | 278 this.observer = new MutationObserver(function(mutations) { |
269 $Array.forEach(mutations, function(mutation) { | 279 $Array.forEach(mutations, function(mutation) { |
270 var oldValue = mutation.oldValue; | 280 var oldValue = mutation.oldValue; |
271 var newValue = this.getValue(); | 281 var newValue = this.getValue(); |
272 if (oldValue != newValue) { | 282 if (oldValue != newValue) { |
273 return; | 283 return; |
274 } | 284 } |
275 this.handleMutation(oldValue, newValue); | 285 this.handleMutation(oldValue, newValue); |
276 }.bind(this)); | 286 }.bind(this)); |
277 }.bind(this)); | 287 }.bind(this)); |
278 var params = { | 288 var params = { |
279 attributes: true, | 289 attributes: true, |
280 attributeOldValue: true, | 290 attributeOldValue: true, |
281 attributeFilter: [this.name] | 291 attributeFilter: [this.name] |
282 }; | 292 }; |
283 this.observer.observe(this.webViewImpl.element, params); | 293 this.observer.observe(this.webViewImpl.element, params); |
284 }; | 294 }; |
285 | 295 |
286 SrcAttribute.prototype.parse = function() { | 296 SrcAttribute.prototype.parse = function() { |
287 if (!this.webViewImpl.elementAttached || | 297 if (!this.elementAttached || |
288 !this.webViewImpl.attributes[ | 298 !this.webViewImpl.attributes[ |
289 WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId || | 299 WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId || |
290 !this.getValue()) { | 300 !this.getValue()) { |
291 return; | 301 return; |
292 } | 302 } |
293 | 303 |
294 if (!this.webViewImpl.guest.getId()) { | 304 if (!this.webViewImpl.guest.getId()) { |
295 if (this.beforeFirstNavigation) { | 305 if (this.beforeFirstNavigation) { |
296 this.beforeFirstNavigation = false; | 306 this.beforeFirstNavigation = false; |
297 this.webViewImpl.createGuest(); | 307 this.webViewImpl.createGuest(); |
298 } | 308 } |
299 return; | 309 return; |
(...skipping 24 matching lines...) Expand all Loading... |
324 | 334 |
325 var autosizeAttributes = [WebViewConstants.ATTRIBUTE_MAXHEIGHT, | 335 var autosizeAttributes = [WebViewConstants.ATTRIBUTE_MAXHEIGHT, |
326 WebViewConstants.ATTRIBUTE_MAXWIDTH, | 336 WebViewConstants.ATTRIBUTE_MAXWIDTH, |
327 WebViewConstants.ATTRIBUTE_MINHEIGHT, | 337 WebViewConstants.ATTRIBUTE_MINHEIGHT, |
328 WebViewConstants.ATTRIBUTE_MINWIDTH]; | 338 WebViewConstants.ATTRIBUTE_MINWIDTH]; |
329 for (var i = 0; autosizeAttributes[i]; ++i) { | 339 for (var i = 0; autosizeAttributes[i]; ++i) { |
330 this.attributes[autosizeAttributes[i]] = | 340 this.attributes[autosizeAttributes[i]] = |
331 new AutosizeDimensionAttribute(autosizeAttributes[i], this); | 341 new AutosizeDimensionAttribute(autosizeAttributes[i], this); |
332 } | 342 } |
333 }; | 343 }; |
OLD | NEW |