Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: chrome/renderer/resources/extensions/extension_options.js

Issue 431503002: Implement autosizing for <extensionoptions> (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add tests and ensure that size constraints make sense Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698