Chromium Code Reviews| 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 /////////////////////////////////////////////////////////////////////////////// | 7 /////////////////////////////////////////////////////////////////////////////// |
| 8 // ExtensionFocusRow: | 8 // ExtensionFocusRow: |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 'use strict'; | 139 'use strict'; |
| 140 | 140 |
| 141 /** | 141 /** |
| 142 * Creates a new list of extensions. | 142 * Creates a new list of extensions. |
| 143 * @constructor | 143 * @constructor |
| 144 * @extends {HTMLDivElement} | 144 * @extends {HTMLDivElement} |
| 145 */ | 145 */ |
| 146 function ExtensionList() { | 146 function ExtensionList() { |
| 147 var div = document.createElement('div'); | 147 var div = document.createElement('div'); |
| 148 div.__proto__ = ExtensionList.prototype; | 148 div.__proto__ = ExtensionList.prototype; |
| 149 /** @private {!Array<ExtensionInfo>} */ | 149 div.initialize(); |
| 150 div.extensions_ = []; | |
| 151 return div; | 150 return div; |
| 152 } | 151 } |
| 153 | 152 |
| 154 /** | 153 /** |
| 155 * @type {Object<string, number>} A map from extension id to last reloaded | 154 * @type {Object<string, number>} A map from extension id to last reloaded |
| 156 * timestamp. The timestamp is recorded when the user click the 'Reload' | 155 * timestamp. The timestamp is recorded when the user click the 'Reload' |
| 157 * link. It is used to refresh the icon of an unpacked extension. | 156 * link. It is used to refresh the icon of an unpacked extension. |
| 158 * This persists between calls to decorate. | 157 * This persists between calls to decorate. |
| 159 */ | 158 */ |
| 160 var extensionReloadedTimestamp = {}; | 159 var extensionReloadedTimestamp = {}; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 */ | 198 */ |
| 200 incognitoAvailable_: false, | 199 incognitoAvailable_: false, |
| 201 | 200 |
| 202 /** | 201 /** |
| 203 * Whether or not the app info dialog is enabled. | 202 * Whether or not the app info dialog is enabled. |
| 204 * @private {boolean} | 203 * @private {boolean} |
| 205 */ | 204 */ |
| 206 enableAppInfoDialog_: false, | 205 enableAppInfoDialog_: false, |
| 207 | 206 |
| 208 /** | 207 /** |
| 208 * Initializes the list. | |
| 209 */ | |
| 210 initialize: function() { | |
| 211 /** @private {!Array<ExtensionInfo>} */ | |
| 212 this.extensions_ = []; | |
| 213 | |
| 214 /** @private {Promise} */ | |
| 215 this.extensionsUpdated_ = null; | |
|
Dan Beam
2015/04/06 23:53:12
1) why are you keeping a |this.extensionsUpdated_|
Dan Beam
2015/04/06 23:55:48
ok, figured out 1) (using in tests), but why 2)?
Devlin
2015/04/07 16:07:54
2 was because I thought it was best practice to in
| |
| 216 | |
| 217 chrome.developerPrivate.onItemStateChanged.addListener( | |
| 218 function(eventData) { | |
| 219 var EventType = chrome.developerPrivate.EventType; | |
| 220 switch (eventData.event_type) { | |
| 221 case EventType.VIEW_REGISTERED: | |
| 222 case EventType.VIEW_UNREGISTERED: | |
| 223 // For now, view notifications are handled through the WebUI. | |
| 224 // TODO(devlin): Transition these. | |
| 225 break; | |
| 226 case EventType.INSTALLED: | |
| 227 case EventType.LOADED: | |
| 228 case EventType.UNLOADED: | |
| 229 case EventType.ERROR_ADDED: | |
| 230 if (eventData.extensionInfo) | |
|
Dan Beam
2015/04/06 23:53:12
when will |eventData.extensionInfo| not exist?
Devlin
2015/04/07 16:07:54
In the case of it being uninstalled, for one. The
| |
| 231 this.updateExtension_(eventData.extensionInfo); | |
| 232 break; | |
| 233 case EventType.UNINSTALLED: | |
| 234 var childNode = $(eventData.item_id); | |
| 235 if (childNode) | |
|
Dan Beam
2015/04/06 23:53:12
when will childNode not exist?
Devlin
2015/04/07 16:07:54
In theory, never. Removed.
| |
| 236 childNode.parentNode.removeChild(childNode); | |
| 237 break; | |
| 238 default: | |
| 239 assertNotReached(); | |
| 240 } | |
| 241 }.bind(this)); | |
| 242 }, | |
| 243 | |
| 244 /** | |
| 209 * Updates the extensions on the page. | 245 * Updates the extensions on the page. |
| 210 * @param {boolean} incognitoAvailable Whether or not incognito is allowed. | 246 * @param {boolean} incognitoAvailable Whether or not incognito is allowed. |
| 211 * @param {boolean} enableAppInfoDialog Whether or not the app info dialog | 247 * @param {boolean} enableAppInfoDialog Whether or not the app info dialog |
| 212 * is enabled. | 248 * is enabled. |
| 213 * @return {Promise} A promise that is resolved once the extensions data is | 249 * @return {Promise} A promise that is resolved once the extensions data is |
| 214 * fully updated. | 250 * fully updated. |
| 215 */ | 251 */ |
| 216 updateExtensionsData: function(incognitoAvailable, enableAppInfoDialog) { | 252 updateExtensionsData: function(incognitoAvailable, enableAppInfoDialog) { |
| 217 // If we start to need more information about the extension configuration, | 253 // If we start to need more information about the extension configuration, |
| 218 // consider passing in the full object from the ExtensionSettings. | 254 // consider passing in the full object from the ExtensionSettings. |
| 219 this.incognitoAvailable_ = incognitoAvailable; | 255 this.incognitoAvailable_ = incognitoAvailable; |
| 220 this.enableAppInfoDialog_ = enableAppInfoDialog; | 256 this.enableAppInfoDialog_ = enableAppInfoDialog; |
| 221 return new Promise(function(resolve, reject) { | 257 this.extensionsUpdated_ = new Promise(function(resolve, reject) { |
| 222 chrome.developerPrivate.getExtensionsInfo( | 258 chrome.developerPrivate.getExtensionsInfo( |
| 223 {includeDisabled: true, includeTerminated: true}, | 259 {includeDisabled: true, includeTerminated: true}, |
| 224 function(extensions) { | 260 function(extensions) { |
| 225 // Sort in order of unpacked vs. packed, followed by name, followed by | 261 // Sort in order of unpacked vs. packed, followed by name, followed by |
| 226 // id. | 262 // id. |
| 227 extensions.sort(function(a, b) { | 263 extensions.sort(function(a, b) { |
| 228 function compare(x, y) { | 264 function compare(x, y) { |
| 229 return x < y ? -1 : (x > y ? 1 : 0); | 265 return x < y ? -1 : (x > y ? 1 : 0); |
| 230 } | 266 } |
| 231 function compareLocation(x, y) { | 267 function compareLocation(x, y) { |
| 232 return x.location == chrome.developerPrivate.Location.UNPACKED ? | 268 return x.location == chrome.developerPrivate.Location.UNPACKED ? |
| 233 -1 : (x.location == y.location ? 0 : 1); | 269 -1 : (x.location == y.location ? 0 : 1); |
| 234 } | 270 } |
| 235 return compareLocation(a, b) || | 271 return compareLocation(a, b) || |
| 236 compare(a.name.toLowerCase(), b.name.toLowerCase()) || | 272 compare(a.name.toLowerCase(), b.name.toLowerCase()) || |
| 237 compare(a.id, b.id); | 273 compare(a.id, b.id); |
| 238 }); | 274 }); |
| 239 this.extensions_ = extensions; | 275 this.extensions_ = extensions; |
| 240 this.showExtensionNodes_(); | 276 this.showExtensionNodes_(); |
| 241 resolve(); | 277 resolve(); |
| 242 }.bind(this)); | 278 }.bind(this)); |
| 243 }.bind(this)); | 279 }.bind(this)); |
| 280 return this.extensionsUpdated_; | |
| 244 }, | 281 }, |
| 245 | 282 |
| 246 /** @return {number} The number of extensions being displayed. */ | 283 /** @return {number} The number of extensions being displayed. */ |
| 247 getNumExtensions: function() { | 284 getNumExtensions: function() { |
| 248 return this.extensions_.length; | 285 return this.extensions_.length; |
| 249 }, | 286 }, |
| 250 | 287 |
| 251 getIdQueryParam_: function() { | 288 getIdQueryParam_: function() { |
| 252 return parseQueryParams(document.location)['id']; | 289 return parseQueryParams(document.location)['id']; |
| 253 }, | 290 }, |
| 254 | 291 |
| 255 getOptionsQueryParam_: function() { | 292 getOptionsQueryParam_: function() { |
| 256 return parseQueryParams(document.location)['options']; | 293 return parseQueryParams(document.location)['options']; |
| 257 }, | 294 }, |
| 258 | 295 |
| 259 /** | 296 /** |
| 260 * Creates or updates all extension items from scratch. | 297 * Creates or updates all extension items from scratch. |
| 261 * @private | 298 * @private |
| 262 */ | 299 */ |
| 263 showExtensionNodes_: function() { | 300 showExtensionNodes_: function() { |
| 264 // Remove the rows from |focusGrid_| without destroying them. | 301 // Remove the rows from |focusGrid_| without destroying them. |
| 265 this.focusGrid_.rows.length = 0; | 302 this.focusGrid_.rows.length = 0; |
| 266 | 303 |
| 267 // Any node that is not updated will be removed. | 304 // Any node that is not updated will be removed. |
| 268 var seenIds = []; | 305 var seenIds = []; |
| 269 | 306 |
| 270 // Iterate over the extension data and add each item to the list. | 307 // Iterate over the extension data and add each item to the list. |
| 271 this.extensions_.forEach(function(extension, i) { | 308 this.extensions_.forEach(function(extension) { |
| 272 var nextExt = this.extensions_[i + 1]; | |
| 273 var node = $(extension.id); | |
| 274 seenIds.push(extension.id); | 309 seenIds.push(extension.id); |
| 275 | 310 this.updateExtension_(extension); |
| 276 if (node) | |
| 277 this.updateNode_(extension, node); | |
| 278 else | |
| 279 this.createNode_(extension, nextExt ? $(nextExt.id) : null); | |
| 280 }, this); | 311 }, this); |
| 281 | 312 |
| 282 // Remove extensions that are no longer installed. | 313 // Remove extensions that are no longer installed. |
| 283 var nodes = document.querySelectorAll('.extension-list-item-wrapper[id]'); | 314 var nodes = document.querySelectorAll('.extension-list-item-wrapper[id]'); |
| 284 for (var i = 0; i < nodes.length; ++i) { | 315 for (var i = 0; i < nodes.length; ++i) { |
| 285 var node = nodes[i]; | 316 var node = nodes[i]; |
| 286 if (seenIds.indexOf(node.id) < 0) { | 317 if (seenIds.indexOf(node.id) < 0) { |
| 287 if (node.contains(document.activeElement)) { | 318 if (node.contains(document.activeElement)) { |
| 288 var focusableNode = nodes[i + 1] || nodes[i - 1]; | 319 var focusableNode = nodes[i + 1] || nodes[i - 1]; |
| 289 if (focusableNode) { | 320 if (focusableNode) { |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 975 var self = this; | 1006 var self = this; |
| 976 $('overlay').addEventListener('cancelOverlay', function f() { | 1007 $('overlay').addEventListener('cancelOverlay', function f() { |
| 977 self.optionsShown_ = false; | 1008 self.optionsShown_ = false; |
| 978 $('overlay').removeEventListener('cancelOverlay', f); | 1009 $('overlay').removeEventListener('cancelOverlay', f); |
| 979 }); | 1010 }); |
| 980 | 1011 |
| 981 // TODO(dbeam): why do we need to focus <extensionoptions> before and | 1012 // TODO(dbeam): why do we need to focus <extensionoptions> before and |
| 982 // after its showing animation? Makes very little sense to me. | 1013 // after its showing animation? Makes very little sense to me. |
| 983 overlay.setInitialFocus(); | 1014 overlay.setInitialFocus(); |
| 984 }, | 1015 }, |
| 1016 | |
| 1017 /** | |
| 1018 * Updates the node for the extension. | |
| 1019 * @param {!ExtensionInfo} extension The information about the extension to | |
| 1020 * update. | |
| 1021 * @private | |
| 1022 */ | |
| 1023 updateExtension_: function(extension) { | |
| 1024 var node = /** @type {ExtensionFocusRow} */ ($(extension.id)); | |
| 1025 if (node) { | |
| 1026 this.updateNode_(extension, node); | |
| 1027 } else { | |
| 1028 var nextExt = this.extensions_[this.extensions_.indexOf(extension) + 1]; | |
| 1029 this.createNode_(extension, nextExt ? $(nextExt.id) : null); | |
| 1030 } | |
| 1031 } | |
| 985 }; | 1032 }; |
| 986 | 1033 |
| 987 return { | 1034 return { |
| 988 ExtensionList: ExtensionList | 1035 ExtensionList: ExtensionList |
| 989 }; | 1036 }; |
| 990 }); | 1037 }); |
| OLD | NEW |