Bug 568728: Move nsAddonRepository.js to a JSM. r=dtownsend

--HG--
rename : toolkit/mozapps/extensions/nsAddonRepository.js => toolkit/mozapps/extensions/AddonRepository.jsm
This commit is contained in:
Ben Parr 2010-06-17 15:47:51 -07:00
Родитель 90ae4aedf0
Коммит 1af482ca7b
7 изменённых файлов: 388 добавлений и 396 удалений

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

@ -265,7 +265,6 @@
@BINPATH@/components/FeedWriter.js
@BINPATH@/components/fuelApplication.js
@BINPATH@/components/WebContentConverter.js
@BINPATH@/components/nsAddonRepository.js
@BINPATH@/components/nsBrowserContentHandler.js
@BINPATH@/components/nsBrowserGlue.js
@BINPATH@/components/nsSetDefaultBrowser.js

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

@ -1,4 +1,3 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -44,6 +43,8 @@ const Cr = Components.results;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/AddonManager.jsm");
var EXPORTED_SYMBOLS = [ "AddonRepository" ];
const PREF_GETADDONS_BROWSEADDONS = "extensions.getAddons.browseAddons";
const PREF_GETADDONS_BROWSERECOMMENDED = "extensions.getAddons.recommended.browseURL";
const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url";
@ -54,33 +55,137 @@ const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xm
const API_VERSION = "1.2";
function AddonSearchResult() {
function AddonSearchResult(aId) {
this.id = aId;
this.screenshots = [];
}
AddonSearchResult.prototype = {
/**
* The ID of the add-on
*/
id: null,
/**
* The name of the add-on
*/
name: null,
/**
* The version of the add-on
*/
version: null,
summary: null,
/**
* A short description of the add-on
*/
description: null,
rating: null,
/**
* The full description of the add-on
*/
fullDescription: null,
/**
* The rating of the add-on, 0-5 or -1 if unrated
*/
rating: -1,
/**
* The url of the add-ons icon or empty if there is no icon
*/
iconURL: null,
thumbnailURL: null,
/**
* An array of screenshot urls for the add-on
*/
screenshots: null,
/**
* The homepage for the add-on
*/
homepageURL: null,
eula: null,
/**
* The add-on type (e.g. "extension" or "theme")
*/
type: null,
xpiURL: null,
xpiHash: null,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAddonSearchResult])
/**
* AddonInstall object generated from the add-on XPI url
*/
install: null,
/**
* True or false depending on whether the add-on is compatible with the
* current version and platform of the application
*/
isCompatible: true,
/**
* True if the add-on has a secure means of updating
*/
providesUpdatesSecurely: true,
/**
* The current blocklist state of the add-on
*/
blocklistState: Ci.nsIBlocklistService.STATE_NOT_BLOCKED,
/**
* True if this add-on cannot be used in the application based on version
* compatibility, dependencies and blocklisting
*/
appDisabled: false,
/**
* True if the user wants this add-on to be disabled
*/
userDisabled: false,
/**
* Indicates what scope the add-on is installed in, per profile, user,
* system or application
*/
scope: AddonManager.SCOPE_PROFILE,
/**
* True if the add-on is currently functional
*/
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
*/
pendingOperations: AddonManager.PENDING_NONE,
/**
* A bitfield holding all the the operations that can be performed on
* this add-on
*/
permissions: 0
}
function AddonRepository() {
}
AddonRepository.prototype = {
/**
* 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
* 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.
*/
var AddonRepository = {
// The current set of results
_addons: null,
_results: null,
// Whether we are currently searching or not
_searching: false,
@ -91,40 +196,75 @@ AddonRepository.prototype = {
// XHR associated with the current request
_request: null,
// Callback object to notify on completion
/*
* Addon search results callback object that contains two functions
*
* 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
*
*
* searchFailed - Called when an error occurred when performing a search.
*/
_callback: null,
// Maximum number of results to return
_maxResults: null,
/**
* The homepage for visiting this repository. This may be null or an empty
* string.
*/
get homepageURL() {
return Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
.getService(Components.interfaces.nsIURLFormatter)
.formatURLPref(PREF_GETADDONS_BROWSEADDONS);
return Cc["@mozilla.org/toolkit/URLFormatterService;1"].
getService(Ci.nsIURLFormatter).
formatURLPref(PREF_GETADDONS_BROWSEADDONS);
},
/**
* Returns whether this instance is currently performing a search. New
* searches will not be performed while this is the case.
*/
get isSearching() {
return this._searching;
},
/**
* The url that can be visited to see recommended add-ons in this repository.
*/
getRecommendedURL: function() {
var urlf = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
.getService(Components.interfaces.nsIURLFormatter);
var urlf = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
getService(Ci.nsIURLFormatter);
return urlf.formatURLPref(PREF_GETADDONS_BROWSERECOMMENDED);
},
/**
* Retrieves the url that can be visited to see search results for the given
* terms.
*
* @param aSearchTerms search terms used to search the repository
*/
getSearchURL: function(aSearchTerms) {
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var urlf = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
.getService(Components.interfaces.nsIURLFormatter);
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var urlf = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
getService(Ci.nsIURLFormatter);
var url = prefs.getCharPref(PREF_GETADDONS_BROWSESEARCHRESULTS);
url = url.replace(/%TERMS%/g, encodeURIComponent(aSearchTerms));
return urlf.formatURL(url);
},
/**
* Cancels the search in progress. If there is no search in progress this
* does nothing.
*/
cancelSearch: function() {
this._searching = false;
if (this._request) {
@ -132,23 +272,30 @@ AddonRepository.prototype = {
this._request = null;
}
this._callback = null;
this._addons = null;
this._results = null;
},
/**
* 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
*/
retrieveRecommendedAddons: function(aMaxResults, aCallback) {
if (this._searching)
return;
this._searching = true;
this._addons = [];
this._results = [];
this._callback = aCallback;
this._recommended = true;
this._maxResults = aMaxResults;
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var urlf = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
.getService(Components.interfaces.nsIURLFormatter);
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var urlf = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
getService(Ci.nsIURLFormatter);
var uri = prefs.getCharPref(PREF_GETADDONS_GETRECOMMENDED);
uri = uri.replace(/%API_VERSION%/g, API_VERSION);
@ -156,20 +303,28 @@ AddonRepository.prototype = {
this._loadList(uri);
},
/**
* 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
*/
searchAddons: function(aSearchTerms, aMaxResults, aCallback) {
if (this._searching)
return;
this._searching = true;
this._addons = [];
this._results = [];
this._callback = aCallback;
this._recommended = false;
this._maxResults = aMaxResults;
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var urlf = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
.getService(Components.interfaces.nsIURLFormatter);
var prefs = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var urlf = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
getService(Ci.nsIURLFormatter);
var uri = prefs.getCharPref(PREF_GETADDONS_GETSEARCHRESULTS);
uri = uri.replace(/%API_VERSION%/g, API_VERSION);
@ -180,57 +335,57 @@ AddonRepository.prototype = {
},
// Posts results to the callback
_reportSuccess: function(aCount) {
_reportSuccess: function(aTotalResults) {
this._searching = false;
this._request = null;
// The callback may want to trigger a new search so clear references early
var addons = this._addons;
var addons = [result.addon for each(result in this._results)];
var callback = this._callback;
this._callback = null;
this._addons = null;
callback.searchSucceeded(addons, addons.length, this._recommended ? -1 : aCount);
this._results = null;
callback.searchSucceeded(addons, addons.length, this._recommended ? -1 : aTotalResults);
},
// Notifies the callback of a failure
_reportFailure: function(aEvent) {
_reportFailure: function() {
this._searching = false;
this._request = null;
// The callback may want to trigger a new search so clear references early
var callback = this._callback;
this._callback = null;
this._addons = null;
this._results = null;
callback.searchFailed();
},
// Parses an add-on entry from an <addon> element
_parseAddon: function(element, known_ids) {
_parseAddon: function(aElement, aSkip) {
var app = Cc["@mozilla.org/xre/app-info;1"].
getService(Ci.nsIXULAppInfo).
QueryInterface(Ci.nsIXULRuntime);
var guidList = element.getElementsByTagName("guid");
var guidList = aElement.getElementsByTagName("guid");
if (guidList.length != 1)
return;
var guid = guidList[0].textContent.trim();
// Ignore add-ons already seen in the results
for (var i = 0; i < this._addons.length; i++)
if (this._addons[i].id == guid)
for (var i = 0; i < this._results.length; i++)
if (this._results[i].addon.id == guid)
return;
// Ignore installed add-ons
if (known_ids.indexOf(guid) != -1)
if (aSkip.ids.indexOf(guid) != -1)
return;
// Ignore sandboxed add-ons
var status = element.getElementsByTagName("status");
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 = element.getElementsByTagName("compatible_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) {
@ -250,7 +405,7 @@ AddonRepository.prototype = {
// Ignore add-ons not compatible with this Application
compatible = false;
var tags = element.getElementsByTagName("compatible_applications");
var tags = aElement.getElementsByTagName("compatible_applications");
if (tags.length != 1)
return;
var vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
@ -273,20 +428,26 @@ AddonRepository.prototype = {
if (!compatible)
return;
var addon = new AddonSearchResult();
addon.id = guid;
addon.rating = -1;
var node = element.firstChild;
var addon = new AddonSearchResult(guid);
var 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":
case "summary":
case "description":
case "eula":
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);
@ -295,7 +456,7 @@ AddonRepository.prototype = {
}
break;
case "thumbnail":
addon.thumbnailURL = node.textContent.trim();
addon.screenshots.push(node.textContent.trim());
break;
case "icon":
addon.iconURL = node.textContent.trim();
@ -306,10 +467,7 @@ AddonRepository.prototype = {
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
if (node.getAttribute("id") == 2)
addon.type = Ci.nsIAddonSearchResult.TYPE_THEME;
else
addon.type = Ci.nsIAddonSearchResult.TYPE_EXTENSION;
addon.type = (node.getAttribute("id") == 2) ? "theme" : "extension";
break;
case "install":
// No os attribute means the xpi is compatible with any os
@ -319,9 +477,13 @@ AddonRepository.prototype = {
if (os != "all" && os != app.OS.toLowerCase())
break;
}
addon.xpiURL = node.textContent.trim();
if (node.hasAttribute("hash"))
addon.xpiHash = node.getAttribute("hash");
result.xpiURL = node.textContent.trim();
// Ignore add-on installs
if (aSkip.sourceURLs.indexOf(result.xpiURL) != -1)
return;
result.xpiHash = node.hasAttribute("hash") ? node.getAttribute("hash") : null;
break;
}
}
@ -329,8 +491,34 @@ AddonRepository.prototype = {
}
// Add only if there was an xpi compatible with this os
if (addon.xpiURL)
this._addons.push(addon);
if (result.xpiURL)
this._results.push(result);
},
_parseAddons: function(aElements, aTotalResults, aSkip) {
for (var i = 0; i < aElements.length && this._results.length < this._maxResults; i++)
this._parseAddon(aElements[i], aSkip);
var pendingResults = this._results.length;
if (pendingResults == 0) {
this._reportSuccess(aTotalResults);
return;
}
var self = this;
this._results.forEach(function(aResult) {
var addon = aResult.addon;
var callback = function(aInstall) {
addon.install = aInstall;
pendingResults--;
if (pendingResults == 0)
self._reportSuccess(aTotalResults);
}
AddonManager.getInstallForURL(aResult.xpiURL, callback,
"application/x-xpinstall", aResult.xpiHash,
addon.name, addon.iconURL, addon.version);
});
},
// Called when a single request has completed, parses out any add-ons and
@ -345,26 +533,30 @@ AddonRepository.prototype = {
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;
var self = this;
AddonManager.getAllAddons(function(addons) {
var known_ids = [a.id for each(a in addons)];
var skip = {ids: null, sourceURLs: null};
var elements = responseXML.documentElement.getElementsByTagName("addon");
for (var i = 0; i < elements.length; i++) {
self._parseAddon(elements[i], known_ids);
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
if (self._addons.length == self._maxResults) {
self._reportSuccess(elements.length);
return;
}
}
AddonManager.getAllAddons(function(aAddons) {
skip.ids = [a.id for each (a in aAddons)];
if (skip.sourceURLs)
self._parseAddons(elements, totalResults, skip);
});
if (responseXML.documentElement.hasAttribute("total_results"))
self._reportSuccess(responseXML.documentElement.getAttribute("total_results"));
else
self._reportSuccess(elements.length);
AddonManager.getAllInstalls(function(aInstalls) {
skip.sourceURLs = [];
aInstalls.forEach(function(aInstall) {
if (aInstall.state != AddonManager.STATE_AVAILABLE)
skip.sourceURLs.push(aInstall.sourceURL);
});
if (skip.ids)
self._parseAddons(elements, totalResults, skip);
});
},
@ -376,17 +568,9 @@ AddonRepository.prototype = {
this._request.overrideMimeType("text/xml");
var self = this;
this._request.onerror = function(event) { self._reportFailure(event); };
this._request.onload = function(event) { self._listLoaded(event); };
this._request.onerror = function(aEvent) { self._reportFailure(); };
this._request.onload = function(aEvent) { self._listLoaded(aEvent); };
this._request.send(null);
},
classDescription: "Addon Repository",
contractID: "@mozilla.org/extensions/addon-repository;1",
classID: Components.ID("{8eaaf524-7d6d-4f7d-ae8b-9277b324008d}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAddonRepository])
}
}
function NSGetModule(aCompMgr, aFileSpec) {
return XPCOMUtils.generateModule([AddonRepository]);
}

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

@ -53,7 +53,6 @@ XPIDLSRCS = \
amIInstallTrigger.idl \
amIWebInstallListener.idl \
amIWebInstaller.idl \
nsIAddonRepository.idl \
$(NULL)
CPPSRCS = \
@ -61,7 +60,6 @@ CPPSRCS = \
$(NULL)
EXTRA_PP_COMPONENTS = \
nsAddonRepository.js \
nsBlocklistService.js \
addonManager.js \
amContentHandler.js \
@ -70,6 +68,7 @@ EXTRA_PP_COMPONENTS = \
EXTRA_PP_JS_MODULES = \
AddonManager.jsm \
AddonRepository.jsm \
XPIProvider.jsm \
PluginProvider.jsm \
AddonUpdateChecker.jsm \

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

@ -1,204 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Extension Manager.
*
* The Initial Developer of the Original Code is mozilla.org
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dave Townsend <dtownsend@oxymoronical.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
[scriptable, uuid(f81ed0bc-ee98-4edd-bf2d-751b47bf665d)]
interface nsIAddonSearchResult : nsISupports
{
/**
* Values for the type attribute
*/
const unsigned long TYPE_EXTENSION = 0x02;
const unsigned long TYPE_THEME = 0x04;
/**
* The ID of the add-on
*/
readonly attribute AString id;
/**
* The name of the add-on
*/
readonly attribute AString name;
/**
* The version of the add-on
*/
readonly attribute AString version;
/**
* A short summary of the add-on
*/
readonly attribute AString summary;
/**
* The full description of the add-on
*/
readonly attribute AString description;
/**
* The rating of the add-on, 0-5 or -1 if unrated.
*/
readonly attribute long rating;
/**
* The url of the add-ons icon or empty if there is no icon.
*/
readonly attribute AString iconURL;
/**
* The url of a thumbnail for the add-on
*/
readonly attribute AString thumbnailURL;
/**
* The homepage for the add-on
*/
readonly attribute AString homepageURL;
/**
* A EULA that must be accepted before install.
*/
readonly attribute AString eula;
/**
* The add-on type (see nsIUpdateItem).
*/
readonly attribute unsigned long type;
/**
* The url of the xpi for this add-on
*/
readonly attribute AString xpiURL;
/**
* The hash for the xpi.
*/
readonly attribute AString xpiHash;
};
[scriptable, uuid(a6f70917-dd30-4eb6-8b3d-453204f96f33)]
interface nsIAddonSearchResultsCallback : nsISupports
{
/**
* 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
*/
void searchSucceeded([array, size_is(aAddonCount)] in nsIAddonSearchResult aAddons,
in unsigned long aAddonCount,
in unsigned long aTotalResults);
/**
* Called when an error occurred when performing a search.
*/
void searchFailed();
};
/**
* 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
* 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.
*/
[scriptable, uuid(c4d2ac29-6edc-43cd-8dc8-e4cf213aa1be)]
interface nsIAddonRepository : nsISupports
{
/**
* The homepage for visiting this repository. This may be null or an empty
* string.
*/
readonly attribute AString homepageURL;
/**
* Returns whether this instance is currently performing a search. New
* searches will not be performed while this is the case.
*/
readonly attribute boolean isSearching;
/**
* The url that can be visited to see recommended add-ons in this repository.
*/
AString getRecommendedURL();
/**
* Retrieves the url that can be visited to see search results for the given
* terms.
*
* @param aSearchTerms search terms used to search the repository
*/
AString getSearchURL(in AString aSearchTerms);
/**
* 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
*/
void retrieveRecommendedAddons(in unsigned long aMaxResults,
in nsIAddonSearchResultsCallback aCallback);
/**
* 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
*/
void searchAddons(in AString aSearchTerms, in unsigned long aMaxResults,
in nsIAddonSearchResultsCallback aCallback);
/**
* Cancels the search in progress. If there is no search in progress this
* does nothing.
*/
void cancelSearch();
};

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

@ -36,6 +36,8 @@
* ***** 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";
@ -55,38 +57,33 @@ var BROWSE_SEARCH_URLS = [
do_load_httpd_js();
var server;
var addonRepo;
var RESULTS = [
{
id: "test5@tests.mozilla.org",
name: "PASS",
version: "1.0",
summary: "This should work fine",
description: "Test description",
rating: -1,
iconURL: null,
thumbnailURL: null,
homepageURL: "https://addons.mozilla.org/addon/5992",
eula: null,
type: Ci.nsIAddonSearchResult.TYPE_EXTENSION,
xpiURL: "http://localhost:4444/test.xpi",
xpiHash: "sha1:c26f0b0d62e5dcddcda95074d3f3fedb9bbc26e3"
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",
sourceURL: "http://localhost:4444/test.xpi"
},
{
id: "test6@tests.mozilla.org",
name: "PASS",
version: "1.0",
summary: "Specific OS should work fine",
description: null,
rating: 4,
iconURL: "http://localhost:4444/test_bug404024/icon.png",
thumbnailURL: "http://localhost:4444/test_bug404024/thumbnail.png",
homepageURL: null,
eula: "EULA should be confirmed",
type: Ci.nsIAddonSearchResult.TYPE_THEME,
xpiURL: "http://localhost:4444/test.xpi",
xpiHash: 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",
sourceURL: "http://localhost:4444/test.xpi"
}
];
@ -102,7 +99,22 @@ function checkResults(addons, length) {
}
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 == "sourceURL") {
do_check_eq(addons[i]["install"][p], 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]);
@ -113,14 +125,14 @@ function checkResults(addons, length) {
var RecommendedCallback = {
searchSucceeded: function(addons, length, total) {
// Search is complete
do_check_false(addonRepo.isSearching);
do_check_false(AddonRepository.isSearching);
checkResults(addons, length);
// "search" for the same results
addonRepo.searchAddons("bug404024", 10, SearchCallback);
AddonRepository.searchAddons("bug404024", 10, SearchCallback);
// Should be searching now and any attempt to retrieve again should be ignored
do_check_true(addonRepo.isSearching);
addonRepo.searchAddons("test search", 10, FailCallback);
do_check_true(AddonRepository.isSearching);
AddonRepository.searchAddons("test search", 10, FailCallback);
},
searchFailed: function() {
@ -131,7 +143,7 @@ var RecommendedCallback = {
var SearchCallback = {
searchSucceeded: function(addons, length, total) {
do_check_false(addonRepo.isSearching);
do_check_false(AddonRepository.isSearching);
checkResults(addons, length);
server.stop(do_test_finished);
@ -177,29 +189,26 @@ function run_test()
Services.prefs.setCharPref(PREF_GETADDONS_BROWSESEARCHRESULTS, SEARCH + "%TERMS%");
Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, "http://localhost:4444/test_%TERMS%.xml");
addonRepo = Components.classes["@mozilla.org/extensions/addon-repository;1"]
.getService(Components.interfaces.nsIAddonRepository);
do_check_neq(addonRepo, null);
do_check_neq(AddonRepository, null);
// Check the homepage and recommended urls
do_check_eq(addonRepo.homepageURL, BROWSE);
do_check_eq(addonRepo.getRecommendedURL(), RECOMMENDED);
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 = addonRepo.getSearchURL(BROWSE_SEARCH_URLS[i][0]);
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.
addonRepo.retrieveRecommendedAddons(10, FailCallback);
addonRepo.cancelSearch();
AddonRepository.retrieveRecommendedAddons(10, FailCallback);
AddonRepository.cancelSearch();
// Pull some results.
addonRepo.retrieveRecommendedAddons(10, RecommendedCallback);
AddonRepository.retrieveRecommendedAddons(10, RecommendedCallback);
// Should be searching now and any attempt to retrieve again should be ignored
do_check_true(addonRepo.isSearching);
addonRepo.retrieveRecommendedAddons(10, FailCallback);
do_check_true(AddonRepository.isSearching);
AddonRepository.retrieveRecommendedAddons(10, FailCallback);
});
}

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

@ -36,6 +36,8 @@
* ***** 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";
@ -55,38 +57,33 @@ var BROWSE_SEARCH_URLS = [
do_load_httpd_js();
var server;
var addonRepo;
var RESULTS = [
{
id: "test5@tests.mozilla.org",
name: "PASS",
version: "1.0",
summary: "This should work fine",
description: "Test description",
rating: -1,
iconURL: null,
thumbnailURL: null,
homepageURL: "https://addons.mozilla.org/addon/5992",
eula: null,
type: Ci.nsIAddonSearchResult.TYPE_EXTENSION,
xpiURL: "http://localhost:4444/test.xpi",
xpiHash: "sha1:c26f0b0d62e5dcddcda95074d3f3fedb9bbc26e3"
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",
sourceURL: "http://localhost:4444/test.xpi"
},
{
id: "test6@tests.mozilla.org",
name: "PASS",
version: "1.0",
summary: "Specific OS should work fine",
description: null,
rating: 4,
iconURL: "http://localhost:4444/test_bug404024/icon.png",
thumbnailURL: "http://localhost:4444/test_bug404024/thumbnail.png",
homepageURL: null,
eula: "EULA should be confirmed",
type: Ci.nsIAddonSearchResult.TYPE_THEME,
xpiURL: "http://localhost:4444/XPCShell.xpi",
xpiHash: 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",
sourceURL: "http://localhost:4444/XPCShell.xpi"
}
];
@ -101,7 +98,22 @@ function checkResults(addons) {
}
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 == "sourceURL") {
do_check_eq(addons[i]["install"][p], 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]);
@ -112,14 +124,14 @@ function checkResults(addons) {
var RecommendedCallback = {
searchSucceeded: function(addons, length, total) {
// Search is complete
do_check_false(addonRepo.isSearching);
do_check_false(AddonRepository.isSearching);
checkResults(addons);
// "search" for the same results
addonRepo.searchAddons("bug417606", 10, SearchCallback);
AddonRepository.searchAddons("bug417606", 10, SearchCallback);
// Should be searching now and any attempt to retrieve again should be ignored
do_check_true(addonRepo.isSearching);
addonRepo.searchAddons("test search", 10, FailCallback);
do_check_true(AddonRepository.isSearching);
AddonRepository.searchAddons("test search", 10, FailCallback);
},
searchFailed: function() {
@ -130,7 +142,7 @@ var RecommendedCallback = {
var SearchCallback = {
searchSucceeded: function(addons, length, total) {
do_check_false(addonRepo.isSearching);
do_check_false(AddonRepository.isSearching);
do_check_eq(total, 100);
checkResults(addons);
@ -177,29 +189,26 @@ function run_test()
Services.prefs.setCharPref(PREF_GETADDONS_BROWSESEARCHRESULTS, SEARCH + "%TERMS%");
Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, "http://localhost:4444/test_%TERMS%.xml");
addonRepo = Components.classes["@mozilla.org/extensions/addon-repository;1"]
.getService(Components.interfaces.nsIAddonRepository);
do_check_neq(addonRepo, null);
do_check_neq(AddonRepository, null);
// Check the homepage and recommended urls
do_check_eq(addonRepo.homepageURL, BROWSE);
do_check_eq(addonRepo.getRecommendedURL(), RECOMMENDED);
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 = addonRepo.getSearchURL(BROWSE_SEARCH_URLS[i][0]);
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.
addonRepo.retrieveRecommendedAddons(10, FailCallback);
addonRepo.cancelSearch();
AddonRepository.retrieveRecommendedAddons(10, FailCallback);
AddonRepository.cancelSearch();
// Pull some results.
addonRepo.retrieveRecommendedAddons(10, RecommendedCallback);
AddonRepository.retrieveRecommendedAddons(10, RecommendedCallback);
// Should be searching now and any attempt to retrieve again should be ignored
do_check_true(addonRepo.isSearching);
addonRepo.retrieveRecommendedAddons(10, FailCallback);
do_check_true(AddonRepository.isSearching);
AddonRepository.retrieveRecommendedAddons(10, FailCallback);
});
}

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

@ -35,13 +35,12 @@
*
* ***** END LICENSE BLOCK *****
*/
Components.utils.import("resource://gre/modules/AddonRepository.jsm");
const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url";
do_load_httpd_js();
var server;
var addonRepo;
var RESULTS = [
-1,
-1,
@ -85,13 +84,10 @@ function run_test()
// Point the addons repository to the test server
Services.prefs.setCharPref(PREF_GETADDONS_GETRECOMMENDED, "http://localhost:4444/test_bug424262.xml");
addonRepo = Components.classes["@mozilla.org/extensions/addon-repository;1"]
.getService(Components.interfaces.nsIAddonRepository);
do_check_neq(addonRepo, null);
do_check_neq(AddonRepository, null);
do_test_pending();
// Pull some results.
addonRepo.retrieveRecommendedAddons(RESULTS.length, RecommendedCallback);
AddonRepository.retrieveRecommendedAddons(RESULTS.length, RecommendedCallback);
}