OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <include src="extension_error.js"> | 5 <include src="extension_error.js"> |
6 | 6 |
7 cr.define('options', function() { | 7 cr.define('options', function() { |
8 'use strict'; | 8 'use strict'; |
9 | 9 |
10 /** | 10 /** |
(...skipping 15 matching lines...) Expand all Loading... |
26 * @type {Object.<string, string>} A map from extension id to last reloaded | 26 * @type {Object.<string, string>} A map from extension id to last reloaded |
27 * timestamp. The timestamp is recorded when the user click the 'Reload' | 27 * timestamp. The timestamp is recorded when the user click the 'Reload' |
28 * link. It is used to refresh the icon of an unpacked extension. | 28 * link. It is used to refresh the icon of an unpacked extension. |
29 * This persists between calls to decorate. | 29 * This persists between calls to decorate. |
30 */ | 30 */ |
31 var extensionReloadedTimestamp = {}; | 31 var extensionReloadedTimestamp = {}; |
32 | 32 |
33 ExtensionsList.prototype = { | 33 ExtensionsList.prototype = { |
34 __proto__: HTMLDivElement.prototype, | 34 __proto__: HTMLDivElement.prototype, |
35 | 35 |
| 36 /** |
| 37 * Indicates whether an embedded options page that was navigated to through |
| 38 * the '?options=' URL query has been shown to the user. This is necessary |
| 39 * to prevent showExtensionNodes_ from opening the options more than once. |
| 40 * @type {boolean} |
| 41 * @private |
| 42 */ |
| 43 optionsShown_: false, |
| 44 |
36 /** @override */ | 45 /** @override */ |
37 decorate: function() { | 46 decorate: function() { |
38 this.textContent = ''; | 47 this.textContent = ''; |
39 | 48 |
40 this.showExtensionNodes_(); | 49 this.showExtensionNodes_(); |
41 }, | 50 }, |
42 | 51 |
43 getIdQueryParam_: function() { | 52 getIdQueryParam_: function() { |
44 return parseQueryParams(document.location)['id']; | 53 return parseQueryParams(document.location)['id']; |
45 }, | 54 }, |
46 | 55 |
| 56 getOptionsQueryParam_: function() { |
| 57 return parseQueryParams(document.location)['options']; |
| 58 }, |
| 59 |
47 /** | 60 /** |
48 * Creates all extension items from scratch. | 61 * Creates all extension items from scratch. |
49 * @private | 62 * @private |
50 */ | 63 */ |
51 showExtensionNodes_: function() { | 64 showExtensionNodes_: function() { |
52 // Iterate over the extension data and add each item to the list. | 65 // Iterate over the extension data and add each item to the list. |
53 this.data_.extensions.forEach(this.createNode_, this); | 66 this.data_.extensions.forEach(this.createNode_, this); |
54 | 67 |
55 var idToHighlight = this.getIdQueryParam_(); | 68 var idToHighlight = this.getIdQueryParam_(); |
56 if (idToHighlight && $(idToHighlight)) { | 69 if (idToHighlight && $(idToHighlight)) |
57 // Scroll offset should be calculated slightly higher than the actual | 70 this.scrollToNode_(idToHighlight); |
58 // offset of the element being scrolled to, so that it ends up not all | 71 |
59 // the way at the top. That way it is clear that there are more elements | 72 var idToOpenOptions = this.getOptionsQueryParam_(); |
60 // above the element being scrolled to. | 73 if (idToOpenOptions && $(idToOpenOptions)) |
61 var scrollFudge = 1.2; | 74 this.showEmbeddedExtensionOptions_(idToOpenOptions, true); |
62 var scrollTop = $(idToHighlight).offsetTop - scrollFudge * | |
63 $(idToHighlight).clientHeight; | |
64 setScrollTopForDocument(document, scrollTop); | |
65 } | |
66 | 75 |
67 if (this.data_.extensions.length == 0) | 76 if (this.data_.extensions.length == 0) |
68 this.classList.add('empty-extension-list'); | 77 this.classList.add('empty-extension-list'); |
69 else | 78 else |
70 this.classList.remove('empty-extension-list'); | 79 this.classList.remove('empty-extension-list'); |
71 }, | 80 }, |
72 | 81 |
73 /** | 82 /** |
| 83 * Scrolls the page down to the extension node with the given id. |
| 84 * @param {string} extensionId The id of the extension to scroll to. |
| 85 * @private |
| 86 */ |
| 87 scrollToNode_: function(extensionId) { |
| 88 // Scroll offset should be calculated slightly higher than the actual |
| 89 // offset of the element being scrolled to, so that it ends up not all |
| 90 // the way at the top. That way it is clear that there are more elements |
| 91 // above the element being scrolled to. |
| 92 var scrollFudge = 1.2; |
| 93 var scrollTop = $(extensionId).offsetTop - scrollFudge * |
| 94 $(extensionId).clientHeight; |
| 95 setScrollTopForDocument(document, scrollTop); |
| 96 }, |
| 97 |
| 98 /** |
74 * Synthesizes and initializes an HTML element for the extension metadata | 99 * Synthesizes and initializes an HTML element for the extension metadata |
75 * given in |extension|. | 100 * given in |extension|. |
76 * @param {Object} extension A dictionary of extension metadata. | 101 * @param {Object} extension A dictionary of extension metadata. |
77 * @private | 102 * @private |
78 */ | 103 */ |
79 createNode_: function(extension) { | 104 createNode_: function(extension) { |
80 var template = $('template-collection').querySelector( | 105 var template = $('template-collection').querySelector( |
81 '.extension-list-item-wrapper'); | 106 '.extension-list-item-wrapper'); |
82 var node = template.cloneNode(true); | 107 var node = template.cloneNode(true); |
83 node.id = extension.id; | 108 node.id = extension.id; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 }); | 212 }); |
188 fileAccess.querySelector('input').checked = extension.allowFileAccess; | 213 fileAccess.querySelector('input').checked = extension.allowFileAccess; |
189 fileAccess.hidden = false; | 214 fileAccess.hidden = false; |
190 } | 215 } |
191 | 216 |
192 // The 'Options' link. | 217 // The 'Options' link. |
193 if (extension.enabled && extension.optionsUrl) { | 218 if (extension.enabled && extension.optionsUrl) { |
194 var options = node.querySelector('.options-link'); | 219 var options = node.querySelector('.options-link'); |
195 options.addEventListener('click', function(e) { | 220 options.addEventListener('click', function(e) { |
196 if (this.data_.enableEmbeddedExtensionOptions) { | 221 if (this.data_.enableEmbeddedExtensionOptions) { |
197 extensions.ExtensionOptionsOverlay.getInstance(). | 222 this.showEmbeddedExtensionOptions_(extension.id, false); |
198 setExtensionAndShowOverlay(extension.id, | |
199 extension.name, | |
200 extension.icon); | |
201 } else { | 223 } else { |
202 chrome.send('extensionSettingsOptions', [extension.id]); | 224 chrome.send('extensionSettingsOptions', [extension.id]); |
203 } | 225 } |
204 e.preventDefault(); | 226 e.preventDefault(); |
205 }.bind(this)); | 227 }.bind(this)); |
206 options.hidden = false; | 228 options.hidden = false; |
207 } | 229 } |
208 | 230 |
209 // The 'Permissions' link. | 231 // The 'Permissions' link. |
210 var permissions = node.querySelector('.permissions-link'); | 232 var permissions = node.querySelector('.permissions-link'); |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 if (location.hash.substr(1) == extension.id) { | 432 if (location.hash.substr(1) == extension.id) { |
411 // Scroll beneath the fixed header so that the extension is not | 433 // Scroll beneath the fixed header so that the extension is not |
412 // obscured. | 434 // obscured. |
413 var topScroll = node.offsetTop - $('page-header').offsetHeight; | 435 var topScroll = node.offsetTop - $('page-header').offsetHeight; |
414 var pad = parseInt(getComputedStyle(node, null).marginTop, 10); | 436 var pad = parseInt(getComputedStyle(node, null).marginTop, 10); |
415 if (!isNaN(pad)) | 437 if (!isNaN(pad)) |
416 topScroll -= pad / 2; | 438 topScroll -= pad / 2; |
417 setScrollTopForDocument(document, topScroll); | 439 setScrollTopForDocument(document, topScroll); |
418 } | 440 } |
419 }, | 441 }, |
| 442 |
| 443 /** |
| 444 * Opens the extension options overlay for the extension with the given id. |
| 445 * @param {string} extensionId The id of extension whose options page should |
| 446 * be displayed. |
| 447 * @param {boolean} scroll Whether the page should scroll to the extension |
| 448 * @private |
| 449 */ |
| 450 showEmbeddedExtensionOptions_: function(extensionId, scroll) { |
| 451 if (this.optionsShown_) |
| 452 return; |
| 453 |
| 454 // Get the extension from the given id. |
| 455 var extension = this.data_.extensions.filter(function(extension) { |
| 456 return extension.id == extensionId; |
| 457 })[0]; |
| 458 |
| 459 if (!extension) |
| 460 return; |
| 461 |
| 462 if (scroll) |
| 463 this.scrollToNode_(extensionId); |
| 464 // Add the options query string. Corner case: the 'options' query string |
| 465 // will clobber the 'id' query string if the options link is clicked when |
| 466 // 'id' is in the URL, or if both query strings are in the URL. |
| 467 uber.replaceState({}, '?options=' + extensionId); |
| 468 |
| 469 extensions.ExtensionOptionsOverlay.getInstance(). |
| 470 setExtensionAndShowOverlay(extensionId, |
| 471 extension.name, |
| 472 extension.icon); |
| 473 |
| 474 this.optionsShown_ = true; |
| 475 $('overlay').addEventListener('cancelOverlay', function() { |
| 476 this.optionsShown_ = false; |
| 477 }.bind(this)); |
| 478 }, |
420 }; | 479 }; |
421 | 480 |
422 return { | 481 return { |
423 ExtensionsList: ExtensionsList | 482 ExtensionsList: ExtensionsList |
424 }; | 483 }; |
425 }); | 484 }); |
OLD | NEW |