Bug 1363925: Part 8c - Move isUsableAddon to XPIDatabase.jsm. r=aswan

MozReview-Commit-ID: 1aIA9Lu5sS2

--HG--
extra : rebase_source : ed39e7050d21d116338000234ab0cc4c6d34cf51
extra : histedit_source : f23e525032390d32e203d0b505cbf19d228d5ff6
This commit is contained in:
Kris Maglione 2018-04-22 14:52:27 -07:00
Родитель 980c561d2e
Коммит 4f17dc56da
3 изменённых файлов: 127 добавлений и 128 удалений

Просмотреть файл

@ -37,7 +37,6 @@ const {nsIBlocklistService} = Ci;
* XPIStates,
* descriptorToPath,
* isTheme,
* isUsableAddon,
* isWebExtension,
* recordAddonTelemetry,
*/
@ -50,7 +49,6 @@ for (let sym of [
"XPIStates",
"descriptorToPath",
"isTheme",
"isUsableAddon",
"isWebExtension",
"recordAddonTelemetry",
]) {
@ -78,6 +76,7 @@ const PREF_DB_SCHEMA = "extensions.databaseSchema";
const PREF_EM_AUTO_DISABLED_SCOPES = "extensions.autoDisableScopes";
const PREF_EM_EXTENSION_FORMAT = "extensions.";
const PREF_PENDING_OPERATIONS = "extensions.pendingOperations";
const PREF_XPI_SIGNATURES_DEV_ROOT = "xpinstall.signatures.dev-root";
const TOOLKIT_ID = "toolkit@mozilla.org";
@ -119,6 +118,10 @@ const PROP_JSON_FIELDS = ["id", "syncGUID", "location", "version", "type",
"userPermissions", "icons", "iconURL", "icon64URL",
"blocklistState", "blocklistURL", "startupData"];
const LEGACY_TYPES = new Set([
"extension",
]);
// Time to wait before async save of XPI JSON database, in milliseconds
const ASYNC_SAVE_DELAY_MS = 20;
@ -472,7 +475,7 @@ AddonInternal.prototype = {
XPIProvider.updateAddonDisabledState(this, userDisabled, softDisabled);
XPIDatabase.saveChanges();
} else {
this.appDisabled = !isUsableAddon(this);
this.appDisabled = !XPIDatabase.isUsableAddon(this);
if (userDisabled !== undefined) {
this.userDisabled = userDisabled;
}
@ -492,7 +495,7 @@ AddonInternal.prototype = {
}
}
}
this.appDisabled = !isUsableAddon(this);
this.appDisabled = !XPIDatabase.isUsableAddon(this);
},
/**
@ -551,7 +554,7 @@ AddonInternal.prototype = {
}
// Compatibility info may have changed so update appDisabled
this.appDisabled = !isUsableAddon(this);
this.appDisabled = !XPIDatabase.isUsableAddon(this);
},
permissions() {
@ -1891,6 +1894,117 @@ this.XPIDatabase = {
return _filterDB(this.addonDB, aAddon => true);
},
/**
* Returns true if signing is required for the given add-on type.
*
* @param {string} aType
* The add-on type to check.
* @returns {boolean}
*/
mustSign(aType) {
if (!SIGNED_TYPES.has(aType))
return false;
if (aType == "webextension-langpack") {
return AddonSettings.LANGPACKS_REQUIRE_SIGNING;
}
return AddonSettings.REQUIRE_SIGNING;
},
/**
* Determine if this addon should be disabled due to being legacy
*
* @param {Addon} addon The addon to check
*
* @returns {boolean} Whether the addon should be disabled for being legacy
*/
isDisabledLegacy(addon) {
return (!AddonSettings.ALLOW_LEGACY_EXTENSIONS &&
LEGACY_TYPES.has(addon.type) &&
// Legacy add-ons are allowed in the system location.
!addon._installLocation.isSystem &&
// Legacy extensions may be installed temporarily in
// non-release builds.
!(AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS &&
addon._installLocation.name == KEY_APP_TEMPORARY) &&
// Properly signed legacy extensions are allowed.
addon.signedState !== AddonManager.SIGNEDSTATE_PRIVILEGED);
},
/**
* Calculates whether an add-on should be appDisabled or not.
*
* @param {AddonInternal} aAddon
* The add-on to check
* @returns {boolean}
* True if the add-on should not be appDisabled
*/
isUsableAddon(aAddon) {
if (this.mustSign(aAddon.type) && !aAddon.isCorrectlySigned) {
logger.warn(`Add-on ${aAddon.id} is not correctly signed.`);
if (Services.prefs.getBoolPref(PREF_XPI_SIGNATURES_DEV_ROOT, false)) {
logger.warn(`Preference ${PREF_XPI_SIGNATURES_DEV_ROOT} is set.`);
}
return false;
}
if (aAddon.blocklistState == nsIBlocklistService.STATE_BLOCKED) {
logger.warn(`Add-on ${aAddon.id} is blocklisted.`);
return false;
}
// If we can't read it, it's not usable:
if (aAddon.brokenManifest) {
return false;
}
if (AddonManager.checkUpdateSecurity && !aAddon.providesUpdatesSecurely) {
logger.warn(`Updates for add-on ${aAddon.id} must be provided over HTTPS.`);
return false;
}
if (!aAddon.isPlatformCompatible) {
logger.warn(`Add-on ${aAddon.id} is not compatible with platform.`);
return false;
}
if (aAddon.dependencies.length) {
let isActive = id => {
let active = XPIProvider.activeAddons.get(id);
return active && !active.disable;
};
if (aAddon.dependencies.some(id => !isActive(id)))
return false;
}
if (this.isDisabledLegacy(aAddon)) {
logger.warn(`disabling legacy extension ${aAddon.id}`);
return false;
}
if (AddonManager.checkCompatibility) {
if (!aAddon.isCompatible) {
logger.warn(`Add-on ${aAddon.id} is not compatible with application version.`);
return false;
}
} else {
let app = aAddon.matchingTargetApplication;
if (!app) {
logger.warn(`Add-on ${aAddon.id} is not compatible with target application.`);
return false;
}
}
return true;
},
/**
* Synchronously adds an AddonInternal's metadata to the database.
*
@ -2251,7 +2365,7 @@ this.XPIDatabaseReconcile = {
aInstallLocation.name != KEY_APP_SYSTEM_DEFAULTS;
// appDisabled depends on whether the add-on is a foreignInstall so update
aNewAddon.appDisabled = !isUsableAddon(aNewAddon);
aNewAddon.appDisabled = !XPIDatabase.isUsableAddon(aNewAddon);
if (isDetectedInstall && aNewAddon.foreignInstall) {
// If the add-on is a foreign install and is in a scope where add-ons
@ -2409,7 +2523,7 @@ this.XPIDatabaseReconcile = {
copyProperties(manifest, props, aOldAddon);
}
aOldAddon.appDisabled = !isUsableAddon(aOldAddon);
aOldAddon.appDisabled = !XPIDatabase.isUsableAddon(aOldAddon);
return aOldAddon;
},

Просмотреть файл

@ -78,7 +78,7 @@ const PREF_XPI_DIRECT_WHITELISTED = "xpinstall.whitelist.directRequest";
const PREF_XPI_FILE_WHITELISTED = "xpinstall.whitelist.fileRequest";
const PREF_XPI_WHITELIST_REQUIRED = "xpinstall.whitelist.required";
/* globals BOOTSTRAP_REASONS, KEY_APP_SYSTEM_ADDONS, KEY_APP_SYSTEM_DEFAULTS, KEY_APP_TEMPORARY, PREF_BRANCH_INSTALLED_ADDON, PREF_SYSTEM_ADDON_SET, TEMPORARY_ADDON_SUFFIX, SIGNED_TYPES, TOOLKIT_ID, XPI_PERMISSION, XPIStates, getExternalType, isTheme, isUsableAddon, isWebExtension, mustSign */
/* globals BOOTSTRAP_REASONS, KEY_APP_SYSTEM_ADDONS, KEY_APP_SYSTEM_DEFAULTS, KEY_APP_TEMPORARY, PREF_BRANCH_INSTALLED_ADDON, PREF_SYSTEM_ADDON_SET, TEMPORARY_ADDON_SUFFIX, SIGNED_TYPES, TOOLKIT_ID, XPI_PERMISSION, XPIStates, getExternalType, isTheme, isWebExtension */
const XPI_INTERNAL_SYMBOLS = [
"BOOTSTRAP_REASONS",
"KEY_APP_SYSTEM_ADDONS",
@ -93,9 +93,7 @@ const XPI_INTERNAL_SYMBOLS = [
"XPIStates",
"getExternalType",
"isTheme",
"isUsableAddon",
"isWebExtension",
"mustSign",
];
for (let name of XPI_INTERNAL_SYMBOLS) {
@ -931,7 +929,7 @@ var loadManifest = async function(aPackage, aInstallLocation, aOldAddon) {
}
await addon.updateBlocklistState({oldAddon: aOldAddon});
addon.appDisabled = !isUsableAddon(addon);
addon.appDisabled = !XPIDatabase.isUsableAddon(addon);
defineSyncGUID(addon);
@ -1775,7 +1773,7 @@ class AddonInstall {
}
}
if (mustSign(this.addon.type)) {
if (XPIDatabase.mustSign(this.addon.type)) {
if (this.addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) {
// This add-on isn't properly signed by a signature that chains to the
// trusted root.
@ -1818,7 +1816,7 @@ class AddonInstall {
this.addon._repositoryAddon = repoAddon;
this.name = this.name || this.addon._repositoryAddon.name;
this.addon.appDisabled = !isUsableAddon(this.addon);
this.addon.appDisabled = !XPIDatabase.isUsableAddon(this.addon);
return undefined;
}
@ -3732,7 +3730,7 @@ var XPIInstall = {
let addon = await loadManifestFromFile(source, location);
if (mustSign(addon.type) &&
if (XPIDatabase.mustSign(addon.type) &&
addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) {
throw new Error(`Refusing to install staged add-on ${id} with signed state ${addon.signedState}`);
}

Просмотреть файл

@ -36,8 +36,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
verifyBundleSignedState: "resource://gre/modules/addons/XPIInstall.jsm",
});
const {nsIBlocklistService} = Ci;
XPCOMUtils.defineLazyServiceGetter(this, "aomStartup",
"@mozilla.org/addons/addon-manager-startup;1",
"amIAddonManagerStartup");
@ -56,7 +54,6 @@ const PREF_EM_STARTUP_SCAN_SCOPES = "extensions.startupScanScopes";
const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI";
// xpinstall.signatures.required only supported in dev builds
const PREF_XPI_SIGNATURES_REQUIRED = "xpinstall.signatures.required";
const PREF_XPI_SIGNATURES_DEV_ROOT = "xpinstall.signatures.dev-root";
const PREF_LANGPACK_SIGNATURES = "extensions.langpacks.signatures.required";
const PREF_XPI_PERMISSIONS_BRANCH = "xpinstall.";
const PREF_INSTALL_DISTRO_ADDONS = "extensions.installDistroAddons";
@ -168,10 +165,6 @@ const SIGNED_TYPES = new Set([
"webextension-theme",
]);
const LEGACY_TYPES = new Set([
"extension",
]);
const ALL_EXTERNAL_TYPES = new Set([
"dictionary",
"extension",
@ -179,18 +172,6 @@ const ALL_EXTERNAL_TYPES = new Set([
"theme",
]);
// Whether add-on signing is required.
function mustSign(aType) {
if (!SIGNED_TYPES.has(aType))
return false;
if (aType == "webextension-langpack") {
return AddonSettings.LANGPACKS_REQUIRE_SIGNING;
}
return AddonSettings.REQUIRE_SIGNING;
}
// Keep track of where we are in startup for telemetry
// event happened during XPIDatabase.startup()
const XPI_STARTING = "XPIStarting";
@ -397,98 +378,6 @@ function canRunInSafeMode(aAddon) {
return location.isSystem;
}
/**
* Determine if this addon should be disabled due to being legacy
*
* @param {Addon} addon The addon to check
*
* @returns {boolean} Whether the addon should be disabled for being legacy
*/
function isDisabledLegacy(addon) {
return (!AddonSettings.ALLOW_LEGACY_EXTENSIONS &&
LEGACY_TYPES.has(addon.type) &&
// Legacy add-ons are allowed in the system location.
!addon._installLocation.isSystem &&
// Legacy extensions may be installed temporarily in
// non-release builds.
!(AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS &&
addon._installLocation.name == KEY_APP_TEMPORARY) &&
// Properly signed legacy extensions are allowed.
addon.signedState !== AddonManager.SIGNEDSTATE_PRIVILEGED);
}
/**
* Calculates whether an add-on should be appDisabled or not.
*
* @param {AddonInternal} aAddon
* The add-on to check
* @returns {boolean}
* True if the add-on should not be appDisabled
*/
function isUsableAddon(aAddon) {
if (mustSign(aAddon.type) && !aAddon.isCorrectlySigned) {
logger.warn(`Add-on ${aAddon.id} is not correctly signed.`);
if (Services.prefs.getBoolPref(PREF_XPI_SIGNATURES_DEV_ROOT, false)) {
logger.warn(`Preference ${PREF_XPI_SIGNATURES_DEV_ROOT} is set.`);
}
return false;
}
if (aAddon.blocklistState == nsIBlocklistService.STATE_BLOCKED) {
logger.warn(`Add-on ${aAddon.id} is blocklisted.`);
return false;
}
// If we can't read it, it's not usable:
if (aAddon.brokenManifest) {
return false;
}
if (AddonManager.checkUpdateSecurity && !aAddon.providesUpdatesSecurely) {
logger.warn(`Updates for add-on ${aAddon.id} must be provided over HTTPS.`);
return false;
}
if (!aAddon.isPlatformCompatible) {
logger.warn(`Add-on ${aAddon.id} is not compatible with platform.`);
return false;
}
if (aAddon.dependencies.length) {
let isActive = id => {
let active = XPIProvider.activeAddons.get(id);
return active && !active.disable;
};
if (aAddon.dependencies.some(id => !isActive(id)))
return false;
}
if (isDisabledLegacy(aAddon)) {
logger.warn(`disabling legacy extension ${aAddon.id}`);
return false;
}
if (AddonManager.checkCompatibility) {
if (!aAddon.isCompatible) {
logger.warn(`Add-on ${aAddon.id} is not compatible with application version.`);
return false;
}
} else {
let app = aAddon.matchingTargetApplication;
if (!app) {
logger.warn(`Add-on ${aAddon.id} is not compatible with target application.`);
return false;
}
}
return true;
}
/**
* Converts an internal add-on type to the type presented through the API.
*
@ -3055,7 +2944,7 @@ var XPIProvider = {
if (aSoftDisabled === undefined || aUserDisabled)
aSoftDisabled = aAddon.softDisabled;
let appDisabled = !isUsableAddon(aAddon);
let appDisabled = !XPIDatabase.isUsableAddon(aAddon);
// No change means nothing to do here
if (aAddon.userDisabled == aUserDisabled &&
aAddon.appDisabled == appDisabled &&
@ -3684,9 +3573,7 @@ var XPIInternal = {
getExternalType,
getURIForResourceInFile,
isTheme,
isUsableAddon,
isWebExtension,
mustSign,
};
var addonTypes = [