| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Closure compiler won't let this be declared inside cr.define(). |
| /** @enum {string} */ |
| const SourceType = { |
| WEBSTORE: 'webstore', |
| POLICY: 'policy', |
| SIDELOADED: 'sideloaded', |
| UNPACKED: 'unpacked', |
| UNKNOWN: 'unknown', |
| }; |
| |
| cr.define('extensions', function() { |
| /** |
| * Returns true if the extension is enabled, including terminated |
| * extensions. |
| * @param {!chrome.developerPrivate.ExtensionState} state |
| * @return {boolean} |
| */ |
| function isEnabled(state) { |
| switch (state) { |
| case chrome.developerPrivate.ExtensionState.ENABLED: |
| case chrome.developerPrivate.ExtensionState.TERMINATED: |
| return true; |
| case chrome.developerPrivate.ExtensionState.BLACKLISTED: |
| case chrome.developerPrivate.ExtensionState.DISABLED: |
| return false; |
| } |
| assertNotReached(); |
| } |
| |
| /** |
| * @param {!chrome.developerPrivate.ExtensionInfo} extensionInfo |
| * @return {boolean} Whether the extension is controlled. |
| */ |
| function isControlled(extensionInfo) { |
| return !!extensionInfo.controlledInfo; |
| } |
| |
| /** |
| * Returns true if the user can change whether or not the extension is |
| * enabled. |
| * @param {!chrome.developerPrivate.ExtensionInfo} item |
| * @return {boolean} |
| */ |
| function userCanChangeEnablement(item) { |
| // User doesn't have permission. |
| if (!item.userMayModify) { |
| return false; |
| } |
| // Item is forcefully disabled. |
| if (item.disableReasons.corruptInstall || |
| item.disableReasons.suspiciousInstall || |
| item.disableReasons.updateRequired) { |
| return false; |
| } |
| // An item with dependent extensions can't be disabled (it would bork the |
| // dependents). |
| if (item.dependentExtensions.length > 0) { |
| return false; |
| } |
| // Blacklisted can't be enabled, either. |
| if (item.state == chrome.developerPrivate.ExtensionState.BLACKLISTED) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** |
| * @param {!chrome.developerPrivate.ExtensionInfo} item |
| * @return {SourceType} |
| */ |
| function getItemSource(item) { |
| if (item.controlledInfo && |
| item.controlledInfo.type == |
| chrome.developerPrivate.ControllerType.POLICY) { |
| return SourceType.POLICY; |
| } |
| |
| switch (item.location) { |
| case chrome.developerPrivate.Location.THIRD_PARTY: |
| return SourceType.SIDELOADED; |
| case chrome.developerPrivate.Location.UNPACKED: |
| return SourceType.UNPACKED; |
| case chrome.developerPrivate.Location.UNKNOWN: |
| return SourceType.UNKNOWN; |
| case chrome.developerPrivate.Location.FROM_STORE: |
| return SourceType.WEBSTORE; |
| } |
| |
| assertNotReached(item.location); |
| } |
| |
| /** |
| * @param {SourceType} source |
| * @return {string} |
| */ |
| function getItemSourceString(source) { |
| switch (source) { |
| case SourceType.POLICY: |
| return loadTimeData.getString('itemSourcePolicy'); |
| case SourceType.SIDELOADED: |
| return loadTimeData.getString('itemSourceSideloaded'); |
| case SourceType.UNPACKED: |
| return loadTimeData.getString('itemSourceUnpacked'); |
| case SourceType.WEBSTORE: |
| return loadTimeData.getString('itemSourceWebstore'); |
| case SourceType.UNKNOWN: |
| // Nothing to return. Calling code should use |
| // chrome.developerPrivate.ExtensionInfo's |locationText| instead. |
| return ''; |
| } |
| assertNotReached(); |
| } |
| |
| /** |
| * Computes the human-facing label for the given inspectable view. |
| * @param {!chrome.developerPrivate.ExtensionView} view |
| * @return {string} |
| */ |
| function computeInspectableViewLabel(view) { |
| // Trim the "chrome-extension://<id>/". |
| const url = new URL(view.url); |
| let label = view.url; |
| if (url.protocol == 'chrome-extension:') { |
| label = url.pathname.substring(1); |
| } |
| if (label == '_generated_background_page.html') { |
| label = loadTimeData.getString('viewBackgroundPage'); |
| } |
| // Add any qualifiers. |
| if (view.incognito) { |
| label += ' ' + loadTimeData.getString('viewIncognito'); |
| } |
| if (view.renderProcessId == -1) { |
| label += ' ' + loadTimeData.getString('viewInactive'); |
| } |
| if (view.isIframe) { |
| label += ' ' + loadTimeData.getString('viewIframe'); |
| } |
| |
| return label; |
| } |
| |
| return { |
| isControlled: isControlled, |
| isEnabled: isEnabled, |
| userCanChangeEnablement: userCanChangeEnablement, |
| getItemSource: getItemSource, |
| getItemSourceString: getItemSourceString, |
| computeInspectableViewLabel: computeInspectableViewLabel |
| }; |
| }); |