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

Side by Side Diff: chrome/browser/resources/extensions_ui.js

Issue 7976023: Remove the old chrome://extensions page, since the URL now redirects to the new Settings page.BUG... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 3 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * This variable structure is here to document the structure that the template
7 * expects to correctly populate the page.
8 */
9 var extensionDataFormat = {
10 'developerMode': false,
11 'extensions': [
12 {
13 'id': '0000000000000000000000000000000000000000',
14 'name': 'Google Chrome',
15 'description': 'Extension long format description',
16 'version': '1.0.231',
17 'mayDisable': 'true',
18 'enabled': 'true',
19 'terminated': 'false',
20 'enabledIncognito': 'false',
21 'wantsFileAccess': 'false',
22 'allowFileAccess': 'false',
23 'allow_reload': true,
24 'is_hosted_app': false,
25 'order': 1,
26 'options_url': 'options.html',
27 'enable_show_button': false,
28 'icon': 'relative-path-to-icon.png',
29 // TODO(aa): It would be nice to also render what type of view each one
30 // is, like 'toolstrip', 'background', etc. Eventually, if we can also
31 // debug and inspect content scripts, maybe we don't need to list the
32 // components, just the views.
33 'views': [
34 {
35 'path': 'toolstrip.html',
36 'renderViewId': 1,
37 'renderProcessId': 1,
38 'incognito': false
39 },
40 {
41 'path': 'background.html',
42 'renderViewId': 2,
43 'renderProcessId': 1,
44 'incognito': false
45 }
46 ]
47 },
48 {
49 'id': '0000000000000000000000000000000000000001',
50 'name': 'RSS Subscriber',
51 'description': 'Extension long format description',
52 'version': '1.0.231',
53 'mayDisable': 'true',
54 'enabled': 'true',
55 'terminated': 'false',
56 'enabledIncognito': 'false',
57 'wantsFileAccess': 'false',
58 'allowFileAccess': 'false',
59 'allow_reload': false,
60 'is_hosted_app': false,
61 'order': 2,
62 'icon': '',
63 "hasPopupAction": false
64 }
65 ]
66 };
67
68 // Keeps track of whether the developer mode subsection has been made visible
69 // (expanded) or not.
70 var devModeExpanded = false;
71
72 /**
73 * Toggles the devModeExpanded, and notifies the c++ WebUI to toggle the
74 * extensions.ui.developer_mode which saved in the preferences.
75 */
76 function toggleDevModeExpanded() {
77 devModeExpanded = !devModeExpanded;
78 chrome.send('toggleDeveloperMode', []);
79 }
80
81 /**
82 * Takes the |extensionsData| input argument which represents data about the
83 * currently installed/running extensions and populates the html jstemplate with
84 * that data. It expects an object structure like the above.
85 * @param {Object} extensionsData Detailed info about installed extensions
86 */
87 function renderTemplate(extensionsData) {
88 // Sort by order specified in the data or (if equal) then sort by
89 // extension name.
90 var locale = new v8Locale(window.navigator.language);
91 var coll = locale.createCollator();
92 extensionsData.extensions.sort(function(a, b) {
93 if (a.order == b.order) {
94 return coll.compare(a.name, b.name);
95 }
96 return a.order < b.order ? -1 : 1;
97 });
98
99 // This is the javascript code that processes the template:
100 var input = new JsEvalContext(extensionsData);
101 var output = $('extensionTemplate');
102 jstProcess(input, output);
103
104 // Hook up the handlers now that the template is processed.
105 $('load-extension').addEventListener('click', loadExtension);
106 $('show-pack-dialog').addEventListener('click', showPackDialog);
107 $('auto-update').addEventListener('click', autoUpdate);
108
109 addHandlerByClass('developer-mode-image', 'click', toggleDeveloperMode);
110 addHandlerByClass('developer-mode-link', 'click', toggleDeveloperMode);
111 addHandlerByClass('extension-path', 'click', selectExtensionPath);
112 addHandlerByClass('private-key-path', 'click', selectPrivateKeyPath);
113 addHandlerByClass('pack-extension', 'click', packExtension);
114 addHandlerByClass('hide-pack-dialog', 'click', hidePackDialog);
115 addHandlerByClass('options-url', 'click', handleOptions);
116 addHandlerByClass('reload-extension', 'click', handleReloadExtension);
117 addHandlerByClass('disable-extension', 'click', handleDisableExtension);
118 addHandlerByClass('enable-extension', 'click', handleEnableExtension);
119 addHandlerByClass('uninstall-extension', 'click', handleUninstallExtension);
120 addHandlerByClass('show-button', 'click', handleShowButton);
121 addHandlerByClass('inspect-message', 'click', handleInspectMessage);
122 addHandlerByClass('toggle-incognito', 'change',
123 handleToggleExtensionIncognito);
124 addHandlerByClass('file-access', 'change',
125 handleToggleAllowFileAccess);
126 }
127
128 /**
129 * Asks the C++ ExtensionDOMHandler to get details about the installed
130 * extensions and return detailed data about the configuration. The
131 * ExtensionDOMHandler should reply to returnExtensionsData() (below).
132 */
133 function requestExtensionsData() {
134 chrome.send('requestExtensionsData', []);
135 }
136
137 // Used for observing function of the backend datasource for this page by
138 // tests.
139 var webui_responded_ = false;
140
141 // Used to only do some work the first time we render.
142 var rendered_once_ = false;
143
144 /**
145 * Called by the web_ui_ to re-populate the page with data representing
146 * the current state of installed extensions.
147 */
148 function returnExtensionsData(extensionsData){
149 webui_responded_ = true;
150 devModeExpanded = extensionsData.developerMode;
151
152 var bodyContainer = $('body-container');
153 var body = document.body;
154
155 // Set all page content to be visible so we can measure heights.
156 bodyContainer.style.visibility = 'hidden';
157 body.className = '';
158 var slidables = document.getElementsByClassName('showInDevMode');
159 for (var i = 0; i < slidables.length; i++)
160 slidables[i].style.height = 'auto';
161
162 renderTemplate(extensionsData);
163
164 // Explicitly set the height for each element that wants to be 'slid' in and
165 // out when the devModeExpanded is toggled.
166 var slidables = document.getElementsByClassName('showInDevMode');
167 for (var i = 0; i < slidables.length; i++)
168 slidables[i].style.height = slidables[i].offsetHeight + 'px';
169
170 // Hide all the incognito warnings that are attached to the wrong extension
171 // ID, which can happen when an extension is added or removed.
172 var warnings = document.getElementsByClassName('incognitoWarning');
173 for (var i = 0; i < warnings.length; i++) {
174 var extension = warnings[i];
175 while (extension.className != "extension")
176 extension = extension.parentNode;
177
178 if (extension.extensionId != warnings[i].attachedExtensionId) {
179 warnings[i].style.display = "none";
180 warnings[i].style.opacity = "0";
181 }
182 }
183
184 // Reset visibility of page based on the current dev mode.
185 $('collapse').style.display = devModeExpanded ? 'inline' : 'none';
186 $('expand').style.display = devModeExpanded ? 'none' : 'inline';
187 bodyContainer.style.visibility = 'visible';
188 body.className = devModeExpanded ?
189 'showDevModeInitial' : 'hideDevModeInitial';
190
191 if (rendered_once_)
192 return;
193
194 // Blech, JSTemplate always inserts the strings as text, which is usually a
195 // feature, but in this case it contains HTML that we want to be rendered.
196 var elm = $('try-gallery');
197 if (elm)
198 elm.innerHTML = elm.textContent;
199
200 elm = $('get-moar-extensions');
201 if (elm)
202 elm.innerHTML = elm.textContent;
203
204 rendered_once_ = true;
205 }
206
207 /**
208 * Tell the C++ ExtensionDOMHandler to inspect the page detailed in |viewData|.
209 */
210 function handleInspectMessage(event) {
211 // TODO(aa): This is ghetto, but WebUIBindings doesn't support sending
212 // anything other than arrays of strings, and this is all going to get
213 // replaced with V8 extensions soon anyway.
214 chrome.send('inspect', [
215 String(this.extensionView.renderProcessId),
216 String(this.extensionView.renderViewId)
217 ]);
218 event.preventDefault();
219 }
220
221 /**
222 * Handles a 'reload' link getting clicked.
223 */
224 function handleReloadExtension(event) {
225 // Tell the C++ ExtensionDOMHandler to reload the extension.
226 chrome.send('reload', [this.extensionId]);
227 event.preventDefault();
228 }
229
230 /**
231 * Handles a 'disable' link getting clicked.
232 */
233 function handleDisableExtension(event) {
234 sendEnableExtension(this, false);
235 event.preventDefault();
236 }
237
238 /**
239 * Handles an 'enable' link getting clicked.
240 */
241 function handleEnableExtension(event) {
242 sendEnableExtension(this, true);
243 event.preventDefault();
244 }
245
246 /**
247 * Peforms the actual work to enable or disable an extension.
248 */
249 function sendEnableExtension(node, enable) {
250 // Tell the C++ ExtensionDOMHandler to reload the extension.
251 chrome.send('enable', [node.extensionId, String(enable)]);
252 requestExtensionsData();
253 }
254
255 /**
256 * Handles the 'enableIncognito' checkbox getting changed.
257 */
258 function handleToggleExtensionIncognito(event) {
259 var warning = this;
260
261 while (warning.className != "extension")
262 warning = warning.parentNode;
263
264 warning = warning.getElementsByClassName("incognitoWarning")[0];
265 if (!this.checked) {
266 warning.style.display = "none";
267 warning.style.opacity = "0";
268 } else {
269 warning.attachedExtensionId = this.extensionId;
270 warning.style.display = "block";
271
272 // Must set the opacity later. Otherwise, the fact that the display is
273 // changing causes the animation to not happen.
274 window.setTimeout(function() {
275 warning.style.opacity = "1";
276 }, 0);
277 }
278
279 chrome.send('enableIncognito', [this.extensionId, String(this.checked)]);
280 event.preventDefault();
281 }
282
283 /**
284 * Handles the 'allowFileAccess' checkbox getting changed.
285 */
286 function handleToggleAllowFileAccess(event) {
287 chrome.send('allowFileAccess', [this.extensionId, String(this.checked)]);
288 event.preventDefault();
289 }
290
291 /**
292 * Handles an 'uninstall' link getting clicked.
293 */
294 function handleUninstallExtension(event) {
295 chrome.send('uninstall', [this.extensionId]);
296 event.preventDefault();
297 }
298
299 /**
300 * Handles an 'options' link getting clicked.
301 */
302 function handleOptions(event) {
303 chrome.send('options', [this.extensionId]);
304 event.preventDefault();
305 }
306
307 /**
308 * Handles a 'show button' link getting clicked.
309 */
310 function handleShowButton(event) {
311 chrome.send('showButton', [this.extensionId]);
312 event.preventDefault();
313 }
314
315 /**
316 * Utility function which asks the C++ to show a platform-specific file select
317 * dialog, and fire |callback| with the |filePath| that resulted. |selectType|
318 * can be either 'file' or 'folder'. |operation| can be 'load', 'packRoot',
319 * or 'pem' which are signals to the C++ to do some operation-specific
320 * configuration.
321 */
322 function showFileDialog(selectType, operation, callback) {
323 handleFilePathSelected = function(filePath) {
324 callback(filePath);
325 handleFilePathSelected = function() {};
326 };
327
328 chrome.send('selectFilePath', [selectType, operation]);
329 }
330
331 /**
332 * Handles the "Load extension..." button being pressed.
333 */
334 function loadExtension() {
335 showFileDialog('folder', 'load', function(filePath) {
336 chrome.send('load', [String(filePath)]);
337 });
338 }
339
340 /**
341 * Handles the "Pack extension..." button being pressed.
342 */
343 function packExtension() {
344 var extensionPath = $('extensionPathText').value;
345 var privateKeyPath = $('privateKeyPath').value;
346 chrome.send('pack', [extensionPath, privateKeyPath]);
347 }
348
349 /**
350 * Shows to modal HTML pack dialog.
351 */
352 function showPackDialog() {
353 $('dialogBackground').style.display = '-webkit-box';
354 }
355
356 /**
357 * Hides the pack dialog.
358 */
359 function hidePackDialog() {
360 $('dialogBackground').style.display = 'none'
361 }
362
363 /*
364 * Toggles visibility of the developer mode.
365 */
366 function toggleDeveloperMode() {
367 toggleDevModeExpanded();
368
369 $('collapse').style.display = devModeExpanded ? 'inline' : 'none';
370 $('expand').style.display = devModeExpanded ? 'none' : 'inline';
371
372 document.body.className =
373 devModeExpanded ? 'showDevMode' : 'hideDevMode';
374 }
375
376 /**
377 * Pop up a select dialog to capture the extension path.
378 */
379 function selectExtensionPath() {
380 showFileDialog('folder', 'packRoot', function(filePath) {
381 $('extensionPathText').value = filePath;
382 });
383 }
384
385 /**
386 * Pop up a select dialog to capture the private key path.
387 */
388 function selectPrivateKeyPath() {
389 showFileDialog('file', 'pem', function(filePath) {
390 $('privateKeyPath').value = filePath;
391 });
392 }
393
394 /**
395 * Handles the "Update extensions now" button being pressed.
396 */
397 function autoUpdate() {
398 chrome.send('autoupdate', []);
399 }
400
401 /**
402 * Convenience routine to hook up nodes duplicated by jstemplate to
403 * event handlers using the class attribute to identify the set of nodes.
404 */
405 function addHandlerByClass(name, event, handler) {
406 var elements = document.getElementsByClassName(name);
407 for (var i = 0; i < elements.length; ++i) {
408 elements[i].addEventListener(event, handler);
409 }
410 }
411
412 document.addEventListener('DOMContentLoaded', requestExtensionsData);
OLDNEW
« no previous file with comments | « chrome/browser/resources/extensions_ui.html ('k') | chrome/browser/resources/options/extension_list.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698