mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge services-central into mozilla-central
This commit is contained in:
commit
9d66d1498f
@ -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
|
||||
|
34
services/common/Makefile.in
Normal file
34
services/common/Makefile.in
Normal file
@ -0,0 +1,34 @@
|
||||
# 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 \
|
||||
tokenserverclient.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
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", "RESTResponse"];
|
||||
|
||||
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
|
||||
|
||||
};
|
7
services/common/services-common.js
Normal file
7
services/common/services-common.js
Normal file
@ -0,0 +1,7 @@
|
||||
// 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");
|
||||
|
||||
pref("services.common.tokenserverclient.logger.level", "Info");
|
@ -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.
|
16
services/common/tests/Makefile.in
Normal file
16
services/common/tests/Makefile.in
Normal file
@ -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
|
54
services/common/tests/unit/head_global.js
Normal file
54
services/common/tests/unit/head_global.js
Normal file
@ -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();
|
173
services/common/tests/unit/head_helpers.js
Normal file
173
services/common/tests/unit/head_helpers.js
Normal file
@ -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");
|
19
services/common/tests/unit/test_load_modules.js
Normal file
19
services/common/tests/unit/test_load_modules.js
Normal file
@ -0,0 +1,19 @@
|
||||
/* 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",
|
||||
"tokenserverclient.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);
|
||||
});
|
||||
});
|
166
services/common/tests/unit/test_tokenserverclient.js
Normal file
166
services/common/tests/unit/test_tokenserverclient.js
Normal file
@ -0,0 +1,166 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-common/async.js");
|
||||
Cu.import("resource://services-common/tokenserverclient.js");
|
||||
|
||||
function run_test() {
|
||||
initTestLogging("Trace");
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_working_bid_exchange() {
|
||||
_("Ensure that working BrowserID token exchange works as expected.");
|
||||
|
||||
let service = "http://example.com/foo";
|
||||
|
||||
let server = httpd_setup({
|
||||
"/1.0/foo/1.0": function(request, response) {
|
||||
do_check_true(request.hasHeader("accept"));
|
||||
do_check_eq("application/json", request.getHeader("accept"));
|
||||
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
|
||||
let body = JSON.stringify({
|
||||
id: "id",
|
||||
secret: "key",
|
||||
api_endpoint: service,
|
||||
uid: "uid",
|
||||
});
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
}
|
||||
});
|
||||
|
||||
let client = new TokenServerClient();
|
||||
let cb = Async.makeSpinningCallback();
|
||||
let url = TEST_SERVER_URL + "1.0/foo/1.0";
|
||||
client.getTokenFromBrowserIDAssertion(url, "assertion", cb);
|
||||
let result = cb.wait();
|
||||
do_check_eq("object", typeof(result));
|
||||
do_check_attribute_count(result, 4);
|
||||
do_check_eq(service, result.endpoint);
|
||||
do_check_eq("id", result.id);
|
||||
do_check_eq("key", result.key);
|
||||
do_check_eq("uid", result.uid);
|
||||
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function test_invalid_arguments() {
|
||||
_("Ensure invalid arguments to APIs are rejected.");
|
||||
|
||||
let args = [
|
||||
[null, "assertion", function() {}],
|
||||
["http://example.com/", null, function() {}],
|
||||
["http://example.com/", "assertion", null]
|
||||
];
|
||||
|
||||
for each (let arg in args) {
|
||||
try {
|
||||
let client = new TokenServerClient();
|
||||
client.getTokenFromBrowserIDAssertion(arg[0], arg[1], arg[2]);
|
||||
do_throw("Should never get here.");
|
||||
} catch (ex) {
|
||||
do_check_true(ex instanceof TokenServerClientError);
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_error_404() {
|
||||
_("Ensure that 404 responses result in error.");
|
||||
|
||||
let server = httpd_setup();
|
||||
|
||||
let client = new TokenServerClient();
|
||||
let url = TEST_SERVER_URL + "foo";
|
||||
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
|
||||
do_check_neq(null, error);
|
||||
do_check_eq("TokenServerClientServerError", error.name);
|
||||
do_check_neq(null, error.response);
|
||||
do_check_eq(null, r);
|
||||
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_bad_json() {
|
||||
_("Ensure that malformed JSON is handled properly.");
|
||||
|
||||
let server = httpd_setup({
|
||||
"/1.0/foo/1.0": function(request, response) {
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
|
||||
let body = '{"id": "id", baz}'
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
}
|
||||
});
|
||||
|
||||
let client = new TokenServerClient();
|
||||
let url = TEST_SERVER_URL + "1.0/foo/1.0";
|
||||
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
|
||||
_(error);
|
||||
do_check_neq(null, error);
|
||||
do_check_eq("TokenServerClientServerError", error.name);
|
||||
do_check_neq(null, error.response);
|
||||
do_check_eq(null, r);
|
||||
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_unhandled_media_type() {
|
||||
_("Ensure that unhandled media types throw an error.");
|
||||
|
||||
let server = httpd_setup({
|
||||
"/1.0/foo/1.0": function(request, response) {
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/plain");
|
||||
|
||||
let body = "hello, world";
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
}
|
||||
});
|
||||
|
||||
let url = TEST_SERVER_URL + "1.0/foo/1.0";
|
||||
let client = new TokenServerClient();
|
||||
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
|
||||
do_check_neq(null, error);
|
||||
do_check_eq("TokenServerClientError", error.name);
|
||||
do_check_neq(null, error.response);
|
||||
do_check_eq(null, r);
|
||||
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_rich_media_types() {
|
||||
_("Ensure that extra tokens in the media type aren't rejected.");
|
||||
|
||||
let server = httpd_setup({
|
||||
"/foo": function(request, response) {
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "application/json; foo=bar; bar=foo");
|
||||
|
||||
let body = JSON.stringify({
|
||||
id: "id",
|
||||
secret: "key",
|
||||
api_endpoint: "foo",
|
||||
uid: "uid",
|
||||
});
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
}
|
||||
});
|
||||
|
||||
let url = TEST_SERVER_URL + "foo";
|
||||
let client = new TokenServerClient();
|
||||
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
|
||||
do_check_eq(null, error);
|
||||
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
});
|
11
services/common/tests/unit/test_utils_atob.js
Normal file
11
services/common/tests/unit/test_utils_atob.js
Normal file
@ -0,0 +1,11 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-common/utils.js");
|
||||
|
||||
function run_test() {
|
||||
let data = ["Zm9vYmE=", "Zm9vYmE==", "Zm9vYmE==="];
|
||||
for (let d in data) {
|
||||
do_check_eq(CommonUtils.safeAtoB(data[d]), "fooba");
|
||||
}
|
||||
}
|
66
services/common/tests/unit/test_utils_makeURI.js
Normal file
66
services/common/tests/unit/test_utils_makeURI.js
Normal file
@ -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");
|
11
services/common/tests/unit/test_utils_utf8.js
Normal file
11
services/common/tests/unit/test_utils_utf8.js
Normal file
@ -0,0 +1,11 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-common/utils.js");
|
||||
|
||||
function run_test() {
|
||||
let str = "Umlaute: \u00FC \u00E4\n"; // Umlaute: ü ä
|
||||
let encoded = CommonUtils.encodeUTF8(str);
|
||||
let decoded = CommonUtils.decodeUTF8(encoded);
|
||||
do_check_eq(decoded, str);
|
||||
}
|
20
services/common/tests/unit/xpcshell.ini
Normal file
20
services/common/tests/unit/xpcshell.ini
Normal file
@ -0,0 +1,20 @@
|
||||
[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_atob.js]
|
||||
[test_utils_makeURI.js]
|
||||
[test_utils_namedTimer.js]
|
||||
[test_utils_stackTrace.js]
|
||||
[test_utils_utf8.js]
|
||||
|
||||
[test_async_chain.js]
|
||||
[test_async_querySpinningly.js]
|
||||
[test_log4moz.js]
|
||||
[test_observers.js]
|
||||
[test_preferences.js]
|
||||
[test_restrequest.js]
|
||||
[test_tokenserverclient.js]
|
238
services/common/tokenserverclient.js
Normal file
238
services/common/tokenserverclient.js
Normal file
@ -0,0 +1,238 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const EXPORTED_SYMBOLS = [
|
||||
"TokenServerClient",
|
||||
"TokenServerClientError",
|
||||
"TokenServerClientNetworkError",
|
||||
"TokenServerClientServerError"
|
||||
];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://services-common/log4moz.js");
|
||||
Cu.import("resource://services-common/preferences.js");
|
||||
Cu.import("resource://services-common/rest.js");
|
||||
|
||||
const Prefs = new Preferences("services.common.tokenserverclient.");
|
||||
|
||||
/**
|
||||
* Represents a TokenServerClient error that occurred on the client.
|
||||
*
|
||||
* This is the base type for all errors raised by client operations.
|
||||
*
|
||||
* @param message
|
||||
* (string) Error message.
|
||||
*/
|
||||
function TokenServerClientError(message) {
|
||||
this.name = "TokenServerClientError";
|
||||
this.message = message || "Client error.";
|
||||
}
|
||||
TokenServerClientError.prototype = new Error();
|
||||
TokenServerClientError.prototype.constructor = TokenServerClientError;
|
||||
|
||||
/**
|
||||
* Represents a TokenServerClient error that occurred in the network layer.
|
||||
*
|
||||
* @param error
|
||||
* The underlying error thrown by the network layer.
|
||||
*/
|
||||
function TokenServerClientNetworkError(error) {
|
||||
this.name = "TokenServerClientNetworkError";
|
||||
this.error = error;
|
||||
}
|
||||
TokenServerClientNetworkError.prototype = new TokenServerClientError();
|
||||
TokenServerClientNetworkError.prototype.constructor =
|
||||
TokenServerClientNetworkError;
|
||||
|
||||
/**
|
||||
* Represents a TokenServerClient error that occurred on the server.
|
||||
*
|
||||
* This type will be encountered for all non-200 response codes from the
|
||||
* server.
|
||||
*
|
||||
* @param message
|
||||
* (string) Error message.
|
||||
*/
|
||||
function TokenServerClientServerError(message) {
|
||||
this.name = "TokenServerClientServerError";
|
||||
this.message = message || "Server error.";
|
||||
}
|
||||
TokenServerClientServerError.prototype = new TokenServerClientError();
|
||||
TokenServerClientServerError.prototype.constructor =
|
||||
TokenServerClientServerError;
|
||||
|
||||
/**
|
||||
* Represents a client to the Token Server.
|
||||
*
|
||||
* http://docs.services.mozilla.com/token/index.html
|
||||
*
|
||||
* The Token Server supports obtaining tokens for arbitrary apps by
|
||||
* constructing URI paths of the form <app>/<app_version>. However, the service
|
||||
* discovery mechanism emphasizes the use of full URIs and tries to not force
|
||||
* the client to manipulate URIs. This client currently enforces this practice
|
||||
* by not implementing an API which would perform URI manipulation.
|
||||
*
|
||||
* If you are tempted to implement this API in the future, consider this your
|
||||
* warning that you may be doing it wrong and that you should store full URIs
|
||||
* instead.
|
||||
*
|
||||
* Areas to Improve:
|
||||
*
|
||||
* - The server sends a JSON response on error. The client does not currently
|
||||
* parse this. It might be convenient if it did.
|
||||
* - Currently all non-200 status codes are rolled into one error type. It
|
||||
* might be helpful if callers had a richer API that communicated who was
|
||||
* at fault (e.g. differentiating a 503 from a 401).
|
||||
*/
|
||||
function TokenServerClient() {
|
||||
this._log = Log4Moz.repository.getLogger("Common.TokenServerClient");
|
||||
this._log.level = Log4Moz.Level[Prefs.get("logger.level")];
|
||||
}
|
||||
TokenServerClient.prototype = {
|
||||
/**
|
||||
* Logger instance.
|
||||
*/
|
||||
_log: null,
|
||||
|
||||
/**
|
||||
* Obtain a token from a BrowserID assertion against a specific URL.
|
||||
*
|
||||
* This asynchronously obtains the token. The callback receives 2 arguments.
|
||||
* The first signifies an error and is a TokenServerClientError (or derived)
|
||||
* type when an error occurs. If an HTTP response was seen, a RESTResponse
|
||||
* instance will be stored in the "response" property of this object.
|
||||
*
|
||||
* The second argument to the callback is a map containing the results from
|
||||
* the server. This map has the following keys:
|
||||
*
|
||||
* id (string) HTTP MAC public key identifier.
|
||||
* key (string) HTTP MAC shared symmetric key.
|
||||
* endpoint (string) URL where service can be connected to.
|
||||
* uid (string) user ID for requested service.
|
||||
*
|
||||
* e.g.
|
||||
*
|
||||
* let client = new TokenServerClient();
|
||||
* let assertion = getBrowserIDAssertionFromSomewhere();
|
||||
* let url = "https://token.services.mozilla.com/1.0/sync/2.0";
|
||||
*
|
||||
* client.getTokenFromBrowserIDAssertion(url, assertion,
|
||||
* function(error, result) {
|
||||
* if (error) {
|
||||
* // Do error handling.
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* let {id: id, key: key, uid: uid, endpoint: endpoint} = result;
|
||||
* // Do stuff with data and carry on.
|
||||
* });
|
||||
*
|
||||
* @param url
|
||||
* (string) URL to fetch token from.
|
||||
* @param assertion
|
||||
* (string) BrowserID assertion to exchange token for.
|
||||
* @param cb
|
||||
* (function) Callback to be invoked with result of operation.
|
||||
*/
|
||||
getTokenFromBrowserIDAssertion:
|
||||
function getTokenFromBrowserIDAssertion(url, assertion, cb) {
|
||||
if (!url) {
|
||||
throw new TokenServerClientError("url argument is not valid.");
|
||||
}
|
||||
|
||||
if (!assertion) {
|
||||
throw new TokenServerClientError("assertion argument is not valid.");
|
||||
}
|
||||
|
||||
if (!cb) {
|
||||
throw new TokenServerClientError("cb argument is not valid.");
|
||||
}
|
||||
|
||||
this._log.debug("Beginning BID assertion exchange: " + url);
|
||||
|
||||
let req = new RESTRequest(url);
|
||||
req.setHeader("accept", "application/json");
|
||||
req.setHeader("authorization", "Browser-ID " + assertion);
|
||||
let client = this;
|
||||
req.get(function onResponse(error) {
|
||||
if (error) {
|
||||
cb(new TokenServerClientNetworkError(error), null);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
client._processTokenResponse(this.response, cb);
|
||||
} catch (ex) {
|
||||
let error = new TokenServerClientError(ex);
|
||||
error.response = this.response;
|
||||
cb(error, null);
|
||||
return;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler to process token request responses.
|
||||
*
|
||||
* @param response
|
||||
* RESTResponse from token HTTP request.
|
||||
* @param cb
|
||||
* The original callback passed to the public API.
|
||||
*/
|
||||
_processTokenResponse: function processTokenResponse(response, cb) {
|
||||
this._log.debug("Got token response.");
|
||||
|
||||
if (!response.success) {
|
||||
this._log.info("Non-200 response code to token request: " +
|
||||
response.status);
|
||||
this._log.debug("Response body: " + response.body);
|
||||
let error = new TokenServerClientServerError("Non 200 response code: " +
|
||||
response.status);
|
||||
error.response = response;
|
||||
cb(error, null);
|
||||
return;
|
||||
}
|
||||
|
||||
let ct = response.headers["content-type"];
|
||||
if (ct != "application/json" && ct.indexOf("application/json;") != 0) {
|
||||
let error = new TokenServerClientError("Unsupported media type: " + ct);
|
||||
error.response = response;
|
||||
cb(error, null);
|
||||
return;
|
||||
}
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = JSON.parse(response.body);
|
||||
} catch (ex) {
|
||||
let error = new TokenServerClientServerError("Invalid JSON returned " +
|
||||
"from server.");
|
||||
error.response = response;
|
||||
cb(error, null);
|
||||
return;
|
||||
}
|
||||
|
||||
for each (let k in ["id", "secret", "api_endpoint", "uid"]) {
|
||||
if (!(k in result)) {
|
||||
let error = new TokenServerClientServerError("Expected key not " +
|
||||
" present in result: " +
|
||||
k);
|
||||
error.response = response;
|
||||
cb(error, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this._log.debug("Successful token response: " + result.id);
|
||||
cb(null, {
|
||||
id: result.id,
|
||||
key: result.secret,
|
||||
endpoint: result.api_endpoint,
|
||||
uid: result.uid,
|
||||
});
|
||||
}
|
||||
};
|
161
services/common/utils.js
Normal file
161
services/common/utils.js
Normal file
@ -0,0 +1,161 @@
|
||||
/* 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://gre/modules/XPCOMUtils.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;
|
||||
},
|
||||
|
||||
encodeUTF8: function encodeUTF8(str) {
|
||||
try {
|
||||
str = this._utf8Converter.ConvertFromUnicode(str);
|
||||
return str + this._utf8Converter.Finish();
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
decodeUTF8: function decodeUTF8(str) {
|
||||
try {
|
||||
str = this._utf8Converter.ConvertToUnicode(str);
|
||||
return str + this._utf8Converter.Finish();
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Trim excess padding from a Base64 string and atob().
|
||||
*
|
||||
* See bug 562431 comment 4.
|
||||
*/
|
||||
safeAtoB: function safeAtoB(b64) {
|
||||
let len = b64.length;
|
||||
let over = len % 4;
|
||||
return over ? atob(b64.substr(0, len - over)) : atob(b64);
|
||||
},
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(CommonUtils, "_utf8Converter", function() {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
return converter;
|
||||
});
|
@ -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,17 @@ 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,
|
||||
encodeUTF8: CommonUtils.encodeUTF8,
|
||||
decodeUTF8: CommonUtils.decodeUTF8,
|
||||
safeAtoB: CommonUtils.safeAtoB,
|
||||
|
||||
/**
|
||||
* Wrap a function to catch all exceptions and log them
|
||||
*
|
||||
@ -269,62 +278,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 +797,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 +870,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);
|
||||
@ -990,24 +890,6 @@ let Utils = {
|
||||
return Str.errors.get("error.reason.unknown");
|
||||
},
|
||||
|
||||
encodeUTF8: function(str) {
|
||||
try {
|
||||
str = this._utf8Converter.ConvertFromUnicode(str);
|
||||
return str + this._utf8Converter.Finish();
|
||||
} catch(ex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
decodeUTF8: function(str) {
|
||||
try {
|
||||
str = this._utf8Converter.ConvertToUnicode(str);
|
||||
return str + this._utf8Converter.Finish();
|
||||
} catch(ex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate 26 characters.
|
||||
*/
|
||||
@ -1108,15 +990,6 @@ let Utils = {
|
||||
return acc.trim();
|
||||
},
|
||||
|
||||
// WeaveCrypto returns bad base64 strings. Truncate excess padding
|
||||
// and decode.
|
||||
// See Bug 562431, comment 4.
|
||||
safeAtoB: function safeAtoB(b64) {
|
||||
let len = b64.length;
|
||||
let over = len % 4;
|
||||
return over ? atob(b64.substr(0, len - over)) : atob(b64);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create an array like the first but without elements of the second. Reuse
|
||||
* arrays if possible.
|
||||
|
@ -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,8 +0,0 @@
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
let data = ["Zm9vYmE=", "Zm9vYmE==", "Zm9vYmE==="];
|
||||
for (let d in data) {
|
||||
do_check_eq(Utils.safeAtoB(data[d]), "fooba");
|
||||
}
|
||||
}
|
@ -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,8 +0,0 @@
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
let str = "Umlaute: \u00FC \u00E4\n"; // Umlaute: ü ä
|
||||
let encoded = Utils.encodeUTF8(str);
|
||||
let decoded = Utils.decodeUTF8(encoded);
|
||||
do_check_eq(decoded, str);
|
||||
}
|
@ -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.
|
||||
@ -12,7 +10,6 @@ tail =
|
||||
[test_load_modules.js]
|
||||
|
||||
# util contains a bunch of functionality used throughout.
|
||||
[test_utils_atob.js]
|
||||
[test_utils_catch.js]
|
||||
[test_utils_deepCopy.js]
|
||||
[test_utils_deepEquals.js]
|
||||
@ -27,23 +24,13 @@ 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");
|
||||
|
@ -40,7 +40,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
version = '0.2.40'
|
||||
|
||||
deps = ['pulsebuildmonitor >= 0.2', 'MozillaPulse == .4',
|
||||
deps = ['pulsebuildmonitor >= 0.62', 'MozillaPulse == 0.61',
|
||||
'mozinfo == 0.3.1', 'mozprofile == 0.1t',
|
||||
'mozprocess == 0.1a', 'mozrunner == 3.0a', 'mozregression == 0.3',
|
||||
'mozautolog >= 0.2.1']
|
||||
|
@ -51,7 +51,7 @@ class TPSPulseMonitor(PulseBuildMonitor):
|
||||
def __init__(self, extensionDir, platform='linux', config=None,
|
||||
autolog=False, emailresults=False, testfile=None,
|
||||
logfile=None, rlock=None, **kwargs):
|
||||
self.buildtype = 'opt'
|
||||
self.buildtype = ['opt']
|
||||
self.autolog = autolog
|
||||
self.emailresults = emailresults
|
||||
self.testfile = testfile
|
||||
@ -59,8 +59,8 @@ class TPSPulseMonitor(PulseBuildMonitor):
|
||||
self.rlock = rlock
|
||||
self.extensionDir = extensionDir
|
||||
self.config = config
|
||||
self.tree = self.config.get('tree', ['services-central', 'places'])
|
||||
self.platform = self.config.get('platform', 'linux')
|
||||
self.tree = self.config.get('tree', ['services-central'])
|
||||
self.platform = [self.config.get('platform', 'linux')]
|
||||
self.label=('crossweave@mozilla.com|tps_build_monitor_' +
|
||||
socket.gethostname())
|
||||
|
||||
@ -70,10 +70,12 @@ class TPSPulseMonitor(PulseBuildMonitor):
|
||||
self.logger.addHandler(handler)
|
||||
|
||||
PulseBuildMonitor.__init__(self,
|
||||
tree=self.tree,
|
||||
trees=self.tree,
|
||||
label=self.label,
|
||||
mobile=False,
|
||||
logger=self.logger,
|
||||
platforms=self.platform,
|
||||
buildtypes=self.buildtype,
|
||||
builds=True,
|
||||
**kwargs)
|
||||
|
||||
def onPulseMessage(self, data):
|
||||
@ -84,12 +86,7 @@ class TPSPulseMonitor(PulseBuildMonitor):
|
||||
print "================================================================="
|
||||
print json.dumps(builddata)
|
||||
print "================================================================="
|
||||
try:
|
||||
if not (builddata['platform'] == self.platform and
|
||||
builddata['buildtype'] == self.buildtype):
|
||||
return
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
thread = TPSTestThread(self.extensionDir,
|
||||
builddata=builddata,
|
||||
emailresults=self.emailresults,
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user