mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 693899 - Support detecting binary components, and enable strict compatibility checking when found. r=dtownsend
This commit is contained in:
parent
7630a6cfe0
commit
b2411cbeef
192
toolkit/mozapps/extensions/ChromeManifestParser.jsm
Normal file
192
toolkit/mozapps/extensions/ChromeManifestParser.jsm
Normal file
@ -0,0 +1,192 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Extension Manager.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Blair McBride <bmcbride@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ChromeManifestParser"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
const MSG_JAR_FLUSH = "AddonJarFlush";
|
||||
|
||||
|
||||
/**
|
||||
* Sends local and remote notifications to flush a JAR file cache entry
|
||||
*
|
||||
* @param aJarFile
|
||||
* The ZIP/XPI/JAR file as a nsIFile
|
||||
*/
|
||||
function flushJarCache(aJarFile) {
|
||||
Services.obs.notifyObservers(aJarFile, "flush-cache-entry", null);
|
||||
Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIChromeFrameMessageManager)
|
||||
.sendAsyncMessage(MSG_JAR_FLUSH, aJarFile.path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses chrome manifest files.
|
||||
*/
|
||||
var ChromeManifestParser = {
|
||||
|
||||
/**
|
||||
* Reads and parses a chrome manifest file located at a specified URI, and all
|
||||
* secondary manifests it references.
|
||||
*
|
||||
* @param aURI
|
||||
* A nsIURI pointing to a chrome manifest.
|
||||
* Typically a file: or jar: URI.
|
||||
* @return Array of objects describing each manifest instruction, in the form:
|
||||
* { type: instruction-type, baseURI: string-uri, args: [arguments] }
|
||||
**/
|
||||
parseSync: function CMP_parseSync(aURI) {
|
||||
function parseLine(aLine) {
|
||||
let line = aLine.trim();
|
||||
if (line.length == 0 || line.charAt(0) == '#')
|
||||
return;
|
||||
let tokens = line.split(/\s+/);
|
||||
let type = tokens.shift();
|
||||
if (type == "manifest") {
|
||||
let uri = NetUtil.newURI(tokens.shift(), null, aURI);
|
||||
data = data.concat(this.parseSync(uri));
|
||||
} else {
|
||||
data.push({type: type, baseURI: baseURI, args: tokens});
|
||||
}
|
||||
}
|
||||
|
||||
let contents = "";
|
||||
try {
|
||||
if (aURI.scheme == "jar")
|
||||
contents = this._readFromJar(aURI);
|
||||
else
|
||||
contents = this._readFromFile(aURI);
|
||||
} catch (e) {
|
||||
// Silently fail.
|
||||
}
|
||||
|
||||
if (!contents)
|
||||
return [];
|
||||
|
||||
let baseURI = NetUtil.newURI(".", null, aURI).spec;
|
||||
|
||||
let data = [];
|
||||
let lines = contents.split("\n");
|
||||
lines.forEach(parseLine.bind(this));
|
||||
return data;
|
||||
},
|
||||
|
||||
_readFromJar: function CMP_readFromJar(aURI) {
|
||||
let data = "";
|
||||
let entries = [];
|
||||
let readers = [];
|
||||
|
||||
try {
|
||||
// Deconstrict URI, which can be nested jar: URIs.
|
||||
let uri = aURI.clone();
|
||||
while (uri instanceof Ci.nsIJARURI) {
|
||||
entries.push(uri.JAREntry);
|
||||
uri = uri.JARFile;
|
||||
}
|
||||
|
||||
// Open the base jar.
|
||||
let reader = Cc["@mozilla.org/libjar/zip-reader;1"].
|
||||
createInstance(Ci.nsIZipReader);
|
||||
reader.open(uri.QueryInterface(Ci.nsIFileURL).file);
|
||||
readers.push(reader);
|
||||
|
||||
// Open the nested jars.
|
||||
for (let i = entries.length - 1; i > 0; i--) {
|
||||
let innerReader = Cc["@mozilla.org/libjar/zip-reader;1"].
|
||||
createInstance(Ci.nsIZipReader);
|
||||
innerReader.openInner(reader, entries[i]);
|
||||
readers.push(innerReader);
|
||||
reader = innerReader;
|
||||
}
|
||||
|
||||
// First entry is the actual file we want to read.
|
||||
let zis = reader.getInputStream(entries[0]);
|
||||
data = NetUtil.readInputStreamToString(zis, zis.available());
|
||||
}
|
||||
finally {
|
||||
// Close readers in reverse order.
|
||||
for (let i = readers.length - 1; i >= 0; i--) {
|
||||
readers[i].close();
|
||||
flushJarCache(readers[i].file);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
_readFromFile: function CMP_readFromFile(aURI) {
|
||||
let file = aURI.QueryInterface(Ci.nsIFileURL).file;
|
||||
if (!file.exists() || !file.isFile())
|
||||
return "";
|
||||
|
||||
let data = "";
|
||||
let fis = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Ci.nsIFileInputStream);
|
||||
try {
|
||||
fis.init(file, -1, -1, false);
|
||||
data = NetUtil.readInputStreamToString(fis, fis.available());
|
||||
} finally {
|
||||
fis.close();
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Detects if there were any instructions of a specified type in a given
|
||||
* chrome manifest.
|
||||
*
|
||||
* @param aManifest
|
||||
* Manifest data, as returned by ChromeManifestParser.parseSync().
|
||||
* @param aType
|
||||
* Instruction type to filter by.
|
||||
* @return True if any matching instructions were found in the manifest.
|
||||
*/
|
||||
hasType: function CMP_hasType(aManifest, aType) {
|
||||
return aManifest.some(function(aEntry) {
|
||||
return aEntry.type == aType;
|
||||
});
|
||||
}
|
||||
};
|
@ -71,6 +71,7 @@ EXTRA_PP_JS_MODULES = \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
ChromeManifestParser.jsm \
|
||||
LightweightThemeManager.jsm \
|
||||
SpellCheckDictionaryBootstrap.js \
|
||||
$(NULL)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#
|
||||
# Contributor(s):
|
||||
# Dave Townsend <dtownsend@oxymoronical.com>
|
||||
# Blair McBride <bmcbride@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -48,6 +49,7 @@ var EXPORTED_SYMBOLS = [];
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/AddonManager.jsm");
|
||||
Components.utils.import("resource://gre/modules/AddonRepository.jsm");
|
||||
Components.utils.import("resource://gre/modules/ChromeManifestParser.jsm");
|
||||
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm");
|
||||
Components.utils.import("resource://gre/modules/FileUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
@ -122,7 +124,7 @@ const TOOLKIT_ID = "toolkit@mozilla.org";
|
||||
|
||||
const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi;
|
||||
|
||||
const DB_SCHEMA = 6;
|
||||
const DB_SCHEMA = 7;
|
||||
const REQ_VERSION = 2;
|
||||
|
||||
#ifdef MOZ_COMPATIBILITY_NIGHTLY
|
||||
@ -146,7 +148,8 @@ const DB_METADATA = ["installDate", "updateDate", "size", "sourceURI",
|
||||
"releaseNotesURI", "applyBackgroundUpdates"];
|
||||
const DB_BOOL_METADATA = ["visible", "active", "userDisabled", "appDisabled",
|
||||
"pendingUninstall", "bootstrap", "skinnable",
|
||||
"softDisabled", "foreignInstall"];
|
||||
"softDisabled", "foreignInstall",
|
||||
"hasBinaryComponents"];
|
||||
|
||||
const BOOTSTRAP_REASONS = {
|
||||
APP_STARTUP : 1,
|
||||
@ -850,6 +853,13 @@ function loadManifestFromDir(aDir) {
|
||||
let addon = loadManifestFromRDF(Services.io.newFileURI(file), bis);
|
||||
addon._sourceBundle = aDir.clone().QueryInterface(Ci.nsILocalFile);
|
||||
addon.size = getFileSize(aDir);
|
||||
|
||||
file = aDir.clone();
|
||||
file.append("chrome.manifest");
|
||||
let chromeManifest = ChromeManifestParser.parseSync(Services.io.newFileURI(file));
|
||||
addon.hasBinaryComponents = ChromeManifestParser.hasType(chromeManifest,
|
||||
"binary-component");
|
||||
|
||||
return addon;
|
||||
}
|
||||
finally {
|
||||
@ -882,6 +892,16 @@ function loadManifestFromZipReader(aZipReader) {
|
||||
while (entries.hasMore())
|
||||
addon.size += aZipReader.getEntry(entries.getNext()).realSize;
|
||||
|
||||
// Binary components can only be loaded from unpacked addons.
|
||||
if (addon.unpack) {
|
||||
uri = buildJarURI(aZipReader.file, "chrome.manifest");
|
||||
let chromeManifest = ChromeManifestParser.parseSync(uri);
|
||||
addon.hasBinaryComponents = ChromeManifestParser.hasType(chromeManifest,
|
||||
"binary-component");
|
||||
} else {
|
||||
addon.hasBinaryComponents = false;
|
||||
}
|
||||
|
||||
return addon;
|
||||
}
|
||||
finally {
|
||||
@ -3880,7 +3900,7 @@ const FIELDS_ADDON = "internal_id, id, location, version, type, internalName, "
|
||||
"userDisabled, appDisabled, pendingUninstall, descriptor, " +
|
||||
"installDate, updateDate, applyBackgroundUpdates, bootstrap, " +
|
||||
"skinnable, size, sourceURI, releaseNotesURI, softDisabled, " +
|
||||
"foreignInstall";
|
||||
"foreignInstall, hasBinaryComponents";
|
||||
|
||||
/**
|
||||
* A helper function to log an SQL error.
|
||||
@ -4026,7 +4046,7 @@ var XPIDatabase = {
|
||||
":descriptor, :installDate, :updateDate, " +
|
||||
":applyBackgroundUpdates, :bootstrap, :skinnable, " +
|
||||
":size, :sourceURI, :releaseNotesURI, :softDisabled, " +
|
||||
":foreignInstall)",
|
||||
":foreignInstall, :hasBinaryComponents)",
|
||||
addAddonMetadata_addon_locale: "INSERT INTO addon_locale VALUES " +
|
||||
"(:internal_id, :name, :locale)",
|
||||
addAddonMetadata_locale: "INSERT INTO locale (name, description, creator, " +
|
||||
@ -4560,6 +4580,7 @@ var XPIDatabase = {
|
||||
"size INTEGER, sourceURI TEXT, " +
|
||||
"releaseNotesURI TEXT, softDisabled INTEGER, " +
|
||||
"foreignInstall INTEGER, " +
|
||||
"hasBinaryComponents INTEGER, " +
|
||||
"UNIQUE (id, location)");
|
||||
this.connection.createTable("targetApplication",
|
||||
"addon_internal_id INTEGER, " +
|
||||
@ -6910,8 +6931,10 @@ AddonInternal.prototype = {
|
||||
|
||||
// Only extensions can be compatible by default; themes always use strict
|
||||
// compatibility checking.
|
||||
if (this.type == "extension" && !AddonManager.strictCompatibility)
|
||||
if (this.type == "extension" && !AddonManager.strictCompatibility &&
|
||||
!this.hasBinaryComponents) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!aAppVersion)
|
||||
aAppVersion = Services.appinfo.version;
|
||||
@ -7128,7 +7151,8 @@ function AddonWrapper(aAddon) {
|
||||
|
||||
["id", "version", "type", "isCompatible", "isPlatformCompatible",
|
||||
"providesUpdatesSecurely", "blocklistState", "blocklistURL", "appDisabled",
|
||||
"softDisabled", "skinnable", "size", "foreignInstall"].forEach(function(aProp) {
|
||||
"softDisabled", "skinnable", "size", "foreignInstall", "hasBinaryComponents"
|
||||
].forEach(function(aProp) {
|
||||
this.__defineGetter__(aProp, function() aAddon[aProp]);
|
||||
}, this);
|
||||
|
||||
|
@ -0,0 +1,6 @@
|
||||
content test-addon-1 chrome/content
|
||||
# comment!
|
||||
locale test-addon-1 en-US locale/en-US
|
||||
# commentaire!
|
||||
locale test-addon-1 fr-FR locale/fr-FR
|
||||
overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>addon1@tests.mozilla.org</em:id>
|
||||
<em:version>1.0</em:version>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>Test 1</em:name>
|
||||
<em:description>Test Description</em:description>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>xpcshell@tests.mozilla.org</em:id>
|
||||
<em:minVersion>1</em:minVersion>
|
||||
<em:maxVersion>2</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
@ -0,0 +1,7 @@
|
||||
content test-addon-1 chrome/content
|
||||
|
||||
locale test-addon-1 en-US locale/en-US
|
||||
locale test-addon-1 fr-FR locale/fr-FR
|
||||
overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul
|
||||
binary-component components/something.so
|
||||
manifest thisdoesntexist.manifest
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>addon2@tests.mozilla.org</em:id>
|
||||
<em:version>1.0</em:version>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>Test 2</em:name>
|
||||
<em:description>Test Description</em:description>
|
||||
<em:unpack>true</em:unpack>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>xpcshell@tests.mozilla.org</em:id>
|
||||
<em:minVersion>1</em:minVersion>
|
||||
<em:maxVersion>2</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
@ -0,0 +1,9 @@
|
||||
content test-addon-1 chrome/content
|
||||
|
||||
locale test-addon-1 en-US locale/en-US
|
||||
locale test-addon-1 fr-FR locale/fr-FR
|
||||
overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul
|
||||
|
||||
binary-component components/something.so
|
||||
|
||||
manifest jar:inner.jar!/nested.manifest
|
Binary file not shown.
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>addon3@tests.mozilla.org</em:id>
|
||||
<em:version>1.0</em:version>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>Test 3</em:name>
|
||||
<em:description>Test Description</em:description>
|
||||
<em:unpack>true</em:unpack>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>xpcshell@tests.mozilla.org</em:id>
|
||||
<em:minVersion>1</em:minVersion>
|
||||
<em:maxVersion>1</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
@ -0,0 +1,6 @@
|
||||
content test-addon-1 chrome/content
|
||||
|
||||
locale test-addon-1 en-US locale/en-US
|
||||
locale test-addon-1 fr-FR locale/fr-FR
|
||||
overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul
|
||||
manifest components/components.manifest
|
@ -0,0 +1,2 @@
|
||||
binary-component mycomponent.dll
|
||||
manifest other/something.manifest
|
@ -0,0 +1 @@
|
||||
binary-component thermalnuclearwar.dll
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>addon4@tests.mozilla.org</em:id>
|
||||
<em:version>1.0</em:version>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>Test 4</em:name>
|
||||
<em:description>Test Description</em:description>
|
||||
<em:unpack>true</em:unpack>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>xpcshell@tests.mozilla.org</em:id>
|
||||
<em:minVersion>1</em:minVersion>
|
||||
<em:maxVersion>1</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
@ -0,0 +1,7 @@
|
||||
content test-addon-1 chrome/content
|
||||
|
||||
locale test-addon-1 en-US locale/en-US
|
||||
locale test-addon-1 fr-FR locale/fr-FR
|
||||
overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul
|
||||
|
||||
binary-component components/something.so
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>addon5@tests.mozilla.org</em:id>
|
||||
<em:version>1.0</em:version>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>Test 5</em:name>
|
||||
<em:description>Test Description</em:description>
|
||||
<em:unpack>false</em:unpack>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>xpcshell@tests.mozilla.org</em:id>
|
||||
<em:minVersion>1</em:minVersion>
|
||||
<em:maxVersion>2</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
@ -0,0 +1,6 @@
|
||||
content test-addon-1 chrome/content
|
||||
|
||||
locale test-addon-1 en-US locale/en-US
|
||||
locale test-addon-1 fr-FR locale/fr-FR
|
||||
overlay chrome://browser/content/browser.xul chrome://test-addon-1/content/overlay.xul
|
||||
binary-component components/something.so
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>addon8@tests.mozilla.org</em:id>
|
||||
<em:version>1.0</em:version>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>Test 8</em:name>
|
||||
<em:description>Test Description</em:description>
|
||||
<em:unpack>true</em:unpack>
|
||||
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>xpcshell@tests.mozilla.org</em:id>
|
||||
<em:minVersion>1</em:minVersion>
|
||||
<em:maxVersion>2</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
</Description>
|
||||
</RDF>
|
@ -0,0 +1,108 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests ChromeManifestParser.js
|
||||
|
||||
Components.utils.import("resource://gre/modules/ChromeManifestParser.jsm");
|
||||
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
|
||||
|
||||
startupManager();
|
||||
|
||||
installAllFiles([do_get_addon("test_chromemanifest_1"),
|
||||
do_get_addon("test_chromemanifest_2"),
|
||||
do_get_addon("test_chromemanifest_3"),
|
||||
do_get_addon("test_chromemanifest_4")],
|
||||
function() {
|
||||
|
||||
restartManager();
|
||||
run_test_1();
|
||||
});
|
||||
}
|
||||
|
||||
function run_test_1() {
|
||||
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org",
|
||||
"addon3@tests.mozilla.org",
|
||||
"addon4@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4]) {
|
||||
// addon1
|
||||
let a1Uri = a1.getResourceURI("/").spec;
|
||||
let expected = [
|
||||
{type: "content", baseURI: a1Uri, args: ["test-addon-1", "chrome/content"]},
|
||||
{type: "locale", baseURI: a1Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
|
||||
{type: "locale", baseURI: a1Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
|
||||
{type: "overlay", baseURI: a1Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]}
|
||||
];
|
||||
let manifestURI = a1.getResourceURI("chrome.manifest");
|
||||
let manifest = ChromeManifestParser.parseSync(manifestURI);
|
||||
|
||||
do_check_true(Array.isArray(manifest));
|
||||
do_check_eq(manifest.length, expected.length);
|
||||
for (let i = 0; i < manifest.length; i++) {
|
||||
do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
|
||||
}
|
||||
|
||||
// addon2
|
||||
let a2Uri = a2.getResourceURI("/").spec;
|
||||
expected = [
|
||||
{type: "content", baseURI: a2Uri, args: ["test-addon-1", "chrome/content"]},
|
||||
{type: "locale", baseURI: a2Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
|
||||
{type: "locale", baseURI: a2Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
|
||||
{type: "overlay", baseURI: a2Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]},
|
||||
{type: "binary-component", baseURI: a2Uri, args: ["components/something.so"]}
|
||||
];
|
||||
manifestURI = a2.getResourceURI("chrome.manifest");
|
||||
manifest = ChromeManifestParser.parseSync(manifestURI);
|
||||
|
||||
do_check_true(Array.isArray(manifest));
|
||||
do_check_eq(manifest.length, expected.length);
|
||||
for (let i = 0; i < manifest.length; i++) {
|
||||
do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
|
||||
}
|
||||
|
||||
// addon3
|
||||
let a3Uri = a3.getResourceURI("/").spec;
|
||||
expected = [
|
||||
{type: "content", baseURI: a3Uri, args: ["test-addon-1", "chrome/content"]},
|
||||
{type: "locale", baseURI: a3Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
|
||||
{type: "locale", baseURI: a3Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
|
||||
{type: "overlay", baseURI: a3Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]},
|
||||
{type: "binary-component", baseURI: a3Uri, args: ["components/something.so"]},
|
||||
{type: "locale", baseURI: "jar:" + a3.getResourceURI("/inner.jar").spec + "!/", args: ["test-addon-1", "en-NZ", "locale/en-NZ"]},
|
||||
];
|
||||
manifestURI = a3.getResourceURI("chrome.manifest");
|
||||
manifest = ChromeManifestParser.parseSync(manifestURI);
|
||||
|
||||
do_check_true(Array.isArray(manifest));
|
||||
do_check_eq(manifest.length, expected.length);
|
||||
for (let i = 0; i < manifest.length; i++) {
|
||||
do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
|
||||
}
|
||||
|
||||
// addon4
|
||||
let a4Uri = a4.getResourceURI("/").spec;
|
||||
expected = [
|
||||
{type: "content", baseURI: a4Uri, args: ["test-addon-1", "chrome/content"]},
|
||||
{type: "locale", baseURI: a4Uri, args: ["test-addon-1", "en-US", "locale/en-US"]},
|
||||
{type: "locale", baseURI: a4Uri, args: ["test-addon-1", "fr-FR", "locale/fr-FR"]},
|
||||
{type: "overlay", baseURI: a4Uri, args: ["chrome://browser/content/browser.xul", "chrome://test-addon-1/content/overlay.xul"]},
|
||||
{type: "binary-component", baseURI: a4.getResourceURI("components/").spec, args: ["mycomponent.dll"]},
|
||||
{type: "binary-component", baseURI: a4.getResourceURI("components/other/").spec, args: ["thermalnuclearwar.dll"]}
|
||||
];
|
||||
manifestURI = a4.getResourceURI("chrome.manifest");
|
||||
manifest = ChromeManifestParser.parseSync(manifestURI);
|
||||
|
||||
do_check_true(Array.isArray(manifest));
|
||||
do_check_eq(manifest.length, expected.length);
|
||||
for (let i = 0; i < manifest.length; i++) {
|
||||
do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
|
||||
}
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests detection of binary components via parsing of chrome manifests.
|
||||
|
||||
const profileDir = gProfD.clone();
|
||||
profileDir.append("extensions");
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
|
||||
|
||||
startupManager();
|
||||
|
||||
installAllFiles([do_get_addon("test_chromemanifest_1"),
|
||||
do_get_addon("test_chromemanifest_2"),
|
||||
do_get_addon("test_chromemanifest_3"),
|
||||
do_get_addon("test_chromemanifest_4"),
|
||||
do_get_addon("test_chromemanifest_5")],
|
||||
function() {
|
||||
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org",
|
||||
"addon3@tests.mozilla.org",
|
||||
"addon4@tests.mozilla.org",
|
||||
"addon5@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4, a5]) {
|
||||
// addon1 has no binary components
|
||||
do_check_neq(a1, null);
|
||||
do_check_false(a1.userDisabled);
|
||||
do_check_false(a1.hasBinaryComponents);
|
||||
do_check_true(a1.isCompatible);
|
||||
do_check_false(a1.appDisabled);
|
||||
do_check_true(a1.isActive);
|
||||
do_check_true(isExtensionInAddonsList(profileDir, a1.id));
|
||||
|
||||
// addon2 has a binary component, is compatible
|
||||
do_check_neq(a2, null);
|
||||
do_check_false(a2.userDisabled);
|
||||
do_check_true(a2.hasBinaryComponents);
|
||||
do_check_true(a2.isCompatible);
|
||||
do_check_false(a2.appDisabled);
|
||||
do_check_true(a2.isActive);
|
||||
do_check_true(isExtensionInAddonsList(profileDir, a2.id));
|
||||
|
||||
// addon3 has a binary component, is incompatible
|
||||
do_check_neq(a3, null);
|
||||
do_check_false(a3.userDisabled);
|
||||
do_check_true(a2.hasBinaryComponents);
|
||||
do_check_false(a3.isCompatible);
|
||||
do_check_true(a3.appDisabled);
|
||||
do_check_false(a3.isActive);
|
||||
do_check_false(isExtensionInAddonsList(profileDir, a3.id));
|
||||
|
||||
// addon4 has a binary component listed in a sub-manifest, is incompatible
|
||||
do_check_neq(a4, null);
|
||||
do_check_false(a4.userDisabled);
|
||||
do_check_true(a2.hasBinaryComponents);
|
||||
do_check_false(a4.isCompatible);
|
||||
do_check_true(a4.appDisabled);
|
||||
do_check_false(a4.isActive);
|
||||
do_check_false(isExtensionInAddonsList(profileDir, a4.id));
|
||||
|
||||
// addon5 has a binary component, but is set to not unpack
|
||||
do_check_neq(a5, null);
|
||||
do_check_false(a5.userDisabled);
|
||||
if (TEST_UNPACKED)
|
||||
do_check_true(a5.hasBinaryComponents);
|
||||
else
|
||||
do_check_false(a5.hasBinaryComponents);
|
||||
do_check_true(a5.isCompatible);
|
||||
do_check_false(a5.appDisabled);
|
||||
do_check_true(a5.isActive);
|
||||
do_check_true(isExtensionInAddonsList(profileDir, a5.id));
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
});
|
||||
}
|
@ -116,6 +116,13 @@ function run_test() {
|
||||
addon7.copyTo(stagedXPIs, "tmp.xpi");
|
||||
stagedXPIs = stagedXPIs.parent;
|
||||
|
||||
stagedXPIs.append("addon8@tests.mozilla.org");
|
||||
stagedXPIs.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
|
||||
|
||||
let addon7 = do_get_addon("test_migrate8");
|
||||
addon7.copyTo(stagedXPIs, "tmp.xpi");
|
||||
stagedXPIs = stagedXPIs.parent;
|
||||
|
||||
let old = do_get_file("data/test_migrate.rdf");
|
||||
old.copyTo(gProfD, "extensions.rdf");
|
||||
|
||||
@ -144,16 +151,19 @@ function run_test() {
|
||||
"addon5@tests.mozilla.org",
|
||||
"addon6@tests.mozilla.org",
|
||||
"addon7@tests.mozilla.org",
|
||||
"addon8@tests.mozilla.org",
|
||||
"theme1@tests.mozilla.org",
|
||||
"theme2@tests.mozilla.org"], function([a1, a2, a3,
|
||||
a4, a5, a6,
|
||||
a7, t1, t2]) {
|
||||
a7, a8, t1,
|
||||
t2]) {
|
||||
// addon1 was user and app enabled in the old extensions.rdf
|
||||
do_check_neq(a1, null);
|
||||
do_check_false(a1.userDisabled);
|
||||
do_check_false(a1.appDisabled);
|
||||
do_check_true(a1.isActive);
|
||||
do_check_true(isExtensionInAddonsList(profileDir, a1.id));
|
||||
do_check_false(a1.hasBinaryComponents);
|
||||
|
||||
// addon2 was user disabled and app enabled in the old extensions.rdf
|
||||
do_check_neq(a2, null);
|
||||
@ -161,6 +171,7 @@ function run_test() {
|
||||
do_check_false(a2.appDisabled);
|
||||
do_check_false(a2.isActive);
|
||||
do_check_false(isExtensionInAddonsList(profileDir, a2.id));
|
||||
do_check_false(a2.hasBinaryComponents);
|
||||
|
||||
// addon3 was pending user disable and app disabled in the old extensions.rdf
|
||||
do_check_neq(a3, null);
|
||||
@ -168,6 +179,7 @@ function run_test() {
|
||||
do_check_true(a3.appDisabled);
|
||||
do_check_false(a3.isActive);
|
||||
do_check_false(isExtensionInAddonsList(profileDir, a3.id));
|
||||
do_check_false(a3.hasBinaryComponents);
|
||||
|
||||
// addon4 was pending user enable and app disabled in the old extensions.rdf
|
||||
do_check_neq(a4, null);
|
||||
@ -175,6 +187,7 @@ function run_test() {
|
||||
do_check_true(a4.appDisabled);
|
||||
do_check_false(a4.isActive);
|
||||
do_check_false(isExtensionInAddonsList(profileDir, a4.id));
|
||||
do_check_false(a4.hasBinaryComponents);
|
||||
|
||||
// addon5 was disabled and compatible but a new version has been installed
|
||||
// since, it should still be disabled but should be incompatible
|
||||
@ -183,6 +196,7 @@ function run_test() {
|
||||
do_check_true(a5.appDisabled);
|
||||
do_check_false(a5.isActive);
|
||||
do_check_false(isExtensionInAddonsList(profileDir, a5.id));
|
||||
do_check_false(a5.hasBinaryComponents);
|
||||
|
||||
// addon6 should be installed and compatible and packed unless unpacking is
|
||||
// forced
|
||||
@ -195,6 +209,7 @@ function run_test() {
|
||||
do_check_eq(a6.getResourceURI("install.rdf").scheme, "file");
|
||||
else
|
||||
do_check_eq(a6.getResourceURI("install.rdf").scheme, "jar");
|
||||
do_check_false(a6.hasBinaryComponents);
|
||||
|
||||
// addon7 should be installed and compatible and unpacked
|
||||
do_check_neq(a7, null);
|
||||
@ -203,6 +218,15 @@ function run_test() {
|
||||
do_check_true(a7.isActive);
|
||||
do_check_true(isExtensionInAddonsList(profileDir, a7.id));
|
||||
do_check_eq(a7.getResourceURI("install.rdf").scheme, "file");
|
||||
do_check_false(a7.hasBinaryComponents);
|
||||
|
||||
// addon8 should be installed and compatible and have binary components
|
||||
do_check_neq(a8, null);
|
||||
do_check_false(a8.userDisabled);
|
||||
do_check_false(a8.appDisabled);
|
||||
do_check_true(a8.isActive);
|
||||
do_check_true(isExtensionInAddonsList(profileDir, a8.id));
|
||||
do_check_true(a8.hasBinaryComponents);
|
||||
|
||||
// Theme 1 was previously enabled
|
||||
do_check_neq(t1, null);
|
||||
|
@ -98,46 +98,51 @@ function prepare_profile() {
|
||||
writeInstallRDFForExtension(addon6, profileDir);
|
||||
|
||||
startupManager();
|
||||
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org",
|
||||
"addon3@tests.mozilla.org",
|
||||
"addon4@tests.mozilla.org",
|
||||
"addon5@tests.mozilla.org",
|
||||
"addon6@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4, a5, a6]) {
|
||||
a2.userDisabled = true;
|
||||
a2.applyBackgroundUpdates = false;
|
||||
a4.userDisabled = true;
|
||||
a6.userDisabled = true;
|
||||
installAllFiles([do_get_addon("test_migrate8")],
|
||||
function() {
|
||||
restartManager();
|
||||
|
||||
a6.findUpdates({
|
||||
onUpdateAvailable: function(aAddon, aInstall6) {
|
||||
AddonManager.getInstallForURL("http://localhost:4444/addons/test_migrate4_7.xpi", function(aInstall7) {
|
||||
completeAllInstalls([aInstall6, aInstall7], function() {
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org",
|
||||
"addon3@tests.mozilla.org",
|
||||
"addon4@tests.mozilla.org",
|
||||
"addon5@tests.mozilla.org",
|
||||
"addon6@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4, a5, a6]) {
|
||||
a3.userDisabled = true;
|
||||
a4.userDisabled = false;
|
||||
|
||||
a5.findUpdates({
|
||||
onUpdateFinished: function() {
|
||||
shutdownManager();
|
||||
|
||||
perform_migration();
|
||||
}
|
||||
}, AddonManager.UPDATE_WHEN_USER_REQUESTED);
|
||||
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org",
|
||||
"addon3@tests.mozilla.org",
|
||||
"addon4@tests.mozilla.org",
|
||||
"addon5@tests.mozilla.org",
|
||||
"addon6@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4, a5, a6]) {
|
||||
a2.userDisabled = true;
|
||||
a2.applyBackgroundUpdates = false;
|
||||
a4.userDisabled = true;
|
||||
a6.userDisabled = true;
|
||||
|
||||
a6.findUpdates({
|
||||
onUpdateAvailable: function(aAddon, aInstall6) {
|
||||
AddonManager.getInstallForURL("http://localhost:4444/addons/test_migrate4_7.xpi", function(aInstall7) {
|
||||
completeAllInstalls([aInstall6, aInstall7], function() {
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
|
||||
"addon2@tests.mozilla.org",
|
||||
"addon3@tests.mozilla.org",
|
||||
"addon4@tests.mozilla.org",
|
||||
"addon5@tests.mozilla.org",
|
||||
"addon6@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4, a5, a6]) {
|
||||
a3.userDisabled = true;
|
||||
a4.userDisabled = false;
|
||||
|
||||
a5.findUpdates({
|
||||
onUpdateFinished: function() {
|
||||
shutdownManager();
|
||||
|
||||
perform_migration();
|
||||
}
|
||||
}, AddonManager.UPDATE_WHEN_USER_REQUESTED);
|
||||
});
|
||||
});
|
||||
});
|
||||
}, "application/x-xpinstall");
|
||||
}
|
||||
}, AddonManager.UPDATE_WHEN_USER_REQUESTED);
|
||||
}, "application/x-xpinstall");
|
||||
}
|
||||
}, AddonManager.UPDATE_WHEN_USER_REQUESTED);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -169,8 +174,9 @@ function test_results() {
|
||||
"addon4@tests.mozilla.org",
|
||||
"addon5@tests.mozilla.org",
|
||||
"addon6@tests.mozilla.org",
|
||||
"addon7@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4, a5, a6, a7]) {
|
||||
"addon7@tests.mozilla.org",
|
||||
"addon8@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4, a5, a6, a7, a8]) {
|
||||
// addon1 was enabled
|
||||
do_check_neq(a1, null);
|
||||
do_check_false(a1.userDisabled);
|
||||
@ -178,6 +184,7 @@ function test_results() {
|
||||
do_check_true(a1.isActive);
|
||||
do_check_true(a1.applyBackgroundUpdates);
|
||||
do_check_true(a1.foreignInstall);
|
||||
do_check_false(a1.hasBinaryComponents);
|
||||
|
||||
// addon2 was disabled
|
||||
do_check_neq(a2, null);
|
||||
@ -186,6 +193,7 @@ function test_results() {
|
||||
do_check_false(a2.isActive);
|
||||
do_check_false(a2.applyBackgroundUpdates);
|
||||
do_check_true(a2.foreignInstall);
|
||||
do_check_false(a2.hasBinaryComponents);
|
||||
|
||||
// addon3 was pending-disable in the database
|
||||
do_check_neq(a3, null);
|
||||
@ -194,6 +202,7 @@ function test_results() {
|
||||
do_check_false(a3.isActive);
|
||||
do_check_true(a3.applyBackgroundUpdates);
|
||||
do_check_true(a3.foreignInstall);
|
||||
do_check_false(a3.hasBinaryComponents);
|
||||
|
||||
// addon4 was pending-enable in the database
|
||||
do_check_neq(a4, null);
|
||||
@ -202,6 +211,7 @@ function test_results() {
|
||||
do_check_true(a4.isActive);
|
||||
do_check_true(a4.applyBackgroundUpdates);
|
||||
do_check_true(a4.foreignInstall);
|
||||
do_check_false(a4.hasBinaryComponents);
|
||||
|
||||
// addon5 was enabled in the database but needed a compatibiltiy update
|
||||
do_check_neq(a5, null);
|
||||
@ -210,6 +220,7 @@ function test_results() {
|
||||
do_check_true(a5.isActive);
|
||||
do_check_true(a5.applyBackgroundUpdates);
|
||||
do_check_true(a5.foreignInstall);
|
||||
do_check_false(a5.hasBinaryComponents);
|
||||
|
||||
// addon6 was disabled and compatible but a new version has been installed
|
||||
do_check_neq(a6, null);
|
||||
@ -221,6 +232,7 @@ function test_results() {
|
||||
do_check_true(a6.foreignInstall);
|
||||
do_check_eq(a6.sourceURI.spec, "http://localhost:4444/addons/test_migrate4_6.xpi");
|
||||
do_check_eq(a6.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml");
|
||||
do_check_false(a6.hasBinaryComponents);
|
||||
|
||||
// addon7 was installed manually
|
||||
do_check_neq(a7, null);
|
||||
@ -232,6 +244,15 @@ function test_results() {
|
||||
do_check_false(a7.foreignInstall);
|
||||
do_check_eq(a7.sourceURI.spec, "http://localhost:4444/addons/test_migrate4_7.xpi");
|
||||
do_check_eq(a7.releaseNotesURI, null);
|
||||
do_check_false(a7.hasBinaryComponents);
|
||||
|
||||
// addon8 was enabled and has binary components
|
||||
do_check_neq(a8, null);
|
||||
do_check_false(a8.userDisabled);
|
||||
do_check_false(a8.appDisabled);
|
||||
do_check_true(a8.isActive);
|
||||
do_check_true(a8.hasBinaryComponents);
|
||||
|
||||
testserver.stop(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
@ -126,6 +126,7 @@ fail-if = os == "android"
|
||||
[test_bug675371.js]
|
||||
[test_cacheflush.js]
|
||||
[test_checkcompatibility.js]
|
||||
[test_ChromeManifestParser.js]
|
||||
[test_corrupt.js]
|
||||
[test_corrupt_strictcompat.js]
|
||||
[test_dictionary.js]
|
||||
@ -157,6 +158,7 @@ skip-if = os == "android"
|
||||
[test_gfxBlacklist_OS.js]
|
||||
[test_gfxBlacklist_Vendor.js]
|
||||
[test_gfxBlacklist_prefs.js]
|
||||
[test_hasbinarycomponents.js]
|
||||
[test_install.js]
|
||||
# Bug 676992: test consistently hangs on Android
|
||||
skip-if = os == "android"
|
||||
|
Loading…
Reference in New Issue
Block a user