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'); |
(...skipping 17 matching lines...) Expand all Loading... |
28 this.autosizeDeferred = false; | 28 this.autosizeDeferred = false; |
29 | 29 |
30 // on* Event handlers. | 30 // on* Event handlers. |
31 this.eventHandlers = {}; | 31 this.eventHandlers = {}; |
32 | 32 |
33 // setupEventProperty is normally called in extension_options_events.js to | 33 // setupEventProperty is normally called in extension_options_events.js to |
34 // register events, but the createfailed event is registered here because | 34 // register events, but the createfailed event is registered here because |
35 // the event is fired from here instead of through | 35 // the event is fired from here instead of through |
36 // extension_options_events.js. | 36 // extension_options_events.js. |
37 this.setupEventProperty('createfailed'); | 37 this.setupEventProperty('createfailed'); |
38 | |
39 new ExtensionOptionsEvents(this, this.viewInstanceId); | 38 new ExtensionOptionsEvents(this, this.viewInstanceId); |
40 | 39 |
41 this.setupNodeProperties(); | 40 this.setupNodeProperties(); |
42 | 41 |
43 if (this.parseExtensionAttribute()) | 42 this.parseExtensionAttribute(); |
44 this.init(); | 43 |
| 44 // Once the browser plugin has been created, the guest view will be created |
| 45 // and attached. See handleBrowserPluginAttributeMutation(). |
| 46 this.browserPluginNode = this.createBrowserPluginNode(); |
| 47 var shadowRoot = this.extensionoptionsNode.createShadowRoot(); |
| 48 shadowRoot.appendChild(this.browserPluginNode); |
45 }; | 49 }; |
46 | 50 |
47 ExtensionOptionsInternal.prototype.attachWindow = function(guestInstanceId) { | 51 ExtensionOptionsInternal.prototype.attachWindow = function() { |
48 this.guestInstanceId = guestInstanceId; | |
49 var params = { | |
50 'autosize': this.autosize, | |
51 'instanceId': this.viewInstanceId, | |
52 'maxheight': parseInt(this.maxheight || 0), | |
53 'maxwidth': parseInt(this.maxwidth || 0), | |
54 'minheight': parseInt(this.minheight || 0), | |
55 'minwidth': parseInt(this.minwidth || 0) | |
56 }; | |
57 return guestViewInternalNatives.AttachGuest( | 52 return guestViewInternalNatives.AttachGuest( |
58 parseInt(this.browserPluginNode.getAttribute('internalinstanceid')), | 53 this.internalInstanceId, |
59 guestInstanceId, | 54 this.guestInstanceId, |
60 params); | 55 { |
| 56 'autosize': this.autosize, |
| 57 'instanceId': this.viewInstanceId, |
| 58 'maxheight': parseInt(this.maxheight || 0), |
| 59 'maxwidth': parseInt(this.maxwidth || 0), |
| 60 'minheight': parseInt(this.minheight || 0), |
| 61 'minwidth': parseInt(this.minwidth || 0) |
| 62 }); |
61 }; | 63 }; |
62 | 64 |
63 ExtensionOptionsInternal.prototype.createBrowserPluginNode = function() { | 65 ExtensionOptionsInternal.prototype.createBrowserPluginNode = function() { |
64 var browserPluginNode = new ExtensionOptionsInternal.BrowserPlugin(); | 66 var browserPluginNode = new ExtensionOptionsInternal.BrowserPlugin(); |
65 privates(browserPluginNode).internal = this; | 67 privates(browserPluginNode).internal = this; |
66 return browserPluginNode; | 68 return browserPluginNode; |
67 }; | 69 }; |
68 | 70 |
69 ExtensionOptionsInternal.prototype.createGuest = function() { | 71 ExtensionOptionsInternal.prototype.createGuest = function() { |
70 var params = { | 72 var params = { |
71 'extensionId': this.extensionId, | 73 'extensionId': this.extensionId, |
72 }; | 74 }; |
73 GuestViewInternal.createGuest( | 75 GuestViewInternal.createGuest( |
74 'extensionoptions', | 76 'extensionoptions', |
75 params, | 77 params, |
76 function(guestInstanceId) { | 78 function(guestInstanceId) { |
77 if (guestInstanceId == 0) { | 79 if (guestInstanceId == 0) { |
78 // Fire a createfailed event here rather than in ExtensionOptionsGuest | 80 // Fire a createfailed event here rather than in ExtensionOptionsGuest |
79 // because the guest will not be created, and cannot fire an event. | 81 // because the guest will not be created, and cannot fire an event. |
80 this.initCalled = false; | 82 this.initCalled = false; |
81 var createFailedEvent = new Event('createfailed', { bubbles: true }); | 83 var createFailedEvent = new Event('createfailed', { bubbles: true }); |
82 this.dispatchEvent(createFailedEvent); | 84 this.dispatchEvent(createFailedEvent); |
83 } else { | 85 } else { |
84 this.attachWindow(guestInstanceId); | 86 this.guestInstanceId = guestInstanceId; |
| 87 this.attachWindow(); |
85 } | 88 } |
86 }.bind(this)); | 89 }.bind(this)); |
87 }; | 90 }; |
88 | 91 |
89 ExtensionOptionsInternal.prototype.dispatchEvent = | 92 ExtensionOptionsInternal.prototype.dispatchEvent = |
90 function(extensionOptionsEvent) { | 93 function(extensionOptionsEvent) { |
91 return this.extensionoptionsNode.dispatchEvent(extensionOptionsEvent); | 94 return this.extensionoptionsNode.dispatchEvent(extensionOptionsEvent); |
92 }; | 95 }; |
93 | 96 |
94 ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation = | 97 ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation = |
95 function(name, oldValue, newValue) { | 98 function(name, oldValue, newValue) { |
96 // We treat null attribute (attribute removed) and the empty string as | 99 // We treat null attribute (attribute removed) and the empty string as |
97 // one case. | 100 // one case. |
98 oldValue = oldValue || ''; | 101 oldValue = oldValue || ''; |
99 newValue = newValue || ''; | 102 newValue = newValue || ''; |
100 | 103 |
101 if (oldValue === newValue) | 104 if (oldValue === newValue) |
102 return; | 105 return; |
103 | 106 |
104 if (name == 'extension') { | 107 if (name == 'extension' && !oldValue && newValue) { |
105 this.extensionId = newValue; | 108 this.extensionId = newValue; |
106 // Create new guest view if one hasn't been created for this element. | 109 // If the browser plugin is not ready then don't create the guest until |
107 if (!this.guestInstanceId && this.parseExtensionAttribute()) | 110 // it is ready (in handleBrowserPluginAttributeMutation). |
108 this.init(); | 111 if (!this.internalInstanceId) |
| 112 return; |
| 113 |
| 114 // If a guest view does not exist then create one. |
| 115 if (!this.guestInstanceId) { |
| 116 this.createGuest(); |
| 117 return; |
| 118 } |
109 // TODO(ericzeng): Implement navigation to another guest view if we want | 119 // TODO(ericzeng): Implement navigation to another guest view if we want |
110 // that functionality. | 120 // that functionality. |
111 } else if (AUTO_SIZE_ATTRIBUTES.hasOwnProperty(name) > -1) { | 121 } else if (AUTO_SIZE_ATTRIBUTES.hasOwnProperty(name) > -1) { |
112 this[name] = newValue; | 122 this[name] = newValue; |
113 this.resetSizeConstraintsIfInvalid(); | 123 this.resetSizeConstraintsIfInvalid(); |
114 | 124 |
115 if (!this.guestInstanceId) | 125 if (!this.guestInstanceId) |
116 return; | 126 return; |
117 | 127 |
118 GuestViewInternal.setAutoSize(this.guestInstanceId, { | 128 GuestViewInternal.setAutoSize(this.guestInstanceId, { |
119 'enableAutoSize': this.extensionoptionsNode.hasAttribute('autosize'), | 129 'enableAutoSize': this.extensionoptionsNode.hasAttribute('autosize'), |
120 'min': { | 130 'min': { |
121 'width': parseInt(this.minwidth || 0), | 131 'width': parseInt(this.minwidth || 0), |
122 'height': parseInt(this.minheight || 0) | 132 'height': parseInt(this.minheight || 0) |
123 }, | 133 }, |
124 'max': { | 134 'max': { |
125 'width': parseInt(this.maxwidth || 0), | 135 'width': parseInt(this.maxwidth || 0), |
126 'height': parseInt(this.maxheight || 0) | 136 'height': parseInt(this.maxheight || 0) |
127 } | 137 } |
128 }); | 138 }); |
129 } | 139 } |
130 }; | 140 }; |
131 | 141 |
132 ExtensionOptionsInternal.prototype.init = function() { | 142 ExtensionOptionsInternal.prototype.handleBrowserPluginAttributeMutation = |
133 if (this.initCalled) | 143 function(name, oldValue, newValue) { |
134 return; | 144 if (name == 'internalinstanceid' && !oldValue && !!newValue) { |
| 145 this.internalInstanceId = parseInt(newValue); |
| 146 this.browserPluginNode.removeAttribute('internalinstanceid'); |
| 147 if (this.extensionId) |
| 148 this.createGuest(); |
135 | 149 |
136 this.initCalled = true; | 150 } |
137 this.browserPluginNode = this.createBrowserPluginNode(); | |
138 var shadowRoot = this.extensionoptionsNode.createShadowRoot(); | |
139 shadowRoot.appendChild(this.browserPluginNode); | |
140 this.createGuest(); | |
141 }; | 151 }; |
142 | 152 |
143 ExtensionOptionsInternal.prototype.onSizeChanged = | 153 ExtensionOptionsInternal.prototype.onSizeChanged = |
144 function(newWidth, newHeight, oldWidth, oldHeight) { | 154 function(newWidth, newHeight, oldWidth, oldHeight) { |
145 if (this.autosizeDeferred) { | 155 if (this.autosizeDeferred) { |
146 this.deferredAutoSizeState = { | 156 this.deferredAutoSizeState = { |
147 newWidth: newWidth, | 157 newWidth: newWidth, |
148 newHeight: newHeight, | 158 newHeight: newHeight, |
149 oldWidth: oldWidth, | 159 oldWidth: oldWidth, |
150 oldHeight: oldHeight | 160 oldHeight: oldHeight |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 | 295 |
286 function registerBrowserPluginElement() { | 296 function registerBrowserPluginElement() { |
287 var proto = Object.create(HTMLObjectElement.prototype); | 297 var proto = Object.create(HTMLObjectElement.prototype); |
288 | 298 |
289 proto.createdCallback = function() { | 299 proto.createdCallback = function() { |
290 this.setAttribute('type', 'application/browser-plugin'); | 300 this.setAttribute('type', 'application/browser-plugin'); |
291 this.style.width = '100%'; | 301 this.style.width = '100%'; |
292 this.style.height = '100%'; | 302 this.style.height = '100%'; |
293 }; | 303 }; |
294 | 304 |
| 305 proto.attributeChangedCallback = function(name, oldValue, newValue) { |
| 306 var internal = privates(this).internal; |
| 307 if (!internal) { |
| 308 return; |
| 309 } |
| 310 internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue); |
| 311 }; |
| 312 |
295 proto.attachedCallback = function() { | 313 proto.attachedCallback = function() { |
296 // Load the plugin immediately. | 314 // Load the plugin immediately. |
297 var unused = this.nonExistentAttribute; | 315 var unused = this.nonExistentAttribute; |
298 }; | 316 }; |
299 | 317 |
300 ExtensionOptionsInternal.BrowserPlugin = | 318 ExtensionOptionsInternal.BrowserPlugin = |
301 DocumentNatives.RegisterElement('extensionoptionsplugin', | 319 DocumentNatives.RegisterElement('extensionoptionsplugin', |
302 {extends: 'object', prototype: proto}); | 320 {extends: 'object', prototype: proto}); |
303 delete proto.createdCallback; | 321 delete proto.createdCallback; |
304 delete proto.attachedCallback; | 322 delete proto.attachedCallback; |
305 delete proto.detachedCallback; | 323 delete proto.detachedCallback; |
306 delete proto.attributeChangedCallback; | 324 delete proto.attributeChangedCallback; |
307 } | 325 } |
308 | 326 |
309 function registerExtensionOptionsElement() { | 327 function registerExtensionOptionsElement() { |
310 var proto = Object.create(HTMLElement.prototype); | 328 var proto = Object.create(HTMLElement.prototype); |
311 | 329 |
312 proto.createdCallback = function() { | 330 proto.createdCallback = function() { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 | 367 |
350 var useCapture = true; | 368 var useCapture = true; |
351 window.addEventListener('readystatechange', function listener(event) { | 369 window.addEventListener('readystatechange', function listener(event) { |
352 if (document.readyState == 'loading') | 370 if (document.readyState == 'loading') |
353 return; | 371 return; |
354 | 372 |
355 registerBrowserPluginElement(); | 373 registerBrowserPluginElement(); |
356 registerExtensionOptionsElement(); | 374 registerExtensionOptionsElement(); |
357 window.removeEventListener(event.type, listener, useCapture); | 375 window.removeEventListener(event.type, listener, useCapture); |
358 }, useCapture); | 376 }, useCapture); |
OLD | NEW |