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 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 */ | 228 */ |
229 enableAppInfoDialog_: false, | 229 enableAppInfoDialog_: false, |
230 | 230 |
231 /** | 231 /** |
232 * Initializes the list. | 232 * Initializes the list. |
233 */ | 233 */ |
234 initialize: function() { | 234 initialize: function() { |
235 /** @private {!Array<ExtensionInfo>} */ | 235 /** @private {!Array<ExtensionInfo>} */ |
236 this.extensions_ = []; | 236 this.extensions_ = []; |
237 | 237 |
| 238 /** |
| 239 * |loadFinished| should be used for testing purposes and will be |
| 240 * fulfilled when this list has finished loading the first time. |
| 241 * @type {Promise} |
| 242 * */ |
| 243 this.loadFinished = new Promise(function(resolve, reject) { |
| 244 /** @private {function(?)} */ |
| 245 this.resolveLoadFinished_ = resolve; |
| 246 }.bind(this)); |
| 247 |
238 chrome.developerPrivate.onItemStateChanged.addListener( | 248 chrome.developerPrivate.onItemStateChanged.addListener( |
239 function(eventData) { | 249 function(eventData) { |
240 var EventType = chrome.developerPrivate.EventType; | 250 var EventType = chrome.developerPrivate.EventType; |
241 switch (eventData.event_type) { | 251 switch (eventData.event_type) { |
242 case EventType.VIEW_REGISTERED: | 252 case EventType.VIEW_REGISTERED: |
243 case EventType.VIEW_UNREGISTERED: | 253 case EventType.VIEW_UNREGISTERED: |
244 case EventType.INSTALLED: | 254 case EventType.INSTALLED: |
245 case EventType.LOADED: | 255 case EventType.LOADED: |
246 case EventType.UNLOADED: | 256 case EventType.UNLOADED: |
247 case EventType.ERROR_ADDED: | 257 case EventType.ERROR_ADDED: |
(...skipping 27 matching lines...) Expand all Loading... |
275 this.extensionsUpdated_ = new Promise(function(resolve, reject) { | 285 this.extensionsUpdated_ = new Promise(function(resolve, reject) { |
276 chrome.developerPrivate.getExtensionsInfo( | 286 chrome.developerPrivate.getExtensionsInfo( |
277 {includeDisabled: true, includeTerminated: true}, | 287 {includeDisabled: true, includeTerminated: true}, |
278 function(extensions) { | 288 function(extensions) { |
279 // Sort in order of unpacked vs. packed, followed by name, followed by | 289 // Sort in order of unpacked vs. packed, followed by name, followed by |
280 // id. | 290 // id. |
281 extensions.sort(compareExtensions); | 291 extensions.sort(compareExtensions); |
282 this.extensions_ = extensions; | 292 this.extensions_ = extensions; |
283 this.showExtensionNodes_(); | 293 this.showExtensionNodes_(); |
284 resolve(); | 294 resolve(); |
| 295 |
| 296 // |resolve| is async so it's necessary to use |then| here in order to |
| 297 // do work after other |then|s have finished. This is important so |
| 298 // elements are visible when these updates happen. |
| 299 this.extensionsUpdated_.then(function() { |
| 300 this.onUpdateFinished_(); |
| 301 this.resolveLoadFinished_(); |
| 302 }.bind(this)); |
285 }.bind(this)); | 303 }.bind(this)); |
286 }.bind(this)); | 304 }.bind(this)); |
287 return this.extensionsUpdated_; | 305 return this.extensionsUpdated_; |
288 }, | 306 }, |
289 | 307 |
| 308 /** |
| 309 * Updates elements that need to be visible in order to update properly. |
| 310 * @private |
| 311 */ |
| 312 onUpdateFinished_: function() { |
| 313 // Cannot focus or highlight a extension if there are none. |
| 314 if (this.extensions_.length == 0) |
| 315 return; |
| 316 |
| 317 assert(!this.hidden); |
| 318 assert(!this.parentElement.hidden); |
| 319 |
| 320 this.updateFocusableElements(); |
| 321 |
| 322 var idToHighlight = this.getIdQueryParam_(); |
| 323 if (idToHighlight && $(idToHighlight)) |
| 324 this.scrollToNode_(idToHighlight); |
| 325 |
| 326 var idToOpenOptions = this.getOptionsQueryParam_(); |
| 327 if (idToOpenOptions && $(idToOpenOptions)) |
| 328 this.showEmbeddedExtensionOptions_(idToOpenOptions, true); |
| 329 }, |
| 330 |
290 /** @return {number} The number of extensions being displayed. */ | 331 /** @return {number} The number of extensions being displayed. */ |
291 getNumExtensions: function() { | 332 getNumExtensions: function() { |
292 return this.extensions_.length; | 333 return this.extensions_.length; |
293 }, | 334 }, |
294 | 335 |
295 getIdQueryParam_: function() { | 336 getIdQueryParam_: function() { |
296 return parseQueryParams(document.location)['id']; | 337 return parseQueryParams(document.location)['id']; |
297 }, | 338 }, |
298 | 339 |
299 getOptionsQueryParam_: function() { | 340 getOptionsQueryParam_: function() { |
(...skipping 29 matching lines...) Expand all Loading... |
329 focusableNode.getEquivalentElement( | 370 focusableNode.getEquivalentElement( |
330 document.activeElement).focus(); | 371 document.activeElement).focus(); |
331 } | 372 } |
332 } | 373 } |
333 | 374 |
334 node.parentElement.removeChild(node); | 375 node.parentElement.removeChild(node); |
335 // Unregister the removed node from events. | 376 // Unregister the removed node from events. |
336 assertInstanceof(node, ExtensionFocusRow).destroy(); | 377 assertInstanceof(node, ExtensionFocusRow).destroy(); |
337 } | 378 } |
338 } | 379 } |
339 | |
340 var idToHighlight = this.getIdQueryParam_(); | |
341 if (idToHighlight && $(idToHighlight)) | |
342 this.scrollToNode_(idToHighlight); | |
343 | |
344 var idToOpenOptions = this.getOptionsQueryParam_(); | |
345 if (idToOpenOptions && $(idToOpenOptions)) | |
346 this.showEmbeddedExtensionOptions_(idToOpenOptions, true); | |
347 }, | 380 }, |
348 | 381 |
349 /** Updates each row's focusable elements without rebuilding the grid. */ | 382 /** Updates each row's focusable elements without rebuilding the grid. */ |
350 updateFocusableElements: function() { | 383 updateFocusableElements: function() { |
351 var rows = document.querySelectorAll('.extension-list-item-wrapper[id]'); | 384 var rows = document.querySelectorAll('.extension-list-item-wrapper[id]'); |
352 for (var i = 0; i < rows.length; ++i) { | 385 for (var i = 0; i < rows.length; ++i) { |
353 assertInstanceof(rows[i], ExtensionFocusRow).updateFocusableElements(); | 386 assertInstanceof(rows[i], ExtensionFocusRow).updateFocusableElements(); |
354 } | 387 } |
355 }, | 388 }, |
356 | 389 |
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 var nextExt = this.extensions_[this.extensions_.indexOf(extension) + 1]; | 1088 var nextExt = this.extensions_[this.extensions_.indexOf(extension) + 1]; |
1056 this.createNode_(extension, nextExt ? $(nextExt.id) : null); | 1089 this.createNode_(extension, nextExt ? $(nextExt.id) : null); |
1057 } | 1090 } |
1058 } | 1091 } |
1059 }; | 1092 }; |
1060 | 1093 |
1061 return { | 1094 return { |
1062 ExtensionList: ExtensionList | 1095 ExtensionList: ExtensionList |
1063 }; | 1096 }; |
1064 }); | 1097 }); |
OLD | NEW |