diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 24e8112ce2c9..7a1d6f62ec88 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -58,6 +58,7 @@ pref("extensions.logging.enabled", false); // Preferences for the Get Add-ons pane pref("extensions.getAddons.maxResults", 15); +pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/guid:%IDS%"); pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%"); // Preferences for AMO integration diff --git a/toolkit/mozapps/extensions/AddonRepository.jsm b/toolkit/mozapps/extensions/AddonRepository.jsm index 55be3c50d93d..09c78e3dfe1f 100644 --- a/toolkit/mozapps/extensions/AddonRepository.jsm +++ b/toolkit/mozapps/extensions/AddonRepository.jsm @@ -20,6 +20,7 @@ # # Contributor(s): # Dave Townsend +# Ben Parr # # 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 @@ -40,12 +41,14 @@ const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; +Components.utils.import("resource://gre/modules/NetUtil.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/AddonManager.jsm"); var EXPORTED_SYMBOLS = [ "AddonRepository" ]; const PREF_GETADDONS_BROWSEADDONS = "extensions.getAddons.browseAddons"; +const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; const PREF_GETADDONS_BROWSERECOMMENDED = "extensions.getAddons.recommended.browseURL"; const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url"; const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; @@ -53,11 +56,35 @@ const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml"; -const API_VERSION = "1.2"; +const API_VERSION = "1.5"; + +// A map between XML keys to AddonSearchResult keys for string values +// that require no extra parsing from XML +const STRING_KEY_MAP = { + name: "name", + version: "version", + summary: "description", + description: "fullDescription", + developer_comments: "developerComments", + eula: "eula", + icon: "iconURL", + homepage: "homepageURL", + support: "supportURL" +}; + +// A map between XML keys to AddonSearchResult keys for integer values +// that require no extra parsing from XML +const INTEGER_KEY_MAP = { + total_downloads: "totalDownloads", + weekly_downloads: "weeklyDownloads", + daily_users: "dailyUsers" +}; + function AddonSearchResult(aId) { this.id = aId; this.screenshots = []; + this.developers = []; } AddonSearchResult.prototype = { @@ -66,6 +93,11 @@ AddonSearchResult.prototype = { */ id: null, + /** + * The add-on type (e.g. "extension" or "theme") + */ + type: null, + /** * The name of the add-on */ @@ -76,6 +108,16 @@ AddonSearchResult.prototype = { */ version: null, + /** + * The creator of the add-on + */ + creator: null, + + /** + * The developers of the add-on + */ + developers: null, + /** * A short description of the add-on */ @@ -87,12 +129,19 @@ AddonSearchResult.prototype = { fullDescription: null, /** - * The rating of the add-on, 0-5 or -1 if unrated + * The developer comments for the add-on. This includes any information + * that may be helpful to end users that isn't necessarily applicable to + * the add-on description (e.g. known major bugs) */ - rating: -1, + developerComments: null, /** - * The url of the add-ons icon or empty if there is no icon + * The end-user licensing agreement (EULA) of the add-on + */ + eula: null, + + /** + * The url of the add-on's icon */ iconURL: null, @@ -107,15 +156,76 @@ AddonSearchResult.prototype = { homepageURL: null, /** - * The add-on type (e.g. "extension" or "theme") + * The support URL for the add-on */ - type: null, + supportURL: null, + + /** + * The contribution url of the add-on + */ + contributionURL: null, + + /** + * The suggested contribution amount + */ + contributionAmount: null, + + /** + * The rating of the add-on, 0-5 + */ + averageRating: null, + + /** + * The number of reviews for this add-on + */ + reviewCount: null, + + /** + * The URL to the list of reviews for this add-on + */ + reviewURL: null, + + /** + * The total number of times the add-on was downloaded + */ + totalDownloads: null, + + /** + * The number of times the add-on was downloaded the current week + */ + weeklyDownloads: null, + + /** + * The number of daily users for the add-on + */ + dailyUsers: null, /** * AddonInstall object generated from the add-on XPI url */ install: null, + /** + * nsIURI storing where this add-on was installed from + */ + sourceURI: null, + + /** + * The status of the add-on in the repository (e.g. 4 = "Public") + */ + repositoryStatus: null, + + /** + * The size of the add-on's files in bytes. For an add-on that have not yet + * been downloaded this may be an estimated value. + */ + size: null, + + /** + * The Date that the add-on was most recently updated + */ + updateDate: null, + /** * True or false depending on whether the add-on is compatible with the * current version and platform of the application @@ -143,12 +253,6 @@ AddonSearchResult.prototype = { */ userDisabled: false, - /** - * The size of the add-on's files in bytes. For an add-on that have not yet - * been downloaded this may be an estimated value. - */ - size: null, - /** * Indicates what scope the add-on is installed in, per profile, user, * system or application @@ -160,11 +264,6 @@ AddonSearchResult.prototype = { */ isActive: true, - /** - * The creator of the add-on - */ - creator: null, - /** * A bitfield holding all of the current operations that are waiting to be * performed for this add-on @@ -175,30 +274,114 @@ AddonSearchResult.prototype = { * A bitfield holding all the the operations that can be performed on * this add-on */ - permissions: 0 + permissions: 0, + + /** + * Tests whether this add-on is known to be compatible with a + * particular application and platform version. + * + * @param appVersion + * An application version to test against + * @param platformVersion + * A platform version to test against + * @return Boolean representing if the add-on is compatible + */ + isCompatibleWith: function(aAppVerison, aPlatformVersion) { + return true; + }, + + /** + * Starts an update check for this add-on. This will perform + * asynchronously and deliver results to the given listener. + * + * @param aListener + * An UpdateListener for the update process + * @param aReason + * A reason code for performing the update + * @param aAppVersion + * An application version to check for updates for + * @param aPlatformVersion + * A platform version to check for updates for + */ + findUpdates: function(aListener, aReason, aAppVersion, aPlatformVersion) { + if ("onNoCompatibilityUpdateAvailable" in aListener) + aListener.onNoCompatibilityUpdateAvailable(this); + if ("onNoUpdateAvailable" in aListener) + aListener.onNoUpdateAvailable(this); + if ("onUpdateFinished" in aListener) + aListener.onUpdateFinished(this); + } +} + +function AddonAuthor(aName, aURL) { + this.name = aName; + this.url = aURL; +} + +AddonAuthor.prototype = { + /** + * The name of the author + */ + name: null, + + /** + * The URL of the author's profile page + */ + url: null, + + /** + * Returns the author's name, defaulting to the empty string + */ + toString: function() { + return this.name || ""; + } +} + +function AddonScreenshot(aURL, aThumbnailURL, aCaption) { + this.url = aURL; + this.thumbnailURL = aThumbnailURL; + this.caption = aCaption; +} + +AddonScreenshot.prototype = { + /** + * The URL to the full version of the screenshot + */ + url: null, + + /** + * The URL to the thumbnail version of the screenshot + */ + thumbnailURL: null, + + /** + * The caption of the screenshot + */ + caption: null, + + /** + * Returns the screenshot URL, defaulting to the empty string + */ + toString: function() { + return this.url || ""; + } } /** * The add-on repository is a source of add-ons that can be installed. It can - * be searched in two ways. One returns a list of add-ons that come highly - * recommended, this list should change frequently. The other way is to + * be searched in three ways. The first takes a list of IDs and returns a + * list of the corresponding add-ons. The second returns a list of add-ons that + * come highly recommended. This list should change frequently. The third is to * search for specific search terms entered by the user. Searches are * asynchronous and results should be passed to the provided callback object * when complete. The results passed to the callback should only include add-ons * that are compatible with the current application and are not already - * installed. Searches are always asynchronous and should be passed to the - * callback object provided. + * installed. */ var AddonRepository = { - // The current set of results - _results: null, - - // Whether we are currently searching or not + // Whether a search is currently in progress _searching: false, - // Is this a search for recommended add-ons - _recommended: false, - // XHR associated with the current request _request: null, @@ -207,12 +390,14 @@ var AddonRepository = { * * searchSucceeded - Called when a search has suceeded. * - * @param aAddons an array of the add-on results. In the case of - * searching for specific terms the ordering of results - * may be determined by the search provider. - * @param aAddonCount The length of aAddons - * @param aTotalResults The total results actually available in the - * repository + * @param aAddons + * An array of the add-on results. In the case of searching for + * specific terms the ordering of results may be determined by + * the search provider. + * @param aAddonCount + * The length of aAddons + * @param aTotalResults + * The total results actually available in the repository * * * searchFailed - Called when an error occurred when performing a search. @@ -223,11 +408,11 @@ var AddonRepository = { _maxResults: null, /** - * The homepage for visiting this repository. This may be null or an empty - * string. + * The homepage for visiting this repository. If the corresponding preference + * is not defined, defaults to about:blank. */ get homepageURL() { - var url = this._formatURLPref(PREF_GETADDONS_BROWSEADDONS, {}); + let url = this._formatURLPref(PREF_GETADDONS_BROWSEADDONS, {}); return (url != null) ? url : "about:blank"; }, @@ -241,20 +426,23 @@ var AddonRepository = { /** * The url that can be visited to see recommended add-ons in this repository. + * If the corresponding preference is not defined, defaults to about:blank. */ getRecommendedURL: function() { - var url = this._formatURLPref(PREF_GETADDONS_BROWSERECOMMENDED, {}); + let url = this._formatURLPref(PREF_GETADDONS_BROWSERECOMMENDED, {}); return (url != null) ? url : "about:blank"; }, /** * Retrieves the url that can be visited to see search results for the given - * terms. + * terms. If the corresponding preference is not defined, defaults to + * about:blank. * - * @param aSearchTerms search terms used to search the repository + * @param aSearchTerms + * Search terms used to search the repository */ getSearchURL: function(aSearchTerms) { - var url = this._formatURLPref(PREF_GETADDONS_BROWSESEARCHRESULTS, { + let url = this._formatURLPref(PREF_GETADDONS_BROWSESEARCHRESULTS, { TERMS : encodeURIComponent(aSearchTerms) }); return (url != null) ? url : "about:blank"; @@ -271,78 +459,117 @@ var AddonRepository = { this._request = null; } this._callback = null; - this._results = null; + }, + + /** + * Begins a search for add-ons in this repository by ID. Results will be + * passed to the given callback. + * + * @param aIDs + * The array of ids to search for + * @param aCallback + * The callback to pass results to + */ + getAddonsByIDs: function(aIDs, aCallback) { + let url = this._formatURLPref(PREF_GETADDONS_BYIDS, { + API_VERSION : API_VERSION, + IDS : aIDs.map(encodeURIComponent).join(',') + }); + + let self = this; + function handleResults(aElements, aTotalResults) { + // Don't use this._parseAddons() so that, for example, + // incompatible add-ons are not filtered out + let results = []; + for (let i = 0; i < aElements.length && results.length < self._maxResults; i++) { + let result = self._parseAddon(aElements[i]); + if (result == null) + continue; + + // Ignore add-on if it wasn't actually requested + let idIndex = aIDs.indexOf(result.addon.id); + if (idIndex == -1) + continue; + + results.push(result); + // Ignore this add-on from now on + aIDs.splice(idIndex, 1); + } + + // aTotalResults irrelevant + self._reportSuccess(results, -1); + } + + this._beginSearch(url, aIDs.length, aCallback, handleResults); }, /** * Begins a search for recommended add-ons in this repository. Results will * be passed to the given callback. * - * @param aMaxResults the maximum number of results to return - * @param aCallback the callback to pass results to + * @param aMaxResults + * The maximum number of results to return + * @param aCallback + * The callback to pass results to */ retrieveRecommendedAddons: function(aMaxResults, aCallback) { - if (this._searching) - return; - - this._searching = true; - this._results = []; - this._callback = aCallback; - this._recommended = true; - this._maxResults = aMaxResults; - - var url = this._formatURLPref(PREF_GETADDONS_GETRECOMMENDED, { + let url = this._formatURLPref(PREF_GETADDONS_GETRECOMMENDED, { API_VERSION : API_VERSION, // Get twice as many results to account for potential filtering MAX_RESULTS : 2 * aMaxResults }); - (url != null) ? this._loadList(url) : this.reportFailure(); + let self = this; + function handleResults(aElements, aTotalResults) { + self._getLocalAddonIds(function(aLocalAddonIds) { + // aTotalResults irrelevant + self._parseAddons(aElements, -1, aLocalAddonIds); + }); + } + + this._beginSearch(url, aMaxResults, aCallback, handleResults); }, /** * Begins a search for add-ons in this repository. Results will be passed to * the given callback. * - * @param aSearchTerms the terms to search for - * @param aMaxResults the maximum number of results to return - * @param aCallback the callback to pass results to + * @param aSearchTerms + * The terms to search for + * @param aMaxResults + * The maximum number of results to return + * @param aCallback + * The callback to pass results to */ searchAddons: function(aSearchTerms, aMaxResults, aCallback) { - if (this._searching) - return; - - this._searching = true; - this._results = []; - this._callback = aCallback; - this._recommended = false; - this._maxResults = aMaxResults; - - // Get twice as many results to account for potential filtering - var url = this._formatURLPref(PREF_GETADDONS_GETSEARCHRESULTS, { + let url = this._formatURLPref(PREF_GETADDONS_GETSEARCHRESULTS, { API_VERSION : API_VERSION, + TERMS : encodeURIComponent(aSearchTerms), // Get twice as many results to account for potential filtering - MAX_RESULTS : 2 * aMaxResults, - - // We double encode due to bug 427155 - TERMS : encodeURIComponent(encodeURIComponent(aSearchTerms)) + MAX_RESULTS : 2 * aMaxResults }); - (url != null) ? this._loadList(url) : this.reportFailure(); + let self = this; + function handleResults(aElements, aTotalResults) { + self._getLocalAddonIds(function(aLocalAddonIds) { + self._parseAddons(aElements, aTotalResults, aLocalAddonIds); + }); + } + + this._beginSearch(url, aMaxResults, aCallback, handleResults); }, // Posts results to the callback - _reportSuccess: function(aTotalResults) { + _reportSuccess: function(aResults, aTotalResults) { this._searching = false; this._request = null; // The callback may want to trigger a new search so clear references early - var addons = [result.addon for each(result in this._results)]; - var callback = this._callback; + let addons = [result.addon for each(result in aResults)]; + let callback = this._callback; this._callback = null; - this._results = null; - callback.searchSucceeded(addons, addons.length, this._recommended ? -1 : aTotalResults); + callback.searchSucceeded(addons, addons.length, aTotalResults); }, // Notifies the callback of a failure @@ -350,165 +577,262 @@ var AddonRepository = { this._searching = false; this._request = null; // The callback may want to trigger a new search so clear references early - var callback = this._callback; + let callback = this._callback; this._callback = null; - this._results = null; callback.searchFailed(); }, - // Parses an add-on entry from an element + // Get descendant by unique tag name. Returns null if not unique tag name. + _getUniqueDescendant: function(aElement, aTagName) { + let elementsList = aElement.getElementsByTagName(aTagName); + return (elementsList.length == 1) ? elementsList[0] : null; + }, + + // Parse out trimmed text content. Returns null if text content empty. + _getTextContent: function(aElement) { + let textContent = aElement.textContent.trim(); + return (textContent.length > 0) ? textContent : null; + }, + + // Parse out trimmed text content of a descendant with the specified tag name + // Returns null if the parsing unsuccessful. + _getDescendantTextContent: function(aElement, aTagName) { + let descendant = this._getUniqueDescendant(aElement, aTagName); + return (descendant != null) ? this._getTextContent(descendant) : null; + }, + + /* + * Creates an AddonSearchResult by parsing an element + * + * @param aElement + * The element to parse + * @param aSkip + * Object containing ids and sourceURIs of add-ons to skip. + * @return Result object containing the parsed AddonSearchResult, xpiURL and + * xpiHash if the parsing was successful. Otherwise returns null. + */ _parseAddon: function(aElement, aSkip) { - var guidList = aElement.getElementsByTagName("guid"); - if (guidList.length != 1) - return; + let skipIDs = (aSkip && aSkip.ids) ? aSkip.ids : []; + let skipSourceURIs = (aSkip && aSkip.sourceURIs) ? aSkip.sourceURIs : []; - var guid = guidList[0].textContent.trim(); + let guid = this._getDescendantTextContent(aElement, "guid"); + if (guid == null || skipIDs.indexOf(guid) != -1) + return null; - // Ignore add-ons already seen in the results - for (var i = 0; i < this._results.length; i++) - if (this._results[i].addon.id == guid) - return; - - // Ignore installed add-ons - if (aSkip.ids.indexOf(guid) != -1) - return; - - // Ignore sandboxed add-ons - var status = aElement.getElementsByTagName("status"); - // The status element has a unique id for each status type. 4 is Public. - if (status.length != 1 || status[0].getAttribute("id") != 4) - return; - - // Ignore add-ons not compatible with this OS - var osList = aElement.getElementsByTagName("compatible_os"); - // Only the version 0 schema included compatible_os if it isn't there then - // we will see os compatibility on the install elements. - if (osList.length > 0) { - var compatible = false; - var i = 0; - while (i < osList.length && !compatible) { - var os = osList[i].textContent.trim(); - if (os == "ALL" || os == Services.appinfo.OS) { - compatible = true; - break; - } - i++; - } - if (!compatible) - return; - } - - // Ignore add-ons not compatible with this Application - compatible = false; - var tags = aElement.getElementsByTagName("compatible_applications"); - if (tags.length != 1) - return; - - var apps = tags[0].getElementsByTagName("appID"); - var i = 0; - while (i < apps.length) { - if (apps[i].textContent.trim() == Services.appinfo.ID) { - var parent = apps[i].parentNode; - var minversion = parent.getElementsByTagName("min_version")[0].textContent.trim(); - var maxversion = parent.getElementsByTagName("max_version")[0].textContent.trim(); - if ((Services.vc.compare(minversion, Services.appinfo.version) > 0) || - (Services.vc.compare(Services.appinfo.version, maxversion) > 0)) - return; - compatible = true; - break; - } - i++; - } - if (!compatible) - return; - - var addon = new AddonSearchResult(guid); - var result = { + let addon = new AddonSearchResult(guid); + let result = { addon: addon, xpiURL: null, xpiHash: null }; - var node = aElement.firstChild; - while (node) { - if (node instanceof Ci.nsIDOMElement) { - switch (node.localName) { - case "name": - case "version": - addon[node.localName] = node.textContent.trim(); - break; - case "summary": - addon.description = node.textContent.trim(); - break; - case "description": - addon.fullDescription = node.textContent.trim(); - break; - case "rating": - if (node.textContent.length > 0) { - var rating = parseInt(node.textContent); - if (rating >= 0) - addon.rating = Math.min(5, rating); - } - break; - case "thumbnail": - addon.screenshots.push(node.textContent.trim()); - break; - case "icon": - addon.iconURL = node.textContent.trim(); - break; - case "learnmore": - addon.homepageURL = node.textContent.trim(); - break; - case "type": - // The type element has an id attribute that is the id from AMO's - // database. This doesn't match our type values to perform a mapping - addon.type = (node.getAttribute("id") == 2) ? "theme" : "extension"; - break; - case "install": - // No os attribute means the xpi is compatible with any os - if (node.hasAttribute("os")) { - var os = node.getAttribute("os").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; - } - result.xpiURL = node.textContent.trim(); - if (node.hasAttribute("size")) - addon.size = node.getAttribute("size"); - // Ignore add-on installs - if (aSkip.sourceURIs.indexOf(result.xpiURL) != -1) + let self = this; + 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 + if (localName in STRING_KEY_MAP) { + addon[STRING_KEY_MAP[localName]] = 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 + let id = parseInt(node.getAttribute("id")); + switch (id) { + case 1: + addon.type = "extension"; + break; + case 2: + addon.type = "theme"; + break; + default: + Cu.reportError("Unknown type id when parsing addon: " + id); + } + break; + case "authors": + let authorNodes = node.getElementsByTagName("author"); + Array.forEach(authorNodes, function(aAuthorNode) { + let name = self._getDescendantTextContent(aAuthorNode, "name"); + let link = self._getDescendantTextContent(aAuthorNode, "link"); + if (name == null || link == null) return; - result.xpiHash = node.hasAttribute("hash") ? node.getAttribute("hash") : null; + let author = new AddonAuthor(name, link); + if (addon.creator == null) + addon.creator = author; + else + addon.developers.push(author); + }); + break; + case "previews": + let previewNodes = node.getElementsByTagName("preview"); + Array.forEach(previewNodes, function(aPreviewNode) { + let full = self._getDescendantTextContent(aPreviewNode, "full"); + if (full == null) + return; + + let thumbnail = self._getDescendantTextContent(aPreviewNode, "thumbnail"); + let caption = self._getDescendantTextContent(aPreviewNode, "caption"); + let screenshot = new AddonScreenshot(full, thumbnail, caption); + + if (aPreviewNode.getAttribute("primary") == 1) + addon.screenshots.unshift(screenshot); + else + addon.screenshots.push(screenshot); + }); + break; + case "learnmore": + addon.homepageURL = addon.homepageURL || this._getTextContent(node); + break; + case "contribution_data": + let meetDevelopers = this._getDescendantTextContent(node, "meet_developers"); + let suggestedAmount = this._getDescendantTextContent(node, "suggested_amount"); + if (meetDevelopers != null && suggestedAmount != null) { + addon.contributionURL = meetDevelopers; + addon.contributionAmount = suggestedAmount; + } + 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 "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.indexOf(xpiURL) != -1) + 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; } - node = node.nextSibling; } - // Add only if there was an xpi compatible with this os - if (result.xpiURL) - this._results.push(result); + return result; }, _parseAddons: function(aElements, aTotalResults, aSkip) { - for (var i = 0; i < aElements.length && this._results.length < this._maxResults; i++) - this._parseAddon(aElements[i], aSkip); + let self = this; + let results = []; + for (let i = 0; i < aElements.length && results.length < this._maxResults; i++) { + let element = aElements[i]; - var pendingResults = this._results.length; + // Ignore sandboxed add-ons + let status = this._getUniqueDescendant(element, "status"); + // The status element has a unique id for each status type. 4 is Public. + if (status == null || status.getAttribute("id") != 4) + continue; + + // Ignore add-ons not compatible with this Application + let tags = this._getUniqueDescendant(element, "compatible_applications"); + if (tags == null) + continue; + + let applications = tags.getElementsByTagName("appID"); + let compatible = Array.some(applications, function(aAppNode) { + if (self._getTextContent(aAppNode) != Services.appinfo.ID) + return false; + + let parent = aAppNode.parentNode; + let minVersion = self._getDescendantTextContent(parent, "min_version"); + let maxVersion = self._getDescendantTextContent(parent, "max_version"); + if (minVersion == null || maxVersion == null) + return false; + + let currentVersion = Services.appinfo.version; + return (Services.vc.compare(minVersion, currentVersion) <= 0 && + Services.vc.compare(currentVersion, maxVersion) <= 0); + }); + + if (!compatible) + continue; + + // Add-on meets all requirements, so parse out data + 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(function(aAttribute) !result.addon[aAttribute])) + continue; + + // Add only if there was an xpi compatible with this OS + if (!result.xpiURL) + continue; + + 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(aTotalResults); + this._reportSuccess(results, aTotalResults); return; } - var self = this; - this._results.forEach(function(aResult) { - var addon = aResult.addon; - var callback = function(aInstall) { + // Create an AddonInstall for each result + let self = this; + results.forEach(function(aResult) { + let addon = aResult.addon; + let callback = function(aInstall) { addon.install = aInstall; pendingResults--; if (pendingResults == 0) - self._reportSuccess(aTotalResults); + self._reportSuccess(results, aTotalResults); } AddonManager.getInstallForURL(aResult.xpiURL, callback, @@ -517,72 +841,85 @@ var AddonRepository = { }); }, - // Called when a single request has completed, parses out any add-ons and - // either notifies the callback or does a new request for more results - _listLoaded: function(aEvent) { - var request = aEvent.target; - var responseXML = request.responseXML; - - if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR || - (request.status != 200 && request.status != 0)) { - this._reportFailure(); + // Begins a new search if one isn't currently executing + _beginSearch: function(aURI, aMaxResults, aCallback, aHandleResults) { + if (this._searching || aURI == null || aMaxResults <= 0) { + aCallback.searchFailed(); return; } - var elements = responseXML.documentElement.getElementsByTagName("addon"); - if (responseXML.documentElement.hasAttribute("total_results")) - var totalResults = responseXML.documentElement.getAttribute("total_results"); - else - var totalResults = elements.length; + this._searching = true; + this._callback = aCallback; + this._maxResults = aMaxResults; - var self = this; - var skip = {ids: null, sourceURIs: null}; - - AddonManager.getAllAddons(function(aAddons) { - skip.ids = [a.id for each (a in aAddons)]; - if (skip.sourceURIs) - self._parseAddons(elements, totalResults, skip); - }); - - AddonManager.getAllInstalls(function(aInstalls) { - skip.sourceURIs = []; - aInstalls.forEach(function(aInstall) { - if (aInstall.state != AddonManager.STATE_AVAILABLE) - skip.sourceURIs.push(aInstall.sourceURI.spec); - }); - - if (skip.ids) - self._parseAddons(elements, totalResults, skip); - }); - }, - - // Performs a new request for results - _loadList: function(aURI) { this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. createInstance(Ci.nsIXMLHttpRequest); this._request.open("GET", aURI, true); this._request.overrideMimeType("text/xml"); - var self = this; + let self = this; this._request.onerror = function(aEvent) { self._reportFailure(); }; - this._request.onload = function(aEvent) { self._listLoaded(aEvent); }; + this._request.onload = function(aEvent) { + let request = aEvent.target; + let responseXML = request.responseXML; + + if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR || + (request.status != 200 && request.status != 0)) { + self._reportFailure(); + return; + } + + 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; + + aHandleResults(elements, totalResults); + }; this._request.send(null); }, - // Create url from pref, returning null if pref does not exist - _formatURLPref: function(aPref, aSubstitutions) { - var url = null; + // Gets the id's of local add-ons, and the sourceURI's of local installs, + // passing the results to aCallback + _getLocalAddonIds: function(aCallback) { + let self = this; + let localAddonIds = {ids: null, sourceURIs: null}; + + AddonManager.getAllAddons(function(aAddons) { + localAddonIds.ids = [a.id for each (a in aAddons)]; + if (localAddonIds.sourceURIs) + aCallback(localAddonIds); + }); + + AddonManager.getAllInstalls(function(aInstalls) { + localAddonIds.sourceURIs = []; + aInstalls.forEach(function(aInstall) { + if (aInstall.state != AddonManager.STATE_AVAILABLE) + localAddonIds.sourceURIs.push(aInstall.sourceURI.spec); + }); + + if (localAddonIds.ids) + aCallback(localAddonIds); + }); + }, + + // Create url from preference, returning null if preference does not exist + _formatURLPref: function(aPreference, aSubstitutions) { + let url = null; try { - url = Services.prefs.getCharPref(aPref); + url = Services.prefs.getCharPref(aPreference); } catch(e) { - Cu.reportError("_formatURLPref: Couldn't get pref: " + aPref); + Cu.reportError("_formatURLPref: Couldn't get pref: " + aPreference); return null; } url = url.replace(/%([A-Z_]+)%/g, function(aMatch, aKey) { return (aKey in aSubstitutions) ? aSubstitutions[aKey] : aMatch; }); - + return Services.urlFormatter.formatURL(url); } } diff --git a/toolkit/mozapps/extensions/test/addons/test_AddonRepository_1/install.rdf b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_1/install.rdf new file mode 100644 index 000000000000..93e9b00fd24e --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_1/install.rdf @@ -0,0 +1,22 @@ + + + + + + test_AddonRepository_1@tests.mozilla.org + 1.0 + + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + + Addon Repository Name + Addon Repository Description + + diff --git a/toolkit/mozapps/extensions/test/addons/test_AddonRepository_2/install.rdf b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_2/install.rdf new file mode 100644 index 000000000000..e4472b3decfa --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_2/install.rdf @@ -0,0 +1,22 @@ + + + + + + test_AddonRepository_2@tests.mozilla.org + 1.0 + + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + + Addon Repository Name + Addon Repository Description + + diff --git a/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/install.rdf b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/install.rdf new file mode 100644 index 000000000000..374afacb66aa --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_AddonRepository_3/install.rdf @@ -0,0 +1,22 @@ + + + + + + test_AddonRepository_3@tests.mozilla.org + 1.0 + + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + + Addon Repository Name + Addon Repository Description + + diff --git a/toolkit/mozapps/extensions/test/browser/browser_searching.xml b/toolkit/mozapps/extensions/test/browser/browser_searching.xml index 4492b1eeaf63..55b049621d74 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_searching.xml +++ b/toolkit/mozapps/extensions/test/browser/browser_searching.xml @@ -5,6 +5,12 @@ Extension addon1@tests.mozilla.org 1.0 + + + Test Creator + http://example.com/creator.html + + Public Addon already installed - SEARCH Test description @@ -24,6 +30,12 @@ Extension install1@tests.mozilla.org 1.0 + + + Test Creator + http://example.com/creator.html + + Public Install already exists - SEARCH Test description @@ -43,6 +55,12 @@ Extension remote1@tests.mozilla.org 3.0 + + + Test Creator + http://example.com/creator.html + + Public Test summary - SEARCH SEARCH Test description @@ -62,6 +80,12 @@ Extension remote2@tests.mozilla.org 4.0 + + + Test Creator + http://example.com/creator.html + + Public Test summary - SEARCHing SEARCH Test description @@ -81,6 +105,12 @@ Extension remote3@tests.mozilla.org 5.0 + + + Test Creator + http://example.com/creator.html + + Public Test summary - Does not match query Test description @@ -100,6 +130,12 @@ Extension remote4@tests.mozilla.org 6.0 + + + Test Creator + http://example.com/creator.html + + Public Test summary - SEARCHing SEARCH SEARCH Test description diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository.xml new file mode 100644 index 000000000000..3b85fe506727 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository.xml @@ -0,0 +1,727 @@ + + + + + PASS + Extension + test1@tests.mozilla.org + 1.1 + + + Test Creator 1 + http://localhost:4444/creator1.html + + + Public + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + -2 + + + + -2 + http://localhost:4444/test1.xpi + + + + + PASS + + Extension + test2@tests.mozilla.org + 1.2 + + + + Test Creator 2 + http://localhost:4444/creator2.html + + + Test Developer 2 + http://localhost:4444/developer2.html + + + Test Summary 2 + Test Description 2 + Test Developer Comments 2 + Test EULA 2 + http://localhost:4444/icon2.png + Public + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + + + http://localhost:4444/full1-2.png + http://localhost:4444/thumbnail1-2.png + + + http://localhost:4444/full2-2.png + http://localhost:4444/thumbnail2-2.png + Caption 2 + + + NaN + + http://localhost:4444/learnmore2.html + http://localhost:4444/support2.html + + http://localhost:4444/contribution2.html + $11.11 + http://localhost:4444/meetDevelopers2.html + + http://localhost:4444/review2.html + NaN + NaN + NaN + Not an acual date + http://localhost:4444/test2.xpi + + + + + PASS + + Theme + test3@tests.mozilla.org + 1.3 + + + + + http://localhost:4444/ignore3.html + + + + Test Creator Ignore + + + + Test Creator 3 + http://localhost:4444/creator3.html + + + First Test Developer 3 + http://localhost:4444/developer1-3.html + + + + + + + Second Test Developer 3 + http://localhost:4444/developer2-3.html + + + Test Summary 3 + Test Description 3 + Test Developer Comments 3 + Test EULA 3 + http://localhost:4444/icon3.png + Public + + + + unknown@tests.mozilla.org + 1 + 1 + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + + + http://localhost:4444/full2-3.png + Caption 2 - 3 + + + + Caption ignore - 3 + + + + + Caption ignore - 3 + + http://localhost:4444/full1-3.png + http://localhost:4444/thumbnail1-3.png + Caption 1 - 3 + + + http://localhost:4444/full3-3.png + http://localhost:4444/thumbnail3-3.png + Caption 3 - 3 + + + + + 2 + + http://localhost:4444/learnmore3.html + http://localhost:4444/homepage3.html + http://localhost:4444/support3.html + + http://localhost:4444/contribution3.html + $11.11 + http://localhost:4444/meetDevelopers3.html + + http://localhost:4444/review3.html + 2222 + 3333 + 4444 + 2010-01-02T03:04:05Z + + http://localhost:4444/fail3.xpi + + http://localhost:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/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:4444/test28.xpi + http://localhost:4444/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:4444/addons/test_AddonRepository_2.xpi + + + + + PASS + Extension + test-lastPassing@tests.mozilla.org + 2.0 + + + Test Creator - Last Passing + http://localhost:4444/creatorLastPassing.html + + + Public + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + 10 + http://localhost:4444/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:4444/test-surpassesLimit.xpi + + + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_failed.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_failed.xml new file mode 100644 index 000000000000..65ecc098b199 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_failed.xml @@ -0,0 +1,21 @@ + + + + + PASS + Extension + test1@tests.mozilla.org + 1.1 + Test Creator 1 + Public + + + xpcshell@tests.mozilla.org + 1 + 1 + + + http://localhost:4444/test1.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 new file mode 100644 index 000000000000..98f973abce52 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_AddonRepository_getAddonsByIDs.xml @@ -0,0 +1,120 @@ + + + + + PASS + Extension + test1@tests.mozilla.org + 1.1 + + + Test Creator 1 + http://localhost:4444/creator1.html + + + Test Developer 1 + http://localhost:4444/developer1.html + + + Test Summary 1 + Test Description 1 + Test EULA 1 + Test Developer Comments 1 + http://localhost:4444/icon1.png + Public + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + + http://localhost:4444/full1-1.png + http://localhost:4444/thumbnail1-1.png + Caption 1 - 1 + + + http://localhost:4444/full2-1.png + http://localhost:4444/thumbnail2-1.png + Caption 2 - 1 + + + 4 + http://localhost:4444/learnmore1.html + http://localhost:4444/support1.html + + http://localhost:4444/contribution1.html + $11.11 + http://localhost:4444/meetDevelopers1.html + + http://localhost:4444/review1.html + 2222 + 3333 + 4444 + 2010-01-02T03:04:05Z + http://localhost:4444/addons/test_AddonRepository_2.xpi + + + + + FAIL + Extension + test1@tests.mozilla.org + 1.2 + Test Creator 2 + Public + Add-on with a guid that matches a previously successful result should be ignored. + + + xpcshell@tests.mozilla.org + 1 + 1 + + + http://localhost:4444/test2.xpi + + + + + FAIL + Extension + notRequested@tests.mozilla.org + 1.3 + Test Creator 3 + Public + Add-on with a guid that wasn't requested should be ignored. + + + xpcshell@tests.mozilla.org + 1 + 1 + + + http://localhost:4444/test3.xpi + + + + + PASS + Unknown + test_AddonRepository_1@tests.mozilla.org + 1.4 + Unknown + + + unknown@tests.mozilla.org + 1 + 1 + + + http://localhost:4444/test4.xpi + http://localhost:4444/test4.xpi + + + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug404024.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug404024.xml deleted file mode 100644 index d314fd042c30..000000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug404024.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - - FAIL - Extension - test1@tests.mozilla.org - 1.0 - Sandbox - Should not return sandboxed add-on - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - ALL - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi - - - FAIL - Extension - test2@tests.mozilla.org - 1.0 - Public - Should not return an incompatible add-on - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 2 - 2 - - - ALL - http://localhost:4444/test.xpi - - - FAIL - Extension - test3@tests.mozilla.org - 1.0 - Public - Should not return an incompatible add-on - - - Firefox - unknown@tests.mozilla.org - 1 - 2 - 2 - - - ALL - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi - - - FAIL - Extension - test4@tests.mozilla.org - 1.0 - Public - Should not return an add-on for a different OS - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - Windows - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi - - - PASS - Extension - test5@tests.mozilla.org - 1.0 - Public - This should work fine - Test description - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - ALL - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi - - - FAIL - Extension - bug397778@tests.mozilla.org - 1.0 - Public - Should not return items that are already installed - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - ALL - http://localhost:4444/test.xpi - - - FAIL - Extension - test5@tests.mozilla.org - 1.0 - Public - Should not include the same result twice - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - ALL - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi - - - PASS - Theme - test6@tests.mozilla.org - 1.0 - Public - 4 - Specific OS should work fine - EULA should be confirmed - http://localhost:4444/test_bug404024/thumbnail.png - http://localhost:4444/test_bug404024/icon.png - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - XPCShell - http://localhost:4444/test.xpi - - - diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug417606.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug417606.xml deleted file mode 100644 index 34b27bbc5742..000000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug417606.xml +++ /dev/null @@ -1,178 +0,0 @@ - - - - FAIL - Extension - test1@tests.mozilla.org - 1.0 - Sandbox - Should not return sandboxed add-on - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi - - - FAIL - Extension - test2@tests.mozilla.org - 1.0 - Public - Should not return an incompatible add-on - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 2 - 2 - - - http://localhost:4444/test.xpi - - - FAIL - Extension - test3@tests.mozilla.org - 1.0 - Public - Should not return an incompatible add-on - - - Firefox - unknown@tests.mozilla.org - 1 - 2 - 2 - - - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi - - - FAIL - Extension - test4@tests.mozilla.org - 1.0 - Public - Should not return an add-on for a different OS - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi - - - PASS - Extension - test5@tests.mozilla.org - 1.0 - Public - - This should work fine - - - Test description - - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - - https://addons.mozilla.org/addon/5992 - - - http://localhost:4444/test.xpi - - - - FAIL - Extension - bug397778@tests.mozilla.org - 1.0 - Public - Should not return items that are already installed - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - http://localhost:4444/test.xpi - - - FAIL - Extension - test5@tests.mozilla.org - 1.0 - Public - Should not include the same result twice - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi - - - PASS - Theme - test6@tests.mozilla.org - 1.0 - Public - 4 - Specific OS should work fine - EULA should be confirmed - - http://localhost:4444/test_bug404024/thumbnail.png - - - http://localhost:4444/test_bug404024/icon.png - - - - XPCShell - xpcshell@tests.mozilla.org - 1 - 1 - 1 - - - - http://localhost:4444/test.xpi - - - http://localhost:4444/XPCShell.xpi - - - http://localhost:4444/test.xpi - - - - diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug424262.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug424262.xml index f0d63a2f3fb6..5e36a6e015d6 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug424262.xml +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug424262.xml @@ -5,166 +5,181 @@ Extension test1@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test addon - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/ - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + TEST -5 Extension test2@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test addon - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/ - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + TEST 0 Extension test3@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test addon - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/ - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + TEST 2 Extension test4@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test addon - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/ - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + TEST 4 Extension test5@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test addon - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/ - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + TEST 5 Extension test6@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test addon - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/ - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + TEST 10 Extension test7@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test addon - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/ - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + TEST 100 Extension test8@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test addon - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/ - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug554133.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug554133.xml index be5f4bdd48b8..52e97127b2e1 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug554133.xml +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug554133.xml @@ -5,277 +5,287 @@ Extension test1@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test sumary - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - ALL http://localhost:4444/test.xpi + FAIL Extension test2@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public Should not return an incompatible add-on - XPCShell xpcshell@tests.mozilla.org - 1 2 2 - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + PASS Extension test3@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test sumary - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - ALL http://localhost:4444/test.xpi + FAIL Extension test4@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public Should not return an add-on for a different OS - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + PASS Extension test5@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - - This should work fine - - - Test description - - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - - https://addons.mozilla.org/addon/5992 - - - http://localhost:4444/test.xpi - + http://localhost:4444/test.xpi + FAIL Extension test5@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public Should not include the same result twice - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - https://addons.mozilla.org/addon/5992 - http://localhost:4444/test.xpi + http://localhost:4444/test.xpi + PASS - Theme + Extension test6@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - 4 - Specific OS should work fine - EULA should be confirmed - - http://localhost:4444/test_bug404024/thumbnail.png - - - http://localhost:4444/test_bug404024/icon.png - - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - - http://localhost:4444/test.xpi - - - http://localhost:4444/XPCShell.xpi - - - http://localhost:4444/test.xpi - + http://localhost:4444/test.xpi + PASS Extension test7@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test sumary - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - ALL http://localhost:4444/test.xpi + PASS Extension test8@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test sumary - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - ALL http://localhost:4444/test.xpi + PASS Extension test9@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test sumary - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - ALL http://localhost:4444/test.xpi + PASS Extension test10@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test sumary - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - ALL http://localhost:4444/test.xpi + PASS Extension test11@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test sumary - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - ALL http://localhost:4444/test.xpi + PASS Extension test12@tests.mozilla.org 1.0 + + + Test Creator + http://localhost:4444/creator.html + + Public - Test sumary - Test description - XPCShell xpcshell@tests.mozilla.org - 1 1 1 - ALL http://localhost:4444/test.xpi diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js new file mode 100644 index 000000000000..6edc2c44408d --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js @@ -0,0 +1,604 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests AddonRepository.jsm + +Components.utils.import("resource://gre/modules/AddonRepository.jsm"); + +do_load_httpd_js(); +var gServer; + +const PREF_GETADDONS_BROWSEADDONS = "extensions.getAddons.browseAddons"; +const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; +const PREF_GETADDONS_BROWSERECOMMENDED = "extensions.getAddons.recommended.browseURL"; +const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url"; +const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; + +const PORT = 4444; +const BASE_URL = "http://localhost:" + PORT; +const DEFAULT_URL = "about:blank"; + +// Path to source URI of installed add-on +const INSTALL_URL1 = "/addons/test_AddonRepository_1.xpi"; +// Path to source URI of installing add-on +const INSTALL_URL2 = "/addons/test_AddonRepository_2.xpi"; +// Path to source URI of non-active add-on (state = STATE_AVAILABLE) +const INSTALL_URL3 = "/addons/test_AddonRepository_3.xpi"; + +// Properties of an individual add-on that should be checked +// Note: name is checked separately +var ADDON_PROPERTIES = ["id", "type", "version", "creator", "developers", + "description", "fullDescription", "developerComments", + "eula", "iconURL", "screenshots", "homepageURL", + "supportURL", "contributionURL", "contributionAmount", + "averageRating", "reviewCount", "reviewURL", + "totalDownloads", "weeklyDownloads", "dailyUsers", + "sourceURI", "repositoryStatus", "size", "updateDate"]; + +// Properties of an individual screenshot that should be checked +var SCREENSHOT_PROPERTIES = ["url", "thumbnailURL", "caption"] + +// Properties of an individual creator or developer that should be checked +var AUTHOR_PROPERTIES = ["name", "url"]; + +// Results of getAddonsByIDs +var GET_RESULTS = [{ + id: "test1@tests.mozilla.org", + type: "extension", + version: "1.1", + creator: { + name: "Test Creator 1", + url: BASE_URL + "/creator1.html" + }, + developers: [{ + name: "Test Developer 1", + url: BASE_URL + "/developer1.html" + }], + description: "Test Summary 1", + fullDescription: "Test Description 1", + developerComments: "Test Developer Comments 1", + eula: "Test EULA 1", + iconURL: BASE_URL + "/icon1.png", + screenshots: [{ + url: BASE_URL + "/full1-1.png", + thumbnailURL: BASE_URL + "/thumbnail1-1.png", + caption: "Caption 1 - 1" + }, { + url: BASE_URL + "/full2-1.png", + thumbnailURL: BASE_URL + "/thumbnail2-1.png", + caption: "Caption 2 - 1" + }], + homepageURL: BASE_URL + "/learnmore1.html", + supportURL: BASE_URL + "/support1.html", + contributionURL: BASE_URL + "/meetDevelopers1.html", + contributionAmount: "$11.11", + averageRating: 4, + reviewCount: 1111, + reviewURL: BASE_URL + "/review1.html", + totalDownloads: 2222, + weeklyDownloads: 3333, + dailyUsers: 4444, + sourceURI: BASE_URL + INSTALL_URL2, + repositoryStatus: 4, + size: 5555, + updateDate: new Date(1265033045000) +}, { + id: "test_AddonRepository_1@tests.mozilla.org", + version: "1.4", + developers: [], + screenshots: [], + repositoryStatus: 9999 +}]; + +// Results of retrieveRecommendedAddons and searchAddons +var SEARCH_RESULTS = [{ + id: "test1@tests.mozilla.org", + type: "extension", + version: "1.1", + creator: { + name: "Test Creator 1", + url: BASE_URL + "/creator1.html" + }, + developers: [], + screenshots: [], + repositoryStatus: 4, + sourceURI: BASE_URL + "/test1.xpi" +}, { + id: "test2@tests.mozilla.org", + type: "extension", + version: "1.2", + creator: { + name: "Test Creator 2", + url: BASE_URL + "/creator2.html" + }, + developers: [{ + name: "Test Developer 2", + url: BASE_URL + "/developer2.html" + }], + description: "Test Summary 2", + fullDescription: "Test Description 2", + developerComments: "Test Developer Comments 2", + eula: "Test EULA 2", + iconURL: BASE_URL + "/icon2.png", + screenshots: [{ + url: BASE_URL + "/full1-2.png", + thumbnailURL: BASE_URL + "/thumbnail1-2.png" + }, { + url: BASE_URL + "/full2-2.png", + thumbnailURL: BASE_URL + "/thumbnail2-2.png", + caption: "Caption 2" + }], + homepageURL: BASE_URL + "/learnmore2.html", + supportURL: BASE_URL + "/support2.html", + contributionURL: BASE_URL + "/meetDevelopers2.html", + contributionAmount: "$11.11", + repositoryStatus: 4, + sourceURI: BASE_URL + "/test2.xpi" +}, { + id: "test3@tests.mozilla.org", + type: "theme", + version: "1.3", + creator: { + name: "Test Creator 3", + url: BASE_URL + "/creator3.html" + }, + developers: [{ + name: "First Test Developer 3", + url: BASE_URL + "/developer1-3.html" + }, { + name: "Second Test Developer 3", + url: BASE_URL + "/developer2-3.html" + }], + description: "Test Summary 3", + fullDescription: "Test Description 3", + developerComments: "Test Developer Comments 3", + eula: "Test EULA 3", + iconURL: BASE_URL + "/icon3.png", + screenshots: [{ + url: BASE_URL + "/full1-3.png", + thumbnailURL: BASE_URL + "/thumbnail1-3.png", + caption: "Caption 1 - 3" + }, { + url: BASE_URL + "/full2-3.png", + caption: "Caption 2 - 3" + }, { + url: BASE_URL + "/full3-3.png", + thumbnailURL: BASE_URL + "/thumbnail3-3.png", + caption: "Caption 3 - 3" + }], + homepageURL: BASE_URL + "/homepage3.html", + supportURL: BASE_URL + "/support3.html", + contributionURL: BASE_URL + "/meetDevelopers3.html", + contributionAmount: "$11.11", + averageRating: 2, + reviewCount: 1111, + reviewURL: BASE_URL + "/review3.html", + totalDownloads: 2222, + weeklyDownloads: 3333, + dailyUsers: 4444, + sourceURI: BASE_URL + "/test3.xpi", + repositoryStatus: 4, + size: 5555, + updateDate: new Date(1265033045000) +}, { + id: "test-lastPassing@tests.mozilla.org", + type: "extension", + version: "2.0", + creator: { + name: "Test Creator - Last Passing", + url: BASE_URL + "/creatorLastPassing.html" + }, + developers: [], + screenshots: [], + averageRating: 5, + repositoryStatus: 4, + sourceURI: BASE_URL + "/addons/test_AddonRepository_3.xpi" +}]; + +const TOTAL_RESULTS = 1111; +const MAX_RESULTS = SEARCH_RESULTS.length; + +// Used to differentiate between testing that a search success +// or a search failure for retrieveRecommendedAddons and searchAddons +const FAILED_MAX_RESULTS = 9999; + +// Values for testing AddonRepository.getAddonsByIDs() +var GET_TEST = { + preference: PREF_GETADDONS_BYIDS, + preferenceValue: BASE_URL + "/%OS%/%VERSION%/%API_VERSION%/" + + "%API_VERSION%/%IDS%", + failedIDs: ["test1@tests.mozilla.org"], + failedURL: "/XPCShell/1/1.5/1.5/test1%40tests.mozilla.org", + successfulIDs: ["test1@tests.mozilla.org", + "{00000000-1111-2222-3333-444444444444}", + "test_AddonRepository_1@tests.mozilla.org"], + successfulURL: "/XPCShell/1/1.5/1.5/test1%40tests.mozilla.org," + + "%7B00000000-1111-2222-3333-444444444444%7D," + + "test_AddonRepository_1%40tests.mozilla.org" +}; + +// Values for testing AddonRepository.retrieveRecommendedAddons() +var RECOMMENDED_TEST = { + preference: PREF_GETADDONS_GETRECOMMENDED, + preferenceValue: BASE_URL + "/%OS%/%VERSION%/%API_VERSION%/" + + "%API_VERSION%/%MAX_RESULTS%", + failedURL: "/XPCShell/1/1.5/1.5/" + (2 * FAILED_MAX_RESULTS), + successfulURL: "/XPCShell/1/1.5/1.5/" + (2 * MAX_RESULTS) +}; + +// Values for testing AddonRepository.searchAddons() +var SEARCH_TEST = { + searchTerms: "odd=search:with&weird\"characters", + preference: PREF_GETADDONS_GETSEARCHRESULTS, + preferenceValue: BASE_URL + "/%OS%/%VERSION%/%API_VERSION%/" + + "%API_VERSION%/%MAX_RESULTS%/%TERMS%", + failedURL: "/XPCShell/1/1.5/1.5/" + (2 * FAILED_MAX_RESULTS) + + "/odd%3Dsearch%3Awith%26weird%22characters", + successfulURL: "/XPCShell/1/1.5/1.5/" + (2 * MAX_RESULTS) + + "/odd%3Dsearch%3Awith%26weird%22characters" +}; + +// Check that objects are equal for specified properties +function check_object(aActual, aExpected, aProperties) { + aProperties.forEach(function(aProperty) { + // Check that all undefined expected properties are null on actual add-on + if (!aExpected.hasOwnProperty(aProperty)) { + do_check_eq(aActual[aProperty], null); + return; + } + + var actualValue = aActual[aProperty]; + var expectedValue = aExpected[aProperty]; + + switch (aProperty) { + case "creator": + do_check_eq(actualValue.toString(), expectedValue.name); + check_object(actualValue, expectedValue, AUTHOR_PROPERTIES); + break; + + case "developers": + do_check_eq(actualValue.length, expectedValue.length); + for (var i = 0; i < actualValue.length; i++) { + do_check_eq(actualValue[i].toString(), expectedValue[i].name); + check_object(actualValue[i], expectedValue[i], AUTHOR_PROPERTIES); + } + break; + + case "screenshots": + do_check_eq(actualValue.length, expectedValue.length); + for (var i = 0; i < actualValue.length; i++) { + do_check_eq(actualValue[i].toString(), expectedValue[i].url); + check_object(actualValue[i], expectedValue[i], SCREENSHOT_PROPERTIES); + } + break; + + case "sourceURI": + do_check_eq(actualValue.spec, expectedValue); + break; + + case "updateDate": + do_check_eq(actualValue.getTime(), expectedValue.getTime()); + break; + + default: + if (actualValue !== expectedValue) + do_throw("Failed for " + aProperty + + " (" + actualValue + " === " + expectedValue + ")"); + } + }); +} + +// Test that actual results and expected results are equal +function check_results(aActualAddons, aExpectedAddons, aAddonCount, aInstallNull) { + do_check_false(AddonRepository.isSearching); + + do_check_eq(aActualAddons.length, aAddonCount); + do_check_eq(aActualAddons.length, aExpectedAddons.length); + + for (var i = 0; i < aAddonCount; i++) { + var actualAddon = aActualAddons[i]; + var expectedAddon = aExpectedAddons[i]; + + // Separately check name so better messages are outputted when failure + if (actualAddon.name == "FAIL") + do_throw(actualAddon.id + " - " + actualAddon.description); + if (actualAddon.name != "PASS") + do_throw(actualAddon.id + " - " + "invalid add-on name " + actualAddon.name); + + do_check_eq(actualAddon.install == null, !!aInstallNull); + + // Check that sourceURI property consistent within actual addon + if (!aInstallNull) + do_check_eq(actualAddon.install.sourceURI.spec, actualAddon.sourceURI.spec); + + check_object(actualAddon, expectedAddon, ADDON_PROPERTIES); + } +} + +// Complete a search, also testing cancelSearch() and isSearching +function complete_search(aSearch, aSearchCallback) { + var failCallback = { + searchSucceeded: function(addons, length, total) { + do_throw("failCallback.searchSucceeded should not be called"); + end_test(); + }, + + searchFailed: function() { + do_throw("failCallback.searchFailed should not be called"); + end_test(); + } + }; + + var callbackCalled = false; + var testCallback = { + searchSucceeded: function(addons, length, total) { + do_throw("testCallback.searchSucceeded should not be called"); + end_test(); + }, + + searchFailed: function() { + callbackCalled = true; + } + }; + + // Should fail because cancelled it immediately + aSearch(failCallback); + do_check_true(AddonRepository.isSearching); + AddonRepository.cancelSearch(); + do_check_false(AddonRepository.isSearching); + + aSearch(aSearchCallback); + do_check_true(AddonRepository.isSearching); + + // searchFailed should be called immediately because already searching + aSearch(testCallback); + do_check_true(callbackCalled); + do_check_true(AddonRepository.isSearching); +} + + +function run_test() { + // Setup for test + do_test_pending(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + + startupManager(); + + // Install an add-on so can check that it isn't returned in the results + installAllFiles([do_get_addon("test_AddonRepository_1")], function() { + restartManager(); + + gServer = new nsHttpServer(); + + // Register other add-on XPI files + gServer.registerFile(INSTALL_URL2, + do_get_addon("test_AddonRepository_2")); + gServer.registerFile(INSTALL_URL3, + do_get_addon("test_AddonRepository_3")); + + // Register files used to test search failure + gServer.registerFile(GET_TEST.failedURL, + do_get_file("data/test_AddonRepository_failed.xml")); + gServer.registerFile(RECOMMENDED_TEST.failedURL, + do_get_file("data/test_AddonRepository_failed.xml")); + gServer.registerFile(SEARCH_TEST.failedURL, + do_get_file("data/test_AddonRepository_failed.xml")); + + // Register files used to test search success + gServer.registerFile(GET_TEST.successfulURL, + do_get_file("data/test_AddonRepository_getAddonsByIDs.xml")); + gServer.registerFile(RECOMMENDED_TEST.successfulURL, + do_get_file("data/test_AddonRepository.xml")); + gServer.registerFile(SEARCH_TEST.successfulURL, + do_get_file("data/test_AddonRepository.xml")); + + gServer.start(PORT); + + // Create an active AddonInstall so can check that it isn't returned in the results + AddonManager.getInstallForURL(BASE_URL + INSTALL_URL2, function(aInstall) { + aInstall.install(); + + // Create a non-active AddonInstall so can check that it is returned in the results + AddonManager.getInstallForURL(BASE_URL + INSTALL_URL3, + run_test_1, "application/x-xpinstall"); + }, "application/x-xpinstall"); + }); +} + +function end_test() { + gServer.stop(do_test_finished); +} + +// Tests homepageURL, getRecommendedURL() and getSearchURL() +function run_test_1() { + function check_urls(aPreference, aGetURL, aTests) { + aTests.forEach(function(aTest) { + Services.prefs.setCharPref(aPreference, aTest.preferenceValue); + do_check_eq(aGetURL(aTest), aTest.expectedURL); + }); + } + + var urlTests = [{ + preferenceValue: BASE_URL, + expectedURL: BASE_URL + }, { + preferenceValue: BASE_URL + "/%OS%/%VERSION%", + expectedURL: BASE_URL + "/XPCShell/1" + }]; + + // Extra tests for AddonRepository.getSearchURL(); + var searchURLTests = [{ + searchTerms: "test", + preferenceValue: BASE_URL + "/search?q=%TERMS%", + expectedURL: BASE_URL + "/search?q=test" + }, { + searchTerms: "test search", + preferenceValue: BASE_URL + "/%TERMS%", + expectedURL: BASE_URL + "/test%20search" + }, { + searchTerms: "odd=search:with&weird\"characters", + preferenceValue: BASE_URL + "/%TERMS%", + expectedURL: BASE_URL + "/odd%3Dsearch%3Awith%26weird%22characters" + }]; + + // Setup tests for homepageURL, getRecommendedURL() and getSearchURL() + var tests = [{ + initiallyUndefined: true, + preference: PREF_GETADDONS_BROWSEADDONS, + urlTests: urlTests, + getURL: function() AddonRepository.homepageURL + }, { + initiallyUndefined: true, + preference: PREF_GETADDONS_BROWSERECOMMENDED, + urlTests: urlTests, + getURL: function() AddonRepository.getRecommendedURL() + }, { + initiallyUndefined: true, + preference: PREF_GETADDONS_BROWSESEARCHRESULTS, + urlTests: urlTests.concat(searchURLTests), + getURL: function getSearchURL(aTest) { + var searchTerms = aTest && aTest.searchTerms ? aTest.searchTerms + : "unused terms"; + return AddonRepository.getSearchURL(searchTerms); + } + }]; + + tests.forEach(function(aTest) { + if (aTest.initiallyUndefined) { + // Preference is not defined by default + do_check_eq(Services.prefs.getPrefType(aTest.preference), + Services.prefs.PREF_INVALID); + do_check_eq(aTest.getURL(), DEFAULT_URL); + } + + check_urls(aTest.preference, aTest.getURL, aTest.urlTests); + }); + + run_test_2(); +} + +// Tests failure of AddonRepository.getAddonsByIDs() +function run_test_2() { + Services.prefs.setCharPref(GET_TEST.preference, GET_TEST.preferenceValue); + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_throw("searchAddons should not have succeeded"); + end_test(); + }, + + searchFailed: function() { + do_check_false(AddonRepository.isSearching); + run_test_3(); + } + }; + + complete_search(function(aCallback) { + AddonRepository.getAddonsByIDs(GET_TEST.failedIDs, aCallback); + }, callback); +} + +// Tests success of AddonRepository.getAddonsByIDs() +function run_test_3() { + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_check_eq(aTotalResults, -1); + check_results(aAddonsList, GET_RESULTS, aAddonCount, true); + run_test_4(); + }, + + searchFailed: function() { + do_throw("searchAddons should not have failed"); + end_test(); + } + }; + + complete_search(function(aCallback) { + AddonRepository.getAddonsByIDs(GET_TEST.successfulIDs, aCallback); + }, callback); +} + +// Tests failure of AddonRepository.retrieveRecommendedAddons() +function run_test_4() { + Services.prefs.setCharPref(RECOMMENDED_TEST.preference, + RECOMMENDED_TEST.preferenceValue); + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_throw("retrieveRecommendedAddons should not have succeeded"); + end_test(); + }, + + searchFailed: function() { + do_check_false(AddonRepository.isSearching); + run_test_5(); + } + }; + + complete_search(function(aCallback) { + AddonRepository.retrieveRecommendedAddons(FAILED_MAX_RESULTS, aCallback); + }, callback); +} + +// Tests success of AddonRepository.retrieveRecommendedAddons() +function run_test_5() { + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_check_eq(aTotalResults, -1); + check_results(aAddonsList, SEARCH_RESULTS, aAddonCount); + run_test_6(); + }, + + searchFailed: function() { + do_throw("retrieveRecommendedAddons should not have failed"); + end_test(); + } + }; + + complete_search(function(aCallback) { + AddonRepository.retrieveRecommendedAddons(MAX_RESULTS, aCallback); + }, callback); +} + +// Tests failure of AddonRepository.searchAddons() +function run_test_6() { + Services.prefs.setCharPref(SEARCH_TEST.preference, SEARCH_TEST.preferenceValue); + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_throw("searchAddons should not have succeeded"); + end_test(); + }, + + searchFailed: function() { + do_check_false(AddonRepository.isSearching); + run_test_7(); + } + }; + + complete_search(function(aCallback) { + var searchTerms = SEARCH_TEST.searchTerms; + AddonRepository.searchAddons(searchTerms, FAILED_MAX_RESULTS, aCallback); + }, callback); +} + +// Tests success of AddonRepository.searchAddons() +function run_test_7() { + var callback = { + searchSucceeded: function(aAddonsList, aAddonCount, aTotalResults) { + do_check_eq(aTotalResults, TOTAL_RESULTS); + check_results(aAddonsList, SEARCH_RESULTS, aAddonCount); + end_test(); + }, + + searchFailed: function() { + do_throw("searchAddons should not have failed"); + end_test(); + } + }; + + complete_search(function(aCallback) { + var searchTerms = SEARCH_TEST.searchTerms; + AddonRepository.searchAddons(searchTerms, MAX_RESULTS, aCallback); + }, callback); +} + diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug404024.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug404024.js deleted file mode 100644 index 971116f8f213..000000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug404024.js +++ /dev/null @@ -1,216 +0,0 @@ -/* ***** 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 mozilla.org code. - * - * The Initial Developer of the Original Code is - * Dave Townsend . - * - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** - */ - -Components.utils.import("resource://gre/modules/AddonRepository.jsm"); - -const PREF_GETADDONS_BROWSEADDONS = "extensions.getAddons.browseAddons"; -const PREF_GETADDONS_BROWSERECOMMENDED = "extensions.getAddons.recommended.browseURL"; -const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url"; -const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; -const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; - -const BROWSE = "http://localhost:4444/"; -const RECOMMENDED = "http://localhost:4444/recommended.html"; -const SEARCH = "http://localhost:4444/search.html?q="; - -var BROWSE_SEARCH_URLS = [ - ["test", SEARCH + "test" ], - ["SEARCH", SEARCH + "SEARCH" ], - ["test search", SEARCH + "test%20search" ], - ["odd=search:with&weird\"characters", SEARCH + "odd%3Dsearch%3Awith%26weird%22characters" ] -]; - -do_load_httpd_js(); -var server; - -var RESULTS = [ -{ - id: "test5@tests.mozilla.org", - name: "PASS", - version: "1.0", - description: "This should work fine", - fullDescription: "Test description", - rating: -1, - iconURL: null, - screenshots: [], - homepageURL: "https://addons.mozilla.org/addon/5992", - type: "extension", - sourceURI: "http://localhost:4444/test.xpi", - size: 234 -}, -{ - id: "test6@tests.mozilla.org", - name: "PASS", - version: "1.0", - description: "Specific OS should work fine", - fullDescription: null, - rating: 4, - iconURL: "http://localhost:4444/test_bug404024/icon.png", - screenshots: ["http://localhost:4444/test_bug404024/thumbnail.png"], - homepageURL: null, - type: "theme", - sourceURI: "http://localhost:4444/test.xpi", - size: 1204 -} -]; - -function checkResults(addons, length) { - do_check_eq(addons.length, RESULTS.length); - do_check_eq(addons.length, length); - - for (var i = 0; i < addons.length; i++) { - if (addons[i].name == "FAIL") - do_throw(addons[i].id + " - " + addons[i].summary); - if (addons[i].name != "PASS") - do_throw(addons[i].id + " - " + "invalid add-on name " + addons[i].name); - } - - for (var i = 0; i < addons.length; i++) { - do_check_neq(addons[i]["install"], null); - - for (var p in RESULTS[i]) { - if (p == "screenshots") { - do_check_eq(addons[i][p].length, RESULTS[i][p].length); - for (var j = 0; j < addons[i][p].length; j++) - do_check_eq(addons[i][p][j], addons[i][p][j]); - - continue; - } - - if (p == "sourceURI") { - do_check_eq(addons[i]["install"][p].spec, RESULTS[i][p]); - continue; - } - - if (addons[i][p] != RESULTS[i][p]) - do_throw("Failed on property " + p + " on add-on " + addons[i].id + - addons[i][p] + " == " + RESULTS[i][p]); - } - } -} - -var RecommendedCallback = { - searchSucceeded: function(addons, length, total) { - // Search is complete - do_check_false(AddonRepository.isSearching); - checkResults(addons, length); - - // "search" for the same results - AddonRepository.searchAddons("bug404024", 10, SearchCallback); - // Should be searching now and any attempt to retrieve again should be ignored - do_check_true(AddonRepository.isSearching); - AddonRepository.searchAddons("test search", 10, FailCallback); - }, - - searchFailed: function() { - server.stop(do_test_finished); - do_throw("Recommended results failed"); - } -}; - -var SearchCallback = { - searchSucceeded: function(addons, length, total) { - do_check_false(AddonRepository.isSearching); - checkResults(addons, length); - - server.stop(do_test_finished); - }, - - searchFailed: function() { - server.stop(do_test_finished); - do_throw("Search results failed"); - } -}; - -var FailCallback = { - searchSucceeded: function(addons, length, total) { - server.stop(do_test_finished); - do_throw("Should not be called"); - }, - - searchFailed: function() { - server.stop(do_test_finished); - do_throw("Should not be called"); - } -}; - -function run_test() -{ - // Setup for test - do_test_pending(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); - - // Install an add-on so we can check the same add-on isn't returns in the results - startupManager(); - installAllFiles([do_get_addon("test_bug397778")], function() { - restartManager(); - - server = new nsHttpServer(); - server.registerDirectory("/", do_get_file("data")); - server.start(4444); - - // Point the addons repository to the test server - Services.prefs.setCharPref(PREF_GETADDONS_BROWSEADDONS, BROWSE); - Services.prefs.setCharPref(PREF_GETADDONS_BROWSERECOMMENDED, RECOMMENDED); - Services.prefs.setCharPref(PREF_GETADDONS_GETRECOMMENDED, "http://localhost:4444/test_bug404024.xml"); - Services.prefs.setCharPref(PREF_GETADDONS_BROWSESEARCHRESULTS, SEARCH + "%TERMS%"); - Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, "http://localhost:4444/test_%TERMS%.xml"); - - do_check_neq(AddonRepository, null); - // Check the homepage and recommended urls - do_check_eq(AddonRepository.homepageURL, BROWSE); - do_check_eq(AddonRepository.getRecommendedURL(), RECOMMENDED); - - // Check that search urls are correct - for (var i = 0; i < BROWSE_SEARCH_URLS.length; i++) { - var url = AddonRepository.getSearchURL(BROWSE_SEARCH_URLS[i][0]); - if (url != BROWSE_SEARCH_URLS[i][1]) - do_throw("BROWSE_SEARCH_URL[" + i + "] returned " + url); - } - - // This should fail because we cancel it immediately. - AddonRepository.retrieveRecommendedAddons(10, FailCallback); - AddonRepository.cancelSearch(); - // Pull some results. - AddonRepository.retrieveRecommendedAddons(10, RecommendedCallback); - // Should be searching now and any attempt to retrieve again should be ignored - do_check_true(AddonRepository.isSearching); - AddonRepository.retrieveRecommendedAddons(10, FailCallback); - }); -} - diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug417606.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug417606.js deleted file mode 100644 index 8abf5ee0fb41..000000000000 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug417606.js +++ /dev/null @@ -1,216 +0,0 @@ -/* ***** 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 mozilla.org code. - * - * The Initial Developer of the Original Code is - * Dave Townsend . - * - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * 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 ***** - */ - -Components.utils.import("resource://gre/modules/AddonRepository.jsm"); - -const PREF_GETADDONS_BROWSEADDONS = "extensions.getAddons.browseAddons"; -const PREF_GETADDONS_BROWSERECOMMENDED = "extensions.getAddons.recommended.browseURL"; -const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url"; -const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; -const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; - -const BROWSE = "http://localhost:4444/"; -const RECOMMENDED = "http://localhost:4444/recommended.html"; -const SEARCH = "http://localhost:4444/search/"; - -var BROWSE_SEARCH_URLS = [ - ["test", SEARCH + "test" ], - ["SEARCH", SEARCH + "SEARCH" ], - ["test search", SEARCH + "test%20search" ], - ["odd=search:with&weird\"characters", SEARCH + "odd%3Dsearch%3Awith%26weird%22characters" ] -]; - -do_load_httpd_js(); -var server; - -var RESULTS = [ -{ - id: "test5@tests.mozilla.org", - name: "PASS", - version: "1.0", - description: "This should work fine", - fullDescription: "Test description", - rating: -1, - iconURL: null, - screenshots: [], - homepageURL: "https://addons.mozilla.org/addon/5992", - type: "extension", - sourceURI: "http://localhost:4444/test.xpi", - size: null -}, -{ - id: "test6@tests.mozilla.org", - name: "PASS", - version: "1.0", - description: "Specific OS should work fine", - fullDescription: null, - rating: 4, - iconURL: "http://localhost:4444/test_bug404024/icon.png", - screenshots: ["http://localhost:4444/test_bug404024/thumbnail.png"], - homepageURL: null, - type: "theme", - sourceURI: "http://localhost:4444/XPCShell.xpi", - size: 456, -} -]; - -function checkResults(addons) { - do_check_eq(addons.length, RESULTS.length); - - for (var i = 0; i < addons.length; i++) { - if (addons[i].name == "FAIL") - do_throw(addons[i].id + " - " + addons[i].summary); - if (addons[i].name != "PASS") - do_throw(addons[i].id + " - " + "invalid add-on name " + addons[i].name); - } - - for (var i = 0; i < addons.length; i++) { - do_check_neq(addons[i]["install"], null); - - for (var p in RESULTS[i]) { - if (p == "screenshots") { - do_check_eq(addons[i][p].length, RESULTS[i][p].length); - for (var j = 0; j < addons[i][p].length; j++) - do_check_eq(addons[i][p][j], addons[i][p][j]); - - continue; - } - - if (p == "sourceURI") { - do_check_eq(addons[i]["install"][p].spec, RESULTS[i][p]); - continue; - } - - if (addons[i][p] != RESULTS[i][p]) - do_throw("Failed on property " + p + " on add-on " + addons[i].id + - addons[i][p] + " == " + RESULTS[i][p]); - } - } -} - -var RecommendedCallback = { - searchSucceeded: function(addons, length, total) { - // Search is complete - do_check_false(AddonRepository.isSearching); - checkResults(addons); - - // "search" for the same results - AddonRepository.searchAddons("bug417606", 10, SearchCallback); - // Should be searching now and any attempt to retrieve again should be ignored - do_check_true(AddonRepository.isSearching); - AddonRepository.searchAddons("test search", 10, FailCallback); - }, - - searchFailed: function() { - server.stop(do_test_finished); - do_throw("Recommended results failed"); - } -}; - -var SearchCallback = { - searchSucceeded: function(addons, length, total) { - do_check_false(AddonRepository.isSearching); - do_check_eq(total, 100); - checkResults(addons); - - server.stop(do_test_finished); - }, - - searchFailed: function() { - server.stop(do_test_finished); - do_throw("Search results failed"); - } -}; - -var FailCallback = { - searchSucceeded: function(addons, length, total) { - server.stop(do_test_finished); - do_throw("Should not be called"); - }, - - searchFailed: function() { - server.stop(do_test_finished); - do_throw("Should not be called"); - } -}; - -function run_test() -{ - // Setup for test - do_test_pending(); - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); - - // Install an add-on so we can check the same add-on isn't returns in the results - startupManager(); - installAllFiles([do_get_addon("test_bug397778")], function() { - restartManager(); - - server = new nsHttpServer(); - server.registerDirectory("/", do_get_file("data")); - server.start(4444); - - // Point the addons repository to the test server - Services.prefs.setCharPref(PREF_GETADDONS_BROWSEADDONS, BROWSE); - Services.prefs.setCharPref(PREF_GETADDONS_BROWSERECOMMENDED, RECOMMENDED); - Services.prefs.setCharPref(PREF_GETADDONS_GETRECOMMENDED, "http://localhost:4444/test_bug417606.xml"); - Services.prefs.setCharPref(PREF_GETADDONS_BROWSESEARCHRESULTS, SEARCH + "%TERMS%"); - Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, "http://localhost:4444/test_%TERMS%.xml"); - - do_check_neq(AddonRepository, null); - // Check the homepage and recommended urls - do_check_eq(AddonRepository.homepageURL, BROWSE); - do_check_eq(AddonRepository.getRecommendedURL(), RECOMMENDED); - - // Check that search urls are correct - for (var i = 0; i < BROWSE_SEARCH_URLS.length; i++) { - var url = AddonRepository.getSearchURL(BROWSE_SEARCH_URLS[i][0]); - if (url != BROWSE_SEARCH_URLS[i][1]) - do_throw("BROWSE_SEARCH_URL[" + i + "] returned " + url); - } - - // This should fail because we cancel it immediately. - AddonRepository.retrieveRecommendedAddons(10, FailCallback); - AddonRepository.cancelSearch(); - // Pull some results. - AddonRepository.retrieveRecommendedAddons(10, RecommendedCallback); - // Should be searching now and any attempt to retrieve again should be ignored - do_check_true(AddonRepository.isSearching); - AddonRepository.retrieveRecommendedAddons(10, FailCallback); - }); -} - diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js index 7a6d5c279dec..0cfc08472e86 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js @@ -42,8 +42,8 @@ const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url do_load_httpd_js(); var server; var RESULTS = [ - -1, - -1, + null, + null, 0, 2, 4, @@ -59,8 +59,8 @@ var RecommendedCallback = { do_check_eq(length, RESULTS.length); for (var i = 0; i < length; i++) { - if (addons[i].rating != RESULTS[i]) - do_throw("Rating for " + addons[i].id + " was " + addons[i].rating + ", should have been " + RESULTS[i]); + if (addons[i].averageRating != RESULTS[i]) + do_throw("Rating for " + addons[i].id + " was " + addons[i].averageRating + ", should have been " + RESULTS[i]); } server.stop(do_test_finished); },