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 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 return -1; | 155 return -1; |
156 if (y.location == chrome.developerPrivate.Location.UNPACKED) | 156 if (y.location == chrome.developerPrivate.Location.UNPACKED) |
157 return 1; | 157 return 1; |
158 return 0; | 158 return 0; |
159 } | 159 } |
160 return compareLocation(a, b) || | 160 return compareLocation(a, b) || |
161 compare(a.name.toLowerCase(), b.name.toLowerCase()) || | 161 compare(a.name.toLowerCase(), b.name.toLowerCase()) || |
162 compare(a.id, b.id); | 162 compare(a.id, b.id); |
163 } | 163 } |
164 | 164 |
165 /** @interface */ | |
166 function ExtensionListDelegate() {} | |
167 | |
168 ExtensionListDelegate.prototype = { | |
169 /** | |
170 * Called when the number of extensions in the list has changed. | |
171 */ | |
172 onExtensionCountChanged: assertNotReached, | |
173 }; | |
174 | |
165 /** | 175 /** |
166 * Creates a new list of extensions. | 176 * Creates a new list of extensions. |
177 * @param {ExtensionListDelegate} delegate | |
Devlin
2015/04/27 20:02:03
Strangely, this (and also lines 244 and 250, as we
Dan Beam
2015/04/27 21:02:27
this will work:
extensions.ExtensionListDelegate
Devlin
2015/04/27 21:11:54
Bummer indeed. Odd that it worked fine when putti
Devlin
2015/04/27 22:19:47
Fixed better, from offline conversation.
| |
167 * @constructor | 178 * @constructor |
168 * @extends {HTMLDivElement} | 179 * @extends {HTMLDivElement} |
169 */ | 180 */ |
170 function ExtensionList() { | 181 function ExtensionList(delegate) { |
171 var div = document.createElement('div'); | 182 var div = document.createElement('div'); |
172 div.__proto__ = ExtensionList.prototype; | 183 div.__proto__ = ExtensionList.prototype; |
173 div.initialize(); | 184 div.initialize(delegate); |
174 return div; | 185 return div; |
175 } | 186 } |
176 | 187 |
177 /** | 188 /** |
178 * @type {Object<string, number>} A map from extension id to last reloaded | 189 * @type {Object<string, number>} A map from extension id to last reloaded |
179 * timestamp. The timestamp is recorded when the user click the 'Reload' | 190 * timestamp. The timestamp is recorded when the user click the 'Reload' |
180 * link. It is used to refresh the icon of an unpacked extension. | 191 * link. It is used to refresh the icon of an unpacked extension. |
181 * This persists between calls to decorate. | 192 * This persists between calls to decorate. |
182 */ | 193 */ |
183 var extensionReloadedTimestamp = {}; | 194 var extensionReloadedTimestamp = {}; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
223 incognitoAvailable_: false, | 234 incognitoAvailable_: false, |
224 | 235 |
225 /** | 236 /** |
226 * Whether or not the app info dialog is enabled. | 237 * Whether or not the app info dialog is enabled. |
227 * @private {boolean} | 238 * @private {boolean} |
228 */ | 239 */ |
229 enableAppInfoDialog_: false, | 240 enableAppInfoDialog_: false, |
230 | 241 |
231 /** | 242 /** |
232 * Initializes the list. | 243 * Initializes the list. |
244 * @param {!ExtensionListDelegate} delegate | |
233 */ | 245 */ |
234 initialize: function() { | 246 initialize: function(delegate) { |
235 /** @private {!Array<ExtensionInfo>} */ | 247 /** @private {!Array<ExtensionInfo>} */ |
236 this.extensions_ = []; | 248 this.extensions_ = []; |
237 | 249 |
250 /** @private {!ExtensionListDelegate} */ | |
251 this.delegate_ = delegate; | |
252 | |
238 /** | 253 /** |
239 * |loadFinished| should be used for testing purposes and will be | 254 * |loadFinished| should be used for testing purposes and will be |
240 * fulfilled when this list has finished loading the first time. | 255 * fulfilled when this list has finished loading the first time. |
241 * @type {Promise} | 256 * @type {Promise} |
242 * */ | 257 * */ |
243 this.loadFinished = new Promise(function(resolve, reject) { | 258 this.loadFinished = new Promise(function(resolve, reject) { |
244 /** @private {function(?)} */ | 259 /** @private {function(?)} */ |
245 this.resolveLoadFinished_ = resolve; | 260 this.resolveLoadFinished_ = resolve; |
246 }.bind(this)); | 261 }.bind(this)); |
247 | 262 |
248 chrome.developerPrivate.onItemStateChanged.addListener( | 263 chrome.developerPrivate.onItemStateChanged.addListener( |
249 function(eventData) { | 264 function(eventData) { |
250 var EventType = chrome.developerPrivate.EventType; | 265 var EventType = chrome.developerPrivate.EventType; |
251 switch (eventData.event_type) { | 266 switch (eventData.event_type) { |
252 case EventType.VIEW_REGISTERED: | 267 case EventType.VIEW_REGISTERED: |
253 case EventType.VIEW_UNREGISTERED: | 268 case EventType.VIEW_UNREGISTERED: |
254 case EventType.INSTALLED: | 269 case EventType.INSTALLED: |
255 case EventType.LOADED: | 270 case EventType.LOADED: |
256 case EventType.UNLOADED: | 271 case EventType.UNLOADED: |
257 case EventType.ERROR_ADDED: | 272 case EventType.ERROR_ADDED: |
258 case EventType.PREFS_CHANGED: | 273 case EventType.PREFS_CHANGED: |
259 if (eventData.extensionInfo) | 274 if (eventData.extensionInfo) |
260 this.updateExtension_(eventData.extensionInfo); | 275 this.updateExtension_(eventData.extensionInfo); |
261 break; | 276 break; |
262 case EventType.UNINSTALLED: | 277 case EventType.UNINSTALLED: |
278 var index = this.getIndexOfExtension_(eventData.item_id); | |
279 this.extensions_.splice(index, 1); | |
263 var childNode = $(eventData.item_id); | 280 var childNode = $(eventData.item_id); |
264 childNode.parentNode.removeChild(childNode); | 281 childNode.parentNode.removeChild(childNode); |
265 break; | 282 break; |
266 default: | 283 default: |
267 assertNotReached(); | 284 assertNotReached(); |
268 } | 285 } |
286 | |
287 if (eventData.event_type == EventType.INSTALLED || | |
288 eventData.event_type == EventType.UNINSTALLED) { | |
289 this.delegate_.onExtensionCountChanged(); | |
290 } | |
269 }.bind(this)); | 291 }.bind(this)); |
270 }, | 292 }, |
271 | 293 |
272 /** | 294 /** |
273 * Updates the extensions on the page. | 295 * Updates the extensions on the page. |
274 * @param {boolean} incognitoAvailable Whether or not incognito is allowed. | 296 * @param {boolean} incognitoAvailable Whether or not incognito is allowed. |
275 * @param {boolean} enableAppInfoDialog Whether or not the app info dialog | 297 * @param {boolean} enableAppInfoDialog Whether or not the app info dialog |
276 * is enabled. | 298 * is enabled. |
277 * @return {Promise} A promise that is resolved once the extensions data is | 299 * @return {Promise} A promise that is resolved once the extensions data is |
278 * fully updated. | 300 * fully updated. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
327 var idToOpenOptions = this.getOptionsQueryParam_(); | 349 var idToOpenOptions = this.getOptionsQueryParam_(); |
328 if (idToOpenOptions && $(idToOpenOptions)) | 350 if (idToOpenOptions && $(idToOpenOptions)) |
329 this.showEmbeddedExtensionOptions_(idToOpenOptions, true); | 351 this.showEmbeddedExtensionOptions_(idToOpenOptions, true); |
330 }, | 352 }, |
331 | 353 |
332 /** @return {number} The number of extensions being displayed. */ | 354 /** @return {number} The number of extensions being displayed. */ |
333 getNumExtensions: function() { | 355 getNumExtensions: function() { |
334 return this.extensions_.length; | 356 return this.extensions_.length; |
335 }, | 357 }, |
336 | 358 |
359 /** | |
360 * @param {string} id The id of the extension. | |
361 * @return {number} The index of the extension with the given id. | |
362 * @private | |
363 */ | |
364 getIndexOfExtension_: function(id) { | |
365 for (var i = 0; i < this.extensions_.length; ++i) { | |
366 if (this.extensions_[i].id == id) | |
367 return i; | |
368 } | |
369 return -1; | |
370 }, | |
371 | |
337 getIdQueryParam_: function() { | 372 getIdQueryParam_: function() { |
338 return parseQueryParams(document.location)['id']; | 373 return parseQueryParams(document.location)['id']; |
339 }, | 374 }, |
340 | 375 |
341 getOptionsQueryParam_: function() { | 376 getOptionsQueryParam_: function() { |
342 return parseQueryParams(document.location)['options']; | 377 return parseQueryParams(document.location)['options']; |
343 }, | 378 }, |
344 | 379 |
345 /** | 380 /** |
346 * Creates or updates all extension items from scratch. | 381 * Creates or updates all extension items from scratch. |
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1056 overlay.setInitialFocus(); | 1091 overlay.setInitialFocus(); |
1057 }, | 1092 }, |
1058 | 1093 |
1059 /** | 1094 /** |
1060 * Updates the node for the extension. | 1095 * Updates the node for the extension. |
1061 * @param {!ExtensionInfo} extension The information about the extension to | 1096 * @param {!ExtensionInfo} extension The information about the extension to |
1062 * update. | 1097 * update. |
1063 * @private | 1098 * @private |
1064 */ | 1099 */ |
1065 updateExtension_: function(extension) { | 1100 updateExtension_: function(extension) { |
1066 var currIndex = -1; | 1101 var currIndex = this.getIndexOfExtension_(extension.id); |
1067 for (var i = 0; i < this.extensions_.length; ++i) { | |
1068 if (this.extensions_[i].id == extension.id) { | |
1069 currIndex = i; | |
1070 break; | |
1071 } | |
1072 } | |
1073 if (currIndex != -1) { | 1102 if (currIndex != -1) { |
1074 // If there is a current version of the extension, update it with the | 1103 // If there is a current version of the extension, update it with the |
1075 // new version. | 1104 // new version. |
1076 this.extensions_[currIndex] = extension; | 1105 this.extensions_[currIndex] = extension; |
1077 } else { | 1106 } else { |
1078 // If the extension isn't found, push it back and sort. Technically, we | 1107 // If the extension isn't found, push it back and sort. Technically, we |
1079 // could optimize by inserting it at the right location, but since this | 1108 // could optimize by inserting it at the right location, but since this |
1080 // only happens on extension install, it's not worth it. | 1109 // only happens on extension install, it's not worth it. |
1081 this.extensions_.push(extension); | 1110 this.extensions_.push(extension); |
1082 this.extensions_.sort(compareExtensions); | 1111 this.extensions_.sort(compareExtensions); |
1083 } | 1112 } |
1084 | 1113 |
1085 var node = /** @type {ExtensionFocusRow} */ ($(extension.id)); | 1114 var node = /** @type {ExtensionFocusRow} */ ($(extension.id)); |
1086 if (node) { | 1115 if (node) { |
1087 this.updateNode_(extension, node); | 1116 this.updateNode_(extension, node); |
1088 } else { | 1117 } else { |
1089 var nextExt = this.extensions_[this.extensions_.indexOf(extension) + 1]; | 1118 var nextExt = this.extensions_[this.extensions_.indexOf(extension) + 1]; |
1090 this.createNode_(extension, nextExt ? $(nextExt.id) : null); | 1119 this.createNode_(extension, nextExt ? $(nextExt.id) : null); |
1091 } | 1120 } |
1092 } | 1121 } |
1093 }; | 1122 }; |
1094 | 1123 |
1095 return { | 1124 return { |
1096 ExtensionList: ExtensionList | 1125 ExtensionList: ExtensionList |
1097 }; | 1126 }; |
1098 }); | 1127 }); |
OLD | NEW |