| 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 |