// 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:///". 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 }; });