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'); |
| 12 |
| 13 // Mapping of the autosize attribute names to default values |
| 14 var AUTO_SIZE_ATTRIBUTES = { |
| 15 'autosize': 'on', |
| 16 'maxheight': 600, |
| 17 'maxwidth': 800, |
| 18 'minheight': 32, |
| 19 'minwidth': 80 |
| 20 }; |
11 | 21 |
12 function ExtensionOptionsInternal(extensionoptionsNode) { | 22 function ExtensionOptionsInternal(extensionoptionsNode) { |
13 privates(extensionoptionsNode).internal = this; | 23 privates(extensionoptionsNode).internal = this; |
14 this.extensionoptionsNode = extensionoptionsNode; | 24 this.extensionoptionsNode = extensionoptionsNode; |
15 this.viewInstanceId = IdGenerator.GetNextId(); | 25 this.viewInstanceId = IdGenerator.GetNextId(); |
16 | 26 |
17 // on* Event handlers. | 27 // on* Event handlers. |
18 this.eventHandlers = {}; | 28 this.eventHandlers = {}; |
19 new ExtensionOptionsEvents(this, this.viewInstanceId); | 29 new ExtensionOptionsEvents(this, this.viewInstanceId); |
20 | 30 |
21 this.setupNodeProperties(); | 31 this.setupNodeProperties(); |
22 | 32 |
23 if (this.parseExtensionAttribute()) | 33 if (this.parseExtensionAttribute()) |
24 this.init(); | 34 this.init(); |
25 }; | 35 }; |
26 | 36 |
27 ExtensionOptionsInternal.prototype.attachWindow = function(instanceId) { | 37 ExtensionOptionsInternal.prototype.attachWindow = function(instanceId) { |
28 this.instanceId = instanceId; | 38 this.instanceId = instanceId; |
29 var params = { | 39 var params = { |
| 40 'autosize': this.autosize, |
30 'instanceId': this.viewInstanceId, | 41 'instanceId': this.viewInstanceId, |
| 42 'maxheight': parseInt(this.maxheight || 0), |
| 43 'maxwidth': parseInt(this.maxwidth || 0), |
| 44 'minheight': parseInt(this.minheight || 0), |
| 45 'minwidth': parseInt(this.minwidth || 0) |
31 } | 46 } |
32 return this.browserPluginNode['-internal-attach'](instanceId, params); | 47 return this.browserPluginNode['-internal-attach'](instanceId, params); |
33 }; | 48 }; |
34 | 49 |
35 ExtensionOptionsInternal.prototype.createBrowserPluginNode = function() { | 50 ExtensionOptionsInternal.prototype.createBrowserPluginNode = function() { |
36 var browserPluginNode = new ExtensionOptionsInternal.BrowserPlugin(); | 51 var browserPluginNode = new ExtensionOptionsInternal.BrowserPlugin(); |
37 privates(browserPluginNode).internal = this; | 52 privates(browserPluginNode).internal = this; |
38 return browserPluginNode; | 53 return browserPluginNode; |
39 }; | 54 }; |
40 | 55 |
41 ExtensionOptionsInternal.prototype.createGuest = function() { | 56 ExtensionOptionsInternal.prototype.createGuest = function() { |
42 var params = { | 57 var params = { |
43 'extensionId': this.extensionId, | 58 'extensionId': this.extensionId, |
44 }; | 59 }; |
45 var self = this; | |
46 GuestViewInternal.createGuest( | 60 GuestViewInternal.createGuest( |
47 'extensionoptions', | 61 'extensionoptions', |
48 params, | 62 params, |
49 function(instanceId) { | 63 function(instanceId) { |
50 if (instanceId == 0) { | 64 if (instanceId == 0) { |
51 self.initCalled = false; | 65 this.initCalled = false; |
52 } else { | 66 } else { |
53 self.attachWindow(instanceId); | 67 this.attachWindow(instanceId); |
| 68 GuestViewInternal.setAutoSize(this.instanceId, { |
| 69 'enableAutoSize': |
| 70 this.extensionoptionsNode.hasAttribute('autosize'), |
| 71 'min': { |
| 72 'width': parseInt(this.minwidth || 0), |
| 73 'height': parseInt(this.minheight || 0) |
| 74 }, |
| 75 'max': { |
| 76 'width': parseInt(this.maxwidth || 0), |
| 77 'height': parseInt(this.maxheight || 0) |
| 78 } |
| 79 }); |
54 } | 80 } |
55 }); | 81 }.bind(this)); |
56 }; | 82 }; |
57 | 83 |
58 ExtensionOptionsInternal.prototype.dispatchEvent = | 84 ExtensionOptionsInternal.prototype.dispatchEvent = |
59 function(extensionOptionsEvent) { | 85 function(extensionOptionsEvent) { |
60 return this.extensionoptionsNode.dispatchEvent(extensionOptionsEvent); | 86 return this.extensionoptionsNode.dispatchEvent(extensionOptionsEvent); |
61 }; | 87 }; |
62 | 88 |
63 ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation = | 89 ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation = |
64 function(name, oldValue, newValue) { | 90 function(name, oldValue, newValue) { |
65 if (name != 'extension') | |
66 return; | |
67 // We treat null attribute (attribute removed) and the empty string as | 91 // We treat null attribute (attribute removed) and the empty string as |
68 // one case. | 92 // one case. |
69 oldValue = oldValue || ''; | 93 oldValue = oldValue || ''; |
70 newValue = newValue || ''; | 94 newValue = newValue || ''; |
71 | 95 |
72 if (oldValue === newValue) | 96 if (oldValue === newValue) |
73 return; | 97 return; |
74 this.extensionId = newValue; | |
75 | 98 |
76 // Create new guest view if one hasn't been created for this element. | 99 if (name == 'extension') { |
77 if (!this.instanceId && this.parseExtensionAttribute()) | 100 this.extensionId = newValue; |
78 this.init(); | 101 // Create new guest view if one hasn't been created for this element. |
79 // TODO(ericzeng): Implement navigation to another guest view if we want | 102 if (!this.instanceId && this.parseExtensionAttribute()) |
80 // that functionality. | 103 this.init(); |
| 104 // TODO(ericzeng): Implement navigation to another guest view if we want |
| 105 // that functionality. |
| 106 } else if (AUTO_SIZE_ATTRIBUTES.hasOwnProperty(name) > -1) { |
| 107 this[name] = newValue; |
| 108 this.resetSizeConstraintsIfInvalid(); |
| 109 |
| 110 if (!this.instanceId) |
| 111 return; |
| 112 |
| 113 GuestViewInternal.setAutoSize(this.instanceId, { |
| 114 'enableAutoSize': this.extensionoptionsNode.hasAttribute('autosize'), |
| 115 'min': { |
| 116 'width': parseInt(this.minwidth || 0), |
| 117 'height': parseInt(this.minheight || 0) |
| 118 }, |
| 119 'max': { |
| 120 'width': parseInt(this.maxwidth || 0), |
| 121 'height': parseInt(this.maxheight || 0) |
| 122 } |
| 123 }); |
| 124 } |
81 }; | 125 }; |
82 | 126 |
83 ExtensionOptionsInternal.prototype.init = function() { | 127 ExtensionOptionsInternal.prototype.init = function() { |
84 if (this.initCalled) | 128 if (this.initCalled) |
85 return; | 129 return; |
86 | 130 |
87 this.initCalled = true; | 131 this.initCalled = true; |
88 this.browserPluginNode = this.createBrowserPluginNode(); | 132 this.browserPluginNode = this.createBrowserPluginNode(); |
89 var shadowRoot = this.extensionoptionsNode.createShadowRoot(); | 133 var shadowRoot = this.extensionoptionsNode.createShadowRoot(); |
90 shadowRoot.appendChild(this.browserPluginNode); | 134 shadowRoot.appendChild(this.browserPluginNode); |
91 this.createGuest(); | 135 this.createGuest(); |
92 }; | 136 }; |
93 | 137 |
| 138 ExtensionOptionsInternal.prototype.onSizeChanged = function(width, height) { |
| 139 this.browserPluginNode.style.width = width + 'px'; |
| 140 this.browserPluginNode.style.height = height + 'px'; |
| 141 }; |
| 142 |
94 ExtensionOptionsInternal.prototype.parseExtensionAttribute = function() { | 143 ExtensionOptionsInternal.prototype.parseExtensionAttribute = function() { |
95 if (this.extensionoptionsNode.hasAttribute('extension')) { | 144 if (this.extensionoptionsNode.hasAttribute('extension')) { |
96 var extensionId = this.extensionoptionsNode.getAttribute('extension'); | 145 var extensionId = this.extensionoptionsNode.getAttribute('extension'); |
97 // Only allow extensions to embed their own options page (if it has one). | 146 // Only allow extensions to embed their own options page (if it has one). |
98 if (chrome.runtime.id == extensionId && | 147 if (chrome.runtime.id == extensionId && |
99 chrome.runtime.getManifest().hasOwnProperty('options_page')) { | 148 chrome.runtime.getManifest().hasOwnProperty('options_page')) { |
100 this.extensionId = extensionId; | 149 this.extensionId = extensionId; |
101 return true; | 150 return true; |
102 } | 151 } |
103 } | 152 } |
(...skipping 16 matching lines...) Expand all Loading... |
120 eventName, self.eventHandlers[propertyName]); | 169 eventName, self.eventHandlers[propertyName]); |
121 self.eventHandlers[propertyName] = value; | 170 self.eventHandlers[propertyName] = value; |
122 if (value) | 171 if (value) |
123 extensionoptionsNode.addEventListener(eventName, value); | 172 extensionoptionsNode.addEventListener(eventName, value); |
124 }, | 173 }, |
125 enumerable: true | 174 enumerable: true |
126 }); | 175 }); |
127 }; | 176 }; |
128 | 177 |
129 ExtensionOptionsInternal.prototype.setupNodeProperties = function() { | 178 ExtensionOptionsInternal.prototype.setupNodeProperties = function() { |
130 var self = this; | 179 utils.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { |
131 this.extensionId = this.extensionoptionsNode.getAttribute('extension'); | 180 // Get the size constraints from the <extensionoptions> tag, or use the |
| 181 // defaults if not specified |
| 182 if (this.extensionoptionsNode.hasAttribute(attributeName)) { |
| 183 this[attributeName] = |
| 184 this.extensionoptionsNode.getAttribute(attributeName); |
| 185 } else { |
| 186 this[attributeName] = AUTO_SIZE_ATTRIBUTES[attributeName]; |
| 187 } |
| 188 |
| 189 Object.defineProperty(this.extensionoptionsNode, attributeName, { |
| 190 get: function() { |
| 191 return this[attributeName]; |
| 192 }.bind(this), |
| 193 set: function(value) { |
| 194 this.extensionoptionsNode.setAttribute(attributeName, value); |
| 195 }.bind(this), |
| 196 enumerable: true |
| 197 }); |
| 198 }, this); |
| 199 |
| 200 this.resetSizeConstraintsIfInvalid(); |
| 201 |
132 Object.defineProperty(this.extensionoptionsNode, 'extension', { | 202 Object.defineProperty(this.extensionoptionsNode, 'extension', { |
133 get: function() { | 203 get: function() { |
134 return self.extensionId; | 204 return this.extensionId; |
135 }, | 205 }.bind(this), |
136 set: function(value) { | 206 set: function(value) { |
137 self.extensionoptionsNode.setAttribute('extension', value); | 207 this.extensionoptionsNode.setAttribute('extension', value); |
138 }, | 208 }.bind(this), |
139 enumerable: true | 209 enumerable: true |
140 }); | 210 }); |
141 }; | 211 }; |
142 | 212 |
| 213 ExtensionOptionsInternal.prototype.resetSizeConstraintsIfInvalid = function () { |
| 214 if (this.minheight > this.maxheight || this.minheight < 0) { |
| 215 this.minheight = AUTO_SIZE_ATTRIBUTES.minheight; |
| 216 this.maxheight = AUTO_SIZE_ATTRIBUTES.maxheight; |
| 217 } |
| 218 if (this.minwidth > this.maxwidth || this.minwidth < 0) { |
| 219 this.minwidth = AUTO_SIZE_ATTRIBUTES.minwidth; |
| 220 this.maxwidth = AUTO_SIZE_ATTRIBUTES.maxwidth; |
| 221 } |
| 222 } |
| 223 |
143 function registerBrowserPluginElement() { | 224 function registerBrowserPluginElement() { |
144 var proto = Object.create(HTMLObjectElement.prototype); | 225 var proto = Object.create(HTMLObjectElement.prototype); |
145 | 226 |
146 proto.createdCallback = function() { | 227 proto.createdCallback = function() { |
147 this.setAttribute('type', 'application/browser-plugin'); | 228 this.setAttribute('type', 'application/browser-plugin'); |
148 this.style.width = '100%'; | 229 this.style.width = '100%'; |
149 this.style.height = '100%'; | 230 this.style.height = '100%'; |
150 }; | 231 }; |
151 | 232 |
152 proto.attachedCallback = function() { | 233 proto.attachedCallback = function() { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 | 271 |
191 var useCapture = true; | 272 var useCapture = true; |
192 window.addEventListener('readystatechange', function listener(event) { | 273 window.addEventListener('readystatechange', function listener(event) { |
193 if (document.readyState == 'loading') | 274 if (document.readyState == 'loading') |
194 return; | 275 return; |
195 | 276 |
196 registerBrowserPluginElement(); | 277 registerBrowserPluginElement(); |
197 registerExtensionOptionsElement(); | 278 registerExtensionOptionsElement(); |
198 window.removeEventListener(event.type, listener, useCapture); | 279 window.removeEventListener(event.type, listener, useCapture); |
199 }, useCapture); | 280 }, useCapture); |
OLD | NEW |