Bug 731494 - Refactor generic code from services/sync into services/common; r=rnewman

--HG--
rename : services/sync/modules/async.js => services/common/async.js
rename : services/sync/modules/log4moz.js => services/common/log4moz.js
rename : services/sync/modules/ext/Observers.js => services/common/observers.js
rename : services/sync/modules/ext/Preferences.js => services/common/preferences.js
rename : services/sync/modules/ext/StringBundle.js => services/common/stringbundle.js
rename : services/sync/tests/unit/test_async_chain.js => services/common/tests/unit/test_async_chain.js
rename : services/sync/tests/unit/test_async_querySpinningly.js => services/common/tests/unit/test_async_querySpinningly.js
rename : services/sync/tests/unit/test_log4moz.js => services/common/tests/unit/test_log4moz.js
rename : services/sync/tests/unit/test_Observers.js => services/common/tests/unit/test_observers.js
rename : services/sync/tests/unit/test_Preferences.js => services/common/tests/unit/test_preferences.js
rename : services/sync/tests/unit/test_restrequest.js => services/common/tests/unit/test_restrequest.js
rename : services/sync/tests/unit/test_utils_makeURI.js => services/common/tests/unit/test_utils_makeURI.js
rename : services/sync/tests/unit/test_utils_namedTimer.js => services/common/tests/unit/test_utils_namedTimer.js
rename : services/sync/tests/unit/test_utils_stackTrace.js => services/common/tests/unit/test_utils_stackTrace.js
This commit is contained in:
Gregory Szorc 2012-04-05 23:26:06 -07:00
Родитель e6daac9d21
Коммит 7ece697368
90 изменённых файлов: 1403 добавлений и 1208 удалений

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

