blob: b6ac452d4f82963d500378295e325fdfb17ba66d [file] [log] [blame]
// 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.
import './strings.m.js';
import {assertNotReached} from 'chrome://resources/js/assert.m.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
// Closure compiler won't let this be declared inside cr.define().
/** @enum {string} */
export const SourceType = {
WEBSTORE: 'webstore',
POLICY: 'policy',
SIDELOADED: 'sideloaded',
UNPACKED: 'unpacked',
UNKNOWN: 'unknown',
};
/** @enum {string} */
export const EnableControl = {
RELOAD: 'RELOAD',
REPAIR: 'REPAIR',
ENABLE_TOGGLE: 'ENABLE_TOGGLE',
};
// TODO(tjudkins): This should be extracted to a shared metrics module.
/** @enum {string} */
export const UserAction = {
ALL_TOGGLED_ON: 'Extensions.Settings.HostList.AllHostsToggledOn',
ALL_TOGGLED_OFF: 'Extensions.Settings.HostList.AllHostsToggledOff',
SPECIFIC_TOGGLED_ON: 'Extensions.Settings.HostList.SpecificHostToggledOn',
SPECIFIC_TOGGLED_OFF: 'Extensions.Settings.HostList.SpecificHostToggledOff',
LEARN_MORE: 'Extensions.Settings.HostList.LearnMoreActivated',
};
/**
* Returns true if the extension is enabled, including terminated
* extensions.
* @param {!chrome.developerPrivate.ExtensionState} state
* @return {boolean}
*/
export 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();
}
/**
* Returns true if the user can change whether or not the extension is
* enabled.
* @param {!chrome.developerPrivate.ExtensionInfo} item
* @return {boolean}
*/
export 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 ||
item.disableReasons.blockedByPolicy) {
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}
*/
export function getItemSource(item) {
if (item.controlledInfo) {
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}
*/
export 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}
*/
export 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');
}
if (view.type === 'EXTENSION_SERVICE_WORKER_BACKGROUND') {
label = loadTimeData.getString('viewServiceWorker');
}
// 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;
}
/**
* Returns true if the extension is in the terminated state.
* @param {!chrome.developerPrivate.ExtensionState} state
* @return {boolean}
* @private
*/
function isTerminated_(state) {
return state === chrome.developerPrivate.ExtensionState.TERMINATED;
}
/**
* Determines which enable control to display for a given extension.
* @param {!chrome.developerPrivate.ExtensionInfo} data
* @return {EnableControl}
*/
export function getEnableControl(data) {
if (isTerminated_(data.state)) {
return EnableControl.RELOAD;
}
if (data.disableReasons.corruptInstall && data.userMayModify) {
return EnableControl.REPAIR;
}
return EnableControl.ENABLE_TOGGLE;
}