element to parse
- * @param aSkip
- * Object containing ids and sourceURIs of add-ons to skip.
- * @param aCompatData
- * Array of parsed addon_compatibility elements to accosiate with the
- * resulting AddonSearchResult. Optional.
- * @return Result object containing the parsed AddonSearchResult, xpiURL and
- * xpiHash if the parsing was successful. Otherwise returns null.
+ * @param aEntry
+ * An entry from the AMO compat overrides API to parse.
+ * @return Result object containing the parsed AddonCompatibilityOverride
*/
- _parseAddon(aElement, aSkip, aCompatData) {
- let skipIDs = (aSkip && aSkip.ids) ? aSkip.ids : [];
- let skipSourceURIs = (aSkip && aSkip.sourceURIs) ? aSkip.sourceURIs : [];
-
- let guid = this._getDescendantTextContent(aElement, "guid");
- if (guid == null || skipIDs.includes(guid))
- return null;
-
- let addon = new AddonSearchResult(guid);
- let result = {
- addon,
- xpiURL: null,
- xpiHash: null
+ _parseCompatEntry(aEntry) {
+ let compat = {
+ id: aEntry.addon_guid,
+ compatRanges: null,
};
- if (aCompatData && guid in aCompatData)
- addon.compatibilityOverrides = aCompatData[guid].compatRanges;
-
- for (let node = aElement.firstChild; node; node = node.nextSibling) {
- if (!(node instanceof Ci.nsIDOMElement))
- continue;
-
- let localName = node.localName;
-
- // Handle case where the wanted string value is located in text content
- // but only if the content is not empty
- if (localName in STRING_KEY_MAP) {
- addon[STRING_KEY_MAP[localName]] = this._getTextContent(node) || addon[STRING_KEY_MAP[localName]];
- continue;
- }
-
- // Handle case where the wanted string value is html located in text content
- if (localName in HTML_KEY_MAP) {
- addon[HTML_KEY_MAP[localName]] = convertHTMLToPlainText(this._getTextContent(node));
- continue;
- }
-
- // Handle case where the wanted integer value is located in text content
- if (localName in INTEGER_KEY_MAP) {
- let value = parseInt(this._getTextContent(node));
- if (value >= 0)
- addon[INTEGER_KEY_MAP[localName]] = value;
- continue;
- }
-
- // Handle cases that aren't as simple as grabbing the text content
- switch (localName) {
- case "type":
- // Map AMO's type id to corresponding string
- // https://github.com/mozilla/olympia/blob/master/apps/constants/base.py#L127
- // These definitions need to be updated whenever AMO adds a new type.
- let id = parseInt(node.getAttribute("id"));
- switch (id) {
- case 1:
- addon.type = "extension";
- break;
- case 2:
- addon.type = "theme";
- break;
- case 3:
- addon.type = "dictionary";
- break;
- case 4:
- addon.type = "search";
- break;
- case 5:
- case 6:
- addon.type = "locale";
- break;
- case 7:
- addon.type = "plugin";
- break;
- case 8:
- addon.type = "api";
- break;
- case 9:
- addon.type = "lightweight-theme";
- break;
- case 11:
- addon.type = "webapp";
- break;
- default:
- logger.info("Unknown type id " + id + " found when parsing response for GUID " + guid);
- }
- break;
- case "authors":
- let authorNodes = node.getElementsByTagName("author");
- for (let authorNode of authorNodes) {
- let name = this._getDescendantTextContent(authorNode, "name");
- let link = this._getDescendantTextContent(authorNode, "link");
- if (name == null || link == null)
- continue;
-
- let author = new AddonManagerPrivate.AddonAuthor(name, link);
- if (addon.creator == null)
- addon.creator = author;
- else {
- if (addon.developers == null)
- addon.developers = [];
-
- addon.developers.push(author);
- }
- }
- break;
- case "previews":
- let previewNodes = node.getElementsByTagName("preview");
- for (let previewNode of previewNodes) {
- let full = this._getUniqueDescendant(previewNode, "full");
- if (full == null)
- continue;
-
- let fullURL = this._getTextContent(full);
- let fullWidth = full.getAttribute("width");
- let fullHeight = full.getAttribute("height");
-
- let thumbnailURL, thumbnailWidth, thumbnailHeight;
- let thumbnail = this._getUniqueDescendant(previewNode, "thumbnail");
- if (thumbnail) {
- thumbnailURL = this._getTextContent(thumbnail);
- thumbnailWidth = thumbnail.getAttribute("width");
- thumbnailHeight = thumbnail.getAttribute("height");
- }
- let caption = this._getDescendantTextContent(previewNode, "caption");
- let screenshot = new AddonManagerPrivate.AddonScreenshot(fullURL, fullWidth, fullHeight,
- thumbnailURL, thumbnailWidth,
- thumbnailHeight, caption);
-
- if (addon.screenshots == null)
- addon.screenshots = [];
-
- if (previewNode.getAttribute("primary") == 1)
- addon.screenshots.unshift(screenshot);
- else
- addon.screenshots.push(screenshot);
- }
- break;
- case "learnmore":
- addon.learnmoreURL = this._getTextContent(node);
- addon.homepageURL = addon.homepageURL || addon.learnmoreURL;
- break;
- case "contribution_data":
- let meetDevelopers = this._getDescendantTextContent(node, "meet_developers");
- let suggestedAmount = this._getDescendantTextContent(node, "suggested_amount");
- if (meetDevelopers != null) {
- addon.contributionURL = meetDevelopers;
- addon.contributionAmount = suggestedAmount;
- }
- break;
- case "payment_data":
- let link = this._getDescendantTextContent(node, "link");
- let amountTag = this._getUniqueDescendant(node, "amount");
- let amount = parseFloat(amountTag.getAttribute("amount"));
- let displayAmount = this._getTextContent(amountTag);
- if (link != null && amount != null && displayAmount != null) {
- addon.purchaseURL = link;
- addon.purchaseAmount = amount;
- addon.purchaseDisplayAmount = displayAmount;
- }
- break;
- case "rating":
- let averageRating = parseInt(this._getTextContent(node));
- if (averageRating >= 0)
- addon.averageRating = Math.min(5, averageRating);
- break;
- case "reviews":
- let url = this._getTextContent(node);
- let num = parseInt(node.getAttribute("num"));
- if (url != null && num >= 0) {
- addon.reviewURL = url;
- addon.reviewCount = num;
- }
- break;
- case "status":
- let repositoryStatus = parseInt(node.getAttribute("id"));
- if (!isNaN(repositoryStatus))
- addon.repositoryStatus = repositoryStatus;
- break;
- case "all_compatible_os":
- let nodes = node.getElementsByTagName("os");
- addon.isPlatformCompatible = Array.some(nodes, function(aNode) {
- let text = aNode.textContent.toLowerCase().trim();
- return text == "all" || text == Services.appinfo.OS.toLowerCase();
- });
- break;
- case "install":
- // No os attribute means the xpi is compatible with any os
- if (node.hasAttribute("os")) {
- let os = node.getAttribute("os").trim().toLowerCase();
- // If the os is not ALL and not the current OS then ignore this xpi
- if (os != "all" && os != Services.appinfo.OS.toLowerCase())
- break;
- }
-
- let xpiURL = this._getTextContent(node);
- if (xpiURL == null)
- break;
-
- if (skipSourceURIs.includes(xpiURL))
- return null;
-
- result.xpiURL = xpiURL;
- addon.sourceURI = NetUtil.newURI(xpiURL);
-
- let size = parseInt(node.getAttribute("size"));
- addon.size = (size >= 0) ? size : null;
-
- let xpiHash = node.getAttribute("hash");
- if (xpiHash != null)
- xpiHash = xpiHash.trim();
- result.xpiHash = xpiHash ? xpiHash : null;
- break;
- case "last_updated":
- let epoch = parseInt(node.getAttribute("epoch"));
- if (!isNaN(epoch))
- addon.updateDate = new Date(1000 * epoch);
- break;
- case "icon":
- addon.icons[node.getAttribute("size")] = this._getTextContent(node);
- break;
- }
- }
-
- return result;
- },
-
- _parseAddons(aElements, aTotalResults, aSkip) {
- let results = [];
-
- let isSameApplication = aAppNode => this._getTextContent(aAppNode) == Services.appinfo.ID;
-
- for (let i = 0; i < aElements.length && results.length < this._maxResults; i++) {
- let element = aElements[i];
-
- let tags = this._getUniqueDescendant(element, "compatible_applications");
- if (tags == null)
- continue;
-
- let applications = tags.getElementsByTagName("appID");
- let compatible = Array.some(applications, aAppNode => {
- if (!isSameApplication(aAppNode))
- return false;
-
- let parent = aAppNode.parentNode;
- let minVersion = this._getDescendantTextContent(parent, "min_version");
- let maxVersion = this._getDescendantTextContent(parent, "max_version");
- if (minVersion == null || maxVersion == null)
- return false;
-
- let currentVersion = Services.appinfo.version;
- return (Services.vc.compare(minVersion, currentVersion) <= 0 &&
- ((!AddonManager.strictCompatibility) ||
- Services.vc.compare(currentVersion, maxVersion) <= 0));
- });
-
- // Ignore add-ons not compatible with this Application
- if (!compatible) {
- if (AddonManager.checkCompatibility)
- continue;
-
- if (!Array.some(applications, isSameApplication))
- continue;
- }
-
- // Add-on meets all requirements, so parse out data.
- // Don't pass in compatiblity override data, because that's only returned
- // in GUID searches, which don't use _parseAddons().
- let result = this._parseAddon(element, aSkip);
- if (result == null)
- continue;
-
- // Ignore add-on missing a required attribute
- let requiredAttributes = ["id", "name", "version", "type", "creator"];
- if (requiredAttributes.some(aAttribute => !result.addon[aAttribute]))
- continue;
-
- // Ignore add-on with a type AddonManager doesn't understand:
- if (!(result.addon.type in AddonManager.addonTypes))
- continue;
-
- // Add only if the add-on is compatible with the platform
- if (!result.addon.isPlatformCompatible)
- continue;
-
- // Add only if there was an xpi compatible with this OS or there was a
- // way to purchase the add-on
- if (!result.xpiURL && !result.addon.purchaseURL)
- continue;
-
- result.addon.isCompatible = compatible;
-
- results.push(result);
- // Ignore this add-on from now on by adding it to the skip array
- aSkip.ids.push(result.addon.id);
- }
-
- // Immediately report success if no AddonInstall instances to create
- let pendingResults = results.length;
- if (pendingResults == 0) {
- this._reportSuccess(results, aTotalResults);
- return;
- }
-
- // Create an AddonInstall for each result
- for (let result of results) {
- let addon = result.addon;
- let callback = aInstall => {
- addon.install = aInstall;
- pendingResults--;
- if (pendingResults == 0)
- this._reportSuccess(results, aTotalResults);
- };
-
- if (result.xpiURL) {
- AddonManager.getInstallForURL(result.xpiURL, callback,
- "application/x-xpinstall", result.xpiHash,
- addon.name, addon.icons, addon.version);
- } else {
- callback(null);
- }
- }
- },
-
- // Parses addon_compatibility nodes, that describe compatibility overrides.
- _parseAddonCompatElement(aResultObj, aElement) {
- let guid = this._getDescendantTextContent(aElement, "guid");
- if (!guid) {
- logger.debug("Compatibility override is missing guid.");
- return;
- }
-
- let compat = {id: guid};
- compat.hosted = aElement.getAttribute("hosted") != "false";
-
- function findMatchingAppRange(aNodes) {
- let toolkitAppRange = null;
- for (let node of aNodes) {
- let appID = this._getDescendantTextContent(node, "appID");
- if (appID != Services.appinfo.ID && appID != TOOLKIT_ID)
- continue;
-
- let minVersion = this._getDescendantTextContent(node, "min_version");
- let maxVersion = this._getDescendantTextContent(node, "max_version");
- if (minVersion == null || maxVersion == null)
- continue;
-
- let appRange = { appID,
- appMinVersion: minVersion,
- appMaxVersion: maxVersion };
-
- // Only use Toolkit app ranges if no ranges match the application ID.
- if (appID == TOOLKIT_ID)
- toolkitAppRange = appRange;
- else
- return appRange;
- }
- return toolkitAppRange;
- }
-
- function parseRangeNode(aNode) {
- let type = aNode.getAttribute("type");
- // Only "incompatible" (blacklisting) is supported for now.
- if (type != "incompatible") {
- logger.debug("Compatibility override of unsupported type found.");
- return null;
- }
-
- let override = new AddonManagerPrivate.AddonCompatibilityOverride(type);
-
- override.minVersion = this._getDirectDescendantTextContent(aNode, "min_version");
- override.maxVersion = this._getDirectDescendantTextContent(aNode, "max_version");
-
- if (!override.minVersion) {
+ for (let range of aEntry.version_ranges) {
+ if (!range.addon_min_version) {
logger.debug("Compatibility override is missing min_version.");
- return null;
+ continue;
}
- if (!override.maxVersion) {
+ if (!range.addon_max_version) {
logger.debug("Compatibility override is missing max_version.");
return null;
}
- let appRanges = aNode.querySelectorAll("compatible_applications > application");
- let appRange = findMatchingAppRange.bind(this)(appRanges);
- if (!appRange) {
+ let override = new AddonManagerPrivate.AddonCompatibilityOverride("incompatible");
+ override.minVersion = range.addon_min_version;
+ override.maxVersion = range.addon_max_version;
+
+ for (let app of range.applications) {
+ if (app.guid != Services.appinfo.ID && app.guid != TOOLKIT_ID) {
+ continue;
+ }
+ if (!app.min_version || !app.max_version) {
+ continue;
+ }
+
+ override.appID = app.guid;
+ override.appMinVersion = app.min_version;
+ override.appMaxVersion = app.max_version;
+ if (app.id != TOOLKIT_ID) {
+ break;
+ }
+ }
+
+ if (!override.appID) {
logger.debug("Compatibility override is missing a valid application range.");
- return null;
+ continue;
}
- override.appID = appRange.appID;
- override.appMinVersion = appRange.appMinVersion;
- override.appMaxVersion = appRange.appMaxVersion;
-
- return override;
- }
-
- let rangeNodes = aElement.querySelectorAll("version_ranges > version_range");
- compat.compatRanges = Array.map(rangeNodes, parseRangeNode.bind(this))
- .filter(aItem => !!aItem);
- if (compat.compatRanges.length == 0)
- return;
-
- aResultObj[compat.id] = compat;
- },
-
- // Parses addon_compatibility elements.
- _parseAddonCompatData(aElements) {
- let compatData = {};
- Array.forEach(aElements, this._parseAddonCompatElement.bind(this, compatData));
- return compatData;
- },
-
- // Begins a new search if one isn't currently executing
- _beginSearch(aURI, aMaxResults, aCallback, aHandleResults, aTimeout) {
- if (this._searching || aURI == null || aMaxResults <= 0) {
- logger.warn("AddonRepository search failed: searching " + this._searching + " aURI " + aURI +
- " aMaxResults " + aMaxResults);
- aCallback.searchFailed();
- return;
- }
-
- this._searching = true;
- this._callback = aCallback;
- this._maxResults = aMaxResults;
-
- logger.debug("Requesting " + aURI);
-
- this._request = new ServiceRequest();
- this._request.mozBackgroundRequest = true;
- this._request.open("GET", aURI, true);
- this._request.overrideMimeType("text/xml");
- if (aTimeout) {
- this._request.timeout = aTimeout;
- }
-
- this._request.addEventListener("error", aEvent => this._reportFailure());
- this._request.addEventListener("timeout", aEvent => this._reportFailure());
- this._request.addEventListener("load", aEvent => {
- logger.debug("Got metadata search load event");
- let request = aEvent.target;
- let responseXML = request.responseXML;
-
- if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR ||
- (request.status != 200 && request.status != 0)) {
- this._reportFailure();
- return;
+ if (compat.compatRanges === null) {
+ compat.compatRanges = [];
}
+ compat.compatRanges.push(override);
+ }
- let documentElement = responseXML.documentElement;
- let elements = documentElement.getElementsByTagName("addon");
- let totalResults = elements.length;
- let parsedTotalResults = parseInt(documentElement.getAttribute("total_results"));
- // Parsed value of total results only makes sense if >= elements.length
- if (parsedTotalResults >= totalResults)
- totalResults = parsedTotalResults;
-
- let compatElements = documentElement.getElementsByTagName("addon_compatibility");
- let compatData = this._parseAddonCompatData(compatElements);
-
- aHandleResults(elements, totalResults, compatData);
- });
- this._request.send(null);
+ return compat;
},
// Create url from preference, returning null if preference does not exist
@@ -1292,7 +726,8 @@ var AddonRepository = {
}
url = url.replace(/%([A-Z_]+)%/g, function(aMatch, aKey) {
- return (aKey in aSubstitutions) ? aSubstitutions[aKey] : aMatch;
+ return (aKey in aSubstitutions) ? encodeURIComponent(aSubstitutions[aKey])
+ : aMatch;
});
return Services.urlFormatter.formatURL(url);
@@ -1301,11 +736,10 @@ var AddonRepository = {
// Find a AddonCompatibilityOverride that matches a given aAddonVersion and
// application/platform version.
findMatchingCompatOverride(aAddonVersion,
- aCompatOverrides,
- aAppVersion,
- aPlatformVersion) {
+ aCompatOverrides,
+ aAppVersion,
+ aPlatformVersion) {
for (let override of aCompatOverrides) {
-
let appVersion = null;
if (override.appID == TOOLKIT_ID)
appVersion = aPlatformVersion || Services.appinfo.platformVersion;
@@ -1324,11 +758,12 @@ var AddonRepository = {
flush() {
return AddonDatabase.flush();
- }
+ },
};
var AddonDatabase = {
connectionPromise: null,
+ _loaded: false,
_saveTask: null,
_blockerAdded: false,
@@ -1340,7 +775,7 @@ var AddonDatabase = {
*/
get jsonFile() {
return OS.Path.join(OS.Constants.Path.profileDir, FILE_DATABASE);
- },
+ },
/**
* Asynchronously opens a new connection to the database file.
@@ -1349,9 +784,7 @@ var AddonDatabase = {
*/
openConnection() {
if (!this.connectionPromise) {
- this.connectionPromise = (async () => {
- this.DB = BLANK_DB();
-
+ this.connectionPromise = (async () => {
let inputDB, schema;
try {
@@ -1384,18 +817,32 @@ var AddonDatabase = {
this.save();
Services.prefs.setIntPref(PREF_GETADDONS_DB_SCHEMA, DB_SCHEMA);
+ this._loaded = true;
return this.DB;
}
Services.prefs.setIntPref(PREF_GETADDONS_DB_SCHEMA, DB_SCHEMA);
- // We use _insertAddon manually instead of calling
- // insertAddons to avoid the write to disk which would
- // be a waste since this is the data that was just read.
+ // Convert the addon and compat override objects as necessary
+ // and store them in our in-memory copy of the database.
for (let addon of inputDB.addons) {
- this._insertAddon(addon);
+ let id = addon.id;
+
+ let entry = this._parseAddon(addon);
+ this.DB.addons.set(id, entry);
+
+ if (entry.compatibilityOverrides) {
+ this.DB.compatOverrides.set(id, entry.compatibilityOverrides);
+ }
}
+ if (inputDB.compatOverrides) {
+ for (let entry of inputDB.compatOverrides) {
+ this.DB.compatOverrides.set(entry.id, entry.compatRanges);
+ }
+ }
+
+ this._loaded = true;
return this.DB;
})();
}
@@ -1419,6 +866,7 @@ var AddonDatabase = {
}
this.connectionPromise = null;
+ this._loaded = false;
if (aSkipFlush || !this._saveTask) {
return Promise.resolve();
@@ -1452,17 +900,20 @@ var AddonDatabase = {
this.jsonFile, error))
.then(() => this._deleting = null)
.then(aCallback);
+
return this._deleting;
},
async _saveNow() {
let json = {
schema: this.DB.schema,
- addons: []
+ addons: Array.from(this.DB.addons.values()),
+ compatOverrides: [],
};
- for (let [, value] of this.DB.addons)
- json.addons.push(value);
+ for (let [id, overrides] of this.DB.compatOverrides.entries()) {
+ json.compatOverrides.push({id, compatRanges: overrides});
+ }
await OS.File.writeAtomic(this.jsonFile, JSON.stringify(json),
{tmpPath: `${this.jsonFile}.tmp`});
@@ -1509,71 +960,79 @@ var AddonDatabase = {
},
/**
- * Asynchronously retrieve all add-ons from the database
- * @return: Promise{Map}
- * Resolves when the add-ons are retrieved from the database
+ * Get an individual addon entry from the in-memory cache.
+ * Note: calling this function before the database is read will
+ * return undefined.
+ *
+ * @param {string} aId The id of the addon to retrieve.
*/
- retrieveStoredData() {
- return this.openConnection().then(db => db.addons);
+ getAddon(aId) {
+ return this.DB.addons.get(aId);
+ },
+
+ /**
+ * Get an individual compatibility override from the in-memory cache.
+ * Note: calling this function before the database is read will
+ * return undefined.
+ *
+ * @param {string} aId The id of the addon to retrieve.
+ */
+ getCompatOverrides(aId) {
+ return this.DB.compatOverrides.get(aId);
},
/**
* Asynchronously repopulates the database so it only contains the
* specified add-ons
*
- * @param aAddons
- * The array of add-ons to repopulate the database with
- * @param aCallback
- * An optional callback to call once complete
+ * @param {Map} aAddons
+ * Add-ons to repopulate the database with.
+ * @param {Map} aCompatOverrides
+ * Compatibility overrides to repopulate the database with.
*/
- repopulate(aAddons, aCallback) {
- this.DB.addons.clear();
- this.insertAddons(aAddons, function() {
- let now = Math.round(Date.now() / 1000);
- logger.debug("Cache repopulated, setting " + PREF_METADATA_LASTUPDATE + " to " + now);
- Services.prefs.setIntPref(PREF_METADATA_LASTUPDATE, now);
- if (aCallback)
- aCallback();
- });
+ repopulate(aAddons, aCompatOverrides) {
+ this.DB = BLANK_DB();
+ this._update(aAddons, aCompatOverrides);
+
+ let now = Math.round(Date.now() / 1000);
+ logger.debug("Cache repopulated, setting " + PREF_METADATA_LASTUPDATE + " to " + now);
+ Services.prefs.setIntPref(PREF_METADATA_LASTUPDATE, now);
},
/**
- * Asynchronously inserts an array of add-ons into the database
+ * Asynchronously insert new addons and/or overrides into the database.
*
- * @param aAddons
- * The array of add-ons to insert
- * @param aCallback
- * An optional callback to call once complete
+ * @param {Map} aAddons
+ * Add-ons to insert/update in the database
+ * @param {Map} aCompatOverrides
+ * Compatibility overrides to insert/update in the database
*/
- async insertAddons(aAddons, aCallback) {
+ async update(aAddons, aCompatOverrides) {
await this.openConnection();
+ this._update(aAddons, aCompatOverrides);
+
+ this.save();
+ },
+
+ /**
+ * Merge the given addons and overrides into the database.
+ *
+ * @param {Map} aAddons
+ * Add-ons to insert/update in the database
+ * @param {Map} aCompatOverrides
+ * Compatibility overrides to insert/update in the database
+ */
+ _update(aAddons, aCompatOverrides) {
for (let addon of aAddons) {
- this._insertAddon(addon);
+ this.DB.addons.set(addon.id, this._parseAddon(addon));
+ }
+
+ for (let entry of aCompatOverrides) {
+ this.DB.compatOverrides.set(entry.id, entry.compatRanges);
}
this.save();
- aCallback && aCallback();
- },
-
- /**
- * Inserts an individual add-on into the database. If the add-on already
- * exists in the database (by id), then the specified add-on will not be
- * inserted.
- *
- * @param aAddon
- * The add-on to insert into the database
- * @param aCallback
- * The callback to call once complete
- */
- _insertAddon(aAddon) {
- let newAddon = this._parseAddon(aAddon);
- if (!newAddon ||
- !newAddon.id ||
- this.DB.addons.has(newAddon.id))
- return;
-
- this.DB.addons.set(newAddon.id, newAddon);
},
/*
@@ -1631,15 +1090,6 @@ var AddonDatabase = {
}
break;
- case "compatibilityOverrides":
- if (!addon.compatibilityOverrides) addon.compatibilityOverrides = [];
- for (let override of value) {
- addon.compatibilityOverrides.push(
- this._makeCompatOverride(override)
- );
- }
- break;
-
case "icons":
if (!addon.icons) addon.icons = {};
for (let size of Object.keys(aObj.icons)) {
@@ -1721,27 +1171,4 @@ var AddonDatabase = {
return new AddonManagerPrivate.AddonScreenshot(url, width, height, thumbnailURL,
thumbnailWidth, thumbnailHeight, caption);
},
-
- /**
- * Make a CompatibilityOverride from a vanilla
- * JS object from the JSON database
- *
- * @param aObj
- * The JS object to use
- * @return The created CompatibilityOverride
- */
- _makeCompatOverride(aObj) {
- let type = aObj.type;
- let minVersion = aObj.minVersion;
- let maxVersion = aObj.maxVersion;
- let appID = aObj.appID;
- let appMinVersion = aObj.appMinVersion;
- let appMaxVersion = aObj.appMaxVersion;
- return new AddonManagerPrivate.AddonCompatibilityOverride(type,
- minVersion,
- maxVersion,
- appID,
- appMinVersion,
- appMaxVersion);
- },
};
diff --git a/toolkit/mozapps/extensions/internal/XPIInstall.jsm b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
index fbc92233efe3..08f0fa74e318 100644
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -1622,12 +1622,15 @@ class AddonInstall {
// makes it impossible to delete on Windows.
// Try to load from the existing cache first
- let repoAddon = await new Promise(resolve => AddonRepository.getCachedAddonByID(this.addon.id, resolve));
+ let repoAddon = await AddonRepository.getCachedAddonByID(this.addon.id);
// It wasn't there so try to re-download it
if (!repoAddon) {
- await new Promise(resolve => AddonRepository.cacheAddons([this.addon.id], resolve));
- repoAddon = await new Promise(resolve => AddonRepository.getCachedAddonByID(this.addon.id, resolve));
+ try {
+ [repoAddon] = await AddonRepository.cacheAddons([this.addon.id]);
+ } catch (err) {
+ logger.debug(`Error getting metadata for ${this.addon.id}: ${err.message}`);
+ }
}
this.addon._repositoryAddon = repoAddon;
diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
index 9e1f81b85e6b..5945ef853441 100644
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -3934,8 +3934,8 @@ var XPIProvider = {
}
for (let addon of aAddons) {
- AddonRepository.getCachedAddonByID(addon.id, aRepoAddon => {
- if (aRepoAddon) {
+ AddonRepository.getCachedAddonByID(addon.id).then(aRepoAddon => {
+ if (aRepoAddon || AddonRepository.getCompatibilityOverridesSync(addon.id)) {
logger.debug("updateAddonRepositoryData got info for " + addon.id);
addon._repositoryAddon = aRepoAddon;
this.updateAddonDisabledState(addon);
@@ -5756,7 +5756,7 @@ function defineAddonWrapperProperty(name, getter) {
["fullDescription", "developerComments", "supportURL",
"contributionURL", "averageRating", "reviewCount",
- "reviewURL"].forEach(function(aProp) {
+ "reviewURL", "weeklyDownloads"].forEach(function(aProp) {
defineAddonWrapperProperty(aProp, function() {
let addon = addonFor(this);
if (addon._repositoryAddon)
diff --git a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
index ed7dfb093f69..89fb8c3514f0 100644
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -76,11 +76,10 @@ function getRepositoryAddon(aAddon, aCallback) {
aCallback(aAddon);
return;
}
- function completeAddon(aRepositoryAddon) {
- aAddon._repositoryAddon = aRepositoryAddon;
+ AddonRepository.getCachedAddonByID(aAddon.id, repoAddon => {
+ aAddon._repositoryAddon = repoAddon;
aCallback(aAddon);
- }
- AddonRepository.getCachedAddonByID(aAddon.id, completeAddon);
+ });
}
/**
diff --git a/toolkit/mozapps/extensions/test/browser/browser.ini b/toolkit/mozapps/extensions/test/browser/browser.ini
index 08ae271f2fa3..9567662b5e85 100644
--- a/toolkit/mozapps/extensions/test/browser/browser.ini
+++ b/toolkit/mozapps/extensions/test/browser/browser.ini
@@ -38,7 +38,6 @@ tags = blocklist
skip-if = buildapp == 'mulet'
[browser_about.js]
skip-if = os == 'linux' || os == 'win' # bug 632290
-[browser_addonrepository_performance.js]
[browser_bug523784.js]
[browser_bug562797.js]
[browser_bug562854.js]
diff --git a/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js b/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js
deleted file mode 100644
index 9d680eea418c..000000000000
--- a/toolkit/mozapps/extensions/test/browser/browser_addonrepository_performance.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Tests that the metadata request includes startup time measurements
-
-var tmp = {};
-ChromeUtils.import("resource://gre/modules/addons/AddonRepository.jsm", tmp);
-var AddonRepository = tmp.AddonRepository;
-
-var gProvider;
-
-function parseParams(aQuery) {
- let params = {};
-
- for (let param of aQuery.split("&")) {
- let [key, value] = param.split("=");
- params[key] = value;
- }
-
- return params;
-}
-
-function test() {
- waitForExplicitFinish();
-
- var gSeenRequest = false;
-
- gProvider = new MockProvider();
- gProvider.createAddons([{
- id: "test1@tests.mozilla.org",
- name: "Test add-on"
- }]);
-
- function observe(aSubject, aTopic, aData) {
- aSubject.QueryInterface(Ci.nsIChannel);
- let url = aSubject.URI.QueryInterface(Ci.nsIURL);
- if (url.filePath != "/extensions-dummy/metadata") {
- return;
- }
- info(url.query);
-
- // Check if we encountered telemetry errors and turn the tests for which
- // we don't have valid data into known failures.
- let snapshot = Services.telemetry.getHistogramById("STARTUP_MEASUREMENT_ERRORS")
- .snapshot();
-
- let tProcessValid = (snapshot.counts[0] == 0);
- let tMainValid = tProcessValid && (snapshot.counts[2] == 0);
- let tFirstPaintValid = tProcessValid && (snapshot.counts[5] == 0);
- let tSessionRestoredValid = tProcessValid && (snapshot.counts[6] == 0);
-
- let params = parseParams(url.query);
-
- is(params.appOS, Services.appinfo.OS, "OS should be correct");
- is(params.appVersion, Services.appinfo.version, "Version should be correct");
-
- if (tMainValid) {
- ok(params.tMain >= 0, "Should be a sensible tMain");
- } else {
- todo(false, "An error occurred while recording the startup timestamps, skipping this test");
- }
-
- if (tFirstPaintValid) {
- ok(params.tFirstPaint >= 0, "Should be a sensible tFirstPaint");
- } else {
- todo(false, "An error occurred while recording the startup timestamps, skipping this test");
- }
-
- if (tSessionRestoredValid) {
- ok(params.tSessionRestored >= 0, "Should be a sensible tSessionRestored");
- } else {
- todo(false, "An error occurred while recording the startup timestamps, skipping this test");
- }
-
- gSeenRequest = true;
- }
-
- const PREF = "extensions.getAddons.getWithPerformance.url";
-
- // Watch HTTP requests
- Services.obs.addObserver(observe, "http-on-modify-request");
- Services.prefs.setCharPref(PREF,
- "http://127.0.0.1:8888/extensions-dummy/metadata?appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
-
- registerCleanupFunction(function() {
- Services.obs.removeObserver(observe, "http-on-modify-request");
- });
-
- AddonRepository._beginGetAddons(["test1@tests.mozilla.org"], {
- searchFailed() {
- ok(gSeenRequest, "Should have seen metadata request");
- finish();
- }
- }, true);
-}
diff --git a/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js b/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js
index ac4a71291052..9d9208768a00 100644
--- a/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_discovery_install.js
@@ -12,8 +12,6 @@ const BAD_FRAMED_URL = "https://example.org/" + RELATIVE_DIR + "discovery_frame.
const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts";
-// Temporarily enable caching
-Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);
// Allow SSL from non-built-in certs
Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
// Allow installs from the test site
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository.xml
deleted file mode 100644
index 0bebca2c1aec..000000000000
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository.xml
+++ /dev/null
@@ -1,820 +0,0 @@
-
-
-
-
- PASS
- Extension
- test1@tests.mozilla.org
- 1.1
-
-
- Test Creator 1
- http://localhost:%PORT%/creator1.html
-
-
- Preliminarily Reviewed
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
-
- -2
-
-
-
- -2
- http://localhost:%PORT%/test1.xpi
-
-
-
-
- PASS
-
- Extension
- test2@tests.mozilla.org
- 1.2
-
-
-
- Test Creator 2
- http://localhost:%PORT%/creator2.html
-
-
- Test Developer 2
- http://localhost:%PORT%/developer2.html
-
-
- <h1>Test Summary 2</h1><p>paragraph</p>
- Test Description 2<br>newline
- Test Developer
- Comments 2
- Test EULA 2
- http://localhost:%PORT%/icon2-64.png
- http://localhost:%PORT%/icon2-48.png
- http://localhost:%PORT%/icon2-32.png
- Public
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
-
-
-
- http://localhost:%PORT%/full1-2.png
- http://localhost:%PORT%/thumbnail1-2.png
-
-
- http://localhost:%PORT%/full2-2.png
- http://localhost:%PORT%/thumbnail2-2.png
- Caption 2
-
-
- NaN
-
- http://localhost:%PORT%/learnmore2.html
-
- http://localhost:%PORT%/support2.html
-
- http://localhost:%PORT%/contribution2.html
- http://localhost:%PORT%/meetDevelopers2.html
-
- http://localhost:%PORT%/review2.html
- NaN
- NaN
- NaN
- Not an acual date
- http://localhost:%PORT%/test2.xpi
-
-
-
-
- PASS
-
- Theme
- test3@tests.mozilla.org
- 1.3
-
-
-
-
- http://localhost:%PORT%/ignore3.html
-
-
-
- Test Creator Ignore
-
-
-
- Test Creator 3
- http://localhost:%PORT%/creator3.html
-
-
- First Test Developer 3
- http://localhost:%PORT%/developer1-3.html
-
-
-
-
-
-
- Second Test Developer 3
- http://localhost:%PORT%/developer2-3.html
-
-
- Test Summary 3
- Test Description 3<br><ul><li>List item 1<li>List item 2</ul>
- Test Developer Comments 3
- Test EULA 3
- http://localhost:%PORT%/icon3.png
- Preliminarily Reviewed
-
-
-
- unknown@tests.mozilla.org
- 1
- 1
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
-
-
-
- http://localhost:%PORT%/full2-3.png
- Caption 2 - 3
-
-
-
- Caption ignore - 3
-
-
-
-
- Caption ignore - 3
-
- http://localhost:%PORT%/full1-3.png
- http://localhost:%PORT%/thumbnail1-3.png
- Caption 1 - 3
-
-
- http://localhost:%PORT%/full3-3.png
- http://localhost:%PORT%/thumbnail3-3.png
- Caption 3 - 3
-
-
-
-
- 2
-
- http://localhost:%PORT%/learnmore3.html
- http://localhost:%PORT%/homepage3.html
- http://localhost:%PORT%/support3.html
-
- http://localhost:%PORT%/contribution3.html
- $11.11
- http://localhost:%PORT%/meetDevelopers3.html
-
- http://localhost:%PORT%/review3.html
- 2222
- 3333
- 4444
- 2010-02-01T14:04:05Z
-
- http://localhost:%PORT%/fail3.xpi
-
- http://localhost:%PORT%/test3.xpi
-
-
-
-
- Extension
- test4@tests.mozilla.org
- 1.4
- Test Creator 4
- Public
- Add-on with undefined name should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test4.xpi
-
-
-
-
-
- Extension
- test5@tests.mozilla.org
- 1.5
- Test Creator 5
- Public
- Add-on with empty name should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test5.xpi
-
-
-
-
- FAIL
- test6@tests.mozilla.org
- 1.6
- Test Creator 6
- Public
- Add-on with undefined type should be ignored
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test6.xpi
-
-
-
-
- FAIL
- Empty id attribute
- test7@tests.mozilla.org
- 1.7
- Test Creator 7
- Public
- Add-on with empty type should be ignored
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test7.xpi
-
-
-
-
- FAIL
- Unknown
- test8@tests.mozilla.org
- 1.8
- Test Creator 8
- Public
- Add-on with unknown type should be ignored
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test8.xpi
-
-
-
-
- FAIL
- Extension
- 1.9
- Test Creator 9
- Public
- Add-on with undefined guid should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test9.xpi
-
-
-
-
- FAIL
- Extension
-
- 1.10
- Test Creator 10
- Public
- Add-on with empty guid should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test10.xpi
-
-
-
-
- FAIL
- Extension
- test1@tests.mozilla.org
- 1.11
- Test Creator 11
- Public
- Add-on with a guid that matches a previously successful result should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test11.xpi
-
-
-
-
- FAIL
- Extension
- test_AddonRepository_1@tests.mozilla.org
- 1.12
- Test Creator 12
- Public
- Add-on with a guid that matches an installed Addon should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test12.xpi
-
-
-
-
- FAIL
- Extension
- test13@tests.mozilla.org
- Test Creator 13
- Public
- Add-on with undefined version should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test13.xpi
-
-
-
-
- FAIL
- Extension
- test14@tests.mozilla.org
-
- Test Creator 14
- Public
- Add-on with empty version should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test14.xpi
-
-
-
-
- FAIL
- Extension
- test15@tests.mozilla.org
- 1.15
- Public
- Add-on with undefined authors should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test15.xpi
-
-
-
-
- FAIL
- Extension
- test16@tests.mozilla.org
- 1.16
-
- Public
- Add-on with no defined author elements should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test16.xpi
-
-
-
-
- FAIL
- Extension
- test17@tests.mozilla.org
- 1.17
-
-
-
-
- Public
- Add-on with no non-empty author elements should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test17.xpi
-
-
-
-
- FAIL
- Extension
- test18@tests.mozilla.org
- 1.18
- Test Creator 18
- Add-on with undefined status should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test18.xpi
-
-
-
-
- FAIL
- Extension
- test19@tests.mozilla.org
- 1.19
- Test Creator 19
- Unknown
- Add-on with non-Public status should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test19.xpi
-
-
-
-
- FAIL
- Extension
- test20@tests.mozilla.org
- 1.20
- Test Creator 20
- Public
- Add-on with undefined compatible_applications should be ignored.
- http://localhost:%PORT%/test20.xpi
-
-
-
-
- FAIL
- Extension
- test21@tests.mozilla.org
- 1.21
- Test Creator 21
- Public
- Add-on with no compatible applications should be ignored.
-
-
- unknown@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test21.xpi
-
-
-
-
- FAIL
- Extension
- test22@tests.mozilla.org
- 1.22
- Test Creator 22
- Public
- Add-on with too high of a compatible application min version should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 2.0
-
-
- http://localhost:%PORT%/test22.xpi
-
-
-
-
- FAIL
- Extension
- test23@tests.mozilla.org
- 1.23
- Test Creator 23
- Public
- Add-on with too high of a compatible application min version should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1.1
- 2.0
-
-
- http://localhost:%PORT%/test23.xpi
-
-
-
-
- FAIL
- Extension
- test24@tests.mozilla.org
- 1.24
- Test Creator 24
- Public
- Add-on with too low of a compatible application max version should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 0.9
-
-
- http://localhost:%PORT%/test24.xpi
-
-
-
-
- FAIL
- Extension
- test25@tests.mozilla.org
- 1.25
- Test Creator 25
- Public
- Add-on with too low of a compatible application max version should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 0.9
- 0.9.9
-
-
- http://localhost:%PORT%/test25.xpi
-
-
-
-
- FAIL
- Extension
- test26@tests.mozilla.org
- 1.26
- Test Creator 26
- Public
- Add-on with undefined XPI URL should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
-
-
-
-
- FAIL
- Extension
- test27@tests.mozilla.org
- 1.27
- Test Creator 27
- Public
- Add-on with an empty XPI URL should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
-
-
-
-
-
- FAIL
- Extension
- test28@tests.mozilla.org
- 1.28
- Test Creator 28
- Public
- Add-on with no installs with compatible OS should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test28.xpi
- http://localhost:%PORT%/test28.xpi
-
-
-
-
- FAIL
- Extension
- test29@tests.mozilla.org
- 1.29
- Test Creator 29
- Public
- Add-on with an XPI URL that matches an installing AddonInstall should be ignored.
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/addons/test_AddonRepository_2.xpi
-
-
-
-
- PASS
- Extension
- purchase1@tests.mozilla.org
- 2.0
-
-
- Test Creator - Last Passing
- http://localhost:%PORT%/creatorLastPassing.html
-
-
- Public
-
- ALL
-
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- 5
-
- http://localhost:%PORT%/purchaseURL1
- $5
-
-
-
-
-
- PASS
- Extension
- purchase2@tests.mozilla.org
- 2.0
-
-
- Test Creator - Last Passing
- http://localhost:%PORT%/creatorLastPassing.html
-
-
- Public
-
- XPCShell
-
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- 5
-
- http://localhost:%PORT%/purchaseURL2
- $10
-
-
-
-
-
- FAIL
- Extension
- purchase3@tests.mozilla.org
- 2.0
-
-
- Test Creator - Last Passing
- http://localhost:%PORT%/creatorLastPassing.html
-
-
- Public
-
- FOO
-
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- 5
-
- http://localhost:%PORT%/purchaseURL3
- $10
-
-
-
-
-
- PASS
- Extension
- test-lastPassing@tests.mozilla.org
- 2.0
-
-
- Test Creator - Last Passing
- http://localhost:%PORT%/creatorLastPassing.html
-
-
- Public
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
-
- 10
- http://localhost:%PORT%/addons/test_AddonRepository_3.xpi
-
-
-
-
- FAIL
- Extension
- test-surpassesLimit@tests.mozilla.org
- 9.9
- Test Creator - Surpasses Limit
- Public
- Add-on should not be added because doing so would surpass MAX_RESULTS limit
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test-surpassesLimit.xpi
-
-
-
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache.json
new file mode 100644
index 000000000000..441a3cd57475
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache.json
@@ -0,0 +1,132 @@
+{
+ "page_size": 25,
+ "page_count": 1,
+ "count": 4,
+ "next": null,
+ "previous": null,
+ "results": [
+ {
+ "name": "Repo Add-on 1",
+ "type": "extension",
+ "guid": "test_AddonRepository_1@tests.mozilla.org",
+ "current_version": {
+ "version": "2.1",
+ "files": [
+ {
+ "platform": "all",
+ "size": 9,
+ "url": "http://localhost:4444/repo/1/install.xpi"
+ }
+ ]
+ },
+ "authors": [
+ {
+ "name": "Repo Add-on 1 - Creator",
+ "url": "http://localhost:4444/repo/1/creator.html"
+ },
+ {
+ "name": "Repo Add-on 1 - First Developer",
+ "url": "http://localhost:4444/repo/1/firstDeveloper.html"
+ },
+ {
+ "name": "Repo Add-on 1 - Second Developer",
+ "url": "http://localhost:4444/repo/1/secondDeveloper.html"
+ }
+ ],
+ "summary": "Repo Add-on 1 - Description
Second line",
+ "description": "Repo Add-on 1 - Full Description & some extra
",
+ "icons": {
+ "32": "http://localhost/repo/1/icon.png"
+ },
+ "ratings": {
+ "count": 1111,
+ "average": 1
+ },
+ "homepage": "http://localhost/repo/1/homepage.html",
+ "support_url": "http://localhost/repo/1/support.html",
+ "contributions_url": "http://localhost/repo/1/meetDevelopers.html",
+ "ratings_url": "http://localhost/repo/1/review.html",
+ "weekly_downloads": 3331,
+ "last_updated": "1970-01-01T00:00:09Z"
+ },
+ {
+ "name": "Repo Add-on 2",
+ "type": "theme",
+ "guid": "test_AddonRepository_2@tests.mozilla.org",
+ "current_version": {
+ "version": "2.2",
+ "files": [
+ {
+ "platform": "all",
+ "size": 9,
+ "url": "http://localhost:4444/repo/2/install.xpi"
+ }
+ ]
+ },
+ "authors": [
+ {
+ "name": "Repo Add-on 2 - Creator",
+ "url": "http://localhost:4444/repo/2/creator.html"
+ },
+ {
+ "name": "Repo Add-on 2 - First Developer",
+ "url": "http://localhost:4444/repo/2/firstDeveloper.html"
+ },
+ {
+ "name": "Repo Add-on 2 - Second Developer",
+ "url": "http://localhost:4444/repo/2/secondDeveloper.html"
+ }
+ ],
+ "summary": "Repo Add-on 2 - Description",
+ "description": "Repo Add-on 2 - Full Description",
+ "icons": {
+ "32": "http://localhost/repo/2/icon.png"
+ },
+ "previews": [
+ {
+ "image_url": "http://localhost:4444/repo/2/firstFull.png",
+ "thumbnail_url": "http://localhost:4444/repo/2/firstThumbnail.png",
+ "caption": "Repo Add-on 2 - First Caption"
+ },
+ {
+ "image_url": "http://localhost:4444/repo/2/secondFull.png",
+ "thumbnail_url": "http://localhost:4444/repo/2/secondThumbnail.png",
+ "caption": "Repo Add-on 2 - Second Caption"
+ }
+ ],
+ "ratings": {
+ "count": 1112,
+ "average": 2
+ },
+ "homepage": "http://localhost/repo/2/homepage.html",
+ "support_url": "http://localhost/repo/2/support.html",
+ "contributions_url": "http://localhost/repo/2/meetDevelopers.html",
+ "ratings_url": "http://localhost/repo/2/review.html",
+ "weekly_downloads": 3332,
+ "last_updated": "1970-01-01T00:00:09Z"
+ },
+ {
+ "name": "Repo Add-on 3",
+ "type": "theme",
+ "guid": "test_AddonRepository_3@tests.mozilla.org",
+ "current_version": {
+ "version": "2.3"
+ },
+ "icons": {
+ "32": "http://localhost/repo/3/icon.png"
+ },
+ "previews": [
+ {
+ "image_url": "http://localhost:4444/repo/3/firstFull.png",
+ "thumbnail_url": "http://localhost:4444/repo/3/firstThumbnail.png",
+ "caption": "Repo Add-on 3 - First Caption"
+ },
+ {
+ "image_url": "http://localhost:4444/repo/3/secondFull.png",
+ "thumbnail_url": "http://localhost:4444/repo/3/secondThumbnail.png",
+ "caption": "Repo Add-on 3 - Second Caption"
+ }
+ ]
+ }
+ ]
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache.xml
deleted file mode 100644
index f707f1217d90..000000000000
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache.xml
+++ /dev/null
@@ -1,182 +0,0 @@
-
-
-
- Repo Add-on 1
- Extension
- test_AddonRepository_1@tests.mozilla.org
- 2.1
-
-
- Repo Add-on 1 - Creator
- http://localhost:4444/repo/1/creator.html
-
-
- Repo Add-on 1 - First Developer
- http://localhost:4444/repo/1/firstDeveloper.html
-
-
- Repo Add-on 1 - Second Developer
- http://localhost:4444/repo/1/secondDeveloper.html
-
-
- Repo Add-on 1 - Description<br>Second line
- <p>Repo Add-on 1 - Full Description & some extra</p>
- Repo Add-on 1 - EULA
- Repo Add-on 1
- Developer Comments
- http://localhost/repo/1/icon.png
- Public
- 1
- http://localhost/repo/1/learnmore.html
- http://localhost/repo/1/homepage.html
- http://localhost/repo/1/support.html
-
- http://localhost/repo/1/contribution.html
- $11.11
- http://localhost/repo/1/meetDevelopers.html
-
- http://localhost/repo/1/review.html
- 2221
- 3331
- 4441
- 1970-01-01T00:00:09Z
- http://localhost:4444/repo/1/install.xpi
-
-
-
- Repo Add-on 2
- Theme
- test_AddonRepository_2@tests.mozilla.org
- 2.2
-
-
- Repo Add-on 2 - Creator
- http://localhost:4444/repo/2/creator.html
-
-
- Repo Add-on 2 - First Developer
- http://localhost:4444/repo/2/firstDeveloper.html
-
-
- Repo Add-on 2 - Second Developer
- http://localhost:4444/repo/2/secondDeveloper.html
-
-
- Repo Add-on 2 - Description
- Repo Add-on 2 - Full Description
- Repo Add-on 2 - EULA
- Repo Add-on 2 - Developer Comments
- http://localhost/repo/2/icon.png
- Unknown
-
-
- http://localhost:4444/repo/2/firstFull.png
- http://localhost:4444/repo/2/firstThumbnail.png
- Repo Add-on 2 - First Caption
-
-
- http://localhost:4444/repo/2/secondFull.png
- http://localhost:4444/repo/2/secondThumbnail.png
- Repo Add-on 2 - Second Caption
-
-
- 2
- http://localhost/repo/2/learnmore.html
- http://localhost/repo/2/homepage.html
- http://localhost/repo/2/support.html
-
- http://localhost/repo/2/contribution.html
- http://localhost/repo/2/meetDevelopers.html
-
- http://localhost/repo/2/review.html
- 2222
- 3332
- 4442
- 1970-01-01T00:00:09Z
- http://localhost:4444/repo/2/install.xpi
-
-
-
- Repo Add-on 3
- Theme
- test_AddonRepository_3@tests.mozilla.org
- 2.3
- http://localhost/repo/3/icon.png
-
-
- http://localhost:4444/repo/3/firstFull.png
- http://localhost:4444/repo/3/firstThumbnail.png
- Repo Add-on 3 - First Caption
-
-
- http://localhost:4444/repo/3/secondFull.png
- http://localhost:4444/repo/3/secondThumbnail.png
- Repo Add-on 3 - Second Caption
-
-
-
-
-
- test_AddonRepository_1@tests.mozilla.org
- PASS
-
-
-
- 0.1
- 0.2
-
-
- XPCShell
- 666
- 3.0
- 4.0
- xpcshell@tests.mozilla.org
-
-
-
-
-
- 0.2
- 0.3
-
-
- XPCShell
- 666
- 5.0
- 6.0
- xpcshell@tests.mozilla.org
-
-
-
-
-
- 9
- 10
-
-
- XPCShell
- 666
- 10.0
- 11.0
- xpcshell@tests.mozilla.org
-
-
-
-
-
- 0.2
- 0.3
-
-
- Unknown App
- 123
- 1.0
- 999.0
- unknown-app@tests.mozilla.org
-
-
-
-
-
-
-
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache_compat.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache_compat.json
new file mode 100644
index 000000000000..7457484ce146
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_cache_compat.json
@@ -0,0 +1,52 @@
+{
+ "page_size": 25,
+ "page_count": 1,
+ "count": 4,
+ "next": null,
+ "previous": null,
+ "results": [
+ {
+ "name": "PASS",
+ "addon_guid": "test_AddonRepository_1@tests.mozilla.org",
+ "version_ranges": [
+ {
+ "addon_min_version": "0.1",
+ "addon_max_version": "0.2",
+ "applications": [
+ {
+ "name": "XPCShell",
+ "guid": "xpcshell@tests.mozilla.org",
+ "min_version": "3.0",
+ "max_version": "4.0"
+ }
+ ]
+ },
+ {
+ "addon_min_version": "0.2",
+ "addon_max_version": "0.3",
+ "applications": [
+ {
+ "name": "XPCShell",
+ "guid": "xpcshell@tests.mozilla.org",
+ "min_version": "5.0",
+ "max_version": "6.0"
+ }
+ ]
+ },
+ {
+ "addon_min_version": "0.2",
+ "addon_max_version": "0.3",
+ "applications": [
+ {
+ "name": "Unknown App",
+ "guid": "unknown-app@tests.mozilla.org",
+ "min_version": "1.0",
+ "max_version": "999.0"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_empty.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_empty.json
new file mode 100644
index 000000000000..64fac5dc8bf9
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_empty.json
@@ -0,0 +1,7 @@
+{
+ "page_size": 25,
+ "count": 0,
+ "next": null,
+ "previous": null,
+ "results": []
+}
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_empty.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_empty.xml
deleted file mode 100644
index 4cd5c144331b..000000000000
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_empty.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_fail.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_fail.json
new file mode 100644
index 000000000000..d29d525a81f5
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_fail.json
@@ -0,0 +1 @@
+this should yield a json parse error
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_failed.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_failed.xml
deleted file mode 100644
index d02fa0249588..000000000000
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_failed.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
- PASS
- Extension
- test1@tests.mozilla.org
- 1.1
- Test Creator 1
- Public
-
-
- xpcshell@tests.mozilla.org
- 1
- 1
-
-
- http://localhost:%PORT%/test1.xpi
-
-
-
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.json b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.json
new file mode 100644
index 000000000000..733ea4883b0c
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.json
@@ -0,0 +1,101 @@
+{
+ "page_size": 25,
+ "page_count": 1,
+ "count": 4,
+ "next": null,
+ "previous": null,
+ "results": [
+ {
+ "name": "PASS",
+ "type": "extension",
+ "guid": "test1@tests.mozilla.org",
+ "current_version": {
+ "version": "1.1",
+ "files": [
+ {
+ "platform": "all",
+ "url": "http://localhost:%PORT%/addons/test_AddonRepository_2.xpi",
+ "size": 5555
+ }
+ ]
+ },
+ "authors": [
+ {
+ "name": "Test Creator 1",
+ "url": "http://localhost:%PORT%/creator1.html"
+ },
+ {
+ "name": "Test Developer 1",
+ "url": "http://localhost:%PORT%/developer1.html"
+ }
+ ],
+ "summary": "Test Summary 1",
+ "description": "Test Description 1",
+ "icons": {
+ "32": "http://localhost:%PORT%/icon1.png"
+ },
+ "previews": [
+ {
+ "caption": "Caption 1 - 1",
+ "image_size": [400, 300],
+ "image_url": "http://localhost:%PORT%/full1-1.png",
+ "thumbnail_size": [200, 150],
+ "thumbnail_url": "http://localhost:%PORT%/thumbnail1-1.png"
+ },
+ {
+ "caption": "Caption 2 - 1",
+ "image_url": "http://localhost:%PORT%/full2-1.png",
+ "thumbnail_url": "http://localhost:%PORT%/thumbnail2-1.png"
+ }
+ ],
+ "ratings": {
+ "count": 1111,
+ "average": 4
+ },
+ "ratings_url": "http://localhost:%PORT%/review1.html",
+ "support_url": "http://localhost:%PORT%/support1.html",
+ "contributions_url": "http://localhost:%PORT%/contribution1.html",
+ "weekly_downloads": 3333,
+ "last_updated": "2010-02-01T14:04:05Z"
+ },
+ {
+ "name": "FAIL",
+ "type": "extension",
+ "guid": "notRequested@tests.mozilla.org",
+ "current_version": {
+ "version": "1.3",
+ "files": [
+ {
+ "platform": "all",
+ "url": "http://localhost:%PORT%/test3.xpi"
+ }
+ ]
+ },
+ "authors": [
+ {
+ "name": "Test Creator 3"
+ }
+ ],
+ "summary": "Add-on with a guid that wasn't requested should be ignored."
+ },
+ {
+ "name": "PASS",
+ "type": "theme",
+ "guid": "test_AddonRepository_1@tests.mozilla.org",
+ "current_version": {
+ "version": "1.4",
+ "files": [
+ {
+ "platform": "UNKNOWN1",
+ "url": "http://localhost:%PORT%/test4.xpi"
+ },
+ {
+ "platform": "UNKNOWN2",
+ "url": "http://localhost:%PORT%/test4.xpi"
+ }
+ ]
+ }
+ }
+ ]
+}
+
diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.xml
deleted file mode 100644
index 8a616796955c..000000000000
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.xml
+++ /dev/null
@@ -1,187 +0,0 @@
-
-