@ -57,7 +57,7 @@
<implementation>
<constructor><![CDATA[
let temp = {};
Cu.import("resource://services-sync/ext/Observers.js", temp);
Cu.import("resource://services-common/observers.js", temp);
temp.Observers.add("weave:notification:added", this.onNotificationAdded, this);
temp.Observers.add("weave:notification:removed", this.onNotificationRemoved, this);
@ -67,7 +67,7 @@
<destructor><![CDATA[
let temp = {};
Cu.import("resource://services-sync/ext/Observers.js", temp);
Cu.import("resource://services-common/observers.js", temp);
temp.Observers.remove("weave:notification:added", this.onNotificationAdded, this);
temp.Observers.remove("weave:notification:removed", this.onNotificationRemoved, this);
]]></destructor>

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

@ -1031,6 +1031,13 @@ xpicleanup@BIN_SUFFIX@
modules/PropertyPanel.jsm
modules/reflect.jsm
modules/Services.jsm
modules/services-common/async.js
modules/services-common/log4moz.js
modules/services-common/observers.js
modules/services-common/preferences.js
modules/services-common/rest.js
modules/services-common/stringbundle.js
modules/services-common/utils.js
modules/services-sync/auth.js
modules/services-sync/base_records/collection.js
modules/services-sync/base_records/crypto.js

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

@ -43,7 +43,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
ifdef MOZ_SERVICES_SYNC
PARALLEL_DIRS += crypto sync
PARALLEL_DIRS += common crypto sync
endif
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,33 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
PREF_JS_EXPORTS = $(srcdir)/services-common.js
modules := \
async.js \
log4moz.js \
observers.js \
preferences.js \
rest.js \
stringbundle.js \
utils.js \
$(NULL)
source_modules = $(foreach module,$(modules),$(srcdir)/$(module))
module_dir = $(FINAL_TARGET)/modules/services-common
libs::
$(NSINSTALL) -D $(module_dir)
$(NSINSTALL) -l $(source_modules) $(module_dir)
TEST_DIRS += tests
include $(topsrcdir)/config/rules.mk

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

@ -1,46 +1,10 @@
/* ***** 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 Firefox Sync.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Richard Newman <rnewman@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const EXPORTED_SYMBOLS = ['Async'];
const EXPORTED_SYMBOLS = ["Async"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
// Constants for makeSyncCallback, waitForSyncCallback.
const CB_READY = {};
@ -61,10 +25,10 @@ let Async = {
* other, passing the callback arguments on to the next one. All functions
* must take a callback function as their last argument. The 'this' object
* will be whatever chain()'s is.
*
*
* @usage this._chain = Async.chain;
* this._chain(this.foo, this.bar, this.baz)(args, for, foo)
*
*
* This is equivalent to:
*
* let self = this;

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

@ -39,10 +39,7 @@
const EXPORTED_SYMBOLS = ['Log4Moz'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
const ONE_BYTE = 1;
const ONE_KILOBYTE = 1024 * ONE_BYTE;
@ -373,7 +370,7 @@ BasicFormatter.prototype = {
__proto__: Formatter.prototype,
format: function BF_format(message) {
return message.time + "\t" + message.loggerName + "\t" + message.levelDesc
return message.time + "\t" + message.loggerName + "\t" + message.levelDesc
+ "\t" + message.message + "\n";
}
};
@ -442,7 +439,7 @@ ConsoleAppender.prototype = {
/**
* Base implementation for stream based appenders.
*
*
* Caution: This writes to the output stream synchronously, thus logging calls
* block as the data is written to the stream. This can have negligible impact
* for in-memory streams, but should be taken into account for I/O streams
@ -460,7 +457,7 @@ BlockingStreamAppender.prototype = {
/**
* Output stream to write to.
*
*
* This will automatically open the stream if it doesn't exist yet by
* calling newOutputStream. The resulting raw stream is wrapped in a
* nsIConverterOutputStream to ensure text is written as UTF-8.
@ -481,7 +478,7 @@ BlockingStreamAppender.prototype = {
}
this._converterStream.init(
this._outputStream, "UTF-8", STREAM_SEGMENT_SIZE,
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
}
return this._converterStream;
},
@ -521,7 +518,7 @@ BlockingStreamAppender.prototype = {
/**
* Append to an nsIStorageStream
*
*
* This writes logging output to an in-memory stream which can later be read
* back as an nsIInputStream. It can be used to avoid expensive I/O operations
* during logging. Instead, one can periodically consume the input stream and
@ -531,7 +528,7 @@ function StorageStreamAppender(formatter) {
this._name = "StorageStreamAppender";
BlockingStreamAppender.call(this, formatter);
}
StorageStreamAppender.prototype = {
StorageStreamAppender.prototype = {
__proto__: BlockingStreamAppender.prototype,
_ss: null,
@ -590,7 +587,7 @@ FileAppender.prototype = {
/**
* Rotating file appender (discouraged)
*
*
* Similar to FileAppender, but rotates logs when they become too large.
*/
function RotatingFileAppender(file, formatter, maxSize, maxBackups) {

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

578
services/common/rest.js Normal file
Просмотреть файл

@ -0,0 +1,578 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const EXPORTED_SYMBOLS = ["RESTRequest"];
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://services-common/utils.js");
const Prefs = new Preferences("services.common.rest.");
/**
* Single use HTTP requests to RESTish resources.
*
* @param uri
* URI for the request. This can be an nsIURI object or a string
* that can be used to create one. An exception will be thrown if
* the string is not a valid URI.
*
* Examples:
*
* (1) Quick GET request:
*
* new RESTRequest("http://server/rest/resource").get(function (error) {
* if (error) {
* // Deal with a network error.
* processNetworkErrorCode(error.result);
* return;
* }
* if (!this.response.success) {
* // Bail out if we're not getting an HTTP 2xx code.
* processHTTPError(this.response.status);
* return;
* }
* processData(this.response.body);
* });
*
* (2) Quick PUT request (non-string data is automatically JSONified)
*
* new RESTRequest("http://server/rest/resource").put(data, function (error) {
* ...
* });
*
* (3) Streaming GET
*
* let request = new RESTRequest("http://server/rest/resource");
* request.setHeader("Accept", "application/newlines");
* request.onComplete = function (error) {
* if (error) {
* // Deal with a network error.
* processNetworkErrorCode(error.result);
* return;
* }
* callbackAfterRequestHasCompleted()
* });
* request.onProgress = function () {
* if (!this.response.success) {
* // Bail out if we're not getting an HTTP 2xx code.
* return;
* }
* // Process body data and reset it so we don't process the same data twice.
* processIncrementalData(this.response.body);
* this.response.body = "";
* });
* request.get();
*/
function RESTRequest(uri) {
this.status = this.NOT_SENT;
// If we don't have an nsIURI object yet, make one. This will throw if
// 'uri' isn't a valid URI string.
if (!(uri instanceof Ci.nsIURI)) {
uri = Services.io.newURI(uri, null, null);
}
this.uri = uri;
this._headers = {};
this._log = Log4Moz.repository.getLogger(this._logName);
this._log.level =
Log4Moz.Level[Prefs.get("log.logger.rest.request")];
}
RESTRequest.prototype = {
_logName: "Services.Common.RESTRequest",
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIBadCertListener2,
Ci.nsIInterfaceRequestor,
Ci.nsIChannelEventSink
]),
/*** Public API: ***/
/**
* URI for the request (an nsIURI object).
*/
uri: null,
/**
* HTTP method (e.g. "GET")
*/
method: null,
/**
* RESTResponse object
*/
response: null,
/**
* nsIRequest load flags. Don't do any caching by default.
*/
loadFlags: Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING,
/**
* nsIHttpChannel
*/
channel: null,
/**
* Flag to indicate the status of the request.
*
* One of NOT_SENT, SENT, IN_PROGRESS, COMPLETED, ABORTED.
*/
status: null,
NOT_SENT: 0,
SENT: 1,
IN_PROGRESS: 2,
COMPLETED: 4,
ABORTED: 8,
/**
* Request timeout (in seconds, though decimal values can be used for
* up to millisecond granularity.)
*
* 0 for no timeout.
*/
timeout: null,
/**
* Called when the request has been completed, including failures and
* timeouts.
*
* @param error
* Error that occurred while making the request, null if there
* was no error.
*/
onComplete: function onComplete(error) {
},
/**
* Called whenever data is being received on the channel. If this throws an
* exception, the request is aborted and the exception is passed as the
* error to onComplete().
*/
onProgress: function onProgress() {
},
/**
* Set a request header.
*/
setHeader: function setHeader(name, value) {
this._headers[name.toLowerCase()] = value;
},
/**
* Perform an HTTP GET.
*
* @param onComplete
* Short-circuit way to set the 'onComplete' method. Optional.
* @param onProgress
* Short-circuit way to set the 'onProgress' method. Optional.
*
* @return the request object.
*/
get: function get(onComplete, onProgress) {
return this.dispatch("GET", null, onComplete, onProgress);
},
/**
* Perform an HTTP PUT.
*
* @param data
* Data to be used as the request body. If this isn't a string
* it will be JSONified automatically.
* @param onComplete
* Short-circuit way to set the 'onComplete' method. Optional.
* @param onProgress
* Short-circuit way to set the 'onProgress' method. Optional.
*
* @return the request object.
*/
put: function put(data, onComplete, onProgress) {
return this.dispatch("PUT", data, onComplete, onProgress);
},
/**
* Perform an HTTP POST.
*
* @param data
* Data to be used as the request body. If this isn't a string
* it will be JSONified automatically.
* @param onComplete
* Short-circuit way to set the 'onComplete' method. Optional.
* @param onProgress
* Short-circuit way to set the 'onProgress' method. Optional.
*
* @return the request object.
*/
post: function post(data, onComplete, onProgress) {
return this.dispatch("POST", data, onComplete, onProgress);
},
/**
* Perform an HTTP DELETE.
*
* @param onComplete
* Short-circuit way to set the 'onComplete' method. Optional.
* @param onProgress
* Short-circuit way to set the 'onProgress' method. Optional.
*
* @return the request object.
*/
delete: function delete_(onComplete, onProgress) {
return this.dispatch("DELETE", null, onComplete, onProgress);
},
/**
* Abort an active request.
*/
abort: function abort() {
if (this.status != this.SENT && this.status != this.IN_PROGRESS) {
throw "Can only abort a request that has been sent.";
}
this.status = this.ABORTED;
this.channel.cancel(Cr.NS_BINDING_ABORTED);
if (this.timeoutTimer) {
// Clear the abort timer now that the channel is done.
this.timeoutTimer.clear();
}
},
/*** Implementation stuff ***/
dispatch: function dispatch(method, data, onComplete, onProgress) {
if (this.status != this.NOT_SENT) {
throw "Request has already been sent!";
}
this.method = method;
if (onComplete) {
this.onComplete = onComplete;
}
if (onProgress) {
this.onProgress = onProgress;
}
// Create and initialize HTTP channel.
let channel = Services.io.newChannelFromURI(this.uri, null, null)
.QueryInterface(Ci.nsIRequest)
.QueryInterface(Ci.nsIHttpChannel);
this.channel = channel;
channel.loadFlags |= this.loadFlags;
channel.notificationCallbacks = this;
// Set request headers.
let headers = this._headers;
for (let key in headers) {
if (key == 'authorization') {
this._log.trace("HTTP Header " + key + ": ***** (suppressed)");
} else {
this._log.trace("HTTP Header " + key + ": " + headers[key]);
}
channel.setRequestHeader(key, headers[key], false);
}
// Set HTTP request body.
if (method == "PUT" || method == "POST") {
// Convert non-string bodies into JSON.
if (typeof data != "string") {
data = JSON.stringify(data);
}
this._log.debug(method + " Length: " + data.length);
if (this._log.level <= Log4Moz.Level.Trace) {
this._log.trace(method + " Body: " + data);
}
let stream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
stream.setData(data, data.length);
let type = headers["content-type"] || "text/plain";
channel.QueryInterface(Ci.nsIUploadChannel);
channel.setUploadStream(stream, type, data.length);
}
// We must set this after setting the upload stream, otherwise it
// will always be 'PUT'. Yeah, I know.
channel.requestMethod = method;
// Blast off!
channel.asyncOpen(this, null);
this.status = this.SENT;
this.delayTimeout();
return this;
},
/**
* Create or push back the abort timer that kills this request.
*/
delayTimeout: function delayTimeout() {
if (this.timeout) {
CommonUtils.namedTimer(this.abortTimeout, this.timeout * 1000, this,
"timeoutTimer");
}
},
/**
* Abort the request based on a timeout.
*/
abortTimeout: function abortTimeout() {
this.abort();
let error = Components.Exception("Aborting due to channel inactivity.",
Cr.NS_ERROR_NET_TIMEOUT);
if (!this.onComplete) {
this._log.error("Unexpected error: onComplete not defined in " +
"abortTimeout.")
return;
}
this.onComplete(error);
},
/*** nsIStreamListener ***/
onStartRequest: function onStartRequest(channel) {
if (this.status == this.ABORTED) {
this._log.trace("Not proceeding with onStartRequest, request was aborted.");
return;
}
try {
channel.QueryInterface(Ci.nsIHttpChannel);
} catch (ex) {
this._log.error("Unexpected error: channel is not a nsIHttpChannel!");
this.status = this.ABORTED;
channel.cancel(Cr.NS_BINDING_ABORTED);
return;
}
this.status = this.IN_PROGRESS;
this._log.trace("onStartRequest: " + channel.requestMethod + " " +
channel.URI.spec);
// Create a response object and fill it with some data.
let response = this.response = new RESTResponse();
response.request = this;
response.body = "";
// Define this here so that we don't have make a new one each time
// onDataAvailable() gets called.
this._inputStream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
this.delayTimeout();
},
onStopRequest: function onStopRequest(channel, context, statusCode) {
if (this.timeoutTimer) {
// Clear the abort timer now that the channel is done.
this.timeoutTimer.clear();
}
// We don't want to do anything for a request that's already been aborted.
if (this.status == this.ABORTED) {
this._log.trace("Not proceeding with onStopRequest, request was aborted.");
return;
}
try {
channel.QueryInterface(Ci.nsIHttpChannel);
} catch (ex) {
this._log.error("Unexpected error: channel not nsIHttpChannel!");
this.status = this.ABORTED;
return;
}
this.status = this.COMPLETED;
let statusSuccess = Components.isSuccessCode(statusCode);
let uri = channel && channel.URI && channel.URI.spec || "<unknown>";
this._log.trace("Channel for " + channel.requestMethod + " " + uri +
" returned status code " + statusCode);
if (!this.onComplete) {
this._log.error("Unexpected error: onComplete not defined in " +
"abortRequest.");
this.onProgress = null;
return;
}
// Throw the failure code and stop execution. Use Components.Exception()
// instead of Error() so the exception is QI-able and can be passed across
// XPCOM borders while preserving the status code.
if (!statusSuccess) {
let message = Components.Exception("", statusCode).name;
let error = Components.Exception(message, statusCode);
this.onComplete(error);
this.onComplete = this.onProgress = null;
return;
}
this._log.debug(this.method + " " + uri + " " + this.response.status);
// Additionally give the full response body when Trace logging.
if (this._log.level <= Log4Moz.Level.Trace) {
this._log.trace(this.method + " body: " + this.response.body);
}
delete this._inputStream;
this.onComplete(null);
this.onComplete = this.onProgress = null;
},
onDataAvailable: function onDataAvailable(req, cb, stream, off, count) {
this._inputStream.init(stream);
try {
this.response.body += this._inputStream.read(count);
} catch (ex) {
this._log.warn("Exception thrown reading " + count +
" bytes from the channel.");
this._log.debug(CommonUtils.exceptionStr(ex));
throw ex;
}
try {
this.onProgress();
} catch (ex) {
this._log.warn("Got exception calling onProgress handler, aborting " +
this.method + " " + req.URI.spec);
this._log.debug("Exception: " + CommonUtils.exceptionStr(ex));
this.abort();
if (!this.onComplete) {
this._log.error("Unexpected error: onComplete not defined in " +
"onDataAvailable.");
this.onProgress = null;
return;
}
this.onComplete(ex);
this.onComplete = this.onProgress = null;
return;
}
this.delayTimeout();
},
/*** nsIInterfaceRequestor ***/
getInterface: function(aIID) {
return this.QueryInterface(aIID);
},
/*** nsIBadCertListener2 ***/
notifyCertProblem: function notifyCertProblem(socketInfo, sslStatus, targetHost) {
this._log.warn("Invalid HTTPS certificate encountered!");
// Suppress invalid HTTPS certificate warnings in the UI.
// (The request will still fail.)
return true;
},
/*** nsIChannelEventSink ***/
asyncOnChannelRedirect:
function asyncOnChannelRedirect(oldChannel, newChannel, flags, callback) {
try {
newChannel.QueryInterface(Ci.nsIHttpChannel);
} catch (ex) {
this._log.error("Unexpected error: channel not nsIHttpChannel!");
callback.onRedirectVerifyCallback(Cr.NS_ERROR_NO_INTERFACE);
return;
}
this.channel = newChannel;
// We let all redirects proceed.
callback.onRedirectVerifyCallback(Cr.NS_OK);
}
};
/**
* Response object for a RESTRequest. This will be created automatically by
* the RESTRequest.
*/
function RESTResponse() {
this._log = Log4Moz.repository.getLogger(this._logName);
this._log.level =
Log4Moz.Level[Prefs.get("log.logger.rest.response")];
}
RESTResponse.prototype = {
_logName: "Sync.RESTResponse",
/**
* Corresponding REST request
*/
request: null,
/**
* HTTP status code
*/
get status() {
let status;
try {
let channel = this.request.channel.QueryInterface(Ci.nsIHttpChannel);
status = channel.responseStatus;
} catch (ex) {
this._log.debug("Caught exception fetching HTTP status code:" +
CommonUtils.exceptionStr(ex));
return null;
}
delete this.status;
return this.status = status;
},
/**
* Boolean flag that indicates whether the HTTP status code is 2xx or not.
*/
get success() {
let success;
try {
let channel = this.request.channel.QueryInterface(Ci.nsIHttpChannel);
success = channel.requestSucceeded;
} catch (ex) {
this._log.debug("Caught exception fetching HTTP success flag:" +
CommonUtils.exceptionStr(ex));
return null;
}
delete this.success;
return this.success = success;
},
/**
* Object containing HTTP headers (keyed as lower case)
*/
get headers() {
let headers = {};
try {
this._log.trace("Processing response headers.");
let channel = this.request.channel.QueryInterface(Ci.nsIHttpChannel);
channel.visitResponseHeaders(function (header, value) {
headers[header.toLowerCase()] = value;
});
} catch (ex) {
this._log.debug("Caught exception processing response headers:" +
CommonUtils.exceptionStr(ex));
return null;
}
delete this.headers;
return this.headers = headers;
},
/**
* HTTP body (string)
*/
body: null
};

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

@ -0,0 +1,5 @@
// This file contains default preference values for components in
// services-common.
pref("services.common.log.logger.rest.request", "Debug");
pref("services.common.log.logger.rest.response", "Debug");

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

@ -34,12 +34,9 @@
*
* ***** END LICENSE BLOCK ***** */
let EXPORTED_SYMBOLS = ["StringBundle"];
const EXPORTED_SYMBOLS = ["StringBundle"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
/**
* A string bundle.

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

@ -0,0 +1,16 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = services/common/tests
include $(DEPTH)/config/autoconf.mk
MODULE = test_services_common
XPCSHELL_TESTS = unit
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,54 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Where to bind test HTTP servers to.
const TEST_SERVER_URL = "http://localhost:8080/";
// This has the side-effect of populating Cc, Ci, Cu, Cr. It's best not to
// ask questions and just accept it.
do_load_httpd_js();
const Cm = Components.manager;
let gSyncProfile = do_get_profile();
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let XULAppInfo = {
vendor: "Mozilla",
name: "XPCShell",
ID: "xpcshell@tests.mozilla.org",
version: "1",
appBuildID: "20100621",
platformVersion: "",
platformBuildID: "20100621",
inSafeMode: false,
logConsoleErrors: true,
OS: "XPCShell",
XPCOMABI: "noarch-spidermonkey",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIXULAppInfo, Ci.nsIXULRuntime]),
invalidateCachesOnRestart: function invalidateCachesOnRestart() { }
};
let XULAppInfoFactory = {
createInstance: function (outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return XULAppInfo.QueryInterface(iid);
}
};
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"),
"XULAppInfo", "@mozilla.org/xre/app-info;1",
XULAppInfoFactory);
function addResourceAlias() {
Cu.import("resource://gre/modules/Services.jsm");
const handler = Services.io.getProtocolHandler("resource")
.QueryInterface(Ci.nsIResProtocolHandler);
let uri = Services.io.newURI("resource:///modules/services-common/", null,
null);
handler.setSubstitution("services-common", uri);
}
addResourceAlias();

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

@ -0,0 +1,173 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
Cu.import("resource://services-common/log4moz.js");
function do_check_empty(obj) {
do_check_attribute_count(obj, 0);
}
function do_check_attribute_count(obj, c) {
do_check_eq(c, Object.keys(obj).length);
}
function do_check_throws(aFunc, aResult, aStack) {
if (!aStack) {
try {
// We might not have a 'Components' object.
aStack = Components.stack.caller;
} catch (e) {}
}
try {
aFunc();
} catch (e) {
do_check_eq(e.result, aResult, aStack);
return;
}
do_throw("Expected result " + aResult + ", none thrown.", aStack);
}
/**
* Print some debug message to the console. All arguments will be printed,
* separated by spaces.
*
* @param [arg0, arg1, arg2, ...]
* Any number of arguments to print out
* @usage _("Hello World") -> prints "Hello World"
* @usage _(1, 2, 3) -> prints "1 2 3"
*/
let _ = function(some, debug, text, to) print(Array.slice(arguments).join(" "));
function initTestLogging(level) {
function LogStats() {
this.errorsLogged = 0;
}
LogStats.prototype = {
format: function BF_format(message) {
if (message.level == Log4Moz.Level.Error)
this.errorsLogged += 1;
return message.loggerName + "\t" + message.levelDesc + "\t" +
message.message + "\n";
}
};
LogStats.prototype.__proto__ = new Log4Moz.Formatter();
var log = Log4Moz.repository.rootLogger;
var logStats = new LogStats();
var appender = new Log4Moz.DumpAppender(logStats);
if (typeof(level) == "undefined")
level = "Debug";
getTestLogger().level = Log4Moz.Level[level];
log.level = Log4Moz.Level.Trace;
appender.level = Log4Moz.Level.Trace;
// Overwrite any other appenders (e.g. from previous incarnations)
log.ownAppenders = [appender];
log.updateAppenders();
return logStats;
}
function getTestLogger(component) {
return Log4Moz.repository.getLogger("Testing");
}
function httpd_setup (handlers, port) {
let port = port || 8080;
let server = new nsHttpServer();
for (let path in handlers) {
server.registerPathHandler(path, handlers[path]);
}
try {
server.start(port);
} catch (ex) {
_("==========================================");
_("Got exception starting HTTP server on port " + port);
_("Error: " + Utils.exceptionStr(ex));
_("Is there a process already listening on port " + port + "?");
_("==========================================");
do_throw(ex);
}
return server;
}
function httpd_handler(statusCode, status, body) {
return function handler(request, response) {
_("Processing request");
// Allow test functions to inspect the request.
request.body = readBytesFromInputStream(request.bodyInputStream);
handler.request = request;
response.setStatusLine(request.httpVersion, statusCode, status);
if (body) {
response.bodyOutputStream.write(body, body.length);
}
};
}
/*
* Read bytes string from an nsIInputStream. If 'count' is omitted,
* all available input is read.
*/
function readBytesFromInputStream(inputStream, count) {
var BinaryInputStream = Components.Constructor(
"@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream");
if (!count) {
count = inputStream.available();
}
return new BinaryInputStream(inputStream).readBytes(count);
}
/**
* Proxy auth helpers.
*/
/**
* Fake a PAC to prompt a channel replacement.
*/
let PACSystemSettings = {
CID: Components.ID("{5645d2c1-d6d8-4091-b117-fe7ee4027db7}"),
contractID: "@mozilla.org/system-proxy-settings;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory,
Ci.nsISystemProxySettings]),
createInstance: function createInstance(outer, iid) {
if (outer) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(iid);
},
lockFactory: function lockFactory(lock) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
// Replace this URI for each test to avoid caching. We want to ensure that
// each test gets a completely fresh setup.
PACURI: null,
getProxyForURI: function getProxyForURI(aURI) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
}
};
function installFakePAC() {
_("Installing fake PAC.");
Cm.nsIComponentRegistrar
.registerFactory(PACSystemSettings.CID,
"Fake system proxy-settings",
PACSystemSettings.contractID,
PACSystemSettings);
}
function uninstallFakePAC() {
_("Uninstalling fake PAC.");
let CID = PACSystemSettings.CID;
Cm.nsIComponentRegistrar.unregisterFactory(CID, PACSystemSettings);
}

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

