| 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 var DocumentNatives = requireNative('document_natives'); | 5 var DocumentNatives = requireNative('document_natives'); |
| 6 var ExtensionOptionsEvents = | 6 var ExtensionOptionsEvents = |
| 7 require('extensionOptionsEvents').ExtensionOptionsEvents; | 7 require('extensionOptionsEvents').ExtensionOptionsEvents; |
| 8 var GuestViewInternal = | 8 var GuestViewInternal = |
| 9 require('binding').Binding.create('guestViewInternal').generate(); | 9 require('binding').Binding.create('guestViewInternal').generate(); |
| 10 var IdGenerator = requireNative('id_generator'); | 10 var IdGenerator = requireNative('id_generator'); |
| 11 var utils = require('utils'); | 11 var utils = require('utils'); |
| 12 var guestViewInternalNatives = requireNative('guest_view_internal'); | 12 var guestViewInternalNatives = requireNative('guest_view_internal'); |
| 13 | 13 |
| 14 // Mapping of the autosize attribute names to default values | 14 // Mapping of the autosize attribute names to default values |
| 15 var AUTO_SIZE_ATTRIBUTES = { | 15 var AUTO_SIZE_ATTRIBUTES = { |
| 16 'autosize': 'on', | 16 'autosize': 'on', |
| 17 'maxheight': window.innerHeight, | 17 'maxheight': window.innerHeight, |
| 18 'maxwidth': window.innerWidth, | 18 'maxwidth': window.innerWidth, |
| 19 'minheight': 32, | 19 'minheight': 32, |
| 20 'minwidth': 32 | 20 'minwidth': 32 |
| 21 }; | 21 }; |
| 22 | 22 |
| 23 function ExtensionOptionsInternal(extensionoptionsNode) { | 23 function ExtensionOptionsInternal(extensionoptionsNode) { |
| 24 privates(extensionoptionsNode).internal = this; | 24 privates(extensionoptionsNode).internal = this; |
| 25 this.extensionoptionsNode = extensionoptionsNode; | 25 this.extensionoptionsNode = extensionoptionsNode; |
| 26 this.viewInstanceId = IdGenerator.GetNextId(); | 26 this.viewInstanceId = IdGenerator.GetNextId(); |
| 27 this.guestInstanceId = 0; |
| 28 this.elementAttached = false; |
| 29 this.pendingGuestCreation = false; |
| 27 | 30 |
| 28 this.autosizeDeferred = false; | 31 this.autosizeDeferred = false; |
| 29 | 32 |
| 30 // on* Event handlers. | 33 // on* Event handlers. |
| 31 this.eventHandlers = {}; | 34 this.eventHandlers = {}; |
| 32 | 35 |
| 33 // setupEventProperty is normally called in extension_options_events.js to | 36 // setupEventProperty is normally called in extension_options_events.js to |
| 34 // register events, but the createfailed event is registered here because | 37 // register events, but the createfailed event is registered here because |
| 35 // the event is fired from here instead of through | 38 // the event is fired from here instead of through |
| 36 // extension_options_events.js. | 39 // extension_options_events.js. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 61 'minwidth': parseInt(this.minwidth || 0) | 64 'minwidth': parseInt(this.minwidth || 0) |
| 62 }); | 65 }); |
| 63 }; | 66 }; |
| 64 | 67 |
| 65 ExtensionOptionsInternal.prototype.createBrowserPluginNode = function() { | 68 ExtensionOptionsInternal.prototype.createBrowserPluginNode = function() { |
| 66 var browserPluginNode = new ExtensionOptionsInternal.BrowserPlugin(); | 69 var browserPluginNode = new ExtensionOptionsInternal.BrowserPlugin(); |
| 67 privates(browserPluginNode).internal = this; | 70 privates(browserPluginNode).internal = this; |
| 68 return browserPluginNode; | 71 return browserPluginNode; |
| 69 }; | 72 }; |
| 70 | 73 |
| 71 ExtensionOptionsInternal.prototype.createGuest = function() { | 74 ExtensionOptionsInternal.prototype.createGuestIfNecessary = function() { |
| 75 if (!this.elementAttached || this.pendingGuestCreation) { |
| 76 return; |
| 77 } |
| 78 if (this.guestInstanceId != 0) { |
| 79 this.attachWindow(); |
| 80 return; |
| 81 } |
| 72 var params = { | 82 var params = { |
| 73 'extensionId': this.extensionId, | 83 'extensionId': this.extensionId, |
| 74 }; | 84 }; |
| 75 GuestViewInternal.createGuest( | 85 GuestViewInternal.createGuest( |
| 76 'extensionoptions', | 86 'extensionoptions', |
| 77 params, | 87 params, |
| 78 function(guestInstanceId) { | 88 function(guestInstanceId) { |
| 89 this.pendingGuestCreation = false; |
| 90 if (guestInstanceId && !this.elementAttached) { |
| 91 GuestViewInternal.destroyGuest(guestInstanceId); |
| 92 guestInstanceId = 0; |
| 93 } |
| 79 if (guestInstanceId == 0) { | 94 if (guestInstanceId == 0) { |
| 80 // Fire a createfailed event here rather than in ExtensionOptionsGuest | 95 // Fire a createfailed event here rather than in ExtensionOptionsGuest |
| 81 // because the guest will not be created, and cannot fire an event. | 96 // because the guest will not be created, and cannot fire an event. |
| 82 this.initCalled = false; | 97 this.initCalled = false; |
| 83 var createFailedEvent = new Event('createfailed', { bubbles: true }); | 98 var createFailedEvent = new Event('createfailed', { bubbles: true }); |
| 84 this.dispatchEvent(createFailedEvent); | 99 this.dispatchEvent(createFailedEvent); |
| 85 } else { | 100 } else { |
| 86 this.guestInstanceId = guestInstanceId; | 101 this.guestInstanceId = guestInstanceId; |
| 87 this.attachWindow(); | 102 this.attachWindow(); |
| 88 } | 103 } |
| 89 }.bind(this)); | 104 }.bind(this) |
| 105 ); |
| 106 this.pendingGuestCreation = true; |
| 90 }; | 107 }; |
| 91 | 108 |
| 92 ExtensionOptionsInternal.prototype.dispatchEvent = | 109 ExtensionOptionsInternal.prototype.dispatchEvent = |
| 93 function(extensionOptionsEvent) { | 110 function(extensionOptionsEvent) { |
| 94 return this.extensionoptionsNode.dispatchEvent(extensionOptionsEvent); | 111 return this.extensionoptionsNode.dispatchEvent(extensionOptionsEvent); |
| 95 }; | 112 }; |
| 96 | 113 |
| 97 ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation = | 114 ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation = |
| 98 function(name, oldValue, newValue) { | 115 function(name, oldValue, newValue) { |
| 99 // We treat null attribute (attribute removed) and the empty string as | 116 // We treat null attribute (attribute removed) and the empty string as |
| 100 // one case. | 117 // one case. |
| 101 oldValue = oldValue || ''; | 118 oldValue = oldValue || ''; |
| 102 newValue = newValue || ''; | 119 newValue = newValue || ''; |
| 103 | 120 |
| 104 if (oldValue === newValue) | 121 if (oldValue === newValue) |
| 105 return; | 122 return; |
| 106 | 123 |
| 107 if (name == 'extension' && !oldValue && newValue) { | 124 if (name == 'extension' && !oldValue && newValue) { |
| 108 this.extensionId = newValue; | 125 this.extensionId = newValue; |
| 109 // If the browser plugin is not ready then don't create the guest until | 126 // If the browser plugin is not ready then don't create the guest until |
| 110 // it is ready (in handleBrowserPluginAttributeMutation). | 127 // it is ready (in handleBrowserPluginAttributeMutation). |
| 111 if (!this.internalInstanceId) | 128 if (!this.internalInstanceId) |
| 112 return; | 129 return; |
| 113 | 130 |
| 114 // If a guest view does not exist then create one. | 131 // If a guest view does not exist then create one. |
| 115 if (!this.guestInstanceId) { | 132 if (!this.guestInstanceId) { |
| 116 this.createGuest(); | 133 this.createGuestIfNecessary(); |
| 117 return; | 134 return; |
| 118 } | 135 } |
| 119 // TODO(ericzeng): Implement navigation to another guest view if we want | 136 // TODO(ericzeng): Implement navigation to another guest view if we want |
| 120 // that functionality. | 137 // that functionality. |
| 121 } else if (AUTO_SIZE_ATTRIBUTES.hasOwnProperty(name) > -1) { | 138 } else if (AUTO_SIZE_ATTRIBUTES.hasOwnProperty(name) > -1) { |
| 122 this[name] = newValue; | 139 this[name] = newValue; |
| 123 this.resetSizeConstraintsIfInvalid(); | 140 this.resetSizeConstraintsIfInvalid(); |
| 124 | 141 |
| 125 if (!this.guestInstanceId) | 142 if (!this.guestInstanceId) |
| 126 return; | 143 return; |
| 127 | 144 |
| 128 GuestViewInternal.setAutoSize(this.guestInstanceId, { | 145 GuestViewInternal.setAutoSize(this.guestInstanceId, { |
| 129 'enableAutoSize': this.extensionoptionsNode.hasAttribute('autosize'), | 146 'enableAutoSize': this.extensionoptionsNode.hasAttribute('autosize'), |
| 130 'min': { | 147 'min': { |
| 131 'width': parseInt(this.minwidth || 0), | 148 'width': parseInt(this.minwidth || 0), |
| 132 'height': parseInt(this.minheight || 0) | 149 'height': parseInt(this.minheight || 0) |
| 133 }, | 150 }, |
| 134 'max': { | 151 'max': { |
| 135 'width': parseInt(this.maxwidth || 0), | 152 'width': parseInt(this.maxwidth || 0), |
| 136 'height': parseInt(this.maxheight || 0) | 153 'height': parseInt(this.maxheight || 0) |
| 137 } | 154 } |
| 138 }); | 155 }); |
| 139 } | 156 } |
| 140 }; | 157 }; |
| 141 | 158 |
| 142 ExtensionOptionsInternal.prototype.handleBrowserPluginAttributeMutation = | 159 ExtensionOptionsInternal.prototype.handleBrowserPluginAttributeMutation = |
| 143 function(name, oldValue, newValue) { | 160 function(name, oldValue, newValue) { |
| 144 if (name == 'internalinstanceid' && !oldValue && !!newValue) { | 161 if (name == 'internalinstanceid' && !oldValue && !!newValue) { |
| 162 this.elementAttached = true; |
| 145 this.internalInstanceId = parseInt(newValue); | 163 this.internalInstanceId = parseInt(newValue); |
| 146 this.browserPluginNode.removeAttribute('internalinstanceid'); | 164 this.browserPluginNode.removeAttribute('internalinstanceid'); |
| 147 if (this.extensionId) | 165 if (this.extensionId) |
| 148 this.createGuest(); | 166 this.createGuestIfNecessary(); |
| 149 | 167 |
| 150 } | 168 } |
| 151 }; | 169 }; |
| 152 | 170 |
| 153 ExtensionOptionsInternal.prototype.onSizeChanged = | 171 ExtensionOptionsInternal.prototype.onSizeChanged = |
| 154 function(newWidth, newHeight, oldWidth, oldHeight) { | 172 function(newWidth, newHeight, oldWidth, oldHeight) { |
| 155 if (this.autosizeDeferred) { | 173 if (this.autosizeDeferred) { |
| 156 this.deferredAutoSizeState = { | 174 this.deferredAutoSizeState = { |
| 157 newWidth: newWidth, | 175 newWidth: newWidth, |
| 158 newHeight: newHeight, | 176 newHeight: newHeight, |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 */ | 304 */ |
| 287 ExtensionOptionsInternal.prototype.resumeDeferredAutoSize = function() { | 305 ExtensionOptionsInternal.prototype.resumeDeferredAutoSize = function() { |
| 288 if (this.autosizeDeferred) { | 306 if (this.autosizeDeferred) { |
| 289 this.resize(this.deferredAutoSizeState.newWidth, | 307 this.resize(this.deferredAutoSizeState.newWidth, |
| 290 this.deferredAutoSizeState.newHeight, | 308 this.deferredAutoSizeState.newHeight, |
| 291 this.deferredAutoSizeState.oldWidth, | 309 this.deferredAutoSizeState.oldWidth, |
| 292 this.deferredAutoSizeState.oldHeight); | 310 this.deferredAutoSizeState.oldHeight); |
| 293 } | 311 } |
| 294 }; | 312 }; |
| 295 | 313 |
| 314 ExtensionOptionsInternal.prototype.reset = function() { |
| 315 if (this.guestInstanceId) { |
| 316 GuestViewInternal.destroyGuest(this.guestInstanceId); |
| 317 this.guestInstanceId = undefined; |
| 318 } |
| 319 }; |
| 320 |
| 296 function registerBrowserPluginElement() { | 321 function registerBrowserPluginElement() { |
| 297 var proto = Object.create(HTMLObjectElement.prototype); | 322 var proto = Object.create(HTMLObjectElement.prototype); |
| 298 | 323 |
| 299 proto.createdCallback = function() { | 324 proto.createdCallback = function() { |
| 300 this.setAttribute('type', 'application/browser-plugin'); | 325 this.setAttribute('type', 'application/browser-plugin'); |
| 301 this.style.width = '100%'; | 326 this.style.width = '100%'; |
| 302 this.style.height = '100%'; | 327 this.style.height = '100%'; |
| 303 }; | 328 }; |
| 304 | 329 |
| 305 proto.attributeChangedCallback = function(name, oldValue, newValue) { | 330 proto.attributeChangedCallback = function(name, oldValue, newValue) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 324 delete proto.attributeChangedCallback; | 349 delete proto.attributeChangedCallback; |
| 325 } | 350 } |
| 326 | 351 |
| 327 function registerExtensionOptionsElement() { | 352 function registerExtensionOptionsElement() { |
| 328 var proto = Object.create(HTMLElement.prototype); | 353 var proto = Object.create(HTMLElement.prototype); |
| 329 | 354 |
| 330 proto.createdCallback = function() { | 355 proto.createdCallback = function() { |
| 331 new ExtensionOptionsInternal(this); | 356 new ExtensionOptionsInternal(this); |
| 332 }; | 357 }; |
| 333 | 358 |
| 359 proto.detachedCallback = function() { |
| 360 var internal = privates(this).internal; |
| 361 if (!internal) { |
| 362 return; |
| 363 } |
| 364 internal.elementAttached = false; |
| 365 internal.reset(); |
| 366 }; |
| 367 |
| 334 proto.attributeChangedCallback = function(name, oldValue, newValue) { | 368 proto.attributeChangedCallback = function(name, oldValue, newValue) { |
| 335 var internal = privates(this).internal; | 369 var internal = privates(this).internal; |
| 336 if (!internal) | 370 if (!internal) { |
| 337 return; | 371 return; |
| 372 } |
| 338 internal.handleExtensionOptionsAttributeMutation(name, oldValue, newValue); | 373 internal.handleExtensionOptionsAttributeMutation(name, oldValue, newValue); |
| 339 }; | 374 }; |
| 340 | 375 |
| 341 var methods = [ | 376 var methods = [ |
| 342 'setDeferAutoSize', | 377 'setDeferAutoSize', |
| 343 'resumeDeferredAutoSize' | 378 'resumeDeferredAutoSize' |
| 344 ]; | 379 ]; |
| 345 | 380 |
| 346 // Forward proto.foo* method calls to ExtensionOptionsInternal.foo*. | 381 // Forward proto.foo* method calls to ExtensionOptionsInternal.foo*. |
| 347 for (var i = 0; methods[i]; ++i) { | 382 for (var i = 0; methods[i]; ++i) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 367 | 402 |
| 368 var useCapture = true; | 403 var useCapture = true; |
| 369 window.addEventListener('readystatechange', function listener(event) { | 404 window.addEventListener('readystatechange', function listener(event) { |
| 370 if (document.readyState == 'loading') | 405 if (document.readyState == 'loading') |
| 371 return; | 406 return; |
| 372 | 407 |
| 373 registerBrowserPluginElement(); | 408 registerBrowserPluginElement(); |
| 374 registerExtensionOptionsElement(); | 409 registerExtensionOptionsElement(); |
| 375 window.removeEventListener(event.type, listener, useCapture); | 410 window.removeEventListener(event.type, listener, useCapture); |
| 376 }, useCapture); | 411 }, useCapture); |
| OLD | NEW |