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 | 27 |
| 28 this.autosizeDeferred = false; |
| 29 |
28 // on* Event handlers. | 30 // on* Event handlers. |
29 this.eventHandlers = {}; | 31 this.eventHandlers = {}; |
30 | 32 |
31 // setupEventProperty is normally called in extension_options_events.js to | 33 // setupEventProperty is normally called in extension_options_events.js to |
32 // register events, but the createfailed event is registered here because | 34 // register events, but the createfailed event is registered here because |
33 // the event is fired from here instead of through | 35 // the event is fired from here instead of through |
34 // extension_options_events.js. | 36 // extension_options_events.js. |
35 this.setupEventProperty('createfailed'); | 37 this.setupEventProperty('createfailed'); |
36 | 38 |
37 new ExtensionOptionsEvents(this, this.viewInstanceId); | 39 new ExtensionOptionsEvents(this, this.viewInstanceId); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 if (this.initCalled) | 133 if (this.initCalled) |
132 return; | 134 return; |
133 | 135 |
134 this.initCalled = true; | 136 this.initCalled = true; |
135 this.browserPluginNode = this.createBrowserPluginNode(); | 137 this.browserPluginNode = this.createBrowserPluginNode(); |
136 var shadowRoot = this.extensionoptionsNode.createShadowRoot(); | 138 var shadowRoot = this.extensionoptionsNode.createShadowRoot(); |
137 shadowRoot.appendChild(this.browserPluginNode); | 139 shadowRoot.appendChild(this.browserPluginNode); |
138 this.createGuest(); | 140 this.createGuest(); |
139 }; | 141 }; |
140 | 142 |
141 ExtensionOptionsInternal.prototype.onSizeChanged = function(width, height) { | 143 ExtensionOptionsInternal.prototype.onSizeChanged = |
142 this.browserPluginNode.style.width = width + 'px'; | 144 function(newWidth, newHeight, oldWidth, oldHeight) { |
143 this.browserPluginNode.style.height = height + 'px'; | 145 if (this.autosizeDeferred) { |
| 146 this.deferredAutoSizeState = { |
| 147 newWidth: newWidth, |
| 148 newHeight: newHeight, |
| 149 oldWidth: oldWidth, |
| 150 oldHeight: oldHeight |
| 151 }; |
| 152 } else { |
| 153 this.resize(newWidth, newHeight, oldWidth, oldHeight); |
| 154 } |
144 }; | 155 }; |
145 | 156 |
146 ExtensionOptionsInternal.prototype.parseExtensionAttribute = function() { | 157 ExtensionOptionsInternal.prototype.parseExtensionAttribute = function() { |
147 if (this.extensionoptionsNode.hasAttribute('extension')) { | 158 if (this.extensionoptionsNode.hasAttribute('extension')) { |
148 this.extensionId = this.extensionoptionsNode.getAttribute('extension'); | 159 this.extensionId = this.extensionoptionsNode.getAttribute('extension'); |
149 return true; | 160 return true; |
150 } | 161 } |
151 return false; | 162 return false; |
152 }; | 163 }; |
153 | 164 |
| 165 ExtensionOptionsInternal.prototype.resize = |
| 166 function(newWidth, newHeight, oldWidth, oldHeight) { |
| 167 this.browserPluginNode.style.width = newWidth + 'px'; |
| 168 this.browserPluginNode.style.height = newHeight + 'px'; |
| 169 |
| 170 // Do not allow the options page's dimensions to shrink so that the options |
| 171 // page has a consistent UI. If the new size is larger than the minimum, |
| 172 // make that the new minimum size. |
| 173 if (newWidth > this.minwidth) |
| 174 this.minwidth = newWidth; |
| 175 if (newHeight > this.minheight) |
| 176 this.minheight = newHeight; |
| 177 |
| 178 GuestViewInternal.setAutoSize(this.guestInstanceId, { |
| 179 'enableAutoSize': this.extensionoptionsNode.hasAttribute('autosize'), |
| 180 'min': { |
| 181 'width': parseInt(this.minwidth || 0), |
| 182 'height': parseInt(this.minheight || 0) |
| 183 }, |
| 184 'max': { |
| 185 'width': parseInt(this.maxwidth || 0), |
| 186 'height': parseInt(this.maxheight || 0) |
| 187 } |
| 188 }); |
| 189 }; |
| 190 |
154 // Adds an 'on<event>' property on the view, which can be used to set/unset | 191 // Adds an 'on<event>' property on the view, which can be used to set/unset |
155 // an event handler. | 192 // an event handler. |
156 ExtensionOptionsInternal.prototype.setupEventProperty = function(eventName) { | 193 ExtensionOptionsInternal.prototype.setupEventProperty = function(eventName) { |
157 var propertyName = 'on' + eventName.toLowerCase(); | 194 var propertyName = 'on' + eventName.toLowerCase(); |
158 var extensionoptionsNode = this.extensionoptionsNode; | 195 var extensionoptionsNode = this.extensionoptionsNode; |
159 Object.defineProperty(extensionoptionsNode, propertyName, { | 196 Object.defineProperty(extensionoptionsNode, propertyName, { |
160 get: function() { | 197 get: function() { |
161 return this.eventHandlers[propertyName]; | 198 return this.eventHandlers[propertyName]; |
162 }.bind(this), | 199 }.bind(this), |
163 set: function(value) { | 200 set: function(value) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 | 246 |
210 ExtensionOptionsInternal.prototype.resetSizeConstraintsIfInvalid = function () { | 247 ExtensionOptionsInternal.prototype.resetSizeConstraintsIfInvalid = function () { |
211 if (this.minheight > this.maxheight || this.minheight < 0) { | 248 if (this.minheight > this.maxheight || this.minheight < 0) { |
212 this.minheight = AUTO_SIZE_ATTRIBUTES.minheight; | 249 this.minheight = AUTO_SIZE_ATTRIBUTES.minheight; |
213 this.maxheight = AUTO_SIZE_ATTRIBUTES.maxheight; | 250 this.maxheight = AUTO_SIZE_ATTRIBUTES.maxheight; |
214 } | 251 } |
215 if (this.minwidth > this.maxwidth || this.minwidth < 0) { | 252 if (this.minwidth > this.maxwidth || this.minwidth < 0) { |
216 this.minwidth = AUTO_SIZE_ATTRIBUTES.minwidth; | 253 this.minwidth = AUTO_SIZE_ATTRIBUTES.minwidth; |
217 this.maxwidth = AUTO_SIZE_ATTRIBUTES.maxwidth; | 254 this.maxwidth = AUTO_SIZE_ATTRIBUTES.maxwidth; |
218 } | 255 } |
219 } | 256 }; |
| 257 |
| 258 /** |
| 259 * Toggles whether the element should automatically resize to its preferred |
| 260 * size. If set to true, when the element receives new autosize dimensions, |
| 261 * it passes them to the embedder in a sizechanged event, but does not resize |
| 262 * itself to those dimensions until the embedder calls resumeDeferredAutoSize. |
| 263 * This allows the embedder to defer the resizing until it is ready. |
| 264 * When set to false, the element resizes whenever it receives new autosize |
| 265 * dimensions. |
| 266 */ |
| 267 ExtensionOptionsInternal.prototype.setDeferAutoSize = function(value) { |
| 268 if (!value) |
| 269 resumeDeferredAutoSize(); |
| 270 this.autosizeDeferred = value; |
| 271 }; |
| 272 |
| 273 /** |
| 274 * Allows the element to resize to most recent set of autosize dimensions if |
| 275 * autosizing is being deferred. |
| 276 */ |
| 277 ExtensionOptionsInternal.prototype.resumeDeferredAutoSize = function() { |
| 278 if (this.autosizeDeferred) { |
| 279 this.resize(this.deferredAutoSizeState.newWidth, |
| 280 this.deferredAutoSizeState.newHeight, |
| 281 this.deferredAutoSizeState.oldWidth, |
| 282 this.deferredAutoSizeState.oldHeight); |
| 283 } |
| 284 }; |
220 | 285 |
221 function registerBrowserPluginElement() { | 286 function registerBrowserPluginElement() { |
222 var proto = Object.create(HTMLObjectElement.prototype); | 287 var proto = Object.create(HTMLObjectElement.prototype); |
223 | 288 |
224 proto.createdCallback = function() { | 289 proto.createdCallback = function() { |
225 this.setAttribute('type', 'application/browser-plugin'); | 290 this.setAttribute('type', 'application/browser-plugin'); |
226 this.style.width = '100%'; | 291 this.style.width = '100%'; |
227 this.style.height = '100%'; | 292 this.style.height = '100%'; |
228 }; | 293 }; |
229 | 294 |
(...skipping 18 matching lines...) Expand all Loading... |
248 new ExtensionOptionsInternal(this); | 313 new ExtensionOptionsInternal(this); |
249 }; | 314 }; |
250 | 315 |
251 proto.attributeChangedCallback = function(name, oldValue, newValue) { | 316 proto.attributeChangedCallback = function(name, oldValue, newValue) { |
252 var internal = privates(this).internal; | 317 var internal = privates(this).internal; |
253 if (!internal) | 318 if (!internal) |
254 return; | 319 return; |
255 internal.handleExtensionOptionsAttributeMutation(name, oldValue, newValue); | 320 internal.handleExtensionOptionsAttributeMutation(name, oldValue, newValue); |
256 }; | 321 }; |
257 | 322 |
| 323 var methods = [ |
| 324 'setDeferAutoSize', |
| 325 'resumeDeferredAutoSize' |
| 326 ]; |
| 327 |
| 328 // Forward proto.foo* method calls to ExtensionOptionsInternal.foo*. |
| 329 for (var i = 0; methods[i]; ++i) { |
| 330 var createHandler = function(m) { |
| 331 return function(var_args) { |
| 332 var internal = privates(this).internal; |
| 333 return $Function.apply(internal[m], internal, arguments); |
| 334 }; |
| 335 }; |
| 336 proto[methods[i]] = createHandler(methods[i]); |
| 337 } |
| 338 |
258 window.ExtensionOptions = | 339 window.ExtensionOptions = |
259 DocumentNatives.RegisterElement('extensionoptions', {prototype: proto}); | 340 DocumentNatives.RegisterElement('extensionoptions', {prototype: proto}); |
260 | 341 |
261 // Delete the callbacks so developers cannot call them and produce unexpected | 342 // Delete the callbacks so developers cannot call them and produce unexpected |
262 // behavior. | 343 // behavior. |
263 delete proto.createdCallback; | 344 delete proto.createdCallback; |
264 delete proto.attachedCallback; | 345 delete proto.attachedCallback; |
265 delete proto.detachedCallback; | 346 delete proto.detachedCallback; |
266 delete proto.attributeChangedCallback; | 347 delete proto.attributeChangedCallback; |
267 } | 348 } |
268 | 349 |
269 var useCapture = true; | 350 var useCapture = true; |
270 window.addEventListener('readystatechange', function listener(event) { | 351 window.addEventListener('readystatechange', function listener(event) { |
271 if (document.readyState == 'loading') | 352 if (document.readyState == 'loading') |
272 return; | 353 return; |
273 | 354 |
274 registerBrowserPluginElement(); | 355 registerBrowserPluginElement(); |
275 registerExtensionOptionsElement(); | 356 registerExtensionOptionsElement(); |
276 window.removeEventListener(event.type, listener, useCapture); | 357 window.removeEventListener(event.type, listener, useCapture); |
277 }, useCapture); | 358 }, useCapture); |
OLD | NEW |