@ -1,4 +1,7 @@
Cu.import("resource://services-sync/async.js");
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-common/async.js");
function run_test() {
_("Chain a few async methods, making sure the 'this' object is correct.");

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

@ -1,12 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/utils.js");
_("Make sure querySpinningly will synchronously fetch rows for a query asyncly");
Cu.import("resource://services-sync/async.js");
const SQLITE_CONSTRAINT_VIOLATION = 19; // http://www.sqlite.org/c3ref/c_abort.html
let Svc = {};
XPCOMUtils.defineLazyServiceGetter(Svc, "Form",
"@mozilla.org/satchel/form-history;1",
"nsIFormHistory2");
function querySpinningly(query, names) {
let q = Svc.Form.DBConnection.createStatement(query);
let r = Async.querySpinningly(q, names);
q.finalize();
q.finalize();
return r;
}
@ -15,7 +26,7 @@ function run_test() {
_("Make sure the call is async and allows other events to process");
let isAsync = false;
Utils.nextTick(function() { isAsync = true; });
CommonUtils.nextTick(function() { isAsync = true; });
do_check_false(isAsync);
_("Empty out the formhistory table");

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

@ -0,0 +1,18 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const modules = [
"async.js",
"log4moz.js",
"preferences.js",
"rest.js",
"stringbundle.js",
"utils.js",
];
function run_test() {
for each (let m in modules) {
let resource = "resource://services-common/" + m;
Components.utils.import(resource, {});
}
}

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

@ -1,8 +1,10 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://services-sync/log4moz.js");
Components.utils.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://services-common/log4moz.js");
let testFormatter = {
format: function format(message) {

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

@ -1,8 +1,15 @@
Components.utils.import("resource://services-sync/ext/Observers.js");
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://services-common/observers.js");
let gSubject = {};
function test_function_observer() {
function run_test() {
run_next_test();
}
add_test(function test_function_observer() {
let foo = false;
let onFoo = function(subject, data) {
@ -22,9 +29,11 @@ function test_function_observer() {
// The observer was not notified after being removed.
do_check_true(foo);
}
function test_method_observer() {
run_next_test();
});
add_test(function test_method_observer() {
let obj = {
foo: false,
onFoo: function(subject, data) {
@ -43,9 +52,11 @@ function test_method_observer() {
Observers.remove("foo", obj.onFoo, obj);
Observers.notify("foo");
do_check_true(obj.foo);
}
function test_object_observer() {
run_next_test();
});
add_test(function test_object_observer() {
let obj = {
foo: false,
observe: function(subject, topic, data) {
@ -68,10 +79,6 @@ function test_object_observer() {
// The observer is not notified after being removed.
do_check_true(obj.foo);
}
function run_test() {
test_function_observer();
test_method_observer();
test_object_observer();
}
run_next_test();
});

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

@ -1,6 +1,13 @@
Components.utils.import("resource://services-sync/ext/Preferences.js");
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function test_set_get_pref() {
Cu.import("resource://services-common/preferences.js");
function run_test() {
run_next_test();
}
add_test(function test_set_get_pref() {
Preferences.set("test_set_get_pref.integer", 1);
do_check_eq(Preferences.get("test_set_get_pref.integer"), 1);
@ -12,9 +19,11 @@ function test_set_get_pref() {
// Clean up.
Preferences.resetBranch("test_set_get_pref.");
}
function test_set_get_branch_pref() {
run_next_test();
});
add_test(function test_set_get_branch_pref() {
let prefs = new Preferences("test_set_get_branch_pref.");
prefs.set("something", 1);
@ -23,9 +32,11 @@ function test_set_get_branch_pref() {
// Clean up.
prefs.reset("something");
}
function test_set_get_multiple_prefs() {
run_next_test();
});
add_test(function test_set_get_multiple_prefs() {
Preferences.set({ "test_set_get_multiple_prefs.integer": 1,
"test_set_get_multiple_prefs.string": "foo",
"test_set_get_multiple_prefs.boolean": true });
@ -40,9 +51,11 @@ function test_set_get_multiple_prefs() {
// Clean up.
Preferences.resetBranch("test_set_get_multiple_prefs.");
}
function test_get_multiple_prefs_with_default_value() {
run_next_test();
});
add_test(function test_get_multiple_prefs_with_default_value() {
Preferences.set({ "test_get_multiple_prefs_with_default_value.a": 1,
"test_get_multiple_prefs_with_default_value.b": 2 });
@ -57,47 +70,57 @@ function test_get_multiple_prefs_with_default_value() {
// Clean up.
Preferences.resetBranch("test_get_multiple_prefs_with_default_value.");
}
function test_set_get_unicode_pref() {
run_next_test();
});
add_test(function test_set_get_unicode_pref() {
Preferences.set("test_set_get_unicode_pref", String.fromCharCode(960));
do_check_eq(Preferences.get("test_set_get_unicode_pref"), String.fromCharCode(960));
// Clean up.
Preferences.reset("test_set_get_unicode_pref");
}
function test_set_null_pref() {
run_next_test();
});
add_test(function test_set_null_pref() {
try {
Preferences.set("test_set_null_pref", null);
// We expect this to throw, so the test is designed to fail if it doesn't.
do_check_true(false);
}
catch(ex) {}
}
function test_set_undefined_pref() {
run_next_test();
});
add_test(function test_set_undefined_pref() {
try {
Preferences.set("test_set_undefined_pref");
// We expect this to throw, so the test is designed to fail if it doesn't.
do_check_true(false);
}
catch(ex) {}
}
function test_set_unsupported_pref() {
run_next_test();
});
add_test(function test_set_unsupported_pref() {
try {
Preferences.set("test_set_unsupported_pref", new Array());
// We expect this to throw, so the test is designed to fail if it doesn't.
do_check_true(false);
}
catch(ex) {}
}
run_next_test();
});
// Make sure that we can get a string pref that we didn't set ourselves
// (i.e. that the way we get a string pref using getComplexValue doesn't
// hork us getting a string pref that wasn't set using setComplexValue).
function test_get_string_pref() {
add_test(function test_get_string_pref() {
let svc = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService).
getBranch("");
@ -106,9 +129,11 @@ function test_get_string_pref() {
// Clean up.
Preferences.reset("test_get_string_pref");
}
function test_set_get_number_pref() {
run_next_test();
});
add_test(function test_set_get_number_pref() {
Preferences.set("test_set_get_number_pref", 5);
do_check_eq(Preferences.get("test_set_get_number_pref"), 5);
@ -126,35 +151,45 @@ function test_set_get_number_pref() {
// Clean up.
Preferences.reset("test_set_get_number_pref");
}
function test_reset_pref() {
run_next_test();
});
add_test(function test_reset_pref() {
Preferences.set("test_reset_pref", 1);
Preferences.reset("test_reset_pref");
do_check_eq(Preferences.get("test_reset_pref"), undefined);
}
function test_reset_pref_branch() {
run_next_test();
});
add_test(function test_reset_pref_branch() {
Preferences.set("test_reset_pref_branch.foo", 1);
Preferences.set("test_reset_pref_branch.bar", 2);
Preferences.resetBranch("test_reset_pref_branch.");
do_check_eq(Preferences.get("test_reset_pref_branch.foo"), undefined);
do_check_eq(Preferences.get("test_reset_pref_branch.bar"), undefined);
}
run_next_test();
});
// Make sure the module doesn't throw an exception when asked to reset
// a nonexistent pref.
function test_reset_nonexistent_pref() {
add_test(function test_reset_nonexistent_pref() {
Preferences.reset("test_reset_nonexistent_pref");
}
run_next_test();
});
// Make sure the module doesn't throw an exception when asked to reset
// a nonexistent pref branch.
function test_reset_nonexistent_pref_branch() {
add_test(function test_reset_nonexistent_pref_branch() {
Preferences.resetBranch("test_reset_nonexistent_pref_branch.");
}
function test_observe_prefs_function() {
run_next_test();
});
add_test(function test_observe_prefs_function() {
let observed = false;
let observer = function() { observed = !observed };
@ -168,9 +203,11 @@ function test_observe_prefs_function() {
// Clean up.
Preferences.reset("test_observe_prefs_function");
}
function test_observe_prefs_object() {
run_next_test();
});
add_test(function test_observe_prefs_object() {
let observer = {
observed: false,
observe: function() {
@ -188,9 +225,11 @@ function test_observe_prefs_object() {
// Clean up.
Preferences.reset("test_observe_prefs_object");
}
function test_observe_prefs_nsIObserver() {
run_next_test();
});
add_test(function test_observe_prefs_nsIObserver() {
let observer = {
observed: false,
observe: function(subject, topic, data) {
@ -211,9 +250,12 @@ function test_observe_prefs_nsIObserver() {
// Clean up.
Preferences.reset("test_observe_prefs_nsIObserver");
}
function test_observe_exact_pref() {
run_next_test();
});
/*
add_test(function test_observe_exact_pref() {
let observed = false;
let observer = function() { observed = !observed };
@ -224,9 +266,12 @@ function test_observe_exact_pref() {
// Clean up.
Preferences.ignore("test_observe_exact_pref", observer);
Preferences.reset("test_observe_exact_pref.sub-pref");
}
function test_observe_value_of_set_pref() {
run_next_test();
});
*/
add_test(function test_observe_value_of_set_pref() {
let observer = function(newVal) { do_check_eq(newVal, "something") };
Preferences.observe("test_observe_value_of_set_pref", observer);
@ -235,9 +280,11 @@ function test_observe_value_of_set_pref() {
// Clean up.
Preferences.ignore("test_observe_value_of_set_pref", observer);
Preferences.reset("test_observe_value_of_set_pref");
}
function test_observe_value_of_reset_pref() {
run_next_test();
});
add_test(function test_observe_value_of_reset_pref() {
let observer = function(newVal) { do_check_true(typeof newVal == "undefined") };
Preferences.set("test_observe_value_of_reset_pref", "something");
@ -246,9 +293,11 @@ function test_observe_value_of_reset_pref() {
// Clean up.
Preferences.ignore("test_observe_value_of_reset_pref", observer);
}
function test_has_pref() {
run_next_test();
});
add_test(function test_has_pref() {
do_check_false(Preferences.has("test_has_pref"));
Preferences.set("test_has_pref", "foo");
do_check_true(Preferences.has("test_has_pref"));
@ -264,9 +313,11 @@ function test_has_pref() {
// Clean up.
Preferences.resetBranch("test_has_pref");
}
function test_isSet_pref() {
run_next_test();
});
add_test(function test_isSet_pref() {
// Use a pref that we know has a default value but no user-set value.
// This feels dangerous; perhaps we should create some other default prefs
// that we can use for testing.
@ -276,9 +327,12 @@ function test_isSet_pref() {
// Clean up.
Preferences.reset("toolkit.defaultChromeURI");
}
function test_lock_prefs() {
run_next_test();
});
/*
add_test(function test_lock_prefs() {
// Use a pref that we know has a default value.
// This feels dangerous; perhaps we should create some other default prefs
// that we can use for testing.
@ -298,9 +352,12 @@ function test_lock_prefs() {
// Clean up.
Preferences.reset("toolkit.defaultChromeURI");
}
function test_site_prefs() {
run_next_test();
});
*/
add_test(function test_site_prefs() {
let prefs = Preferences.site("www.example.com");
prefs.set("test_site_prefs.integer", 1);
@ -323,32 +380,6 @@ function test_site_prefs() {
do_check_false(Preferences.has("test_site_prefs.boolean"));
prefs.reset("test_site_prefs.boolean");
do_check_false(prefs.has("test_site_prefs.boolean"));
}
function run_test() {
test_set_get_pref();
test_set_get_branch_pref();
test_set_get_multiple_prefs();
test_get_multiple_prefs_with_default_value();
test_set_get_unicode_pref();
test_set_null_pref();
test_set_undefined_pref();
test_set_unsupported_pref();
test_get_string_pref();
test_set_get_number_pref();
test_reset_pref();
test_reset_pref_branch();
test_reset_nonexistent_pref();
test_reset_nonexistent_pref_branch();
test_observe_prefs_function();
test_observe_prefs_object();
test_observe_prefs_nsIObserver();
//test_observe_exact_pref();
test_observe_value_of_set_pref();
test_observe_value_of_reset_pref();
test_has_pref();
test_isSet_pref();
//test_lock_prefs();
test_site_prefs();
}
run_next_test();
});

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

@ -1,14 +1,18 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-sync/rest.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-common/utils.js");
const TEST_RESOURCE_URL = TEST_SERVER_URL + "resource";
//DEBUG = true;
function run_test() {
Log4Moz.repository.getLogger("Sync.RESTRequest").level = Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Services.Common.RESTRequest").level =
Log4Moz.Level.Trace;
initTestLogging();
run_next_test();
@ -140,7 +144,7 @@ add_test(function test_get() {
do_check_eq(handler.request.method, "GET");
do_check_true(onProgress_called);
Utils.nextTick(function () {
CommonUtils.nextTick(function () {
do_check_eq(request.onComplete, null);
do_check_eq(request.onProgress, null);
server.stop(run_next_test);
@ -189,7 +193,7 @@ add_test(function test_put() {
do_check_eq(handler.request.getHeader("Content-Type"), "text/plain");
do_check_true(onProgress_called);
Utils.nextTick(function () {
CommonUtils.nextTick(function () {
do_check_eq(request.onComplete, null);
do_check_eq(request.onProgress, null);
server.stop(run_next_test);
@ -238,7 +242,7 @@ add_test(function test_post() {
do_check_eq(handler.request.getHeader("Content-Type"), "text/plain");
do_check_true(onProgress_called);
Utils.nextTick(function () {
CommonUtils.nextTick(function () {
do_check_eq(request.onComplete, null);
do_check_eq(request.onProgress, null);
server.stop(run_next_test);
@ -284,7 +288,7 @@ add_test(function test_delete() {
do_check_eq(handler.request.method, "DELETE");
do_check_true(onProgress_called);
Utils.nextTick(function () {
CommonUtils.nextTick(function () {
do_check_eq(request.onComplete, null);
do_check_eq(request.onProgress, null);
server.stop(run_next_test);
@ -467,7 +471,7 @@ add_test(function test_changing_uri() {
let server = httpd_setup({"/resource": handler});
let request = new RESTRequest("http://localhost:8080/the-wrong-resource");
request.uri = Utils.makeURI(TEST_RESOURCE_URL);
request.uri = CommonUtils.makeURI(TEST_RESOURCE_URL);
request.get(function (error) {
do_check_eq(error, null);
do_check_eq(this.response.status, 200);
@ -572,7 +576,7 @@ add_test(function test_abort() {
});
do_check_eq(request.status, request.ABORTED);
Utils.nextTick(function () {
CommonUtils.nextTick(function () {
server.stop(run_next_test);
});
});

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

@ -0,0 +1,66 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
_("Make sure uri strings are converted to nsIURIs");
Cu.import("resource://services-common/utils.js");
function run_test() {
_test_makeURI();
}
function _test_makeURI() {
_("Check http uris");
let uri1 = "http://mozillalabs.com/";
do_check_eq(CommonUtils.makeURI(uri1).spec, uri1);
let uri2 = "http://www.mozillalabs.com/";
do_check_eq(CommonUtils.makeURI(uri2).spec, uri2);
let uri3 = "http://mozillalabs.com/path";
do_check_eq(CommonUtils.makeURI(uri3).spec, uri3);
let uri4 = "http://mozillalabs.com/multi/path";
do_check_eq(CommonUtils.makeURI(uri4).spec, uri4);
let uri5 = "http://mozillalabs.com/?query";
do_check_eq(CommonUtils.makeURI(uri5).spec, uri5);
let uri6 = "http://mozillalabs.com/#hash";
do_check_eq(CommonUtils.makeURI(uri6).spec, uri6);
_("Check https uris");
let uris1 = "https://mozillalabs.com/";
do_check_eq(CommonUtils.makeURI(uris1).spec, uris1);
let uris2 = "https://www.mozillalabs.com/";
do_check_eq(CommonUtils.makeURI(uris2).spec, uris2);
let uris3 = "https://mozillalabs.com/path";
do_check_eq(CommonUtils.makeURI(uris3).spec, uris3);
let uris4 = "https://mozillalabs.com/multi/path";
do_check_eq(CommonUtils.makeURI(uris4).spec, uris4);
let uris5 = "https://mozillalabs.com/?query";
do_check_eq(CommonUtils.makeURI(uris5).spec, uris5);
let uris6 = "https://mozillalabs.com/#hash";
do_check_eq(CommonUtils.makeURI(uris6).spec, uris6);
_("Check chrome uris");
let uric1 = "chrome://browser/content/browser.xul";
do_check_eq(CommonUtils.makeURI(uric1).spec, uric1);
let uric2 = "chrome://browser/skin/browser.css";
do_check_eq(CommonUtils.makeURI(uric2).spec, uric2);
let uric3 = "chrome://browser/locale/browser.dtd";
do_check_eq(CommonUtils.makeURI(uric3).spec, uric3);
_("Check about uris");
let uria1 = "about:weave";
do_check_eq(CommonUtils.makeURI(uria1).spec, uria1);
let uria2 = "about:weave/";
do_check_eq(CommonUtils.makeURI(uria2).spec, uria2);
let uria3 = "about:weave/path";
do_check_eq(CommonUtils.makeURI(uria3).spec, uria3);
let uria4 = "about:weave/multi/path";
do_check_eq(CommonUtils.makeURI(uria4).spec, uria4);
let uria5 = "about:weave/?query";
do_check_eq(CommonUtils.makeURI(uria5).spec, uria5);
let uria6 = "about:weave/#hash";
do_check_eq(CommonUtils.makeURI(uria6).spec, uria6);
_("Invalid uris are undefined");
do_check_eq(CommonUtils.makeURI("mozillalabs.com"), undefined);
do_check_eq(CommonUtils.makeURI("chrome://badstuff"), undefined);
do_check_eq(CommonUtils.makeURI("this is a test"), undefined);
}

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

@ -1,7 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-common/utils.js");
function run_test() {
run_next_test();
@ -9,7 +9,7 @@ function run_test() {
add_test(function test_required_args() {
try {
Utils.namedTimer(function callback() {
CommonUtils.namedTimer(function callback() {
do_throw("Shouldn't fire.");
}, 0);
do_throw("Should have thrown!");
@ -19,12 +19,12 @@ add_test(function test_required_args() {
});
add_test(function test_simple() {
_("Test basic properties of Utils.namedTimer.");
_("Test basic properties of CommonUtils.namedTimer.");
const delay = 200;
let that = {};
let t0 = Date.now();
Utils.namedTimer(function callback(timer) {
CommonUtils.namedTimer(function callback(timer) {
do_check_eq(this, that);
do_check_eq(this._zetimer, null);
do_check_true(timer instanceof Ci.nsITimer);
@ -37,7 +37,7 @@ add_test(function test_simple() {
add_test(function test_delay() {
_("Test delaying a timer that hasn't fired yet.");
const delay = 100;
let that = {};
let t0 = Date.now();
@ -47,8 +47,8 @@ add_test(function test_delay() {
do_check_true((Date.now() - t0) > delay);
run_next_test();
}
Utils.namedTimer(callback, delay, that, "_zetimer");
Utils.namedTimer(callback, 2 * delay, that, "_zetimer");
CommonUtils.namedTimer(callback, delay, that, "_zetimer");
CommonUtils.namedTimer(callback, 2 * delay, that, "_zetimer");
run_next_test();
});
@ -57,13 +57,13 @@ add_test(function test_clear() {
const delay = 0;
let that = {};
Utils.namedTimer(function callback(timer) {
CommonUtils.namedTimer(function callback(timer) {
do_throw("Shouldn't fire!");
}, delay, that, "_zetimer");
that._zetimer.clear();
do_check_eq(that._zetimer, null);
Utils.nextTick(run_next_test);
CommonUtils.nextTick(run_next_test);
run_next_test();
});

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

@ -1,10 +1,13 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
_("Define some functions in well defined line positions for the test");
function foo(v) bar(v + 1); // line 2
function bar(v) baz(v + 1); // line 3
function baz(v) { throw new Error(v + 1); } // line 4
_("Make sure lazy constructor calling/assignment works");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-common/utils.js");
function run_test() {
_("Make sure functions, arguments, files are pretty printed in the trace");
@ -13,14 +16,14 @@ function run_test() {
foo(0);
}
catch(ex) {
trace = Utils.stackTrace(ex);
trace = CommonUtils.stackTrace(ex);
}
_("Got trace:", trace);
do_check_neq(trace, "");
let bazPos = trace.indexOf("baz(2)@test_utils_stackTrace.js:4");
let barPos = trace.indexOf("bar(1)@test_utils_stackTrace.js:3");
let fooPos = trace.indexOf("foo(0)@test_utils_stackTrace.js:2");
let bazPos = trace.indexOf("baz(2)@test_utils_stackTrace.js:7");
let barPos = trace.indexOf("bar(1)@test_utils_stackTrace.js:6");
let fooPos = trace.indexOf("foo(0)@test_utils_stackTrace.js:5");
_("String positions:", bazPos, barPos, fooPos);
_("Make sure the desired messages show up");

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

@ -0,0 +1,17 @@
[DEFAULT]
head = head_global.js head_helpers.js
tail =
# Test load modules first so syntax failures are caught early.
[test_load_modules.js]
[test_utils_makeURI.js]
[test_utils_namedTimer.js]
[test_utils_stackTrace.js]
[test_async_chain.js]
[test_async_querySpinningly.js]
[test_log4moz.js]
[test_observers.js]
[test_preferences.js]
[test_restrequest.js]

125
services/common/utils.js Normal file
Просмотреть файл

@ -0,0 +1,125 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const EXPORTED_SYMBOLS = ["CommonUtils"];
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://services-common/log4moz.js");
let CommonUtils = {
exceptionStr: function exceptionStr(e) {
let message = e.message ? e.message : e;
return message + " " + CommonUtils.stackTrace(e);
},
stackTrace: function stackTrace(e) {
// Wrapped nsIException
if (e.location) {
let frame = e.location;
let output = [];
while (frame) {
// Works on frames or exceptions, munges file:// URIs to shorten the paths
// FIXME: filename munging is sort of hackish, might be confusing if
// there are multiple extensions with similar filenames
let str = "<file:unknown>";
let file = frame.filename || frame.fileName;
if (file){
str = file.replace(/^(?:chrome|file):.*?([^\/\.]+\.\w+)$/, "$1");
}
if (frame.lineNumber){
str += ":" + frame.lineNumber;
}
if (frame.name){
str = frame.name + "()@" + str;
}
if (str){
output.push(str);
}
frame = frame.caller;
}
return "Stack trace: " + output.join(" < ");
}
// Standard JS exception
if (e.stack){
return "JS Stack trace: " + e.stack.trim().replace(/\n/g, " < ").
replace(/@[^@]*?([^\/\.]+\.\w+:)/g, "@$1");
}
return "No traceback available";
},
/**
* Create a nsIURI instance from a string.
*/
makeURI: function makeURI(URIString) {
if (!URIString)
return null;
try {
return Services.io.newURI(URIString, null, null);
} catch (e) {
let log = Log4Moz.repository.getLogger("Common.Utils");
log.debug("Could not create URI: " + CommonUtils.exceptionStr(e));
return null;
}
},
/**
* Execute a function on the next event loop tick.
*
* @param callback
* Function to invoke.
* @param thisObj [optional]
* Object to bind the callback to.
*/
nextTick: function nextTick(callback, thisObj) {
if (thisObj) {
callback = callback.bind(thisObj);
}
Services.tm.currentThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
},
/**
* Return a timer that is scheduled to call the callback after waiting the
* provided time or as soon as possible. The timer will be set as a property
* of the provided object with the given timer name.
*/
namedTimer: function namedTimer(callback, wait, thisObj, name) {
if (!thisObj || !name) {
throw "You must provide both an object and a property name for the timer!";
}
// Delay an existing timer if it exists
if (name in thisObj && thisObj[name] instanceof Ci.nsITimer) {
thisObj[name].delay = wait;
return;
}
// Create a special timer that we can add extra properties
let timer = {};
timer.__proto__ = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
// Provide an easy way to clear out the timer
timer.clear = function() {
thisObj[name] = null;
timer.cancel();
};
// Initialize the timer with a smart callback
timer.initWithCallback({
notify: function notify() {
// Clear out the timer once it's been triggered
timer.clear();
callback.call(thisObj, timer);
}
}, wait, timer.TYPE_ONE_SHOT);
return thisObj[name] = timer;
},
};

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

@ -35,24 +35,18 @@
#
# ***** END LICENSE BLOCK *****
MAKEFILES_crypto="
add_makefiles "
services/Makefile
services/common/Makefile
services/crypto/Makefile
services/crypto/component/Makefile
"
MAKEFILES_sync="
services/sync/Makefile
services/sync/locales/Makefile
"
add_makefiles "
services/Makefile
$MAKEFILES_crypto
$MAKEFILES_sync
"
if [ "$ENABLE_TESTS" ]; then
add_makefiles "
services/common/tests/Makefile
services/crypto/tests/Makefile
services/sync/tests/Makefile
"

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

@ -6,4 +6,5 @@ component {d28f8a0b-95da-48f4-b712-caf37097be41} Weave.js
contract @mozilla.org/network/protocol/about;1?what=sync-log {d28f8a0b-95da-48f4-b712-caf37097be41}
# Register resource aliases
resource services-sync resource:///modules/services-sync/
resource services-common resource:///modules/services-common/
resource services-crypto resource:///modules/services-crypto/

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

@ -52,7 +52,7 @@
const Cu = Components.utils;
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://gre/modules/AddonManager.jsm");

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

@ -46,12 +46,12 @@ const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/ext/Observers.js");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/util.js");

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

@ -72,8 +72,8 @@ Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://gre/modules/AddonManager.jsm");
Cu.import("resource://gre/modules/AddonRepository.jsm");

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

@ -51,7 +51,7 @@ Cu.import("resource://gre/modules/PlacesUtils.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");

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

@ -42,9 +42,9 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://services-common/stringbundle.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/ext/StringBundle.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/util.js");

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

@ -43,10 +43,10 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
const FORMS_TTL = 5184000; // 60 days

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

@ -51,9 +51,9 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
function HistoryRec(collection, id) {
CryptoWrapper.call(this, collection, id);

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

@ -47,7 +47,7 @@ Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
const PREFS_GUID = Utils.encodeBase64url(Services.appinfo.ID);

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

@ -51,7 +51,7 @@ Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/preferences.js");
// It is safer to inspect the private browsing preferences rather than
// the flags of nsIPrivateBrowsingService. The user may have turned on

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

@ -10,7 +10,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/keys.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/util.js");
XPCOMUtils.defineLazyGetter(this, "Identity", function() {

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

@ -40,8 +40,8 @@ const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-sync/rest.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/util.js");

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

@ -12,7 +12,7 @@ const EXPORTED_SYMBOLS = [
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/util.js");
/**

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

@ -41,8 +41,8 @@ const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://services-sync/ext/Observers.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/util.js");
let Notifications = {

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

@ -45,7 +45,7 @@ const EXPORTED_SYMBOLS = ["SyncScheduler",
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/engines/clients.js");

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

@ -51,7 +51,7 @@ const KEYS_WBO = "keys";
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/keys.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/util.js");

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

@ -47,12 +47,12 @@ const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/ext/Observers.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/util.js");
/*

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

@ -40,581 +40,16 @@
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/constants.js");
const EXPORTED_SYMBOLS = ["RESTRequest", "SyncStorageRequest"];
const EXPORTED_SYMBOLS = ["SyncStorageRequest"];
const STORAGE_REQUEST_TIMEOUT = 5 * 60; // 5 minutes
/**
* Single use HTTP requests to RESTish resources.
*
* @param uri
* URI for the request. This can be an nsIURI object or a string
* that can be used to create one. An exception will be thrown if
* the string is not a valid URI.
*
* Examples:
*
* (1) Quick GET request:
*
* new RESTRequest("http://server/rest/resource").get(function (error) {
* if (error) {
* // Deal with a network error.
* processNetworkErrorCode(error.result);
* return;
* }
* if (!this.response.success) {
* * // Bail out if we're not getting an HTTP 2xx code.
* processHTTPError(this.response.status);
* return;
* }
* processData(this.response.body);
* });
*
* (2) Quick PUT request (non-string data is automatically JSONified)
*
* new RESTRequest("http://server/rest/resource").put(data, function (error) {
* ...
* });
*
* (3) Streaming GET
*
* let request = new RESTRequest("http://server/rest/resource");
* request.setHeader("Accept", "application/newlines");
* request.onComplete = function (error) {
* if (error) {
* // Deal with a network error.
* processNetworkErrorCode(error.result);
* return;
* }
* callbackAfterRequestHasCompleted()
* });
* request.onProgress = function () {
* if (!this.response.success) {
* // Bail out if we're not getting an HTTP 2xx code.
* return;
* }
* // Process body data and reset it so we don't process the same data twice.
* processIncrementalData(this.response.body);
* this.response.body = "";
* });
* request.get();
*/
function RESTRequest(uri) {
this.status = this.NOT_SENT;
// If we don't have an nsIURI object yet, make one. This will throw if
// 'uri' isn't a valid URI string.
if (!(uri instanceof Ci.nsIURI)) {
uri = Services.io.newURI(uri, null, null);
}
this.uri = uri;
this._headers = {};
this._log = Log4Moz.repository.getLogger(this._logName);
this._log.level =
Log4Moz.Level[Svc.Prefs.get("log.logger.network.resources")];
}
RESTRequest.prototype = {
_logName: "Sync.RESTRequest",
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIBadCertListener2,
Ci.nsIInterfaceRequestor,
Ci.nsIChannelEventSink
]),
/*** Public API: ***/
/**
* URI for the request (an nsIURI object).
*/
uri: null,
/**
* HTTP method (e.g. "GET")
*/
method: null,
/**
* RESTResponse object
*/
response: null,
/**
* nsIRequest load flags. Don't do any caching by default.
*/
loadFlags: Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING,
/**
* nsIHttpChannel
*/
channel: null,
/**
* Flag to indicate the status of the request.
*
* One of NOT_SENT, SENT, IN_PROGRESS, COMPLETED, ABORTED.
*/
status: null,
NOT_SENT: 0,
SENT: 1,
IN_PROGRESS: 2,
COMPLETED: 4,
ABORTED: 8,
/**
* Request timeout (in seconds, though decimal values can be used for
* up to millisecond granularity.)
*
* 0 for no timeout.
*/
timeout: null,
/**
* Called when the request has been completed, including failures and
* timeouts.
*
* @param error
* Error that occurred while making the request, null if there
* was no error.
*/
onComplete: function onComplete(error) {
},
/**
* Called whenever data is being received on the channel. If this throws an
* exception, the request is aborted and the exception is passed as the
* error to onComplete().
*/
onProgress: function onProgress() {
},
/**
* Set a request header.
*/
setHeader: function setHeader(name, value) {
this._headers[name.toLowerCase()] = value;
},
/**
* Perform an HTTP GET.
*
* @param onComplete
* Short-circuit way to set the 'onComplete' method. Optional.
* @param onProgress
* Short-circuit way to set the 'onProgress' method. Optional.
*
* @return the request object.
*/
get: function get(onComplete, onProgress) {
return this.dispatch("GET", null, onComplete, onProgress);
},
/**
* Perform an HTTP PUT.
*
* @param data
* Data to be used as the request body. If this isn't a string
* it will be JSONified automatically.
* @param onComplete
* Short-circuit way to set the 'onComplete' method. Optional.
* @param onProgress
* Short-circuit way to set the 'onProgress' method. Optional.
*
* @return the request object.
*/
put: function put(data, onComplete, onProgress) {
return this.dispatch("PUT", data, onComplete, onProgress);
},
/**
* Perform an HTTP POST.
*
* @param data
* Data to be used as the request body. If this isn't a string
* it will be JSONified automatically.
* @param onComplete
* Short-circuit way to set the 'onComplete' method. Optional.
* @param onProgress
* Short-circuit way to set the 'onProgress' method. Optional.
*
* @return the request object.
*/
post: function post(data, onComplete, onProgress) {
return this.dispatch("POST", data, onComplete, onProgress);
},
/**
* Perform an HTTP DELETE.
*
* @param onComplete
* Short-circuit way to set the 'onComplete' method. Optional.
* @param onProgress
* Short-circuit way to set the 'onProgress' method. Optional.
*
* @return the request object.
*/
delete: function delete_(onComplete, onProgress) {
return this.dispatch("DELETE", null, onComplete, onProgress);
},
/**
* Abort an active request.
*/
abort: function abort() {
if (this.status != this.SENT && this.status != this.IN_PROGRESS) {
throw "Can only abort a request that has been sent.";
}
this.status = this.ABORTED;
this.channel.cancel(Cr.NS_BINDING_ABORTED);
if (this.timeoutTimer) {
// Clear the abort timer now that the channel is done.
this.timeoutTimer.clear();
}
},
/*** Implementation stuff ***/
dispatch: function dispatch(method, data, onComplete, onProgress) {
if (this.status != this.NOT_SENT) {
throw "Request has already been sent!";
}
this.method = method;
if (onComplete) {
this.onComplete = onComplete;
}
if (onProgress) {
this.onProgress = onProgress;
}
// Create and initialize HTTP channel.
let channel = Services.io.newChannelFromURI(this.uri, null, null)
.QueryInterface(Ci.nsIRequest)
.QueryInterface(Ci.nsIHttpChannel);
this.channel = channel;
channel.loadFlags |= this.loadFlags;
channel.notificationCallbacks = this;
// Set request headers.
let headers = this._headers;
for (let key in headers) {
if (key == 'authorization') {
this._log.trace("HTTP Header " + key + ": ***** (suppressed)");
} else {
this._log.trace("HTTP Header " + key + ": " + headers[key]);
}
channel.setRequestHeader(key, headers[key], false);
}
// Set HTTP request body.
if (method == "PUT" || method == "POST") {
// Convert non-string bodies into JSON.
if (typeof data != "string") {
data = JSON.stringify(data);
}
this._log.debug(method + " Length: " + data.length);
if (this._log.level <= Log4Moz.Level.Trace) {
this._log.trace(method + " Body: " + data);
}
let stream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
stream.setData(data, data.length);
let type = headers["content-type"] || "text/plain";
channel.QueryInterface(Ci.nsIUploadChannel);
channel.setUploadStream(stream, type, data.length);
}
// We must set this after setting the upload stream, otherwise it
// will always be 'PUT'. Yeah, I know.
channel.requestMethod = method;
// Blast off!
channel.asyncOpen(this, null);
this.status = this.SENT;
this.delayTimeout();
return this;
},
/**
* Create or push back the abort timer that kills this request.
*/
delayTimeout: function delayTimeout() {
if (this.timeout) {
Utils.namedTimer(this.abortTimeout, this.timeout * 1000, this,
"timeoutTimer");
}
},
/**
* Abort the request based on a timeout.
*/
abortTimeout: function abortTimeout() {
this.abort();
let error = Components.Exception("Aborting due to channel inactivity.",
Cr.NS_ERROR_NET_TIMEOUT);
if (!this.onComplete) {
this._log.error("Unexpected error: onComplete not defined in " +
"abortTimeout.")
return;
}
this.onComplete(error);
},
/*** nsIStreamListener ***/
onStartRequest: function onStartRequest(channel) {
if (this.status == this.ABORTED) {
this._log.trace("Not proceeding with onStartRequest, request was aborted.");
return;
}
try {
channel.QueryInterface(Ci.nsIHttpChannel);
} catch (ex) {
this._log.error("Unexpected error: channel is not a nsIHttpChannel!");
this.status = this.ABORTED;
channel.cancel(Cr.NS_BINDING_ABORTED);
return;
}
this.status = this.IN_PROGRESS;
this._log.trace("onStartRequest: " + channel.requestMethod + " " +
channel.URI.spec);
// Create a response object and fill it with some data.
let response = this.response = new RESTResponse();
response.request = this;
response.body = "";
// Define this here so that we don't have make a new one each time
// onDataAvailable() gets called.
this._inputStream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
this.delayTimeout();
},
onStopRequest: function onStopRequest(channel, context, statusCode) {
if (this.timeoutTimer) {
// Clear the abort timer now that the channel is done.
this.timeoutTimer.clear();
}
// We don't want to do anything for a request that's already been aborted.
if (this.status == this.ABORTED) {
this._log.trace("Not proceeding with onStopRequest, request was aborted.");
return;
}
try {
channel.QueryInterface(Ci.nsIHttpChannel);
} catch (ex) {
this._log.error("Unexpected error: channel not nsIHttpChannel!");
this.status = this.ABORTED;
return;
}
this.status = this.COMPLETED;
let statusSuccess = Components.isSuccessCode(statusCode);
let uri = channel && channel.URI && channel.URI.spec || "<unknown>";
this._log.trace("Channel for " + channel.requestMethod + " " + uri +
" returned status code " + statusCode);
if (!this.onComplete) {
this._log.error("Unexpected error: onComplete not defined in " +
"abortRequest.");
this.onProgress = null;
return;
}
// Throw the failure code and stop execution. Use Components.Exception()
// instead of Error() so the exception is QI-able and can be passed across
// XPCOM borders while preserving the status code.
if (!statusSuccess) {
let message = Components.Exception("", statusCode).name;
let error = Components.Exception(message, statusCode);
this.onComplete(error);
this.onComplete = this.onProgress = null;
return;
}
this._log.debug(this.method + " " + uri + " " + this.response.status);
// Additionally give the full response body when Trace logging.
if (this._log.level <= Log4Moz.Level.Trace) {
this._log.trace(this.method + " body: " + this.response.body);
}
delete this._inputStream;
this.onComplete(null);
this.onComplete = this.onProgress = null;
},
onDataAvailable: function onDataAvailable(req, cb, stream, off, count) {
this._inputStream.init(stream);
try {
this.response.body += this._inputStream.read(count);
} catch (ex) {
this._log.warn("Exception thrown reading " + count +
" bytes from the channel.");
this._log.debug(Utils.exceptionStr(ex));
throw ex;
}
try {
this.onProgress();
} catch (ex) {
this._log.warn("Got exception calling onProgress handler, aborting " +
this.method + " " + req.URI.spec);
this._log.debug("Exception: " + Utils.exceptionStr(ex));
this.abort();
if (!this.onComplete) {
this._log.error("Unexpected error: onComplete not defined in " +
"onDataAvailable.");
this.onProgress = null;
return;
}
this.onComplete(ex);
this.onComplete = this.onProgress = null;
return;
}
this.delayTimeout();
},
/*** nsIInterfaceRequestor ***/
getInterface: function(aIID) {
return this.QueryInterface(aIID);
},
/*** nsIBadCertListener2 ***/
notifyCertProblem: function notifyCertProblem(socketInfo, sslStatus, targetHost) {
this._log.warn("Invalid HTTPS certificate encountered!");
// Suppress invalid HTTPS certificate warnings in the UI.
// (The request will still fail.)
return true;
},
/*** nsIChannelEventSink ***/
asyncOnChannelRedirect:
function asyncOnChannelRedirect(oldChannel, newChannel, flags, callback) {
try {
newChannel.QueryInterface(Ci.nsIHttpChannel);
} catch (ex) {
this._log.error("Unexpected error: channel not nsIHttpChannel!");
callback.onRedirectVerifyCallback(Cr.NS_ERROR_NO_INTERFACE);
return;
}
this.channel = newChannel;
// We let all redirects proceed.
callback.onRedirectVerifyCallback(Cr.NS_OK);
}
};
/**
* Response object for a RESTRequest. This will be created automatically by
* the RESTRequest.
*/
function RESTResponse() {
this._log = Log4Moz.repository.getLogger(this._logName);
this._log.level =
Log4Moz.Level[Svc.Prefs.get("log.logger.network.resources")];
}
RESTResponse.prototype = {
_logName: "Sync.RESTResponse",
/**
* Corresponding REST request
*/
request: null,
/**
* HTTP status code
*/
get status() {
let status;
try {
let channel = this.request.channel.QueryInterface(Ci.nsIHttpChannel);
status = channel.responseStatus;
} catch (ex) {
this._log.debug("Caught exception fetching HTTP status code:" +
Utils.exceptionStr(ex));
return null;
}
delete this.status;
return this.status = status;
},
/**
* Boolean flag that indicates whether the HTTP status code is 2xx or not.
*/
get success() {
let success;
try {
let channel = this.request.channel.QueryInterface(Ci.nsIHttpChannel);
success = channel.requestSucceeded;
} catch (ex) {
this._log.debug("Caught exception fetching HTTP success flag:" +
Utils.exceptionStr(ex));
return null;
}
delete this.success;
return this.success = success;
},
/**
* Object containing HTTP headers (keyed as lower case)
*/
get headers() {
let headers = {};
try {
this._log.trace("Processing response headers.");
let channel = this.request.channel.QueryInterface(Ci.nsIHttpChannel);
channel.visitResponseHeaders(function (header, value) {
headers[header.toLowerCase()] = value;
});
} catch (ex) {
this._log.debug("Caught exception processing response headers:" +
Utils.exceptionStr(ex));
return null;
}
delete this.headers;
return this.headers = headers;
},
/**
* HTTP body (string)
*/
body: null
};
/**
* RESTRequest variant for use against a Sync storage server.
*/

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

@ -63,9 +63,9 @@ Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/engines/clients.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/rest.js");
Cu.import("resource://services-sync/status.js");

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

@ -41,7 +41,7 @@ const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://gre/modules/Services.jsm");

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

@ -38,17 +38,15 @@
const EXPORTED_SYMBOLS = ["XPCOMUtils", "Services", "NetUtil", "PlacesUtils",
"FileUtils", "Utils", "Async", "Svc", "Str"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://services-common/stringbundle.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/ext/Observers.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-sync/ext/StringBundle.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/PlacesUtils.jsm");
@ -60,6 +58,14 @@ Cu.import("resource://gre/modules/FileUtils.jsm");
*/
let Utils = {
// Alias in functions from CommonUtils. These previously were defined here.
// In the ideal world, references to these would be removed.
nextTick: CommonUtils.nextTick,
namedTimer: CommonUtils.namedTimer,
exceptionStr: CommonUtils.exceptionStr,
stackTrace: CommonUtils.stackTrace,
makeURI: CommonUtils.makeURI,
/**
* Wrap a function to catch all exceptions and log them
*
@ -269,62 +275,18 @@ let Utils = {
return true;
},
exceptionStr: function Weave_exceptionStr(e) {
let message = e.message ? e.message : e;
return message + " " + Utils.stackTrace(e);
},
stackTrace: function Weave_stackTrace(e) {
// Wrapped nsIException
if (e.location){
let frame = e.location;
let output = [];
while (frame) {
// Works on frames or exceptions, munges file:// URIs to shorten the paths
// FIXME: filename munging is sort of hackish, might be confusing if
// there are multiple extensions with similar filenames
let str = "<file:unknown>";
let file = frame.filename || frame.fileName;
if (file){
str = file.replace(/^(?:chrome|file):.*?([^\/\.]+\.\w+)$/, "$1");
}
if (frame.lineNumber){
str += ":" + frame.lineNumber;
}
if (frame.name){
str = frame.name + "()@" + str;
}
if (str){
output.push(str);
}
frame = frame.caller;
}
return "Stack trace: " + output.join(" < ");
}
// Standard JS exception
if (e.stack){
return "JS Stack trace: " + e.stack.trim().replace(/\n/g, " < ").
replace(/@[^@]*?([^\/\.]+\.\w+:)/g, "@$1");
}
return "No traceback available";
},
// Generator and discriminator for HMAC exceptions.
// Split these out in case we want to make them richer in future, and to
// Split these out in case we want to make them richer in future, and to
// avoid inevitable confusion if the message changes.
throwHMACMismatch: function throwHMACMismatch(shouldBe, is) {
throw "Record SHA256 HMAC mismatch: should be " + shouldBe + ", is " + is;
},
isHMACMismatch: function isHMACMismatch(ex) {
const hmacFail = "Record SHA256 HMAC mismatch: ";
return ex && ex.indexOf && (ex.indexOf(hmacFail) == 0);
},
/**
* UTF8-encode a message and hash it with the given hasher. Returns a
* string containing bytes. The hasher is reset if it's an HMAC hasher.
@ -832,18 +794,6 @@ let Utils = {
return header += ', ext="' + ext +'"';
},
makeURI: function Weave_makeURI(URIString) {
if (!URIString)
return null;
try {
return Services.io.newURI(URIString, null, null);
} catch (e) {
let log = Log4Moz.repository.getLogger("Sync.Utils");
log.debug("Could not create URI: " + Utils.exceptionStr(e));
return null;
}
},
/**
* Load a json object from disk
*
@ -917,59 +867,6 @@ let Utils = {
});
},
/**
* Execute a function on the next event loop tick.
*
* @param callback
* Function to invoke.
* @param thisObj [optional]
* Object to bind the callback to.
*/
nextTick: function nextTick(callback, thisObj) {
if (thisObj) {
callback = callback.bind(thisObj);
}
Services.tm.currentThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
},
/**
* Return a timer that is scheduled to call the callback after waiting the
* provided time or as soon as possible. The timer will be set as a property
* of the provided object with the given timer name.
*/
namedTimer: function delay(callback, wait, thisObj, name) {
if (!thisObj || !name) {
throw "You must provide both an object and a property name for the timer!";
}
// Delay an existing timer if it exists
if (name in thisObj && thisObj[name] instanceof Ci.nsITimer) {
thisObj[name].delay = wait;
return;
}
// Create a special timer that we can add extra properties
let timer = {};
timer.__proto__ = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
// Provide an easy way to clear out the timer
timer.clear = function() {
thisObj[name] = null;
timer.cancel();
};
// Initialize the timer with a smart callback
timer.initWithCallback({
notify: function notify() {
// Clear out the timer once it's been triggered
timer.clear();
callback.call(thisObj, timer);
}
}, wait, timer.TYPE_ONE_SHOT);
return thisObj[name] = timer;
},
getIcon: function(iconUri, defaultIcon) {
try {
let iconURI = Utils.makeURI(iconUri);

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

@ -49,10 +49,10 @@ function addResourceAlias() {
Cu.import("resource://gre/modules/Services.jsm");
const resProt = Services.io.getProtocolHandler("resource")
.QueryInterface(Ci.nsIResProtocolHandler);
let uri;
uri = Services.io.newURI("resource:///modules/services-sync/", null, null);
resProt.setSubstitution("services-sync", uri);
uri = Services.io.newURI("resource:///modules/services-crypto/", null, null);
resProt.setSubstitution("services-crypto", uri);
for each (let s in ["common", "sync", "crypto"]) {
let uri = Services.io.newURI("resource:///modules/services-" + s + "/", null,
null);
resProt.setSubstitution("services-" + s, uri);
}
}
addResourceAlias();

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

@ -1,7 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/record.js");
@ -40,42 +41,8 @@ function waitForZeroTimer(callback) {
timer = Utils.namedTimer(wait, 150, {}, "timer");
}
btoa = Cu.import("resource://services-sync/log4moz.js").btoa;
atob = Cu.import("resource://services-sync/log4moz.js").atob;
function getTestLogger(component) {
return Log4Moz.repository.getLogger("Testing");
}
function initTestLogging(level) {
function LogStats() {
this.errorsLogged = 0;
}
LogStats.prototype = {
format: function BF_format(message) {
if (message.level == Log4Moz.Level.Error)
this.errorsLogged += 1;
return message.loggerName + "\t" + message.levelDesc + "\t" +
message.message + "\n";
}
};
LogStats.prototype.__proto__ = new Log4Moz.Formatter();
var log = Log4Moz.repository.rootLogger;
var logStats = new LogStats();
var appender = new Log4Moz.DumpAppender(logStats);
if (typeof(level) == "undefined")
level = "Debug";
getTestLogger().level = Log4Moz.Level[level];
log.level = Log4Moz.Level.Trace;
appender.level = Log4Moz.Level.Trace;
// Overwrite any other appenders (e.g. from previous incarnations)
log.ownAppenders = [appender];
log.updateAppenders();
return logStats;
}
btoa = Cu.import("resource://services-common/log4moz.js").btoa;
atob = Cu.import("resource://services-common/log4moz.js").atob;
// This is needed for loadAddonTestFunctions().
let gGlobalScope = this;
@ -298,21 +265,9 @@ function ensureThrows(func) {
}
/**
* Print some debug message to the console. All arguments will be printed,
* separated by spaces.
*
* @param [arg0, arg1, arg2, ...]
* Any number of arguments to print out
* @usage _("Hello World") -> prints "Hello World"
* @usage _(1, 2, 3) -> prints "1 2 3"
*/
let _ = function(some, debug, text, to) print(Array.slice(arguments).join(" "));
_("Setting the identity for passphrase");
Cu.import("resource://services-sync/identity.js");
/*
* Test setup helpers.
*/
@ -334,32 +289,6 @@ function generateNewKeys(collections) {
CollectionKeys.setContents(wbo.cleartext, modified);
}
function do_check_empty(obj) {
do_check_attribute_count(obj, 0);
}
function do_check_attribute_count(obj, c) {
do_check_eq(c, Object.keys(obj).length);
}
function do_check_throws(aFunc, aResult, aStack)
{
if (!aStack) {
try {
// We might not have a 'Components' object.
aStack = Components.stack.caller;
} catch (e) {}
}
try {
aFunc();
} catch (e) {
do_check_eq(e.result, aResult, aStack);
return;
}
do_throw("Expected result " + aResult + ", none thrown.", aStack);
}
/*
* A fake engine implementation.
* This is used all over the place.
@ -487,4 +416,4 @@ deepCopy: function deepCopy(thing, noSort) {
}
return ret;
};
};

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

@ -4,7 +4,7 @@ const TEST_CLUSTER_URL = "http://localhost:8080/";
const TEST_SERVER_URL = "http://localhost:8080/";
// Shared logging for all HTTP server functions.
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
const SYNC_HTTP_LOGGER = "Sync.Test.Server";
const SYNC_API_VERSION = "1.1";
@ -26,39 +26,6 @@ function return_timestamp(request, response, timestamp) {
return timestamp;
}
function httpd_setup (handlers, port) {
let port = port || 8080;
let server = new nsHttpServer();
for (let path in handlers) {
server.registerPathHandler(path, handlers[path]);
}
try {
server.start(port);
} catch (ex) {
_("==========================================");
_("Got exception starting HTTP server on port " + port);
_("Error: " + Utils.exceptionStr(ex));
_("Is there a process already listening on port " + port + "?");
_("==========================================");
do_throw(ex);
}
return server;
}
function httpd_handler(statusCode, status, body) {
return function handler(request, response) {
// Allow test functions to inspect the request.
request.body = readBytesFromInputStream(request.bodyInputStream);
handler.request = request;
response.setStatusLine(request.httpVersion, statusCode, status);
if (body) {
response.bodyOutputStream.write(body, body.length);
}
};
}
function basic_auth_header(user, password) {
return "Basic " + btoa(user + ":" + Utils.encodeUTF8(password));
}
@ -84,21 +51,6 @@ function httpd_basic_auth_handler(body, metadata, response) {
response.bodyOutputStream.write(body, body.length);
}
/*
* Read bytes string from an nsIInputStream. If 'count' is omitted,
* all available input is read.
*/
function readBytesFromInputStream(inputStream, count) {
var BinaryInputStream = Components.Constructor(
"@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream");
if (!count) {
count = inputStream.available();
}
return new BinaryInputStream(inputStream).readBytes(count);
}
/*
* Represent a WBO on the server
*/
@ -1044,51 +996,3 @@ function serverForUsers(users, contents, callback) {
server.start();
return server;
}
/**
* Proxy auth helpers.
*/
/**
* Fake a PAC to prompt a channel replacement.
*/
let PACSystemSettings = {
CID: Components.ID("{5645d2c1-d6d8-4091-b117-fe7ee4027db7}"),
contractID: "@mozilla.org/system-proxy-settings;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory,
Ci.nsISystemProxySettings]),
createInstance: function createInstance(outer, iid) {
if (outer) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(iid);
},
lockFactory: function lockFactory(lock) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
// Replace this URI for each test to avoid caching. We want to ensure that
// each test gets a completely fresh setup.
PACURI: null,
getProxyForURI: function getProxyForURI(aURI) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
}
};
function installFakePAC() {
_("Installing fake PAC.");
Cm.nsIComponentRegistrar
.registerFactory(PACSystemSettings.CID,
"Fake system proxy-settings",
PACSystemSettings.contractID,
PACSystemSettings);
}
function uninstallFakePAC() {
_("Uninstalling fake PAC.");
let CID = PACSystemSettings.CID;
Cm.nsIComponentRegistrar.unregisterFactory(CID, PACSystemSettings);
}

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

@ -6,9 +6,9 @@
Cu.import("resource://gre/modules/AddonManager.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://services-sync/addonsreconciler.js");
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/engines/addons.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://services-sync/service.js");
let prefs = new Preferences();

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

@ -4,7 +4,7 @@
"use strict";
Cu.import("resource://services-sync/engines/addons.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/preferences.js");
const HTTP_PORT = 8888;

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

@ -1,8 +1,8 @@
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/engines/bookmarks.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/service.js");

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

@ -6,7 +6,7 @@
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/engines/bookmarks.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://gre/modules/Services.jsm");

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

@ -1,4 +1,4 @@
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/engines/bookmarks.js");

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

@ -5,7 +5,7 @@ Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/keys.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/engines/bookmarks.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/util.js");
function prepareBookmarkItem(collection, id) {

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

@ -1,7 +1,7 @@
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/engines/bookmarks.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/service.js");

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

@ -7,7 +7,7 @@ Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/engines/tabs.js");
Cu.import("resource://services-sync/engines/history.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
add_test(function test_locally_changed_keys() {
let passphrase = "abcdeabcdeabcdeabcdeabcdea";

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

@ -1,5 +1,5 @@
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/ext/Observers.js");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-sync/util.js");

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

@ -4,7 +4,7 @@
Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/policies.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
const LOG_PREFIX_SUCCESS = "success-";

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

@ -1,6 +1,6 @@
Cu.import("resource://services-sync/engines/forms.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
function run_test() {
_("Verify we've got an empty tracker to work with.");

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

@ -1,6 +1,6 @@
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-sync/engines/history.js");
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/util.js");
const TIMESTAMP1 = (Date.now() - 103406528) * 1000;

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

@ -59,7 +59,7 @@ add_test(function test_url_parsing() {
run_next_test();
});
Cu.import("resource://services-sync/rest.js");
Cu.import("resource://services-common/rest.js");
function localRequest(path) {
_("localRequest: " + path);
let url = "http://127.0.0.1:8080" + path;

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

@ -1,4 +1,4 @@
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/jpakeclient.js");
Cu.import("resource://services-sync/constants.js");
@ -190,7 +190,8 @@ function run_test() {
initTestLogging("Trace");
Log4Moz.repository.getLogger("Sync.JPAKEClient").level = Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Sync.RESTRequest").level = Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Common.RESTRequest").level =
Log4Moz.Level.Trace;
run_next_test();
}

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

@ -1,6 +1,5 @@
const modules = [
"addonsreconciler.js",
"async.js",
"constants.js",
"engines/addons.js",
"engines/bookmarks.js",
@ -11,12 +10,9 @@ const modules = [
"engines/prefs.js",
"engines/tabs.js",
"engines.js",
"ext/Observers.js",
"ext/Preferences.js",
"identity.js",
"jpakeclient.js",
"keys.js",
"log4moz.js",
"main.js",
"notifications.js",
"policies.js",

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

@ -7,12 +7,12 @@ _("Test that node reassignment responses are respected on all kinds of " +
// Don't sync any engines by default.
Svc.DefaultPrefs.set("registerEngines", "")
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/policies.js");
Cu.import("resource://services-sync/rest.js");
Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
function run_test() {
Log4Moz.repository.getLogger("Sync.AsyncResource").level = Log4Moz.Level.Trace;

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

@ -1,4 +1,4 @@
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/engines/history.js");

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

@ -1,6 +1,6 @@
Cu.import("resource://services-sync/engines/prefs.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://gre/modules/LightweightThemeManager.jsm");
Cu.import("resource://gre/modules/Services.jsm");

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

@ -1,7 +1,7 @@
Cu.import("resource://services-sync/engines/prefs.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/preferences.js");
function run_test() {
let engine = new PrefsEngine();

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

@ -6,7 +6,7 @@ Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/keys.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/util.js");
let cryptoWrap;

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

@ -1,9 +1,9 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-sync/ext/Observers.js");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/util.js");

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

@ -1,9 +1,9 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-sync/ext/Observers.js");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/util.js");

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

@ -6,7 +6,7 @@ Cu.import("resource://services-sync/main.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
function run_test() {
initTestLogging("Trace");

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

@ -10,7 +10,7 @@ Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/keys.js");
Cu.import("resource://services-sync/engines/tabs.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Engines.register(TabEngine);

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

@ -1,8 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/rest.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/util.js");

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

@ -1,5 +1,5 @@
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/util.js");

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

@ -1,4 +1,4 @@
Cu.import("resource://services-sync/ext/Preferences.js");
Cu.import("resource://services-common/preferences.js");
function test_migrate_logging() {
_("Testing log pref migration.");

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

@ -1,7 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-sync/ext/Observers.js");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/util.js");

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

@ -6,7 +6,7 @@ Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/keys.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
function run_test() {
let logger = Log4Moz.repository.rootLogger;

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

@ -1,5 +1,5 @@
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/util.js");

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

@ -5,7 +5,7 @@ Cu.import("resource://services-sync/rest.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-common/log4moz.js");
const STORAGE_REQUEST_RESOURCE_URL = TEST_SERVER_URL + "resource";

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

@ -1,5 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-common/stringbundle.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/ext/StringBundle.js");
function run_test() {
let fn = Utils.lazyStrings("sync");

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

@ -1,66 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
_("Make sure uri strings are converted to nsIURIs");
Cu.import("resource://services-sync/util.js");
function run_test() {
_test_makeURI();
}
function _test_makeURI() {
_("Check http uris");
let uri1 = "http://mozillalabs.com/";
do_check_eq(Utils.makeURI(uri1).spec, uri1);
let uri2 = "http://www.mozillalabs.com/";
do_check_eq(Utils.makeURI(uri2).spec, uri2);
let uri3 = "http://mozillalabs.com/path";
do_check_eq(Utils.makeURI(uri3).spec, uri3);
let uri4 = "http://mozillalabs.com/multi/path";
do_check_eq(Utils.makeURI(uri4).spec, uri4);
let uri5 = "http://mozillalabs.com/?query";
do_check_eq(Utils.makeURI(uri5).spec, uri5);
let uri6 = "http://mozillalabs.com/#hash";
do_check_eq(Utils.makeURI(uri6).spec, uri6);
_("Check https uris");
let uris1 = "https://mozillalabs.com/";
do_check_eq(Utils.makeURI(uris1).spec, uris1);
let uris2 = "https://www.mozillalabs.com/";
do_check_eq(Utils.makeURI(uris2).spec, uris2);
let uris3 = "https://mozillalabs.com/path";
do_check_eq(Utils.makeURI(uris3).spec, uris3);
let uris4 = "https://mozillalabs.com/multi/path";
do_check_eq(Utils.makeURI(uris4).spec, uris4);
let uris5 = "https://mozillalabs.com/?query";
do_check_eq(Utils.makeURI(uris5).spec, uris5);
let uris6 = "https://mozillalabs.com/#hash";
do_check_eq(Utils.makeURI(uris6).spec, uris6);
_("Check chrome uris");
let uric1 = "chrome://browser/content/browser.xul";
do_check_eq(Utils.makeURI(uric1).spec, uric1);
let uric2 = "chrome://browser/skin/browser.css";
do_check_eq(Utils.makeURI(uric2).spec, uric2);
let uric3 = "chrome://browser/locale/browser.dtd";
do_check_eq(Utils.makeURI(uric3).spec, uric3);
_("Check about uris");
let uria1 = "about:weave";
do_check_eq(Utils.makeURI(uria1).spec, uria1);
let uria2 = "about:weave/";
do_check_eq(Utils.makeURI(uria2).spec, uria2);
let uria3 = "about:weave/path";
do_check_eq(Utils.makeURI(uria3).spec, uria3);
let uria4 = "about:weave/multi/path";
do_check_eq(Utils.makeURI(uria4).spec, uria4);
let uria5 = "about:weave/?query";
do_check_eq(Utils.makeURI(uria5).spec, uria5);
let uria6 = "about:weave/#hash";
do_check_eq(Utils.makeURI(uria6).spec, uria6);
_("Invalid uris are undefined");
do_check_eq(Utils.makeURI("mozillalabs.com"), undefined);
do_check_eq(Utils.makeURI("chrome://badstuff"), undefined);
do_check_eq(Utils.makeURI("this is a test"), undefined);
}

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

@ -1,9 +1,7 @@
[DEFAULT]
head = head_appinfo.js head_helpers.js head_http_server.js
head = head_appinfo.js ../../../common/tests/unit/head_helpers.js head_helpers.js head_http_server.js
tail =
[test_load_modules.js]
# The manifest is roughly ordered from low-level to high-level. When making
# systemic sweeping changes, this makes it easier to identify errors closer to
# the source.
@ -27,23 +25,14 @@ tail =
[test_utils_lazyStrings.js]
[test_utils_lock.js]
[test_utils_makeGUID.js]
[test_utils_makeURI.js]
[test_utils_namedTimer.js]
[test_utils_notify.js]
[test_utils_passphrase.js]
[test_utils_pbkdf2.js]
[test_utils_sha1.js]
[test_utils_stackTrace.js]
[test_utils_utf8.js]
# We have a number of other libraries that are pretty much standalone.
[test_Observers.js]
[test_Preferences.js]
[test_async_chain.js]
[test_async_querySpinningly.js]
[test_httpd_sync_server.js]
[test_log4moz.js]
[test_restrequest.js]
[test_jpakeclient.js]
# Bug 618233: this test produces random failures on Windows 7.
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)

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

@ -42,7 +42,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/AddonManager.jsm");
Cu.import("resource://gre/modules/AddonRepository.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://services-sync/async.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://tps/logger.jsm");

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

@ -50,7 +50,7 @@ const CU = Components.utils;
CU.import("resource://tps/logger.jsm");
CU.import("resource://gre/modules/Services.jsm");
CU.import("resource://gre/modules/PlacesUtils.jsm");
CU.import("resource://services-sync/async.js");
CU.import("resource://services-common/async.js");
var DumpBookmarks = function TPS_Bookmarks__DumpBookmarks() {
let writer = {

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

@ -49,7 +49,7 @@ const CU = Components.utils;
CU.import("resource://gre/modules/Services.jsm");
CU.import("resource://gre/modules/PlacesUtils.jsm");
CU.import("resource://tps/logger.jsm");
CU.import("resource://services-sync/async.js");
CU.import("resource://services-common/async.js");
var DumpHistory = function TPS_History__DumpHistory() {
let writer = {

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

@ -47,7 +47,7 @@ const {classes: CC, interfaces: CI, utils: CU} = Components;
CU.import("resource://services-sync/service.js");
CU.import("resource://services-sync/constants.js");
CU.import("resource://services-sync/engines.js");
CU.import("resource://services-sync/async.js");
CU.import("resource://services-common/async.js");
CU.import("resource://services-sync/util.js");
CU.import("resource://gre/modules/XPCOMUtils.jsm");
CU.import("resource://gre/modules/Services.jsm");

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

@ -67,6 +67,7 @@ skip-if = os == "android"
[include:content/base/test/unit/xpcshell.ini]
[include:content/test/unit/xpcshell.ini]
[include:toolkit/components/url-classifier/tests/unit/xpcshell.ini]
[include:services/common/tests/unit/xpcshell.ini]
[include:services/crypto/tests/unit/xpcshell.ini]
[include:services/crypto/components/tests/unit/xpcshell.ini]
[include:services/sync/tests/unit/xpcshell.ini]