| 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 |