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

Side by Side Diff: chrome/browser/resources/extensions/extension_list.js

Issue 2939273002: DO NOT SUBMIT: what chrome/browser/resources/ could eventually look like with clang-format (Closed)
Patch Set: Created 3 years, 6 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
OLDNEW
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('extensions', function() { 7 cr.define('extensions', function() {
8 'use strict'; 8 'use strict';
9 9
10 var ExtensionType = chrome.developerPrivate.ExtensionType; 10 var ExtensionType = chrome.developerPrivate.ExtensionType;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 function compareLocation(x, y) { 77 function compareLocation(x, y) {
78 if (x.location == y.location) 78 if (x.location == y.location)
79 return 0; 79 return 0;
80 if (x.location == chrome.developerPrivate.Location.UNPACKED) 80 if (x.location == chrome.developerPrivate.Location.UNPACKED)
81 return -1; 81 return -1;
82 if (y.location == chrome.developerPrivate.Location.UNPACKED) 82 if (y.location == chrome.developerPrivate.Location.UNPACKED)
83 return 1; 83 return 1;
84 return 0; 84 return 0;
85 } 85 }
86 return compareLocation(a, b) || 86 return compareLocation(a, b) ||
87 compare(a.name.toLowerCase(), b.name.toLowerCase()) || 87 compare(a.name.toLowerCase(), b.name.toLowerCase()) ||
88 compare(a.id, b.id); 88 compare(a.id, b.id);
89 } 89 }
90 90
91 /** @interface */ 91 /** @interface */
92 function ExtensionListDelegate() {} 92 function ExtensionListDelegate() {}
93 93
94 ExtensionListDelegate.prototype = { 94 ExtensionListDelegate.prototype = {
95 /** 95 /**
96 * Called when the number of extensions in the list has changed. 96 * Called when the number of extensions in the list has changed.
97 */ 97 */
98 onExtensionCountChanged: assertNotReached, 98 onExtensionCountChanged: assertNotReached,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 */ 164 */
165 initialize: function(delegate) { 165 initialize: function(delegate) {
166 /** @private {!Array<chrome.developerPrivate.ExtensionInfo>} */ 166 /** @private {!Array<chrome.developerPrivate.ExtensionInfo>} */
167 this.extensions_ = []; 167 this.extensions_ = [];
168 168
169 /** @private {!extensions.ExtensionListDelegate} */ 169 /** @private {!extensions.ExtensionListDelegate} */
170 this.delegate_ = delegate; 170 this.delegate_ = delegate;
171 171
172 this.resetLoadFinished(); 172 this.resetLoadFinished();
173 173
174 chrome.developerPrivate.onItemStateChanged.addListener( 174 chrome.developerPrivate.onItemStateChanged.addListener(function(
175 function(eventData) { 175 eventData) {
176 var EventType = chrome.developerPrivate.EventType; 176 var EventType = chrome.developerPrivate.EventType;
177 switch (eventData.event_type) { 177 switch (eventData.event_type) {
178 case EventType.VIEW_REGISTERED: 178 case EventType.VIEW_REGISTERED:
179 case EventType.VIEW_UNREGISTERED: 179 case EventType.VIEW_UNREGISTERED:
180 case EventType.INSTALLED: 180 case EventType.INSTALLED:
181 case EventType.LOADED: 181 case EventType.LOADED:
182 case EventType.UNLOADED: 182 case EventType.UNLOADED:
183 case EventType.ERROR_ADDED: 183 case EventType.ERROR_ADDED:
184 case EventType.ERRORS_REMOVED: 184 case EventType.ERRORS_REMOVED:
185 case EventType.PREFS_CHANGED: 185 case EventType.PREFS_CHANGED:
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 updateExtensionsData: function(incognitoAvailable, enableAppInfoDialog) { 246 updateExtensionsData: function(incognitoAvailable, enableAppInfoDialog) {
247 // If we start to need more information about the extension configuration, 247 // If we start to need more information about the extension configuration,
248 // consider passing in the full object from the ExtensionSettings. 248 // consider passing in the full object from the ExtensionSettings.
249 this.incognitoAvailable_ = incognitoAvailable; 249 this.incognitoAvailable_ = incognitoAvailable;
250 this.enableAppInfoDialog_ = enableAppInfoDialog; 250 this.enableAppInfoDialog_ = enableAppInfoDialog;
251 /** @private {Promise} */ 251 /** @private {Promise} */
252 this.extensionsUpdated_ = new Promise(function(resolve, reject) { 252 this.extensionsUpdated_ = new Promise(function(resolve, reject) {
253 chrome.developerPrivate.getExtensionsInfo( 253 chrome.developerPrivate.getExtensionsInfo(
254 {includeDisabled: true, includeTerminated: true}, 254 {includeDisabled: true, includeTerminated: true},
255 function(extensions) { 255 function(extensions) {
256 // Sort in order of unpacked vs. packed, followed by name, followed by 256 // Sort in order of unpacked vs. packed, followed by name,
257 // id. 257 // followed by id.
258 extensions.sort(compareExtensions); 258 extensions.sort(compareExtensions);
259 this.extensions_ = extensions; 259 this.extensions_ = extensions;
260 this.showExtensionNodes_(); 260 this.showExtensionNodes_();
261 261
262 // We keep the commands overlay's extension info in sync, so that we 262 // We keep the commands overlay's extension info in sync, so that
263 // don't duplicate the same querying logic there. 263 // we don't duplicate the same querying logic there.
264 ExtensionCommandsOverlay.updateExtensionsData(this.extensions_); 264 ExtensionCommandsOverlay.updateExtensionsData(this.extensions_);
265 265
266 resolve(); 266 resolve();
267 267
268 // |resolve| is async so it's necessary to use |then| here in order to 268 // |resolve| is async so it's necessary to use |then| here in
269 // do work after other |then|s have finished. This is important so 269 // order to do work after other |then|s have finished. This is
270 // elements are visible when these updates happen. 270 // important so elements are visible when these updates happen.
271 this.extensionsUpdated_.then(function() { 271 this.extensionsUpdated_.then(function() {
272 this.onUpdateFinished_(); 272 this.onUpdateFinished_();
273 this.resolveLoadFinished_(); 273 this.resolveLoadFinished_();
274 }.bind(this)); 274 }.bind(this));
275 }.bind(this)); 275 }.bind(this));
276 }.bind(this)); 276 }.bind(this));
277 return this.extensionsUpdated_; 277 return this.extensionsUpdated_;
278 }, 278 },
279 279
280 /** 280 /**
281 * Updates elements that need to be visible in order to update properly. 281 * Updates elements that need to be visible in order to update properly.
282 * @private 282 * @private
283 */ 283 */
284 onUpdateFinished_: function() { 284 onUpdateFinished_: function() {
285 // Cannot focus or highlight a extension if there are none, and we should 285 // Cannot focus or highlight a extension if there are none, and we should
286 // only scroll to a particular extension or open the options page once. 286 // only scroll to a particular extension or open the options page once.
287 if (this.extensions_.length == 0 || this.didInitialNavigation_) 287 if (this.extensions_.length == 0 || this.didInitialNavigation_)
288 return; 288 return;
289 289
290 this.didInitialNavigation_ = true; 290 this.didInitialNavigation_ = true;
291 assert(!this.hidden); 291 assert(!this.hidden);
292 assert(!this.parentElement.hidden); 292 assert(!this.parentElement.hidden);
293 293
294 var idToHighlight = this.getIdQueryParam_(); 294 var idToHighlight = this.getIdQueryParam_();
295 if (idToHighlight) { 295 if (idToHighlight) {
296 var wrapper = $(idToHighlight); 296 var wrapper = $(idToHighlight);
297 if (wrapper) { 297 if (wrapper) {
298 this.scrollToWrapper_(idToHighlight); 298 this.scrollToWrapper_(idToHighlight);
299 299
300 var focusRow = wrapper.getFocusRow(); 300 var focusRow = wrapper.getFocusRow();
301 (focusRow.getFirstFocusable('enabled') || 301 (focusRow.getFirstFocusable('enabled') ||
302 focusRow.getFirstFocusable('remove-enterprise') || 302 focusRow.getFirstFocusable('remove-enterprise') ||
303 focusRow.getFirstFocusable('website') || 303 focusRow.getFirstFocusable('website') ||
304 focusRow.getFirstFocusable('details')).focus(); 304 focusRow.getFirstFocusable('details'))
305 .focus();
305 } 306 }
306 } 307 }
307 308
308 var idToOpenOptions = this.getOptionsQueryParam_(); 309 var idToOpenOptions = this.getOptionsQueryParam_();
309 if (idToOpenOptions && $(idToOpenOptions)) 310 if (idToOpenOptions && $(idToOpenOptions))
310 this.showEmbeddedExtensionOptions_(idToOpenOptions, true); 311 this.showEmbeddedExtensionOptions_(idToOpenOptions, true);
311 }, 312 },
312 313
313 /** @return {number} The number of extensions being displayed. */ 314 /** @return {number} The number of extensions being displayed. */
314 getNumExtensions: function() { 315 getNumExtensions: function() {
(...skipping 30 matching lines...) Expand all
345 var seenIds = []; 346 var seenIds = [];
346 347
347 // Iterate over the extension data and add each item to the list. 348 // Iterate over the extension data and add each item to the list.
348 this.extensions_.forEach(function(extension) { 349 this.extensions_.forEach(function(extension) {
349 seenIds.push(extension.id); 350 seenIds.push(extension.id);
350 this.updateOrCreateWrapper_(extension); 351 this.updateOrCreateWrapper_(extension);
351 }, this); 352 }, this);
352 this.focusGrid_.ensureRowActive(); 353 this.focusGrid_.ensureRowActive();
353 354
354 // Remove extensions that are no longer installed. 355 // Remove extensions that are no longer installed.
355 var wrappers = document.querySelectorAll( 356 var wrappers =
356 '.extension-list-item-wrapper[id]'); 357 document.querySelectorAll('.extension-list-item-wrapper[id]');
357 Array.prototype.forEach.call(wrappers, function(wrapper) { 358 Array.prototype.forEach.call(wrappers, function(wrapper) {
358 if (seenIds.indexOf(wrapper.id) < 0) 359 if (seenIds.indexOf(wrapper.id) < 0)
359 this.removeWrapper_(wrapper); 360 this.removeWrapper_(wrapper);
360 }, this); 361 }, this);
361 }, 362 },
362 363
363 /** 364 /**
364 * Removes the wrapper from the DOM and updates the focused element if 365 * Removes the wrapper from the DOM and updates the focused element if
365 * needed. 366 * needed.
366 * @param {!Element} wrapper 367 * @param {!Element} wrapper
367 * @private 368 * @private
368 */ 369 */
369 removeWrapper_: function(wrapper) { 370 removeWrapper_: function(wrapper) {
370 // If focus is in the wrapper about to be removed, move it first. This 371 // If focus is in the wrapper about to be removed, move it first. This
371 // happens when clicking the trash can to remove an extension. 372 // happens when clicking the trash can to remove an extension.
372 if (wrapper.contains(document.activeElement)) { 373 if (wrapper.contains(document.activeElement)) {
373 var wrappers = document.querySelectorAll( 374 var wrappers =
374 '.extension-list-item-wrapper[id]'); 375 document.querySelectorAll('.extension-list-item-wrapper[id]');
375 var index = Array.prototype.indexOf.call(wrappers, wrapper); 376 var index = Array.prototype.indexOf.call(wrappers, wrapper);
376 assert(index != -1); 377 assert(index != -1);
377 var focusableWrapper = wrappers[index + 1] || wrappers[index - 1]; 378 var focusableWrapper = wrappers[index + 1] || wrappers[index - 1];
378 if (focusableWrapper) { 379 if (focusableWrapper) {
379 var newFocusRow = focusableWrapper.getFocusRow(); 380 var newFocusRow = focusableWrapper.getFocusRow();
380 newFocusRow.getEquivalentElement(document.activeElement).focus(); 381 newFocusRow.getEquivalentElement(document.activeElement).focus();
381 } 382 }
382 } 383 }
383 384
384 var focusRow = wrapper.getFocusRow(); 385 var focusRow = wrapper.getFocusRow();
(...skipping 30 matching lines...) Expand all
415 * wrapper list). 416 * wrapper list).
416 * @private 417 * @private
417 */ 418 */
418 createWrapper_: function(extension, nextWrapper) { 419 createWrapper_: function(extension, nextWrapper) {
419 var wrapper = new ExtensionWrapper; 420 var wrapper = new ExtensionWrapper;
420 wrapper.id = extension.id; 421 wrapper.id = extension.id;
421 422
422 // The 'Permissions' link. 423 // The 'Permissions' link.
423 wrapper.setupColumn('details', '.permissions-link', 'click', function(e) { 424 wrapper.setupColumn('details', '.permissions-link', 'click', function(e) {
424 if (!this.permissionsPromptIsShowing_) { 425 if (!this.permissionsPromptIsShowing_) {
425 chrome.developerPrivate.showPermissionsDialog(extension.id, 426 chrome.developerPrivate.showPermissionsDialog(
426 function() { 427 extension.id, function() {
427 this.permissionsPromptIsShowing_ = false; 428 this.permissionsPromptIsShowing_ = false;
428 }.bind(this)); 429 }.bind(this));
429 this.permissionsPromptIsShowing_ = true; 430 this.permissionsPromptIsShowing_ = true;
430 } 431 }
431 e.preventDefault(); 432 e.preventDefault();
432 }); 433 });
433 434
434 wrapper.setupColumn('options', '.options-button', 'click', function(e) { 435 wrapper.setupColumn('options', '.options-button', 'click', function(e) {
435 this.showEmbeddedExtensionOptions_(extension.id, false); 436 this.showEmbeddedExtensionOptions_(extension.id, false);
436 e.preventDefault(); 437 e.preventDefault();
437 }.bind(this)); 438 }.bind(this));
438 439
(...skipping 25 matching lines...) Expand all
464 var extensionId = extension.id; 465 var extensionId = extension.id;
465 assert(this.extensions_.length > 0); 466 assert(this.extensions_.length > 0);
466 var newEx = this.extensions_.filter(function(e) { 467 var newEx = this.extensions_.filter(function(e) {
467 return e.id == extensionId; 468 return e.id == extensionId;
468 })[0]; 469 })[0];
469 var errors = newEx.manifestErrors.concat(newEx.runtimeErrors); 470 var errors = newEx.manifestErrors.concat(newEx.runtimeErrors);
470 extensions.ExtensionErrorOverlay.getInstance().setErrorsAndShowOverlay( 471 extensions.ExtensionErrorOverlay.getInstance().setErrorsAndShowOverlay(
471 errors, extensionId, newEx.name); 472 errors, extensionId, newEx.name);
472 }.bind(this)); 473 }.bind(this));
473 474
474 wrapper.setupColumn('suspiciousLearnMore', 475 wrapper.setupColumn(
475 '.suspicious-install-message .learn-more-link'); 476 'suspiciousLearnMore',
477 '.suspicious-install-message .learn-more-link');
476 478
477 // The path, if provided by unpacked extension. 479 // The path, if provided by unpacked extension.
478 wrapper.setupColumn('loadPath', '.load-path a:first-of-type', 'click', 480 wrapper.setupColumn(
479 function(e) { 481 'loadPath', '.load-path a:first-of-type', 'click', function(e) {
480 chrome.developerPrivate.showPath(extension.id); 482 chrome.developerPrivate.showPath(extension.id);
481 e.preventDefault(); 483 e.preventDefault();
482 }); 484 });
483 485
484 // The 'allow in incognito' checkbox. 486 // The 'allow in incognito' checkbox.
485 wrapper.setupColumn('incognito', '.incognito-control input', 'change', 487 wrapper.setupColumn(
486 function(e) { 488 'incognito', '.incognito-control input', 'change', function(e) {
487 var butterBar = wrapper.querySelector('.butter-bar'); 489 var butterBar = wrapper.querySelector('.butter-bar');
488 var checked = e.target.checked; 490 var checked = e.target.checked;
489 butterBar.hidden = !checked || 491 butterBar.hidden =
490 extension.type == ExtensionType.HOSTED_APP; 492 !checked || extension.type == ExtensionType.HOSTED_APP;
491 chrome.developerPrivate.updateExtensionConfiguration({ 493 chrome.developerPrivate.updateExtensionConfiguration(
492 extensionId: extension.id, 494 {extensionId: extension.id, incognitoAccess: e.target.checked});
493 incognitoAccess: e.target.checked 495 }.bind(this));
494 });
495 }.bind(this));
496 496
497 // The 'collect errors' checkbox. This should only be visible if the 497 // The 'collect errors' checkbox. This should only be visible if the
498 // error console is enabled - we can detect this by the existence of the 498 // error console is enabled - we can detect this by the existence of the
499 // |errorCollectionEnabled| property. 499 // |errorCollectionEnabled| property.
500 wrapper.setupColumn('collectErrors', '.error-collection-control input', 500 wrapper.setupColumn(
501 'change', function(e) { 501 'collectErrors', '.error-collection-control input', 'change',
502 chrome.developerPrivate.updateExtensionConfiguration({ 502 function(e) {
503 extensionId: extension.id, 503 chrome.developerPrivate.updateExtensionConfiguration(
504 errorCollection: e.target.checked 504 {extensionId: extension.id, errorCollection: e.target.checked});
505 }); 505 });
506 });
507 506
508 // The 'allow on all urls' checkbox. This should only be visible if 507 // The 'allow on all urls' checkbox. This should only be visible if
509 // active script restrictions are enabled. If they are not enabled, no 508 // active script restrictions are enabled. If they are not enabled, no
510 // extensions should want all urls. 509 // extensions should want all urls.
511 wrapper.setupColumn('allUrls', '.all-urls-control input', 'click', 510 wrapper.setupColumn(
512 function(e) { 511 'allUrls', '.all-urls-control input', 'click', function(e) {
513 chrome.developerPrivate.updateExtensionConfiguration({ 512 chrome.developerPrivate.updateExtensionConfiguration(
514 extensionId: extension.id, 513 {extensionId: extension.id, runOnAllUrls: e.target.checked});
515 runOnAllUrls: e.target.checked 514 });
516 });
517 });
518 515
519 // The 'allow file:// access' checkbox. 516 // The 'allow file:// access' checkbox.
520 wrapper.setupColumn('localUrls', '.file-access-control input', 'click', 517 wrapper.setupColumn(
521 function(e) { 518 'localUrls', '.file-access-control input', 'click', function(e) {
522 chrome.developerPrivate.updateExtensionConfiguration({ 519 chrome.developerPrivate.updateExtensionConfiguration(
523 extensionId: extension.id, 520 {extensionId: extension.id, fileAccess: e.target.checked});
524 fileAccess: e.target.checked 521 });
525 });
526 });
527 522
528 // The 'Reload' terminated link. 523 // The 'Reload' terminated link.
529 wrapper.setupColumn('terminatedReload', '.terminated-reload-link', 524 wrapper.setupColumn(
530 'click', function(e) { 525 'terminatedReload', '.terminated-reload-link', 'click', function(e) {
531 chrome.developerPrivate.reload(extension.id, {failQuietly: true}); 526 chrome.developerPrivate.reload(extension.id, {failQuietly: true});
532 }); 527 });
533 528
534 // The 'Repair' corrupted link. 529 // The 'Repair' corrupted link.
535 wrapper.setupColumn('repair', '.corrupted-repair-button', 'click', 530 wrapper.setupColumn(
536 function(e) { 531 'repair', '.corrupted-repair-button', 'click', function(e) {
537 chrome.developerPrivate.repairExtension(extension.id); 532 chrome.developerPrivate.repairExtension(extension.id);
538 }); 533 });
539 534
540 // The 'Enabled' checkbox. 535 // The 'Enabled' checkbox.
541 wrapper.setupColumn('enabled', '.enable-checkbox input', 'click', 536 wrapper.setupColumn(
542 function(e) { 537 'enabled', '.enable-checkbox input', 'click', function(e) {
543 var checked = e.target.checked; 538 var checked = e.target.checked;
544 // TODO(devlin): What should we do if this fails? Ideally we want to 539 // TODO(devlin): What should we do if this fails? Ideally we want to
545 // show some kind of error or feedback to the user if this fails. 540 // show some kind of error or feedback to the user if this fails.
546 chrome.management.setEnabled(extension.id, checked); 541 chrome.management.setEnabled(extension.id, checked);
547 542
548 // This may seem counter-intuitive (to not set/clear the checkmark) 543 // This may seem counter-intuitive (to not set/clear the checkmark)
549 // but this page will be updated asynchronously if the extension 544 // but this page will be updated asynchronously if the extension
550 // becomes enabled/disabled. It also might not become enabled or 545 // becomes enabled/disabled. It also might not become enabled or
551 // disabled, because the user might e.g. get prompted when enabling 546 // disabled, because the user might e.g. get prompted when enabling
552 // and choose not to. 547 // and choose not to.
553 e.preventDefault(); 548 e.preventDefault();
554 }); 549 });
555 550
556 // 'Remove' button. 551 // 'Remove' button.
557 var trash = cloneTemplate('trash'); 552 var trash = cloneTemplate('trash');
558 trash.title = loadTimeData.getString('extensionUninstall'); 553 trash.title = loadTimeData.getString('extensionUninstall');
559 554
560 wrapper.querySelector('.enable-controls').appendChild(trash); 555 wrapper.querySelector('.enable-controls').appendChild(trash);
561 556
562 wrapper.setupColumn('remove-enterprise', '.trash', 'click', function(e) { 557 wrapper.setupColumn('remove-enterprise', '.trash', 'click', function(e) {
563 trash.classList.add('open'); 558 trash.classList.add('open');
564 trash.classList.toggle('mouse-clicked', e.detail > 0); 559 trash.classList.toggle('mouse-clicked', e.detail > 0);
565 if (this.uninstallIsShowing_) 560 if (this.uninstallIsShowing_)
566 return; 561 return;
567 this.uninstallIsShowing_ = true; 562 this.uninstallIsShowing_ = true;
568 chrome.management.uninstall(extension.id, 563 chrome.management.uninstall(
569 {showConfirmDialog: true}, 564 extension.id, {showConfirmDialog: true}, function() {
570 function() { 565 // TODO(devlin): What should we do if the uninstall fails?
571 // TODO(devlin): What should we do if the uninstall fails? 566 this.uninstallIsShowing_ = false;
572 this.uninstallIsShowing_ = false;
573 567
574 if (trash.classList.contains('mouse-clicked')) 568 if (trash.classList.contains('mouse-clicked'))
575 trash.blur(); 569 trash.blur();
576 570
577 if (chrome.runtime.lastError) { 571 if (chrome.runtime.lastError) {
578 // The uninstall failed (e.g. a cancel). Allow the trash to close. 572 // The uninstall failed (e.g. a cancel). Allow the trash to
579 trash.classList.remove('open'); 573 // close.
580 } else { 574 trash.classList.remove('open');
581 // Leave the trash open if the uninstall succeded. Otherwise it can 575 } else {
582 // half-close right before it's removed when the DOM is modified. 576 // Leave the trash open if the uninstall succeded. Otherwise it
583 } 577 // can half-close right before it's removed when the DOM is
584 }.bind(this)); 578 // modified.
579 }
580 }.bind(this));
585 }.bind(this)); 581 }.bind(this));
586 582
587 // Maintain the order that nodes should be in when creating as well as 583 // Maintain the order that nodes should be in when creating as well as
588 // when adding only one new wrapper. 584 // when adding only one new wrapper.
589 this.insertBefore(wrapper, nextWrapper); 585 this.insertBefore(wrapper, nextWrapper);
590 this.updateWrapper_(extension, wrapper); 586 this.updateWrapper_(extension, wrapper);
591 587
592 var nextRow = this.focusGrid_.getRowForRoot(nextWrapper); // May be null. 588 var nextRow = this.focusGrid_.getRowForRoot(nextWrapper); // May be null.
593 this.focusGrid_.addRowBefore(wrapper.getFocusRow(), nextRow); 589 this.focusGrid_.addRowBefore(wrapper.getFocusRow(), nextRow);
594 }, 590 },
595 591
596 /** 592 /**
597 * Updates an HTML element for the extension metadata given in |extension|. 593 * Updates an HTML element for the extension metadata given in |extension|.
598 * @param {!chrome.developerPrivate.ExtensionInfo} extension A dictionary of 594 * @param {!chrome.developerPrivate.ExtensionInfo} extension A dictionary of
599 * extension metadata. 595 * extension metadata.
600 * @param {!Element} wrapper The extension wrapper element to update. 596 * @param {!Element} wrapper The extension wrapper element to update.
601 * @private 597 * @private
602 */ 598 */
603 updateWrapper_: function(extension, wrapper) { 599 updateWrapper_: function(extension, wrapper) {
604 var isActive = 600 var isActive =
605 extension.state == chrome.developerPrivate.ExtensionState.ENABLED; 601 extension.state == chrome.developerPrivate.ExtensionState.ENABLED;
606 wrapper.classList.toggle('inactive-extension', !isActive); 602 wrapper.classList.toggle('inactive-extension', !isActive);
607 wrapper.classList.remove('controlled', 'may-not-remove'); 603 wrapper.classList.remove('controlled', 'may-not-remove');
608 604
609 if (extension.controlledInfo) { 605 if (extension.controlledInfo) {
610 wrapper.classList.add('controlled'); 606 wrapper.classList.add('controlled');
611 } else if (!extension.userMayModify || 607 } else if (
612 extension.mustRemainInstalled || 608 !extension.userMayModify || extension.mustRemainInstalled ||
613 extension.dependentExtensions.length > 0) { 609 extension.dependentExtensions.length > 0) {
614 wrapper.classList.add('may-not-remove'); 610 wrapper.classList.add('may-not-remove');
615 } 611 }
616 612
617 var item = wrapper.querySelector('.extension-list-item'); 613 var item = wrapper.querySelector('.extension-list-item');
618 item.style.backgroundImage = 'url(' + extension.iconUrl + ')'; 614 item.style.backgroundImage = 'url(' + extension.iconUrl + ')';
619 615
620 this.setText_(wrapper, '.extension-title', extension.name); 616 this.setText_(wrapper, '.extension-title', extension.name);
621 this.setText_(wrapper, '.extension-version', extension.version); 617 this.setText_(wrapper, '.extension-version', extension.version);
622 this.setText_(wrapper, '.location-text', extension.locationText || ''); 618 this.setText_(wrapper, '.location-text', extension.locationText || '');
623 this.setText_(wrapper, '.blacklist-text', extension.blacklistText || ''); 619 this.setText_(wrapper, '.blacklist-text', extension.blacklistText || '');
624 this.setText_(wrapper, '.extension-description', extension.description); 620 this.setText_(wrapper, '.extension-description', extension.description);
625 621
626 // The 'allow in incognito' checkbox. 622 // The 'allow in incognito' checkbox.
627 this.updateVisibility_(wrapper, '.incognito-control', 623 this.updateVisibility_(
628 isActive && this.incognitoAvailable_, 624 wrapper, '.incognito-control', isActive && this.incognitoAvailable_,
629 function(item) { 625 function(item) {
630 var incognito = item.querySelector('input'); 626 var incognito = item.querySelector('input');
631 incognito.disabled = !extension.incognitoAccess.isEnabled; 627 incognito.disabled = !extension.incognitoAccess.isEnabled;
632 incognito.checked = extension.incognitoAccess.isActive; 628 incognito.checked = extension.incognitoAccess.isActive;
633 }); 629 });
634 var showButterBar = isActive && 630 var showButterBar = isActive && extension.incognitoAccess.isActive &&
635 extension.incognitoAccess.isActive && 631 extension.type != ExtensionType.HOSTED_APP;
636 extension.type != ExtensionType.HOSTED_APP;
637 // The 'allow in incognito' butter bar. 632 // The 'allow in incognito' butter bar.
638 this.updateVisibility_(wrapper, '.butter-bar', showButterBar); 633 this.updateVisibility_(wrapper, '.butter-bar', showButterBar);
639 634
640 // The 'collect errors' checkbox. This should only be visible if the 635 // The 'collect errors' checkbox. This should only be visible if the
641 // error console is enabled - we can detect this by the existence of the 636 // error console is enabled - we can detect this by the existence of the
642 // |errorCollectionEnabled| property. 637 // |errorCollectionEnabled| property.
643 this.updateVisibility_( 638 this.updateVisibility_(
644 wrapper, '.error-collection-control', 639 wrapper, '.error-collection-control',
645 isActive && extension.errorCollection.isEnabled, 640 isActive && extension.errorCollection.isEnabled, function(item) {
646 function(item) { 641 item.querySelector('input').checked =
647 item.querySelector('input').checked = 642 extension.errorCollection.isActive;
648 extension.errorCollection.isActive; 643 });
649 });
650 644
651 // The 'allow on all urls' checkbox. This should only be visible if 645 // The 'allow on all urls' checkbox. This should only be visible if
652 // active script restrictions are enabled. If they are not enabled, no 646 // active script restrictions are enabled. If they are not enabled, no
653 // extensions should want all urls. 647 // extensions should want all urls.
654 this.updateVisibility_( 648 this.updateVisibility_(
655 wrapper, '.all-urls-control', 649 wrapper, '.all-urls-control',
656 isActive && extension.runOnAllUrls.isEnabled, 650 isActive && extension.runOnAllUrls.isEnabled, function(item) {
657 function(item) { 651 item.querySelector('input').checked =
658 item.querySelector('input').checked = extension.runOnAllUrls.isActive; 652 extension.runOnAllUrls.isActive;
659 }); 653 });
660 654
661 // The 'allow file:// access' checkbox. 655 // The 'allow file:// access' checkbox.
662 this.updateVisibility_(wrapper, '.file-access-control', 656 this.updateVisibility_(
663 isActive && extension.fileAccess.isEnabled, 657 wrapper, '.file-access-control',
664 function(item) { 658 isActive && extension.fileAccess.isEnabled, function(item) {
665 item.querySelector('input').checked = extension.fileAccess.isActive; 659 item.querySelector('input').checked = extension.fileAccess.isActive;
666 }); 660 });
667 661
668 // The 'Options' button or link, depending on its behaviour. 662 // The 'Options' button or link, depending on its behaviour.
669 var optionsEnabled = isActive && !!extension.optionsPage; 663 var optionsEnabled = isActive && !!extension.optionsPage;
670 this.updateVisibility_(wrapper, '.options-link', optionsEnabled && 664 this.updateVisibility_(
671 extension.optionsPage.openInTab); 665 wrapper, '.options-link',
672 this.updateVisibility_(wrapper, '.options-button', optionsEnabled && 666 optionsEnabled && extension.optionsPage.openInTab);
673 !extension.optionsPage.openInTab); 667 this.updateVisibility_(
668 wrapper, '.options-button',
669 optionsEnabled && !extension.optionsPage.openInTab);
674 670
675 // The 'View in Web Store/View Web Site' link. 671 // The 'View in Web Store/View Web Site' link.
676 var siteLinkEnabled = !!extension.homePage.url && 672 var siteLinkEnabled =
677 !this.enableAppInfoDialog_; 673 !!extension.homePage.url && !this.enableAppInfoDialog_;
678 this.updateVisibility_(wrapper, '.site-link', siteLinkEnabled, 674 this.updateVisibility_(
679 function(item) { 675 wrapper, '.site-link', siteLinkEnabled, function(item) {
680 item.href = extension.homePage.url; 676 item.href = extension.homePage.url;
681 item.textContent = loadTimeData.getString( 677 item.textContent = loadTimeData.getString(
682 extension.homePage.specified ? 'extensionSettingsVisitWebsite' : 678 extension.homePage.specified ?
683 'extensionSettingsVisitWebStore'); 679 'extensionSettingsVisitWebsite' :
684 }); 680 'extensionSettingsVisitWebStore');
681 });
685 682
686 var isUnpacked = 683 var isUnpacked =
687 extension.location == chrome.developerPrivate.Location.UNPACKED; 684 extension.location == chrome.developerPrivate.Location.UNPACKED;
688 // The 'Reload' link. 685 // The 'Reload' link.
689 this.updateVisibility_(wrapper, '.reload-link', isActive && isUnpacked); 686 this.updateVisibility_(wrapper, '.reload-link', isActive && isUnpacked);
690 687
691 // The 'Launch' link. 688 // The 'Launch' link.
692 this.updateVisibility_( 689 this.updateVisibility_(
693 wrapper, '.launch-link', 690 wrapper, '.launch-link',
694 isUnpacked && extension.type == ExtensionType.PLATFORM_APP && 691 isUnpacked && extension.type == ExtensionType.PLATFORM_APP &&
695 isActive); 692 isActive);
696 693
697 // The 'Errors' link. 694 // The 'Errors' link.
698 var hasErrors = extension.runtimeErrors.length > 0 || 695 var hasErrors = extension.runtimeErrors.length > 0 ||
699 extension.manifestErrors.length > 0; 696 extension.manifestErrors.length > 0;
700 this.updateVisibility_(wrapper, '.errors-link', hasErrors, 697 this.updateVisibility_(
701 function(item) { 698 wrapper, '.errors-link', hasErrors, function(item) {
702 var Level = chrome.developerPrivate.ErrorLevel; 699 var Level = chrome.developerPrivate.ErrorLevel;
703 700
704 var map = {}; 701 var map = {};
705 map[Level.LOG] = {weight: 0, name: 'extension-error-info-icon'}; 702 map[Level.LOG] = {weight: 0, name: 'extension-error-info-icon'};
706 map[Level.WARN] = {weight: 1, name: 'extension-error-warning-icon'}; 703 map[Level.WARN] = {weight: 1, name: 'extension-error-warning-icon'};
707 map[Level.ERROR] = {weight: 2, name: 'extension-error-fatal-icon'}; 704 map[Level.ERROR] = {weight: 2, name: 'extension-error-fatal-icon'};
708 705
709 // Find the highest severity of all the errors; manifest errors all have 706 // Find the highest severity of all the errors; manifest errors all
710 // a 'warning' level severity. 707 // have a 'warning' level severity.
711 var highestSeverity = extension.runtimeErrors.reduce( 708 var highestSeverity =
712 function(prev, error) { 709 extension.runtimeErrors.reduce(function(prev, error) {
713 return map[error.severity].weight > map[prev].weight ? 710 return map[error.severity].weight > map[prev].weight ?
714 error.severity : prev; 711 error.severity :
715 }, extension.manifestErrors.length ? Level.WARN : Level.LOG); 712 prev;
713 }, extension.manifestErrors.length ? Level.WARN : Level.LOG);
716 714
717 // Adjust the class on the icon. 715 // Adjust the class on the icon.
718 var icon = item.querySelector('.extension-error-icon'); 716 var icon = item.querySelector('.extension-error-icon');
719 // TODO(hcarmona): Populate alt text with a proper description since 717 // TODO(hcarmona): Populate alt text with a proper description since
720 // this icon conveys the severity of the error. (info, warning, fatal). 718 // this icon conveys the severity of the error. (info, warning,
721 icon.alt = ''; 719 // fatal).
722 icon.className = 'extension-error-icon'; // Remove other classes. 720 icon.alt = '';
723 icon.classList.add(map[highestSeverity].name); 721 icon.className = 'extension-error-icon'; // Remove other classes.
724 }); 722 icon.classList.add(map[highestSeverity].name);
723 });
725 724
726 // The 'Reload' terminated link. 725 // The 'Reload' terminated link.
727 var isTerminated = 726 var isTerminated =
728 extension.state == chrome.developerPrivate.ExtensionState.TERMINATED; 727 extension.state == chrome.developerPrivate.ExtensionState.TERMINATED;
729 this.updateVisibility_(wrapper, '.terminated-reload-link', isTerminated); 728 this.updateVisibility_(wrapper, '.terminated-reload-link', isTerminated);
730 729
731 // The 'Repair' corrupted link. 730 // The 'Repair' corrupted link.
732 var canRepair = !isTerminated && 731 var canRepair = !isTerminated &&
733 extension.disableReasons.corruptInstall && 732 extension.disableReasons.corruptInstall &&
734 extension.location == 733 extension.location == chrome.developerPrivate.Location.FROM_STORE;
735 chrome.developerPrivate.Location.FROM_STORE;
736 this.updateVisibility_(wrapper, '.corrupted-repair-button', canRepair); 734 this.updateVisibility_(wrapper, '.corrupted-repair-button', canRepair);
737 735
738 // The 'Enabled' checkbox. 736 // The 'Enabled' checkbox.
739 var isOK = !isTerminated && !canRepair; 737 var isOK = !isTerminated && !canRepair;
740 this.updateVisibility_(wrapper, '.enable-checkbox', isOK, function(item) { 738 this.updateVisibility_(wrapper, '.enable-checkbox', isOK, function(item) {
741 var enableCheckboxDisabled = 739 var enableCheckboxDisabled = !extension.userMayModify ||
742 !extension.userMayModify ||
743 extension.disableReasons.suspiciousInstall || 740 extension.disableReasons.suspiciousInstall ||
744 extension.disableReasons.corruptInstall || 741 extension.disableReasons.corruptInstall ||
745 extension.disableReasons.updateRequired || 742 extension.disableReasons.updateRequired ||
746 extension.dependentExtensions.length > 0 || 743 extension.dependentExtensions.length > 0 ||
747 extension.state == 744 extension.state ==
748 chrome.developerPrivate.ExtensionState.BLACKLISTED; 745 chrome.developerPrivate.ExtensionState.BLACKLISTED;
749 item.querySelector('input').disabled = enableCheckboxDisabled; 746 item.querySelector('input').disabled = enableCheckboxDisabled;
750 item.querySelector('input').checked = isActive; 747 item.querySelector('input').checked = isActive;
751 }); 748 });
752 749
(...skipping 29 matching lines...) Expand all
782 controlNode.removeChild(indicator); 779 controlNode.removeChild(indicator);
783 } 780 }
784 781
785 // Developer mode //////////////////////////////////////////////////////// 782 // Developer mode ////////////////////////////////////////////////////////
786 783
787 // First we have the id. 784 // First we have the id.
788 var idLabel = wrapper.querySelector('.extension-id'); 785 var idLabel = wrapper.querySelector('.extension-id');
789 idLabel.textContent = ' ' + extension.id; 786 idLabel.textContent = ' ' + extension.id;
790 787
791 // Then the path, if provided by unpacked extension. 788 // Then the path, if provided by unpacked extension.
792 this.updateVisibility_(wrapper, '.load-path', isUnpacked, 789 this.updateVisibility_(wrapper, '.load-path', isUnpacked, function(item) {
793 function(item) {
794 item.querySelector('a:first-of-type').textContent = 790 item.querySelector('a:first-of-type').textContent =
795 ' ' + extension.prettifiedPath; 791 ' ' + extension.prettifiedPath;
796 }); 792 });
797 793
798 // Then the 'managed, cannot uninstall/disable' message. 794 // Then the 'managed, cannot uninstall/disable' message.
799 // We would like to hide managed installed message since this 795 // We would like to hide managed installed message since this
800 // extension is disabled. 796 // extension is disabled.
801 var isRequired = 797 var isRequired =
802 !extension.userMayModify || extension.mustRemainInstalled; 798 !extension.userMayModify || extension.mustRemainInstalled;
803 this.updateVisibility_(wrapper, '.managed-message', isRequired && 799 this.updateVisibility_(
804 !extension.disableReasons.updateRequired); 800 wrapper, '.managed-message',
801 isRequired && !extension.disableReasons.updateRequired);
805 802
806 // Then the 'This isn't from the webstore, looks suspicious' message. 803 // Then the 'This isn't from the webstore, looks suspicious' message.
807 var isSuspicious = extension.disableReasons.suspiciousInstall; 804 var isSuspicious = extension.disableReasons.suspiciousInstall;
808 this.updateVisibility_(wrapper, '.suspicious-install-message', 805 this.updateVisibility_(
809 !isRequired && isSuspicious); 806 wrapper, '.suspicious-install-message', !isRequired && isSuspicious);
810 807
811 // Then the 'This is a corrupt extension' message. 808 // Then the 'This is a corrupt extension' message.
812 this.updateVisibility_(wrapper, '.corrupt-install-message', !isRequired && 809 this.updateVisibility_(
813 extension.disableReasons.corruptInstall); 810 wrapper, '.corrupt-install-message',
811 !isRequired && extension.disableReasons.corruptInstall);
814 812
815 // Then the 'An update required by enterprise policy' message. Note that 813 // Then the 'An update required by enterprise policy' message. Note that
816 // a force-installed extension might be disabled due to being outdated 814 // a force-installed extension might be disabled due to being outdated
817 // as well. 815 // as well.
818 this.updateVisibility_(wrapper, '.update-required-message', 816 this.updateVisibility_(
819 extension.disableReasons.updateRequired); 817 wrapper, '.update-required-message',
818 extension.disableReasons.updateRequired);
820 819
821 // The 'following extensions depend on this extension' list. 820 // The 'following extensions depend on this extension' list.
822 var hasDependents = extension.dependentExtensions.length > 0; 821 var hasDependents = extension.dependentExtensions.length > 0;
823 wrapper.classList.toggle('developer-extras', hasDependents); 822 wrapper.classList.toggle('developer-extras', hasDependents);
824 this.updateVisibility_(wrapper, '.dependent-extensions-message', 823 this.updateVisibility_(
825 hasDependents, function(item) { 824 wrapper, '.dependent-extensions-message', hasDependents,
826 var dependentList = item.querySelector('ul'); 825 function(item) {
827 dependentList.textContent = ''; 826 var dependentList = item.querySelector('ul');
828 extension.dependentExtensions.forEach(function(dependentExtension) { 827 dependentList.textContent = '';
829 var depNode = cloneTemplate('dependent-list-item'); 828 extension.dependentExtensions.forEach(function(dependentExtension) {
830 depNode.querySelector('.dep-extension-title').textContent = 829 var depNode = cloneTemplate('dependent-list-item');
831 dependentExtension.name; 830 depNode.querySelector('.dep-extension-title').textContent =
832 depNode.querySelector('.dep-extension-id').textContent = 831 dependentExtension.name;
833 dependentExtension.id; 832 depNode.querySelector('.dep-extension-id').textContent =
834 dependentList.appendChild(depNode); 833 dependentExtension.id;
835 }, this); 834 dependentList.appendChild(depNode);
836 }.bind(this)); 835 }, this);
836 }.bind(this));
837 837
838 // The active views. 838 // The active views.
839 this.updateVisibility_(wrapper, '.active-views', 839 this.updateVisibility_(
840 extension.views.length > 0, function(item) { 840 wrapper, '.active-views', extension.views.length > 0, function(item) {
841 var link = item.querySelector('a'); 841 var link = item.querySelector('a');
842 842
843 // Link needs to be an only child before the list is updated. 843 // Link needs to be an only child before the list is updated.
844 while (link.nextElementSibling) 844 while (link.nextElementSibling)
845 item.removeChild(link.nextElementSibling); 845 item.removeChild(link.nextElementSibling);
846 846
847 // Link needs to be cleaned up if it was used before. 847 // Link needs to be cleaned up if it was used before.
848 link.textContent = ''; 848 link.textContent = '';
849 if (link.clickHandler) 849 if (link.clickHandler)
850 link.removeEventListener('click', link.clickHandler); 850 link.removeEventListener('click', link.clickHandler);
851 851
852 extension.views.forEach(function(view, i) { 852 extension.views.forEach(function(view, i) {
853 if (view.type == chrome.developerPrivate.ViewType.EXTENSION_DIALOG || 853 if (view.type ==
854 view.type == chrome.developerPrivate.ViewType.EXTENSION_POPUP) { 854 chrome.developerPrivate.ViewType.EXTENSION_DIALOG ||
855 return; 855 view.type ==
856 } 856 chrome.developerPrivate.ViewType.EXTENSION_POPUP) {
857 var displayName; 857 return;
858 if (view.url.startsWith('chrome-extension://')) { 858 }
859 var pathOffset = 'chrome-extension://'.length + 32 + 1; 859 var displayName;
860 displayName = view.url.substring(pathOffset); 860 if (view.url.startsWith('chrome-extension://')) {
861 if (displayName == '_generated_background_page.html') 861 var pathOffset = 'chrome-extension://'.length + 32 + 1;
862 displayName = loadTimeData.getString('backgroundPage'); 862 displayName = view.url.substring(pathOffset);
863 } else { 863 if (displayName == '_generated_background_page.html')
864 displayName = view.url; 864 displayName = loadTimeData.getString('backgroundPage');
865 } 865 } else {
866 var label = displayName + 866 displayName = view.url;
867 (view.incognito ? 867 }
868 ' ' + loadTimeData.getString('viewIncognito') : '') + 868 var label = displayName +
869 (view.renderProcessId == -1 ? 869 (view.incognito ?
870 ' ' + loadTimeData.getString('viewInactive') : '') + 870 ' ' + loadTimeData.getString('viewIncognito') :
871 (view.isIframe ? 871 '') +
872 ' ' + loadTimeData.getString('viewIframe') : ''); 872 (view.renderProcessId == -1 ?
873 link.textContent = label; 873 ' ' + loadTimeData.getString('viewInactive') :
874 link.clickHandler = function(e) { 874 '') +
875 chrome.developerPrivate.openDevTools({ 875 (view.isIframe ? ' ' + loadTimeData.getString('viewIframe') :
876 extensionId: extension.id, 876 '');
877 renderProcessId: view.renderProcessId, 877 link.textContent = label;
878 renderViewId: view.renderViewId, 878 link.clickHandler = function(e) {
879 incognito: view.incognito 879 chrome.developerPrivate.openDevTools({
880 extensionId: extension.id,
881 renderProcessId: view.renderProcessId,
882 renderViewId: view.renderViewId,
883 incognito: view.incognito
884 });
885 };
886 link.addEventListener('click', link.clickHandler);
887
888 if (i < extension.views.length - 1) {
889 link = link.cloneNode(true);
890 item.appendChild(link);
891 }
892
893 wrapper.setupColumn('activeView', '.active-views a:last-of-type');
880 }); 894 });
881 }; 895 });
882 link.addEventListener('click', link.clickHandler);
883
884 if (i < extension.views.length - 1) {
885 link = link.cloneNode(true);
886 item.appendChild(link);
887 }
888
889 wrapper.setupColumn('activeView', '.active-views a:last-of-type');
890 });
891 });
892 896
893 // The extension warnings (describing runtime issues). 897 // The extension warnings (describing runtime issues).
894 this.updateVisibility_(wrapper, '.extension-warnings', 898 this.updateVisibility_(
895 extension.runtimeWarnings.length > 0, 899 wrapper, '.extension-warnings', extension.runtimeWarnings.length > 0,
896 function(item) { 900 function(item) {
897 var warningList = item.querySelector('ul'); 901 var warningList = item.querySelector('ul');
898 warningList.textContent = ''; 902 warningList.textContent = '';
899 extension.runtimeWarnings.forEach(function(warning) { 903 extension.runtimeWarnings.forEach(function(warning) {
900 var li = document.createElement('li'); 904 var li = document.createElement('li');
901 warningList.appendChild(li).innerText = warning; 905 warningList.appendChild(li).innerText = warning;
902 }); 906 });
903 }); 907 });
904 908
905 // Install warnings. 909 // Install warnings.
906 this.updateVisibility_(wrapper, '.install-warnings', 910 this.updateVisibility_(
907 extension.installWarnings.length > 0, 911 wrapper, '.install-warnings', extension.installWarnings.length > 0,
908 function(item) { 912 function(item) {
909 var installWarningList = item.querySelector('ul'); 913 var installWarningList = item.querySelector('ul');
910 installWarningList.textContent = ''; 914 installWarningList.textContent = '';
911 if (extension.installWarnings) { 915 if (extension.installWarnings) {
912 extension.installWarnings.forEach(function(warning) { 916 extension.installWarnings.forEach(function(warning) {
913 var li = document.createElement('li'); 917 var li = document.createElement('li');
914 li.innerText = warning; 918 li.innerText = warning;
915 installWarningList.appendChild(li); 919 installWarningList.appendChild(li);
920 });
921 }
916 }); 922 });
917 }
918 });
919 923
920 if (location.hash.substr(1) == extension.id) { 924 if (location.hash.substr(1) == extension.id) {
921 // Scroll beneath the fixed header so that the extension is not 925 // Scroll beneath the fixed header so that the extension is not
922 // obscured. 926 // obscured.
923 var topScroll = wrapper.offsetTop - $('page-header').offsetHeight; 927 var topScroll = wrapper.offsetTop - $('page-header').offsetHeight;
924 var pad = parseInt(window.getComputedStyle(wrapper).marginTop, 10); 928 var pad = parseInt(window.getComputedStyle(wrapper).marginTop, 10);
925 if (!isNaN(pad)) 929 if (!isNaN(pad))
926 topScroll -= pad / 2; 930 topScroll -= pad / 2;
927 setScrollTopForDocument(document, topScroll); 931 setScrollTopForDocument(document, topScroll);
928 } 932 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 * @param {boolean} scroll Whether the page should scroll to the extension 968 * @param {boolean} scroll Whether the page should scroll to the extension
965 * @private 969 * @private
966 */ 970 */
967 showEmbeddedExtensionOptions_: function(extensionId, scroll) { 971 showEmbeddedExtensionOptions_: function(extensionId, scroll) {
968 if (this.optionsShown_) 972 if (this.optionsShown_)
969 return; 973 return;
970 974
971 // Get the extension from the given id. 975 // Get the extension from the given id.
972 var extension = this.extensions_.filter(function(extension) { 976 var extension = this.extensions_.filter(function(extension) {
973 return extension.state == 977 return extension.state ==
974 chrome.developerPrivate.ExtensionState.ENABLED && 978 chrome.developerPrivate.ExtensionState.ENABLED &&
975 extension.id == extensionId; 979 extension.id == extensionId;
976 })[0]; 980 })[0];
977 981
978 if (!extension) 982 if (!extension)
979 return; 983 return;
980 984
981 if (scroll) 985 if (scroll)
982 this.scrollToWrapper_(extensionId); 986 this.scrollToWrapper_(extensionId);
983 987
984 // Add the options query string. Corner case: the 'options' query string 988 // Add the options query string. Corner case: the 'options' query string
985 // will clobber the 'id' query string if the options link is clicked when 989 // will clobber the 'id' query string if the options link is clicked when
986 // 'id' is in the URL, or if both query strings are in the URL. 990 // 'id' is in the URL, or if both query strings are in the URL.
987 window.history.replaceState({}, '', '/?options=' + extensionId); 991 window.history.replaceState({}, '', '/?options=' + extensionId);
988 992
989 var overlay = extensions.ExtensionOptionsOverlay.getInstance(); 993 var overlay = extensions.ExtensionOptionsOverlay.getInstance();
990 var shownCallback = function() { 994 var shownCallback = function() {
991 // This overlay doesn't get focused automatically as <extensionoptions> 995 // This overlay doesn't get focused automatically as <extensionoptions>
992 // is created after the overlay is shown. 996 // is created after the overlay is shown.
993 if (cr.ui.FocusOutlineManager.forDocument(document).visible) 997 if (cr.ui.FocusOutlineManager.forDocument(document).visible)
994 overlay.setInitialFocus(); 998 overlay.setInitialFocus();
995 }; 999 };
996 overlay.setExtensionAndShow(extensionId, extension.name, 1000 overlay.setExtensionAndShow(
997 extension.iconUrl, shownCallback); 1001 extensionId, extension.name, extension.iconUrl, shownCallback);
998 this.optionsShown_ = true; 1002 this.optionsShown_ = true;
999 1003
1000 var self = this; 1004 var self = this;
1001 $('overlay').addEventListener('cancelOverlay', function f() { 1005 $('overlay').addEventListener('cancelOverlay', function f() {
1002 self.optionsShown_ = false; 1006 self.optionsShown_ = false;
1003 $('overlay').removeEventListener('cancelOverlay', f); 1007 $('overlay').removeEventListener('cancelOverlay', f);
1004 1008
1005 // Remove the options query string. 1009 // Remove the options query string.
1006 window.history.replaceState({}, '', '/'); 1010 window.history.replaceState({}, '', '/');
1007 }); 1011 });
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 this.createWrapper_(extension, nextExt ? $(nextExt.id) : null); 1059 this.createWrapper_(extension, nextExt ? $(nextExt.id) : null);
1056 } 1060 }
1057 } 1061 }
1058 }; 1062 };
1059 1063
1060 return { 1064 return {
1061 ExtensionList: ExtensionList, 1065 ExtensionList: ExtensionList,
1062 ExtensionListDelegate: ExtensionListDelegate 1066 ExtensionListDelegate: ExtensionListDelegate
1063 }; 1067 };
1064 }); 1068 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698