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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 /** @private {!Array<ExtensionInfo>} */ | 
| 150 div.extensions_ = []; | 150 div.extensions_ = []; | 
| 151 chrome.developerPrivate.onItemStateChanged.addListener( | |
| 152 div.onItemStateChanged_.bind(div)); | |
| 151 return div; | 153 return div; | 
| 152 } | 154 } | 
| 153 | 155 | 
| 154 /** | 156 /** | 
| 155 * @type {Object<string, number>} A map from extension id to last reloaded | 157 * @type {Object<string, number>} A map from extension id to last reloaded | 
| 156 * timestamp. The timestamp is recorded when the user click the 'Reload' | 158 * timestamp. The timestamp is recorded when the user click the 'Reload' | 
| 157 * link. It is used to refresh the icon of an unpacked extension. | 159 * link. It is used to refresh the icon of an unpacked extension. | 
| 158 * This persists between calls to decorate. | 160 * This persists between calls to decorate. | 
| 159 */ | 161 */ | 
| 160 var extensionReloadedTimestamp = {}; | 162 var extensionReloadedTimestamp = {}; | 
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 row.setupColumn('.reload-link', 'localReload', 'click', function(e) { | 443 row.setupColumn('.reload-link', 'localReload', 'click', function(e) { | 
| 442 chrome.developerPrivate.reload(extension.id, {failQuietly: true}); | 444 chrome.developerPrivate.reload(extension.id, {failQuietly: true}); | 
| 443 extensionReloadedTimestamp[extension.id] = Date.now(); | 445 extensionReloadedTimestamp[extension.id] = Date.now(); | 
| 444 }); | 446 }); | 
| 445 | 447 | 
| 446 // The 'Launch' link. | 448 // The 'Launch' link. | 
| 447 row.setupColumn('.launch-link', 'launch', 'click', function(e) { | 449 row.setupColumn('.launch-link', 'launch', 'click', function(e) { | 
| 448 chrome.send('extensionSettingsLaunch', [extension.id]); | 450 chrome.send('extensionSettingsLaunch', [extension.id]); | 
| 449 }); | 451 }); | 
| 450 | 452 | 
| 453 row.setupColumn('.errors-link', 'errors', 'click', function(e) { | |
| 454 var extensionId = extension.id; | |
| 455 var newEx = this.extensions_.filter(function(e) { | |
| 
 
Dan Beam
2015/04/22 21:02:38
what if this.extensions_ is empty?
 
Devlin
2015/04/22 23:17:32
I don't think it can be - there'd be no node to cr
 
 | |
| 456 return e.state == chrome.developerPrivate.ExtensionState.ENABLED && | |
| 457 e.id == extensionId; | |
| 458 })[0]; | |
| 459 var errors = newEx.manifestErrors.concat(newEx.runtimeErrors); | |
| 460 extensions.ExtensionErrorOverlay.getInstance().setErrorsAndShowOverlay( | |
| 461 errors, extensionId, newEx.name); | |
| 462 }.bind(this)); | |
| 463 | |
| 451 // The 'Reload' terminated link. | 464 // The 'Reload' terminated link. | 
| 452 row.setupColumn('.terminated-reload-link', 'terminatedReload', 'click', | 465 row.setupColumn('.terminated-reload-link', 'terminatedReload', 'click', | 
| 453 function(e) { | 466 function(e) { | 
| 454 chrome.developerPrivate.reload(extension.id, {failQuietly: true}); | 467 chrome.developerPrivate.reload(extension.id, {failQuietly: true}); | 
| 455 }); | 468 }); | 
| 456 | 469 | 
| 457 // The 'Repair' corrupted link. | 470 // The 'Repair' corrupted link. | 
| 458 row.setupColumn('.corrupted-repair-button', 'repair', 'click', | 471 row.setupColumn('.corrupted-repair-button', 'repair', 'click', | 
| 459 function(e) { | 472 function(e) { | 
| 460 chrome.send('extensionSettingsRepair', [extension.id]); | 473 chrome.send('extensionSettingsRepair', [extension.id]); | 
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 640 var isUnpacked = | 653 var isUnpacked = | 
| 641 extension.location == chrome.developerPrivate.Location.UNPACKED; | 654 extension.location == chrome.developerPrivate.Location.UNPACKED; | 
| 642 // The 'Reload' link. | 655 // The 'Reload' link. | 
| 643 this.updateVisibility_(row, '.reload-link', isUnpacked); | 656 this.updateVisibility_(row, '.reload-link', isUnpacked); | 
| 644 | 657 | 
| 645 // The 'Launch' link. | 658 // The 'Launch' link. | 
| 646 this.updateVisibility_( | 659 this.updateVisibility_( | 
| 647 row, '.launch-link', | 660 row, '.launch-link', | 
| 648 isUnpacked && extension.type == | 661 isUnpacked && extension.type == | 
| 649 chrome.developerPrivate.ExtensionType.PLATFORM_APP); | 662 chrome.developerPrivate.ExtensionType.PLATFORM_APP); | 
| 650 | 663 | 
| 
 
Dan Beam
2015/04/22 21:02:38
var errors = extension.runtimeErrors.length || ext
 
Devlin
2015/04/22 23:17:32
Done.
 
 | |
| 664 // The 'Errors' link. | |
| 665 this.updateVisibility_( | |
| 666 row, '.errors-link', | |
| 667 extension.runtimeErrors.length > 0 || | |
| 668 extension.manifestErrors.length > 0, | |
| 669 function(item) { | |
| 670 var Level = chrome.developerPrivate.ErrorLevel; | |
| 
 
Dan Beam
2015/04/28 03:47:03
\n
 
Devlin
2015/04/29 16:08:37
Done.
 
 | |
| 671 var map = {}; | |
| 672 map[Level.LOG] = {weight: 0, name: 'extension-error-info-icon'}; | |
| 673 map[Level.WARN] = {weight: 1, name: 'extension-error-warning-icon'}; | |
| 674 map[Level.ERROR] = {weight: 2, name: 'extension-error-fatal-icon'}; | |
| 
 
Dan Beam
2015/04/28 03:47:03
\n
 
Devlin
2015/04/29 16:08:37
Done.
 
 | |
| 675 // Find the highest severity of all the errors; manifest errors all have | |
| 676 // a 'warning' level severity. | |
| 677 var highSeverity = extension.runtimeErrors.reduce( | |
| 
 
Dan Beam
2015/04/28 03:47:03
nit: highestSeverity or mostSevere
 
Devlin
2015/04/29 16:08:37
Done.
 
 | |
| 678 function(prev, error) { | |
| 679 return map[error.severity].weight > map[prev].weight ? | |
| 680 error.severity : prev; | |
| 681 }, extension.manifestErrors.length ? Level.WARN : Level.LOG); | |
| 
 
Dan Beam
2015/04/22 21:02:38
i have no idea what this does
 
Devlin
2015/04/22 23:17:32
Comment on line 675. :)
It goes through and looks
 
 | |
| 682 | |
| 683 // Adjust the class on the icon. | |
| 684 var icon = item.querySelector('.extension-error-icon'); | |
| 685 icon.className = 'extension-error-icon'; | |
| 
 
Dan Beam
2015/04/22 21:02:38
and the point of this is... to remove other classe
 
Devlin
2015/04/22 23:17:32
Exactly.  We could also remove all the possibles,
 
Dan Beam
2015/04/28 03:47:03
leave as is, maybe add "  // Remove other classes.
 
Devlin
2015/04/29 16:08:37
Done.
 
 | |
| 686 icon.classList.add(map[highSeverity].name); | |
| 687 }); | |
| 688 | |
| 651 // The 'Reload' terminated link. | 689 // The 'Reload' terminated link. | 
| 652 var isTerminated = | 690 var isTerminated = | 
| 653 extension.state == chrome.developerPrivate.ExtensionState.TERMINATED; | 691 extension.state == chrome.developerPrivate.ExtensionState.TERMINATED; | 
| 654 this.updateVisibility_(row, '.terminated-reload-link', isTerminated); | 692 this.updateVisibility_(row, '.terminated-reload-link', isTerminated); | 
| 655 | 693 | 
| 656 // The 'Repair' corrupted link. | 694 // The 'Repair' corrupted link. | 
| 657 var canRepair = !isTerminated && | 695 var canRepair = !isTerminated && | 
| 658 extension.disableReasons.corruptInstall && | 696 extension.disableReasons.corruptInstall && | 
| 659 extension.location == | 697 extension.location == | 
| 660 chrome.developerPrivate.Location.FROM_STORE; | 698 chrome.developerPrivate.Location.FROM_STORE; | 
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 826 extension.runtimeWarnings.length > 0, | 864 extension.runtimeWarnings.length > 0, | 
| 827 function(item) { | 865 function(item) { | 
| 828 var warningList = item.querySelector('ul'); | 866 var warningList = item.querySelector('ul'); | 
| 829 warningList.textContent = ''; | 867 warningList.textContent = ''; | 
| 830 extension.runtimeWarnings.forEach(function(warning) { | 868 extension.runtimeWarnings.forEach(function(warning) { | 
| 831 var li = document.createElement('li'); | 869 var li = document.createElement('li'); | 
| 832 warningList.appendChild(li).innerText = warning; | 870 warningList.appendChild(li).innerText = warning; | 
| 833 }); | 871 }); | 
| 834 }); | 872 }); | 
| 835 | 873 | 
| 836 // If the ErrorConsole is enabled, we should have manifest and/or runtime | |
| 837 // errors. Otherwise, we may have install warnings. We should not have | |
| 838 // both ErrorConsole errors and install warnings. | |
| 839 // Errors. | |
| 840 this.updateErrors_(row.querySelector('.manifest-errors'), | |
| 841 'dev-manifestErrors', extension.manifestErrors); | |
| 842 this.updateErrors_(row.querySelector('.runtime-errors'), | |
| 843 'dev-runtimeErrors', extension.runtimeErrors); | |
| 844 | |
| 845 // Install warnings. | 874 // Install warnings. | 
| 846 this.updateVisibility_(row, '.install-warnings', | 875 this.updateVisibility_(row, '.install-warnings', | 
| 847 extension.installWarnings.length > 0, | 876 extension.installWarnings.length > 0, | 
| 848 function(item) { | 877 function(item) { | 
| 849 var installWarningList = item.querySelector('ul'); | 878 var installWarningList = item.querySelector('ul'); | 
| 850 installWarningList.textContent = ''; | 879 installWarningList.textContent = ''; | 
| 851 if (extension.installWarnings) { | 880 if (extension.installWarnings) { | 
| 852 extension.installWarnings.forEach(function(warning) { | 881 extension.installWarnings.forEach(function(warning) { | 
| 853 var li = document.createElement('li'); | 882 var li = document.createElement('li'); | 
| 854 li.innerText = warning; | 883 li.innerText = warning; | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 894 * @private | 923 * @private | 
| 895 */ | 924 */ | 
| 896 updateVisibility_: function(node, query, visible, opt_shownCallback) { | 925 updateVisibility_: function(node, query, visible, opt_shownCallback) { | 
| 897 var item = assert(node.querySelector(query)); | 926 var item = assert(node.querySelector(query)); | 
| 898 item.hidden = !visible; | 927 item.hidden = !visible; | 
| 899 if (visible && opt_shownCallback) | 928 if (visible && opt_shownCallback) | 
| 900 opt_shownCallback(item); | 929 opt_shownCallback(item); | 
| 901 }, | 930 }, | 
| 902 | 931 | 
| 903 /** | 932 /** | 
| 904 * Updates an element to show a list of errors. | |
| 905 * @param {Element} panel An element to hold the errors. | |
| 906 * @param {string} columnType A tag used to identify the column when | |
| 907 * changing focus. | |
| 908 * @param {Array<RuntimeError|ManifestError>|undefined} errors The errors | |
| 909 * to be displayed. | |
| 910 * @private | |
| 911 */ | |
| 912 updateErrors_: function(panel, columnType, errors) { | |
| 913 // TODO(hcarmona): Look into updating the ExtensionErrorList rather than | |
| 914 // rebuilding it every time. | |
| 915 panel.hidden = !errors || errors.length == 0; | |
| 916 panel.textContent = ''; | |
| 917 | |
| 918 if (panel.hidden) | |
| 919 return; | |
| 920 | |
| 921 var errorList = | |
| 922 new extensions.ExtensionErrorList(assertInstanceof(errors, Array)); | |
| 923 | |
| 924 panel.appendChild(errorList); | |
| 925 | |
| 926 var list = errorList.getErrorListElement(); | |
| 927 if (list) | |
| 928 list.setAttribute('column-type', columnType + 'list'); | |
| 929 | |
| 930 var button = errorList.getToggleElement(); | |
| 931 if (button) | |
| 932 button.setAttribute('column-type', columnType + 'button'); | |
| 933 }, | |
| 934 | |
| 935 /** | |
| 936 * Opens the extension options overlay for the extension with the given id. | 933 * Opens the extension options overlay for the extension with the given id. | 
| 937 * @param {string} extensionId The id of extension whose options page should | 934 * @param {string} extensionId The id of extension whose options page should | 
| 938 * be displayed. | 935 * be displayed. | 
| 939 * @param {boolean} scroll Whether the page should scroll to the extension | 936 * @param {boolean} scroll Whether the page should scroll to the extension | 
| 940 * @private | 937 * @private | 
| 941 */ | 938 */ | 
| 942 showEmbeddedExtensionOptions_: function(extensionId, scroll) { | 939 showEmbeddedExtensionOptions_: function(extensionId, scroll) { | 
| 943 if (this.optionsShown_) | 940 if (this.optionsShown_) | 
| 944 return; | 941 return; | 
| 945 | 942 | 
| (...skipping 29 matching lines...) Expand all Loading... | |
| 975 var self = this; | 972 var self = this; | 
| 976 $('overlay').addEventListener('cancelOverlay', function f() { | 973 $('overlay').addEventListener('cancelOverlay', function f() { | 
| 977 self.optionsShown_ = false; | 974 self.optionsShown_ = false; | 
| 978 $('overlay').removeEventListener('cancelOverlay', f); | 975 $('overlay').removeEventListener('cancelOverlay', f); | 
| 979 }); | 976 }); | 
| 980 | 977 | 
| 981 // TODO(dbeam): why do we need to focus <extensionoptions> before and | 978 // TODO(dbeam): why do we need to focus <extensionoptions> before and | 
| 982 // after its showing animation? Makes very little sense to me. | 979 // after its showing animation? Makes very little sense to me. | 
| 983 overlay.setInitialFocus(); | 980 overlay.setInitialFocus(); | 
| 984 }, | 981 }, | 
| 982 | |
| 983 /** | |
| 984 * Handle an extension changing. Currently this only checks when errors are | |
| 985 * deleted. | |
| 986 * @param {EventData} e The event data for the extension change. | |
| 987 * @private | |
| 988 */ | |
| 989 onItemStateChanged_: function(e) { | |
| 990 // TODO(devlin): We should be doing this for far more than just | |
| 991 // ERRORS_REMOVED, instead of re-generating all extension data whenever | |
| 992 // anything happens. | |
| 993 if (e.event_type == chrome.developerPrivate.EventType.ERRORS_REMOVED && | |
| 994 e.info) { | |
| 995 var node = /** @type {ExtensionFocusRow} */($(e.info.id)); | |
| 996 if (node) | |
| 997 this.updateNode_(e.info, node); | |
| 998 } | |
| 999 }, | |
| 985 }; | 1000 }; | 
| 986 | 1001 | 
| 987 return { | 1002 return { | 
| 988 ExtensionList: ExtensionList | 1003 ExtensionList: ExtensionList | 
| 989 }; | 1004 }; | 
| 990 }); | 1005 }); | 
| OLD | NEW |