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 | |
30 // on* Event handlers. | 28 // on* Event handlers. |
31 this.eventHandlers = {}; | 29 this.eventHandlers = {}; |
32 | 30 |
33 // setupEventProperty is normally called in extension_options_events.js to | 31 // setupEventProperty is normally called in extension_options_events.js to |
34 // register events, but the createfailed event is registered here because | 32 // register events, but the createfailed event is registered here because |
35 // the event is fired from here instead of through | 33 // the event is fired from here instead of through |
36 // extension_options_events.js. | 34 // extension_options_events.js. |
37 this.setupEventProperty('createfailed'); | 35 this.setupEventProperty('createfailed'); |
38 | 36 |
39 new ExtensionOptionsEvents(this, this.viewInstanceId); | 37 new ExtensionOptionsEvents(this, this.viewInstanceId); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 if (this.initCalled) | 131 if (this.initCalled) |
134 return; | 132 return; |
135 | 133 |
136 this.initCalled = true; | 134 this.initCalled = true; |
137 this.browserPluginNode = this.createBrowserPluginNode(); | 135 this.browserPluginNode = this.createBrowserPluginNode(); |
138 var shadowRoot = this.extensionoptionsNode.createShadowRoot(); | 136 var shadowRoot = this.extensionoptionsNode.createShadowRoot(); |
139 shadowRoot.appendChild(this.browserPluginNode); | 137 shadowRoot.appendChild(this.browserPluginNode); |
140 this.createGuest(); | 138 this.createGuest(); |
141 }; | 139 }; |
142 | 140 |
143 ExtensionOptionsInternal.prototype.onSizeChanged = | 141 ExtensionOptionsInternal.prototype.onSizeChanged = function(width, height) { |
144 function(newWidth, newHeight, oldWidth, oldHeight) { | 142 this.browserPluginNode.style.width = width + 'px'; |
145 if (this.autosizeDeferred) { | 143 this.browserPluginNode.style.height = height + 'px'; |
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 } | |
155 }; | 144 }; |
156 | 145 |
157 ExtensionOptionsInternal.prototype.parseExtensionAttribute = function() { | 146 ExtensionOptionsInternal.prototype.parseExtensionAttribute = function() { |
158 if (this.extensionoptionsNode.hasAttribute('extension')) { | 147 if (this.extensionoptionsNode.hasAttribute('extension')) { |
159 this.extensionId = this.extensionoptionsNode.getAttribute('extension'); | 148 this.extensionId = this.extensionoptionsNode.getAttribute('extension'); |
160 return true; | 149 return true; |
161 } | 150 } |
162 return false; | 151 return false; |
163 }; | 152 }; |
164 | 153 |
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.instanceId, { | |
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 | |
191 // Adds an 'on<event>' property on the view, which can be used to set/unset | 154 // Adds an 'on<event>' property on the view, which can be used to set/unset |
192 // an event handler. | 155 // an event handler. |
193 ExtensionOptionsInternal.prototype.setupEventProperty = function(eventName) { | 156 ExtensionOptionsInternal.prototype.setupEventProperty = function(eventName) { |
194 var propertyName = 'on' + eventName.toLowerCase(); | 157 var propertyName = 'on' + eventName.toLowerCase(); |
195 var extensionoptionsNode = this.extensionoptionsNode; | 158 var extensionoptionsNode = this.extensionoptionsNode; |
196 Object.defineProperty(extensionoptionsNode, propertyName, { | 159 Object.defineProperty(extensionoptionsNode, propertyName, { |
197 get: function() { | 160 get: function() { |
198 return this.eventHandlers[propertyName]; | 161 return this.eventHandlers[propertyName]; |
199 }.bind(this), | 162 }.bind(this), |
200 set: function(value) { | 163 set: function(value) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 | 209 |
247 ExtensionOptionsInternal.prototype.resetSizeConstraintsIfInvalid = function () { | 210 ExtensionOptionsInternal.prototype.resetSizeConstraintsIfInvalid = function () { |
248 if (this.minheight > this.maxheight || this.minheight < 0) { | 211 if (this.minheight > this.maxheight || this.minheight < 0) { |
249 this.minheight = AUTO_SIZE_ATTRIBUTES.minheight; | 212 this.minheight = AUTO_SIZE_ATTRIBUTES.minheight; |
250 this.maxheight = AUTO_SIZE_ATTRIBUTES.maxheight; | 213 this.maxheight = AUTO_SIZE_ATTRIBUTES.maxheight; |
251 } | 214 } |
252 if (this.minwidth > this.maxwidth || this.minwidth < 0) { | 215 if (this.minwidth > this.maxwidth || this.minwidth < 0) { |
253 this.minwidth = AUTO_SIZE_ATTRIBUTES.minwidth; | 216 this.minwidth = AUTO_SIZE_ATTRIBUTES.minwidth; |
254 this.maxwidth = AUTO_SIZE_ATTRIBUTES.maxwidth; | 217 this.maxwidth = AUTO_SIZE_ATTRIBUTES.maxwidth; |
255 } | 218 } |
256 }; | 219 } |
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 }; | |
285 | 220 |
286 function registerBrowserPluginElement() { | 221 function registerBrowserPluginElement() { |
287 var proto = Object.create(HTMLObjectElement.prototype); | 222 var proto = Object.create(HTMLObjectElement.prototype); |
288 | 223 |
289 proto.createdCallback = function() { | 224 proto.createdCallback = function() { |
290 this.setAttribute('type', 'application/browser-plugin'); | 225 this.setAttribute('type', 'application/browser-plugin'); |
291 this.style.width = '100%'; | 226 this.style.width = '100%'; |
292 this.style.height = '100%'; | 227 this.style.height = '100%'; |
293 }; | 228 }; |
294 | 229 |
(...skipping 18 matching lines...) Expand all Loading... |
313 new ExtensionOptionsInternal(this); | 248 new ExtensionOptionsInternal(this); |
314 }; | 249 }; |
315 | 250 |
316 proto.attributeChangedCallback = function(name, oldValue, newValue) { | 251 proto.attributeChangedCallback = function(name, oldValue, newValue) { |
317 var internal = privates(this).internal; | 252 var internal = privates(this).internal; |
318 if (!internal) | 253 if (!internal) |
319 return; | 254 return; |
320 internal.handleExtensionOptionsAttributeMutation(name, oldValue, newValue); | 255 internal.handleExtensionOptionsAttributeMutation(name, oldValue, newValue); |
321 }; | 256 }; |
322 | 257 |
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 | |
339 window.ExtensionOptions = | 258 window.ExtensionOptions = |
340 DocumentNatives.RegisterElement('extensionoptions', {prototype: proto}); | 259 DocumentNatives.RegisterElement('extensionoptions', {prototype: proto}); |
341 | 260 |
342 // Delete the callbacks so developers cannot call them and produce unexpected | 261 // Delete the callbacks so developers cannot call them and produce unexpected |
343 // behavior. | 262 // behavior. |
344 delete proto.createdCallback; | 263 delete proto.createdCallback; |
345 delete proto.attachedCallback; | 264 delete proto.attachedCallback; |
346 delete proto.detachedCallback; | 265 delete proto.detachedCallback; |
347 delete proto.attributeChangedCallback; | 266 delete proto.attributeChangedCallback; |
348 } | 267 } |
349 | 268 |
350 var useCapture = true; | 269 var useCapture = true; |
351 window.addEventListener('readystatechange', function listener(event) { | 270 window.addEventListener('readystatechange', function listener(event) { |
352 if (document.readyState == 'loading') | 271 if (document.readyState == 'loading') |
353 return; | 272 return; |
354 | 273 |
355 registerBrowserPluginElement(); | 274 registerBrowserPluginElement(); |
356 registerExtensionOptionsElement(); | 275 registerExtensionOptionsElement(); |
357 window.removeEventListener(event.type, listener, useCapture); | 276 window.removeEventListener(event.type, listener, useCapture); |
358 }, useCapture); | 277 }, useCapture); |
OLD | NEW |