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) { |
| 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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 |
| 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; |
| 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'}; |
| 675 // Find the highest severity of all the errors; manifest errors all have |
| 676 // a 'warning' level severity. |
| 677 var highSeverity = extension.runtimeErrors.reduce( |
| 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); |
| 682 |
| 683 // Adjust the class on the icon. |
| 684 var icon = item.querySelector('.extension-error-icon'); |
| 685 icon.className = 'extension-error-icon'; |
| 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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 extension.runtimeWarnings.length > 0, | 857 extension.runtimeWarnings.length > 0, |
820 function(item) { | 858 function(item) { |
821 var warningList = item.querySelector('ul'); | 859 var warningList = item.querySelector('ul'); |
822 warningList.textContent = ''; | 860 warningList.textContent = ''; |
823 extension.runtimeWarnings.forEach(function(warning) { | 861 extension.runtimeWarnings.forEach(function(warning) { |
824 var li = document.createElement('li'); | 862 var li = document.createElement('li'); |
825 warningList.appendChild(li).innerText = warning; | 863 warningList.appendChild(li).innerText = warning; |
826 }); | 864 }); |
827 }); | 865 }); |
828 | 866 |
829 // If the ErrorConsole is enabled, we should have manifest and/or runtime | |
830 // errors. Otherwise, we may have install warnings. We should not have | |
831 // both ErrorConsole errors and install warnings. | |
832 // Errors. | |
833 this.updateErrors_(row.querySelector('.manifest-errors'), | |
834 'dev-manifestErrors', extension.manifestErrors); | |
835 this.updateErrors_(row.querySelector('.runtime-errors'), | |
836 'dev-runtimeErrors', extension.runtimeErrors); | |
837 | |
838 // Install warnings. | 867 // Install warnings. |
839 this.updateVisibility_(row, '.install-warnings', | 868 this.updateVisibility_(row, '.install-warnings', |
840 extension.installWarnings.length > 0, | 869 extension.installWarnings.length > 0, |
841 function(item) { | 870 function(item) { |
842 var installWarningList = item.querySelector('ul'); | 871 var installWarningList = item.querySelector('ul'); |
843 installWarningList.textContent = ''; | 872 installWarningList.textContent = ''; |
844 if (extension.installWarnings) { | 873 if (extension.installWarnings) { |
845 extension.installWarnings.forEach(function(warning) { | 874 extension.installWarnings.forEach(function(warning) { |
846 var li = document.createElement('li'); | 875 var li = document.createElement('li'); |
847 li.innerText = warning; | 876 li.innerText = warning; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 * @private | 916 * @private |
888 */ | 917 */ |
889 updateVisibility_: function(node, query, visible, opt_shownCallback) { | 918 updateVisibility_: function(node, query, visible, opt_shownCallback) { |
890 var item = assert(node.querySelector(query)); | 919 var item = assert(node.querySelector(query)); |
891 item.hidden = !visible; | 920 item.hidden = !visible; |
892 if (visible && opt_shownCallback) | 921 if (visible && opt_shownCallback) |
893 opt_shownCallback(item); | 922 opt_shownCallback(item); |
894 }, | 923 }, |
895 | 924 |
896 /** | 925 /** |
897 * Updates an element to show a list of errors. | |
898 * @param {Element} panel An element to hold the errors. | |
899 * @param {string} columnType A tag used to identify the column when | |
900 * changing focus. | |
901 * @param {Array<RuntimeError|ManifestError>|undefined} errors The errors | |
902 * to be displayed. | |
903 * @private | |
904 */ | |
905 updateErrors_: function(panel, columnType, errors) { | |
906 // TODO(hcarmona): Look into updating the ExtensionErrorList rather than | |
907 // rebuilding it every time. | |
908 panel.hidden = !errors || errors.length == 0; | |
909 panel.textContent = ''; | |
910 | |
911 if (panel.hidden) | |
912 return; | |
913 | |
914 var errorList = | |
915 new extensions.ExtensionErrorList(assertInstanceof(errors, Array)); | |
916 | |
917 panel.appendChild(errorList); | |
918 | |
919 var list = errorList.getErrorListElement(); | |
920 if (list) | |
921 list.setAttribute('column-type', columnType + 'list'); | |
922 | |
923 var button = errorList.getToggleElement(); | |
924 if (button) | |
925 button.setAttribute('column-type', columnType + 'button'); | |
926 }, | |
927 | |
928 /** | |
929 * Opens the extension options overlay for the extension with the given id. | 926 * Opens the extension options overlay for the extension with the given id. |
930 * @param {string} extensionId The id of extension whose options page should | 927 * @param {string} extensionId The id of extension whose options page should |
931 * be displayed. | 928 * be displayed. |
932 * @param {boolean} scroll Whether the page should scroll to the extension | 929 * @param {boolean} scroll Whether the page should scroll to the extension |
933 * @private | 930 * @private |
934 */ | 931 */ |
935 showEmbeddedExtensionOptions_: function(extensionId, scroll) { | 932 showEmbeddedExtensionOptions_: function(extensionId, scroll) { |
936 if (this.optionsShown_) | 933 if (this.optionsShown_) |
937 return; | 934 return; |
938 | 935 |
(...skipping 29 matching lines...) Expand all Loading... |
968 var self = this; | 965 var self = this; |
969 $('overlay').addEventListener('cancelOverlay', function f() { | 966 $('overlay').addEventListener('cancelOverlay', function f() { |
970 self.optionsShown_ = false; | 967 self.optionsShown_ = false; |
971 $('overlay').removeEventListener('cancelOverlay', f); | 968 $('overlay').removeEventListener('cancelOverlay', f); |
972 }); | 969 }); |
973 | 970 |
974 // TODO(dbeam): why do we need to focus <extensionoptions> before and | 971 // TODO(dbeam): why do we need to focus <extensionoptions> before and |
975 // after its showing animation? Makes very little sense to me. | 972 // after its showing animation? Makes very little sense to me. |
976 overlay.setInitialFocus(); | 973 overlay.setInitialFocus(); |
977 }, | 974 }, |
| 975 |
| 976 /** |
| 977 * Handle an extension changing. Currently this only checks when errors are |
| 978 * deleted. |
| 979 * @param {EventData} e The event data for the extension change. |
| 980 * @private |
| 981 */ |
| 982 onItemStateChanged_: function(e) { |
| 983 // TODO(devlin): We should be doing this for far more than just |
| 984 // ERRORS_REMOVED, instead of re-generating all extension data whenever |
| 985 // anything happens. |
| 986 if (e.event_type == chrome.developerPrivate.EventType.ERRORS_REMOVED && |
| 987 e.info) { |
| 988 var node = /** @type {ExtensionFocusRow} */($(e.info.id)); |
| 989 if (node) |
| 990 this.updateNode_(e.info, node); |
| 991 } |
| 992 }, |
978 }; | 993 }; |
979 | 994 |
980 return { | 995 return { |
981 ExtensionList: ExtensionList | 996 ExtensionList: ExtensionList |
982 }; | 997 }; |
983 }); | 998 }); |
OLD | NEW |