Bug 1561435 - Format netwerk/, a=automatic-formatting

# ignore-this-changeset

Differential Revision: https://phabricator.services.mozilla.com/D35919

--HG--
extra : source : afa5bd771feba466ba7670c58f3d93233a14e202
This commit is contained in:
Victor Porof 2019-07-05 10:55:23 +02:00
parent ea8b91c51d
commit 2c53a5dcd9
455 changed files with 25908 additions and 16247 deletions

View file

@ -45,7 +45,6 @@ module.exports = {
"overrides": [{
"files": [
"devtools/**",
"netwerk/**",
"nsprpub/**",
"other-licenses/**",
"parser/**",

View file

@ -40,7 +40,6 @@ toolkit/components/telemetry/datareporting-prefs.js
toolkit/components/telemetry/healthreport-prefs.js
# Ignore all top-level directories for now.
netwerk/**
nsprpub/**
other-licenses/**
parser/**

View file

@ -4,9 +4,7 @@
* 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/. */
var EXPORTED_SYMBOLS = [
"NetUtil",
];
var EXPORTED_SYMBOLS = ["NetUtil"];
/**
* Necko utilities
@ -17,413 +15,435 @@ var EXPORTED_SYMBOLS = [
const PR_UINT32_MAX = 0xffffffff;
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const BinaryInputStream = Components.Constructor("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream", "setInputStream");
const BinaryInputStream = Components.Constructor(
"@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream"
);
// //////////////////////////////////////////////////////////////////////////////
// // NetUtil Object
var NetUtil = {
/**
* Function to perform simple async copying from aSource (an input stream)
* to aSink (an output stream). The copy will happen on some background
* thread. Both streams will be closed when the copy completes.
*
* @param aSource
* The input stream to read from
* @param aSink
* The output stream to write to
* @param aCallback [optional]
* A function that will be called at copy completion with a single
* argument: the nsresult status code for the copy operation.
*
* @return An nsIRequest representing the copy operation (for example, this
* can be used to cancel the copying). The consumer can ignore the
* return value if desired.
*/
asyncCopy: function NetUtil_asyncCopy(aSource, aSink,
aCallback = null) {
if (!aSource || !aSink) {
let exception = new Components.Exception(
"Must have a source and a sink",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
/**
* Function to perform simple async copying from aSource (an input stream)
* to aSink (an output stream). The copy will happen on some background
* thread. Both streams will be closed when the copy completes.
*
* @param aSource
* The input stream to read from
* @param aSink
* The output stream to write to
* @param aCallback [optional]
* A function that will be called at copy completion with a single
* argument: the nsresult status code for the copy operation.
*
* @return An nsIRequest representing the copy operation (for example, this
* can be used to cancel the copying). The consumer can ignore the
* return value if desired.
*/
asyncCopy: function NetUtil_asyncCopy(aSource, aSink, aCallback = null) {
if (!aSource || !aSink) {
let exception = new Components.Exception(
"Must have a source and a sink",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
// make a stream copier
var copier = Cc[
"@mozilla.org/network/async-stream-copier;1"
].createInstance(Ci.nsIAsyncStreamCopier2);
copier.init(
aSource,
aSink,
null /* Default event target */,
0 /* Default length */,
true,
true /* Auto-close */
);
var observer;
if (aCallback) {
observer = {
onStartRequest(aRequest) {},
onStopRequest(aRequest, aStatusCode) {
aCallback(aStatusCode);
},
};
} else {
observer = null;
}
// start the copying
copier.QueryInterface(Ci.nsIAsyncStreamCopier).asyncCopy(observer, null);
return copier;
},
/**
* Asynchronously opens a source and fetches the response. While the fetch
* is asynchronous, I/O may happen on the main thread. When reading from
* a local file, prefer using "OS.File" methods instead.
*
* @param aSource
* This argument can be one of the following:
* - An options object that will be passed to NetUtil.newChannel.
* - An existing nsIChannel.
* - An existing nsIInputStream.
* Using an nsIURI, nsIFile, or string spec directly is deprecated.
* @param aCallback
* The callback function that will be notified upon completion. It
* will get these arguments:
* 1) An nsIInputStream containing the data from aSource, if any.
* 2) The status code from opening the source.
* 3) Reference to the nsIRequest.
*/
asyncFetch: function NetUtil_asyncFetch(aSource, aCallback) {
if (!aSource || !aCallback) {
let exception = new Components.Exception(
"Must have a source and a callback",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
// Create a pipe that will create our output stream that we can use once
// we have gotten all the data.
let pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
pipe.init(true, true, 0, PR_UINT32_MAX, null);
// Create a listener that will give data to the pipe's output stream.
let listener = Cc[
"@mozilla.org/network/simple-stream-listener;1"
].createInstance(Ci.nsISimpleStreamListener);
listener.init(pipe.outputStream, {
onStartRequest(aRequest) {},
onStopRequest(aRequest, aStatusCode) {
pipe.outputStream.close();
aCallback(pipe.inputStream, aStatusCode, aRequest);
},
});
// Input streams are handled slightly differently from everything else.
if (aSource instanceof Ci.nsIInputStream) {
let pump = Cc["@mozilla.org/network/input-stream-pump;1"].createInstance(
Ci.nsIInputStreamPump
);
pump.init(aSource, 0, 0, true);
pump.asyncRead(listener, null);
return;
}
let channel = aSource;
if (!(channel instanceof Ci.nsIChannel)) {
channel = this.newChannel(aSource);
}
try {
channel.asyncOpen(listener);
} catch (e) {
let exception = new Components.Exception(
"Failed to open input source '" + channel.originalURI.spec + "'",
e.result,
Components.stack.caller,
aSource,
e
);
throw exception;
}
},
/**
* Constructs a new URI for the given spec, character set, and base URI, or
* an nsIFile.
*
* @param aTarget
* The string spec for the desired URI or an nsIFile.
* @param aOriginCharset [optional]
* The character set for the URI. Only used if aTarget is not an
* nsIFile.
* @param aBaseURI [optional]
* The base URI for the spec. Only used if aTarget is not an
* nsIFile.
*
* @return an nsIURI object.
*/
newURI: function NetUtil_newURI(aTarget, aOriginCharset, aBaseURI) {
if (!aTarget) {
let exception = new Components.Exception(
"Must have a non-null string spec or nsIFile object",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
if (aTarget instanceof Ci.nsIFile) {
return Services.io.newFileURI(aTarget);
}
return Services.io.newURI(aTarget, aOriginCharset, aBaseURI);
},
/**
* Constructs a new channel for the given source.
*
* Keep in mind that URIs coming from a webpage should *never* use the
* systemPrincipal as the loadingPrincipal.
*
* @param aWhatToLoad
* This argument used to be a string spec for the desired URI, an
* nsIURI, or an nsIFile. Now it should be an options object with
* the following properties:
* {
* uri:
* The full URI spec string, nsIURI or nsIFile to create the
* channel for.
* Note that this cannot be an nsIFile if you have to specify a
* non-default charset or base URI. Call NetUtil.newURI first if
* you need to construct an URI using those options.
* loadingNode:
* loadingPrincipal:
* triggeringPrincipal:
* securityFlags:
* contentPolicyType:
* These will be used as values for the nsILoadInfo object on the
* created channel. For details, see nsILoadInfo in nsILoadInfo.idl
* loadUsingSystemPrincipal:
* Set this to true to use the system principal as
* loadingPrincipal. This must be omitted if loadingPrincipal or
* loadingNode are present.
* This should be used with care as it skips security checks.
* }
* @return an nsIChannel object.
*/
newChannel: function NetUtil_newChannel(aWhatToLoad) {
// Make sure the API is called using only the options object.
if (typeof aWhatToLoad != "object" || arguments.length != 1) {
throw new Components.Exception(
"newChannel requires a single object argument",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
let {
uri,
loadingNode,
loadingPrincipal,
loadUsingSystemPrincipal,
triggeringPrincipal,
securityFlags,
contentPolicyType,
} = aWhatToLoad;
if (!uri) {
throw new Components.Exception(
"newChannel requires the 'uri' property on the options object.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
if (typeof uri == "string" || uri instanceof Ci.nsIFile) {
uri = this.newURI(uri);
}
if (!loadingNode && !loadingPrincipal && !loadUsingSystemPrincipal) {
throw new Components.Exception(
"newChannel requires at least one of the 'loadingNode'," +
" 'loadingPrincipal', or 'loadUsingSystemPrincipal'" +
" properties on the options object.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
if (loadUsingSystemPrincipal === true) {
if (loadingNode || loadingPrincipal) {
throw new Components.Exception(
"newChannel does not accept 'loadUsingSystemPrincipal'" +
" if the 'loadingNode' or 'loadingPrincipal' properties" +
" are present on the options object.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
loadingPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
} else if (loadUsingSystemPrincipal !== undefined) {
throw new Components.Exception(
"newChannel requires the 'loadUsingSystemPrincipal'" +
" property on the options object to be 'true' or 'undefined'.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
if (securityFlags === undefined) {
if (!loadUsingSystemPrincipal) {
throw new Components.Exception(
"newChannel requires the 'securityFlags' property on" +
" the options object unless loading from system principal.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
}
if (contentPolicyType === undefined) {
if (!loadUsingSystemPrincipal) {
throw new Components.Exception(
"newChannel requires the 'contentPolicyType' property on" +
" the options object unless loading from system principal.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
}
return Services.io.newChannelFromURI(
uri,
loadingNode || null,
loadingPrincipal || null,
triggeringPrincipal || null,
securityFlags,
contentPolicyType
);
},
/**
* Reads aCount bytes from aInputStream into a string.
*
* @param aInputStream
* The input stream to read from.
* @param aCount
* The number of bytes to read from the stream.
* @param aOptions [optional]
* charset
* The character encoding of stream data.
* replacement
* The character to replace unknown byte sequences.
* If unset, it causes an exceptions to be thrown.
*
* @return the bytes from the input stream in string form.
*
* @throws NS_ERROR_INVALID_ARG if aInputStream is not an nsIInputStream.
* @throws NS_BASE_STREAM_WOULD_BLOCK if reading from aInputStream would
* block the calling thread (non-blocking mode only).
* @throws NS_ERROR_FAILURE if there are not enough bytes available to read
* aCount amount of data.
* @throws NS_ERROR_ILLEGAL_INPUT if aInputStream has invalid sequences
*/
readInputStreamToString: function NetUtil_readInputStreamToString(
aInputStream,
aCount,
aOptions
) {
if (!(aInputStream instanceof Ci.nsIInputStream)) {
let exception = new Components.Exception(
"First argument should be an nsIInputStream",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
if (!aCount) {
let exception = new Components.Exception(
"Non-zero amount of bytes must be specified",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
if (aOptions && "charset" in aOptions) {
let cis = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(
Ci.nsIConverterInputStream
);
try {
// When replacement is set, the character that is unknown sequence
// replaces with aOptions.replacement character.
if (!("replacement" in aOptions)) {
// aOptions.replacement isn't set.
// If input stream has unknown sequences for aOptions.charset,
// throw NS_ERROR_ILLEGAL_INPUT.
aOptions.replacement = 0;
}
// make a stream copier
var copier = Cc["@mozilla.org/network/async-stream-copier;1"].
createInstance(Ci.nsIAsyncStreamCopier2);
copier.init(aSource, aSink,
null /* Default event target */,
0 /* Default length */,
true, true /* Auto-close */);
cis.init(aInputStream, aOptions.charset, aCount, aOptions.replacement);
let str = {};
cis.readString(-1, str);
cis.close();
return str.value;
} catch (e) {
// Adjust the stack so it throws at the caller's location.
throw new Components.Exception(
e.message,
e.result,
Components.stack.caller,
e.data
);
}
}
var observer;
if (aCallback) {
observer = {
onStartRequest(aRequest) {},
onStopRequest(aRequest, aStatusCode) {
aCallback(aStatusCode);
},
};
} else {
observer = null;
}
let sis = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
Ci.nsIScriptableInputStream
);
sis.init(aInputStream);
try {
return sis.readBytes(aCount);
} catch (e) {
// Adjust the stack so it throws at the caller's location.
throw new Components.Exception(
e.message,
e.result,
Components.stack.caller,
e.data
);
}
},
// start the copying
copier.QueryInterface(Ci.nsIAsyncStreamCopier).asyncCopy(observer, null);
return copier;
},
/**
* Reads aCount bytes from aInputStream into a string.
*
* @param {nsIInputStream} aInputStream
* The input stream to read from.
* @param {integer} [aCount = aInputStream.available()]
* The number of bytes to read from the stream.
*
* @return the bytes from the input stream in string form.
*
* @throws NS_ERROR_INVALID_ARG if aInputStream is not an nsIInputStream.
* @throws NS_BASE_STREAM_WOULD_BLOCK if reading from aInputStream would
* block the calling thread (non-blocking mode only).
* @throws NS_ERROR_FAILURE if there are not enough bytes available to read
* aCount amount of data.
*/
readInputStream(aInputStream, aCount) {
if (!(aInputStream instanceof Ci.nsIInputStream)) {
let exception = new Components.Exception(
"First argument should be an nsIInputStream",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
/**
* Asynchronously opens a source and fetches the response. While the fetch
* is asynchronous, I/O may happen on the main thread. When reading from
* a local file, prefer using "OS.File" methods instead.
*
* @param aSource
* This argument can be one of the following:
* - An options object that will be passed to NetUtil.newChannel.
* - An existing nsIChannel.
* - An existing nsIInputStream.
* Using an nsIURI, nsIFile, or string spec directly is deprecated.
* @param aCallback
* The callback function that will be notified upon completion. It
* will get these arguments:
* 1) An nsIInputStream containing the data from aSource, if any.
* 2) The status code from opening the source.
* 3) Reference to the nsIRequest.
*/
asyncFetch: function NetUtil_asyncFetch(aSource, aCallback) {
if (!aSource || !aCallback) {
let exception = new Components.Exception(
"Must have a source and a callback",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
if (!aCount) {
aCount = aInputStream.available();
}
// Create a pipe that will create our output stream that we can use once
// we have gotten all the data.
let pipe = Cc["@mozilla.org/pipe;1"].
createInstance(Ci.nsIPipe);
pipe.init(true, true, 0, PR_UINT32_MAX, null);
// Create a listener that will give data to the pipe's output stream.
let listener = Cc["@mozilla.org/network/simple-stream-listener;1"].
createInstance(Ci.nsISimpleStreamListener);
listener.init(pipe.outputStream, {
onStartRequest(aRequest) {},
onStopRequest(aRequest, aStatusCode) {
pipe.outputStream.close();
aCallback(pipe.inputStream, aStatusCode, aRequest);
},
});
// Input streams are handled slightly differently from everything else.
if (aSource instanceof Ci.nsIInputStream) {
let pump = Cc["@mozilla.org/network/input-stream-pump;1"].
createInstance(Ci.nsIInputStreamPump);
pump.init(aSource, 0, 0, true);
pump.asyncRead(listener, null);
return;
}
let channel = aSource;
if (!(channel instanceof Ci.nsIChannel)) {
channel = this.newChannel(aSource);
}
try {
channel.asyncOpen(listener);
} catch (e) {
let exception = new Components.Exception(
"Failed to open input source '" + channel.originalURI.spec + "'",
e.result,
Components.stack.caller,
aSource,
e
);
throw exception;
}
},
/**
* Constructs a new URI for the given spec, character set, and base URI, or
* an nsIFile.
*
* @param aTarget
* The string spec for the desired URI or an nsIFile.
* @param aOriginCharset [optional]
* The character set for the URI. Only used if aTarget is not an
* nsIFile.
* @param aBaseURI [optional]
* The base URI for the spec. Only used if aTarget is not an
* nsIFile.
*
* @return an nsIURI object.
*/
newURI: function NetUtil_newURI(aTarget, aOriginCharset, aBaseURI) {
if (!aTarget) {
let exception = new Components.Exception(
"Must have a non-null string spec or nsIFile object",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
if (aTarget instanceof Ci.nsIFile) {
return Services.io.newFileURI(aTarget);
}
return Services.io.newURI(aTarget, aOriginCharset, aBaseURI);
},
/**
* Constructs a new channel for the given source.
*
* Keep in mind that URIs coming from a webpage should *never* use the
* systemPrincipal as the loadingPrincipal.
*
* @param aWhatToLoad
* This argument used to be a string spec for the desired URI, an
* nsIURI, or an nsIFile. Now it should be an options object with
* the following properties:
* {
* uri:
* The full URI spec string, nsIURI or nsIFile to create the
* channel for.
* Note that this cannot be an nsIFile if you have to specify a
* non-default charset or base URI. Call NetUtil.newURI first if
* you need to construct an URI using those options.
* loadingNode:
* loadingPrincipal:
* triggeringPrincipal:
* securityFlags:
* contentPolicyType:
* These will be used as values for the nsILoadInfo object on the
* created channel. For details, see nsILoadInfo in nsILoadInfo.idl
* loadUsingSystemPrincipal:
* Set this to true to use the system principal as
* loadingPrincipal. This must be omitted if loadingPrincipal or
* loadingNode are present.
* This should be used with care as it skips security checks.
* }
* @return an nsIChannel object.
*/
newChannel: function NetUtil_newChannel(aWhatToLoad) {
// Make sure the API is called using only the options object.
if (typeof aWhatToLoad != "object" || arguments.length != 1) {
throw new Components.Exception(
"newChannel requires a single object argument",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
let { uri,
loadingNode,
loadingPrincipal,
loadUsingSystemPrincipal,
triggeringPrincipal,
securityFlags,
contentPolicyType } = aWhatToLoad;
if (!uri) {
throw new Components.Exception(
"newChannel requires the 'uri' property on the options object.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
if (typeof uri == "string" || uri instanceof Ci.nsIFile) {
uri = this.newURI(uri);
}
if (!loadingNode && !loadingPrincipal && !loadUsingSystemPrincipal) {
throw new Components.Exception(
"newChannel requires at least one of the 'loadingNode'," +
" 'loadingPrincipal', or 'loadUsingSystemPrincipal'" +
" properties on the options object.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
if (loadUsingSystemPrincipal === true) {
if (loadingNode || loadingPrincipal) {
throw new Components.Exception(
"newChannel does not accept 'loadUsingSystemPrincipal'" +
" if the 'loadingNode' or 'loadingPrincipal' properties" +
" are present on the options object.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
loadingPrincipal = Services.scriptSecurityManager
.getSystemPrincipal();
} else if (loadUsingSystemPrincipal !== undefined) {
throw new Components.Exception(
"newChannel requires the 'loadUsingSystemPrincipal'" +
" property on the options object to be 'true' or 'undefined'.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
if (securityFlags === undefined) {
if (!loadUsingSystemPrincipal) {
throw new Components.Exception(
"newChannel requires the 'securityFlags' property on" +
" the options object unless loading from system principal.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
}
if (contentPolicyType === undefined) {
if (!loadUsingSystemPrincipal) {
throw new Components.Exception(
"newChannel requires the 'contentPolicyType' property on" +
" the options object unless loading from system principal.",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
}
contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
}
return Services.io.newChannelFromURI(uri,
loadingNode || null,
loadingPrincipal || null,
triggeringPrincipal || null,
securityFlags,
contentPolicyType);
},
/**
* Reads aCount bytes from aInputStream into a string.
*
* @param aInputStream
* The input stream to read from.
* @param aCount
* The number of bytes to read from the stream.
* @param aOptions [optional]
* charset
* The character encoding of stream data.
* replacement
* The character to replace unknown byte sequences.
* If unset, it causes an exceptions to be thrown.
*
* @return the bytes from the input stream in string form.
*
* @throws NS_ERROR_INVALID_ARG if aInputStream is not an nsIInputStream.
* @throws NS_BASE_STREAM_WOULD_BLOCK if reading from aInputStream would
* block the calling thread (non-blocking mode only).
* @throws NS_ERROR_FAILURE if there are not enough bytes available to read
* aCount amount of data.
* @throws NS_ERROR_ILLEGAL_INPUT if aInputStream has invalid sequences
*/
readInputStreamToString: function NetUtil_readInputStreamToString(aInputStream,
aCount,
aOptions) {
if (!(aInputStream instanceof Ci.nsIInputStream)) {
let exception = new Components.Exception(
"First argument should be an nsIInputStream",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
if (!aCount) {
let exception = new Components.Exception(
"Non-zero amount of bytes must be specified",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
if (aOptions && "charset" in aOptions) {
let cis = Cc["@mozilla.org/intl/converter-input-stream;1"].
createInstance(Ci.nsIConverterInputStream);
try {
// When replacement is set, the character that is unknown sequence
// replaces with aOptions.replacement character.
if (!("replacement" in aOptions)) {
// aOptions.replacement isn't set.
// If input stream has unknown sequences for aOptions.charset,
// throw NS_ERROR_ILLEGAL_INPUT.
aOptions.replacement = 0;
}
cis.init(aInputStream, aOptions.charset, aCount,
aOptions.replacement);
let str = {};
cis.readString(-1, str);
cis.close();
return str.value;
} catch (e) {
// Adjust the stack so it throws at the caller's location.
throw new Components.Exception(e.message, e.result,
Components.stack.caller, e.data);
}
}
let sis = Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
sis.init(aInputStream);
try {
return sis.readBytes(aCount);
} catch (e) {
// Adjust the stack so it throws at the caller's location.
throw new Components.Exception(e.message, e.result,
Components.stack.caller, e.data);
}
},
/**
* Reads aCount bytes from aInputStream into a string.
*
* @param {nsIInputStream} aInputStream
* The input stream to read from.
* @param {integer} [aCount = aInputStream.available()]
* The number of bytes to read from the stream.
*
* @return the bytes from the input stream in string form.
*
* @throws NS_ERROR_INVALID_ARG if aInputStream is not an nsIInputStream.
* @throws NS_BASE_STREAM_WOULD_BLOCK if reading from aInputStream would
* block the calling thread (non-blocking mode only).
* @throws NS_ERROR_FAILURE if there are not enough bytes available to read
* aCount amount of data.
*/
readInputStream(aInputStream, aCount) {
if (!(aInputStream instanceof Ci.nsIInputStream)) {
let exception = new Components.Exception(
"First argument should be an nsIInputStream",
Cr.NS_ERROR_INVALID_ARG,
Components.stack.caller
);
throw exception;
}
if (!aCount) {
aCount = aInputStream.available();
}
let stream = new BinaryInputStream(aInputStream);
let result = new ArrayBuffer(aCount);
stream.readArrayBuffer(result.byteLength, result);
return result;
},
let stream = new BinaryInputStream(aInputStream);
let result = new ArrayBuffer(aCount);
stream.readArrayBuffer(result.byteLength, result);
return result;
},
};

View file

@ -15,7 +15,7 @@ CookiePolicyHelper.runTest("BroadcastChannel", {
ok(true, "BroadcastChannel cannot be used!");
is(e.name, "SecurityError", "We want a security error message.");
}
}
},
});
CookiePolicyHelper.runTest("BroadcastChannel in workers", {
@ -25,7 +25,9 @@ CookiePolicyHelper.runTest("BroadcastChannel in workers", {
postMessage(true);
}
let blob = new w.Blob([nonBlockingCode.toString() + "; nonBlockingCode();"]);
let blob = new w.Blob([
nonBlockingCode.toString() + "; nonBlockingCode();",
]);
ok(blob, "Blob has been created");
let blobURL = w.URL.createObjectURL(blob);
@ -73,5 +75,5 @@ CookiePolicyHelper.runTest("BroadcastChannel in workers", {
}
};
});
}
},
});

View file

@ -2,17 +2,27 @@ CookiePolicyHelper.runTest("document.cookies", {
cookieJarAccessAllowed: async _ => {
let hasCookie = !!content.document.cookie.length;
await content.fetch("server.sjs").then(r => r.text()).then(text => {
is(text, hasCookie ? "cookie-present" : "cookie-not-present", "document.cookie is consistent with fetch requests");
});
await content
.fetch("server.sjs")
.then(r => r.text())
.then(text => {
is(
text,
hasCookie ? "cookie-present" : "cookie-not-present",
"document.cookie is consistent with fetch requests"
);
});
content.document.cookie = "name=value";
ok(content.document.cookie.includes("name=value"), "Some cookies for me");
ok(content.document.cookie.includes("foopy=1"), "Some cookies for me");
await content.fetch("server.sjs").then(r => r.text()).then(text => {
is(text, "cookie-present", "We should have cookies");
});
await content
.fetch("server.sjs")
.then(r => r.text())
.then(text => {
is(text, "cookie-present", "We should have cookies");
});
ok(!!content.document.cookie.length, "Some Cookies for me");
},
@ -22,14 +32,20 @@ CookiePolicyHelper.runTest("document.cookies", {
content.document.cookie = "name=value";
is(content.document.cookie, "", "No cookies for me");
await content.fetch("server.sjs").then(r => r.text()).then(text => {
is(text, "cookie-not-present", "We should not have cookies");
});
await content
.fetch("server.sjs")
.then(r => r.text())
.then(text => {
is(text, "cookie-not-present", "We should not have cookies");
});
// Let's do it twice.
await content.fetch("server.sjs").then(r => r.text()).then(text => {
is(text, "cookie-not-present", "We should not have cookies");
});
await content
.fetch("server.sjs")
.then(r => r.text())
.then(text => {
is(text, "cookie-not-present", "We should not have cookies");
});
is(content.document.cookie, "", "Still no cookies for me");
}
},
});

View file

@ -1,13 +1,23 @@
CookiePolicyHelper.runTest("DOM Cache", {
cookieJarAccessAllowed: async w => {
await w.caches.open("wow").then(
_ => { ok(true, "DOM Cache can be used!"); },
_ => { ok(false, "DOM Cache can be used!"); });
_ => {
ok(true, "DOM Cache can be used!");
},
_ => {
ok(false, "DOM Cache can be used!");
}
);
},
cookieJarAccessDenied: async w => {
await w.caches.open("wow").then(
_ => { ok(false, "DOM Cache cannot be used!"); },
_ => { ok(true, "DOM Cache cannot be used!"); });
_ => {
ok(false, "DOM Cache cannot be used!");
},
_ => {
ok(true, "DOM Cache cannot be used!");
}
);
},
});

View file

@ -14,7 +14,7 @@ let cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
// returns the newly opened tab
async function openTabInUserContext(uri, userContextId) {
// open the tab in the correct userContextId
let tab = BrowserTestUtils.addTab(gBrowser, uri, {userContextId});
let tab = BrowserTestUtils.addTab(gBrowser, uri, { userContextId });
// select tab and make sure its browser is focused
gBrowser.selectedTab = tab;
@ -24,15 +24,16 @@ async function openTabInUserContext(uri, userContextId) {
// wait for tab load
await BrowserTestUtils.browserLoaded(browser);
return {tab, browser};
return { tab, browser };
}
add_task(async function setup() {
// make sure userContext is enabled.
await new Promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [
["privacy.userContext.enabled", true]
]}, resolve);
SpecialPowers.pushPrefEnv(
{ set: [["privacy.userContext.enabled", true]] },
resolve
);
});
});
@ -41,15 +42,17 @@ add_task(async function test() {
// which should only be visible in that context
for (let userContextId of Object.keys(USER_CONTEXTS)) {
// open our tab in the given user context
let {tab, browser} = await openTabInUserContext(TEST_URL, userContextId);
let { tab, browser } = await openTabInUserContext(TEST_URL, userContextId);
await ContentTask.spawn(browser,
{names: COOKIE_NAMES, value: USER_CONTEXTS[userContextId]},
function(opts) {
for (let name of opts.names) {
content.document.cookie = name + "=" + opts.value;
}
});
await ContentTask.spawn(
browser,
{ names: COOKIE_NAMES, value: USER_CONTEXTS[userContextId] },
function(opts) {
for (let name of opts.names) {
content.document.cookie = name + "=" + opts.value;
}
}
);
// remove the tab
gBrowser.removeTab(tab);
@ -59,7 +62,7 @@ add_task(async function test() {
await checkCookies(expectedValues, "before removal");
// remove cookies that belongs to user context id #1
cm.removeCookiesWithOriginAttributes(JSON.stringify({userContextId: 1}));
cm.removeCookiesWithOriginAttributes(JSON.stringify({ userContextId: 1 }));
expectedValues[1] = undefined;
await checkCookies(expectedValues, "after removal");
@ -72,18 +75,25 @@ async function checkCookies(expectedValues, time) {
let expectedValue = expectedValues[userContextId];
for (let name of COOKIE_NAMES) {
is(cookiesFromTitle[name], expectedValue,
`User context ${userContextId}: ${name} should be correct from title ${time}`);
is(cookiesFromManager[name], expectedValue,
`User context ${userContextId}: ${name} should be correct from manager ${time}`);
is(
cookiesFromTitle[name],
expectedValue,
`User context ${userContextId}: ${name} should be correct from title ${time}`
);
is(
cookiesFromManager[name],
expectedValue,
`User context ${userContextId}: ${name} should be correct from manager ${time}`
);
}
}
}
function getCookiesFromManager(userContextId) {
let cookies = {};
let enumerator = cm.getCookiesWithOriginAttributes(JSON.stringify({userContextId}));
let enumerator = cm.getCookiesWithOriginAttributes(
JSON.stringify({ userContextId })
);
for (let cookie of enumerator) {
cookies[cookie.name] = cookie.value;
}
@ -91,7 +101,7 @@ function getCookiesFromManager(userContextId) {
}
async function getCookiesFromJS(userContextId) {
let {tab, browser} = await openTabInUserContext(TEST_URL, userContextId);
let { tab, browser } = await openTabInUserContext(TEST_URL, userContextId);
// get the cookies
let cookieString = await ContentTask.spawn(browser, null, function() {

View file

@ -7,18 +7,37 @@ CookiePolicyHelper.runTest("ServiceWorker", {
],
cookieJarAccessAllowed: async w => {
await w.navigator.serviceWorker.register("file_empty.js").then(
reg => { ok(true, "ServiceWorker can be used!"); return reg; },
_ => { ok(false, "ServiceWorker cannot be used! " + _); }).then(
reg => reg.unregister(),
_ => { ok(false, "unregister failed"); }).
catch(e => ok(false, "Promise rejected: " + e));
await w.navigator.serviceWorker
.register("file_empty.js")
.then(
reg => {
ok(true, "ServiceWorker can be used!");
return reg;
},
_ => {
ok(false, "ServiceWorker cannot be used! " + _);
}
)
.then(
reg => reg.unregister(),
_ => {
ok(false, "unregister failed");
}
)
.catch(e => ok(false, "Promise rejected: " + e));
},
cookieJarAccessDenied: async w => {
await w.navigator.serviceWorker.register("file_empty.js").then(
_ => { ok(false, "ServiceWorker cannot be used!"); },
_ => { ok(true, "ServiceWorker cannot be used!"); }).
catch(e => ok(false, "Promise rejected: " + e));
await w.navigator.serviceWorker
.register("file_empty.js")
.then(
_ => {
ok(false, "ServiceWorker cannot be used!");
},
_ => {
ok(true, "ServiceWorker cannot be used!");
}
)
.catch(e => ok(false, "Promise rejected: " + e));
},
});

View file

@ -20,52 +20,60 @@ const TEST_TOP_PAGE = TEST_DOMAIN + TEST_PATH + "file_empty.html";
this.CookiePolicyHelper = {
runTest(testName, config) {
// Testing allowed to blocked by cookie behavior
this._createTest(testName,
config.cookieJarAccessAllowed,
config.cookieJarAccessDenied,
config.prefs,
{
fromBehavior: BEHAVIOR_ACCEPT,
toBehavior: BEHAVIOR_REJECT,
fromPermission: PERM_DEFAULT,
toPermission: PERM_DEFAULT,
});
this._createTest(
testName,
config.cookieJarAccessAllowed,
config.cookieJarAccessDenied,
config.prefs,
{
fromBehavior: BEHAVIOR_ACCEPT,
toBehavior: BEHAVIOR_REJECT,
fromPermission: PERM_DEFAULT,
toPermission: PERM_DEFAULT,
}
);
// Testing blocked to allowed by cookie behavior
this._createTest(testName,
config.cookieJarAccessDenied,
config.cookieJarAccessAllowed,
config.prefs,
{
fromBehavior: BEHAVIOR_REJECT,
toBehavior: BEHAVIOR_ACCEPT,
fromPermission: PERM_DEFAULT,
toPermission: PERM_DEFAULT,
});
this._createTest(
testName,
config.cookieJarAccessDenied,
config.cookieJarAccessAllowed,
config.prefs,
{
fromBehavior: BEHAVIOR_REJECT,
toBehavior: BEHAVIOR_ACCEPT,
fromPermission: PERM_DEFAULT,
toPermission: PERM_DEFAULT,
}
);
// Testing allowed to blocked by cookie permission
this._createTest(testName,
config.cookieJarAccessAllowed,
config.cookieJarAccessDenied,
config.prefs,
{
fromBehavior: BEHAVIOR_REJECT,
toBehavior: BEHAVIOR_REJECT,
fromPermission: PERM_ALLOW,
toPermission: PERM_DEFAULT,
});
this._createTest(
testName,
config.cookieJarAccessAllowed,
config.cookieJarAccessDenied,
config.prefs,
{
fromBehavior: BEHAVIOR_REJECT,
toBehavior: BEHAVIOR_REJECT,
fromPermission: PERM_ALLOW,
toPermission: PERM_DEFAULT,
}
);
// Testing blocked to allowed by cookie permission
this._createTest(testName,
config.cookieJarAccessDenied,
config.cookieJarAccessAllowed,
config.prefs,
{
fromBehavior: BEHAVIOR_ACCEPT,
toBehavior: BEHAVIOR_ACCEPT,
fromPermission: PERM_DENY,
toPermission: PERM_DEFAULT,
});
this._createTest(
testName,
config.cookieJarAccessDenied,
config.cookieJarAccessAllowed,
config.prefs,
{
fromBehavior: BEHAVIOR_ACCEPT,
toBehavior: BEHAVIOR_ACCEPT,
fromPermission: PERM_DENY,
toPermission: PERM_DEFAULT,
}
);
},
_createTest(testName, goodCb, badCb, prefs, config) {
@ -75,16 +83,16 @@ this.CookiePolicyHelper = {
await SpecialPowers.flushPrefEnv();
if (prefs) {
await SpecialPowers.pushPrefEnv({"set": prefs });
await SpecialPowers.pushPrefEnv({ set: prefs });
}
let uri = Services.io.newURI(TEST_DOMAIN);
// Let's set the first cookie pref.
Services.perms.add(uri, "cookie", config.fromPermission);
await SpecialPowers.pushPrefEnv({"set": [
["network.cookie.cookieBehavior", config.fromBehavior],
]});
await SpecialPowers.pushPrefEnv({
set: [["network.cookie.cookieBehavior", config.fromBehavior]],
});
// Let's open a tab and load content.
let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
@ -94,10 +102,9 @@ this.CookiePolicyHelper = {
await BrowserTestUtils.browserLoaded(browser);
// Let's create an iframe.
await ContentTask.spawn(browser, { url: TEST_TOP_PAGE },
async obj => {
await ContentTask.spawn(browser, { url: TEST_TOP_PAGE }, async obj => {
return new content.Promise(resolve => {
let ifr = content.document.createElement('iframe');
let ifr = content.document.createElement("iframe");
ifr.setAttribute("id", "iframe");
ifr.src = obj.url;
ifr.onload = resolve;
@ -106,36 +113,50 @@ this.CookiePolicyHelper = {
});
// Let's exec the "good" callback.
info("Executing the test after setting the cookie behavior to " + config.fromBehavior + " and permission to " + config.fromPermission);
await ContentTask.spawn(browser,
{ callback: goodCb.toString() },
async obj => {
let runnableStr = `(() => {return (${obj.callback});})();`;
let runnable = eval(runnableStr); // eslint-disable-line no-eval
await runnable(content);
info(
"Executing the test after setting the cookie behavior to " +
config.fromBehavior +
" and permission to " +
config.fromPermission
);
await ContentTask.spawn(
browser,
{ callback: goodCb.toString() },
async obj => {
let runnableStr = `(() => {return (${obj.callback});})();`;
let runnable = eval(runnableStr); // eslint-disable-line no-eval
await runnable(content);
let ifr = content.document.getElementById("iframe");
await runnable(ifr.contentWindow);
});
let ifr = content.document.getElementById("iframe");
await runnable(ifr.contentWindow);
}
);
// Now, let's change the cookie settings
Services.perms.add(uri, "cookie", config.toPermission);
await SpecialPowers.pushPrefEnv({"set": [
["network.cookie.cookieBehavior", config.toBehavior],
]});
await SpecialPowers.pushPrefEnv({
set: [["network.cookie.cookieBehavior", config.toBehavior]],
});
// We still want the good callback to succeed.
info("Executing the test after setting the cookie behavior to " + config.toBehavior + " and permission to " + config.toPermission);
await ContentTask.spawn(browser,
{ callback: goodCb.toString() },
async obj => {
let runnableStr = `(() => {return (${obj.callback});})();`;
let runnable = eval(runnableStr); // eslint-disable-line no-eval
await runnable(content);
info(
"Executing the test after setting the cookie behavior to " +
config.toBehavior +
" and permission to " +
config.toPermission
);
await ContentTask.spawn(
browser,
{ callback: goodCb.toString() },
async obj => {
let runnableStr = `(() => {return (${obj.callback});})();`;
let runnable = eval(runnableStr); // eslint-disable-line no-eval
await runnable(content);
let ifr = content.document.getElementById("iframe");
await runnable(ifr.contentWindow);
});
let ifr = content.document.getElementById("iframe");
await runnable(ifr.contentWindow);
}
);
// Let's close the tab.
BrowserTestUtils.removeTab(tab);
@ -149,20 +170,25 @@ this.CookiePolicyHelper = {
// Let's exec the "bad" callback.
info("Executing the test in a new tab");
await ContentTask.spawn(browser,
{ callback: badCb.toString() },
async obj => {
let runnableStr = `(() => {return (${obj.callback});})();`;
let runnable = eval(runnableStr); // eslint-disable-line no-eval
await runnable(content);
});
await ContentTask.spawn(
browser,
{ callback: badCb.toString() },
async obj => {
let runnableStr = `(() => {return (${obj.callback});})();`;
let runnable = eval(runnableStr); // eslint-disable-line no-eval
await runnable(content);
}
);
// Let's close the tab.
BrowserTestUtils.removeTab(tab);
// Cleanup.
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, resolve);
Services.clearData.deleteData(
Ci.nsIClearDataService.CLEAR_ALL,
resolve
);
});
});
},

View file

@ -6,13 +6,18 @@ async function cleanupData() {
const chromeScript = SpecialPowers.loadChromeScript(_ => {
// eslint-disable-next-line no-undef
addMessageListener("go", __ => {
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Services.clearData.deleteData(Services.clearData.CLEAR_COOKIES |
Services.clearData.CLEAR_ALL_CACHES |
Services.clearData.CLEAR_DOM_STORAGES, ___ => {
// eslint-disable-next-line no-undef
sendAsyncMessage("done");
});
const { Services } = ChromeUtils.import(
"resource://gre/modules/Services.jsm"
);
Services.clearData.deleteData(
Services.clearData.CLEAR_COOKIES |
Services.clearData.CLEAR_ALL_CACHES |
Services.clearData.CLEAR_DOM_STORAGES,
___ => {
// eslint-disable-next-line no-undef
sendAsyncMessage("done");
}
);
});
});
@ -26,23 +31,33 @@ async function cleanupData() {
}
async function checkLastRequest(type, state) {
let json = await fetch("cookie.sjs?last&" + Math.random()).then(r => r.json());
let json = await fetch("cookie.sjs?last&" + Math.random()).then(r =>
r.json()
);
is(json.type, type, "Type: " + type);
is(json.hasCookie, state == ALLOWED, "Fetch has cookies");
}
async function runTests(currentTest) {
await cleanupData();
await SpecialPowers.pushPrefEnv({ set: [["network.cookie.cookieBehavior", 2]] });
await SpecialPowers.pushPrefEnv({
set: [["network.cookie.cookieBehavior", 2]],
});
let windowBlocked = window.open("cookie.sjs?window&" + Math.random());
await new Promise(resolve => { windowBlocked.onload = resolve; });
await new Promise(resolve => {
windowBlocked.onload = resolve;
});
await currentTest(windowBlocked, BLOCKED);
windowBlocked.close();
await cleanupData();
await SpecialPowers.pushPrefEnv({ set: [["network.cookie.cookieBehavior", 1]] });
await SpecialPowers.pushPrefEnv({
set: [["network.cookie.cookieBehavior", 1]],
});
let windowAllowed = window.open("cookie.sjs?window&" + Math.random());
await new Promise(resolve => { windowAllowed.onload = resolve; });
await new Promise(resolve => {
windowAllowed.onload = resolve;
});
await currentTest(windowAllowed, ALLOWED);
windowAllowed.close();

View file

@ -1,9 +1,8 @@
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const URI = Services.io.newURI("http://example.org/");
const cs = Cc["@mozilla.org/cookieService;1"]
.getService(Ci.nsICookieService);
const cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
function run_test() {
// Allow all cookies.
@ -14,29 +13,44 @@ function run_test() {
// Add a new cookie.
setCookie("foo=bar", {
type: "added", isSession: true, isSecure: false, isHttpOnly: false,
type: "added",
isSession: true,
isSecure: false,
isHttpOnly: false,
});
// Update cookie with isHttpOnly=true.
setCookie("foo=bar; HttpOnly", {
type: "changed", isSession: true, isSecure: false, isHttpOnly: true,
type: "changed",
isSession: true,
isSecure: false,
isHttpOnly: true,
});
// Update cookie with isSecure=true.
setCookie("foo=bar; Secure", {
type: "changed", isSession: true, isSecure: true, isHttpOnly: false,
type: "changed",
isSession: true,
isSecure: true,
isHttpOnly: false,
});
// Update cookie with isSession=false.
let expiry = new Date();
expiry.setUTCFullYear(expiry.getUTCFullYear() + 2);
setCookie(`foo=bar; Expires=${expiry.toGMTString()}`, {
type: "changed", isSession: false, isSecure: false, isHttpOnly: false,
type: "changed",
isSession: false,
isSecure: false,
isHttpOnly: false,
});
// Reset cookie.
setCookie("foo=bar", {
type: "changed", isSession: true, isSecure: false, isHttpOnly: false,
type: "changed",
isSession: true,
isSecure: false,
isHttpOnly: false,
});
}

View file

@ -1,4 +1,4 @@
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
do_get_profile();
const dirSvc = Services.dirsvc;
@ -7,52 +7,66 @@ let dbFile = dirSvc.get("ProfD", Ci.nsIFile);
dbFile.append("cookies.sqlite");
let storage = Services.storage;
let properties = Cc["@mozilla.org/hash-property-bag;1"].
createInstance(Ci.nsIWritablePropertyBag);
let properties = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
Ci.nsIWritablePropertyBag
);
properties.setProperty("shared", true);
let conn = storage.openDatabase(dbFile);
// Write the schema v7 to the database.
conn.schemaVersion = 7;
conn.executeSimpleSQL("CREATE TABLE moz_cookies (" +
"id INTEGER PRIMARY KEY, " +
"baseDomain TEXT, " +
"originAttributes TEXT NOT NULL DEFAULT '', " +
"name TEXT, " +
"value TEXT, " +
"host TEXT, " +
"path TEXT, " +
"expiry INTEGER, " +
"lastAccessed INTEGER, " +
"creationTime INTEGER, " +
"isSecure INTEGER, " +
"isHttpOnly INTEGER, " +
"appId INTEGER DEFAULT 0, " +
"inBrowserElement INTEGER DEFAULT 0, " +
"CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)" +
")");
conn.executeSimpleSQL("CREATE INDEX moz_basedomain ON moz_cookies (baseDomain, " +
"originAttributes)");
conn.executeSimpleSQL(
"CREATE TABLE moz_cookies (" +
"id INTEGER PRIMARY KEY, " +
"baseDomain TEXT, " +
"originAttributes TEXT NOT NULL DEFAULT '', " +
"name TEXT, " +
"value TEXT, " +
"host TEXT, " +
"path TEXT, " +
"expiry INTEGER, " +
"lastAccessed INTEGER, " +
"creationTime INTEGER, " +
"isSecure INTEGER, " +
"isHttpOnly INTEGER, " +
"appId INTEGER DEFAULT 0, " +
"inBrowserElement INTEGER DEFAULT 0, " +
"CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)" +
")"
);
conn.executeSimpleSQL(
"CREATE INDEX moz_basedomain ON moz_cookies (baseDomain, " +
"originAttributes)"
);
conn.executeSimpleSQL("PRAGMA synchronous = OFF");
conn.executeSimpleSQL("PRAGMA journal_mode = WAL");
conn.executeSimpleSQL("PRAGMA wal_autocheckpoint = 16");
let now = Date.now();
conn.executeSimpleSQL("INSERT INTO moz_cookies(" +
"baseDomain, host, name, value, path, expiry, " +
"lastAccessed, creationTime, isSecure, isHttpOnly) VALUES (" +
"'foo.com', '.foo.com', 'foo', 'bar=baz', '/', " +
now + ", " + now + ", " + now + ", 1, 1)");
conn.executeSimpleSQL(
"INSERT INTO moz_cookies(" +
"baseDomain, host, name, value, path, expiry, " +
"lastAccessed, creationTime, isSecure, isHttpOnly) VALUES (" +
"'foo.com', '.foo.com', 'foo', 'bar=baz', '/', " +
now +
", " +
now +
", " +
now +
", 1, 1)"
);
// Now start the cookie service, and then check the fields in the table.
// Get sessionEnumerator to wait for the initialization in cookie thread
const enumerator = Services.cookies.sessionEnumerator;
Assert.equal(conn.schemaVersion, 10);
let stmt = conn.createStatement("SELECT sql FROM sqlite_master " +
"WHERE type = 'table' AND " +
" name = 'moz_cookies'");
let stmt = conn.createStatement(
"SELECT sql FROM sqlite_master " +
"WHERE type = 'table' AND " +
" name = 'moz_cookies'"
);
try {
Assert.ok(stmt.executeStep());
let sql = stmt.getString(0);
@ -61,17 +75,25 @@ try {
stmt.finalize();
}
stmt = conn.createStatement("SELECT * FROM moz_cookies " +
"WHERE baseDomain = 'foo.com' AND " +
" host = '.foo.com' AND " +
" name = 'foo' AND " +
" value = 'bar=baz' AND " +
" path = '/' AND " +
" expiry = " + now + " AND " +
" lastAccessed = " + now + " AND " +
" creationTime = " + now + " AND " +
" isSecure = 1 AND " +
" isHttpOnly = 1");
stmt = conn.createStatement(
"SELECT * FROM moz_cookies " +
"WHERE baseDomain = 'foo.com' AND " +
" host = '.foo.com' AND " +
" name = 'foo' AND " +
" value = 'bar=baz' AND " +
" path = '/' AND " +
" expiry = " +
now +
" AND " +
" lastAccessed = " +
now +
" AND " +
" creationTime = " +
now +
" AND " +
" isSecure = 1 AND " +
" isHttpOnly = 1"
);
try {
Assert.ok(stmt.executeStep());
} finally {

View file

@ -1,5 +1,5 @@
const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
function run_test() {
// Allow all cookies.
@ -23,4 +23,3 @@ function run_test() {
actual = cs.getCookieString(uri, null, null);
Assert.equal(actual, expected);
}

View file

@ -1,4 +1,4 @@
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const BASE_HOSTNAMES = ["example.org", "example.co.uk"];
const SUBDOMAINS = ["", "pub.", "www.", "other."];
@ -7,138 +7,178 @@ const cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
const cm = cs.QueryInterface(Ci.nsICookieManager);
function run_test() {
Services.prefs.setIntPref("network.cookie.staleThreshold", 0);
add_task(async function() {
await test_basic_eviction("example.org");
cm.removeAll();
});
Services.prefs.setIntPref("network.cookie.staleThreshold", 0);
add_task(async function() {
await test_basic_eviction("example.org");
cm.removeAll();
});
run_next_test();
run_next_test();
}
async function test_basic_eviction(base_host) {
Services.prefs.setIntPref("network.cookie.quotaPerHost", 2);
Services.prefs.setIntPref("network.cookie.maxPerHost", 5);
Services.prefs.setIntPref("network.cookie.quotaPerHost", 2);
Services.prefs.setIntPref("network.cookie.maxPerHost", 5);
const BASE_URI = Services.io.newURI("http://" + base_host);
const FOO_PATH = Services.io.newURI("http://" + base_host + "/foo/");
const BAR_PATH = Services.io.newURI("http://" + base_host + "/bar/");
const BASE_URI = Services.io.newURI("http://" + base_host);
const FOO_PATH = Services.io.newURI("http://" + base_host + "/foo/");
const BAR_PATH = Services.io.newURI("http://" + base_host + "/bar/");
await setCookie("session_foo_path_1", null, "/foo", null, FOO_PATH);
await setCookie("session_foo_path_2", null, "/foo", null, FOO_PATH);
await setCookie("session_foo_path_3", null, "/foo", null, FOO_PATH);
await setCookie("session_foo_path_4", null, "/foo", null, FOO_PATH);
await setCookie("session_foo_path_5", null, "/foo", null, FOO_PATH);
verifyCookies(["session_foo_path_1",
"session_foo_path_2",
"session_foo_path_3",
"session_foo_path_4",
"session_foo_path_5"], BASE_URI);
await setCookie("session_foo_path_1", null, "/foo", null, FOO_PATH);
await setCookie("session_foo_path_2", null, "/foo", null, FOO_PATH);
await setCookie("session_foo_path_3", null, "/foo", null, FOO_PATH);
await setCookie("session_foo_path_4", null, "/foo", null, FOO_PATH);
await setCookie("session_foo_path_5", null, "/foo", null, FOO_PATH);
verifyCookies(
[
"session_foo_path_1",
"session_foo_path_2",
"session_foo_path_3",
"session_foo_path_4",
"session_foo_path_5",
],
BASE_URI
);
// Check if cookies are evicted by creation time.
await setCookie("session_foo_path_6", null, "/foo", null, FOO_PATH);
verifyCookies(["session_foo_path_4",
"session_foo_path_5",
"session_foo_path_6"], BASE_URI);
// Check if cookies are evicted by creation time.
await setCookie("session_foo_path_6", null, "/foo", null, FOO_PATH);
verifyCookies(
["session_foo_path_4", "session_foo_path_5", "session_foo_path_6"],
BASE_URI
);
await setCookie("session_bar_path_1", null, "/bar", null, BAR_PATH);
await setCookie("session_bar_path_2", null, "/bar", null, BAR_PATH);
await setCookie("session_bar_path_1", null, "/bar", null, BAR_PATH);
await setCookie("session_bar_path_2", null, "/bar", null, BAR_PATH);
verifyCookies(["session_foo_path_4",
"session_foo_path_5",
"session_foo_path_6",
"session_bar_path_1",
"session_bar_path_2"], BASE_URI);
verifyCookies(
[
"session_foo_path_4",
"session_foo_path_5",
"session_foo_path_6",
"session_bar_path_1",
"session_bar_path_2",
],
BASE_URI
);
// Check if cookies are evicted by last accessed time.
cs.getCookieString(FOO_PATH, null);
await setCookie("session_foo_path_7", null, "/foo", null, FOO_PATH);
verifyCookies(["session_foo_path_5",
"session_foo_path_6",
"session_foo_path_7"], BASE_URI);
// Check if cookies are evicted by last accessed time.
cs.getCookieString(FOO_PATH, null);
await setCookie("session_foo_path_7", null, "/foo", null, FOO_PATH);
verifyCookies(
["session_foo_path_5", "session_foo_path_6", "session_foo_path_7"],
BASE_URI
);
const EXPIRED_TIME = 3;
const EXPIRED_TIME = 3;
await setCookie("non_session_expired_foo_path_1", null, "/foo", EXPIRED_TIME, FOO_PATH);
await setCookie("non_session_expired_foo_path_2", null, "/foo", EXPIRED_TIME, FOO_PATH);
verifyCookies(["session_foo_path_5",
"session_foo_path_6",
"session_foo_path_7",
"non_session_expired_foo_path_1",
"non_session_expired_foo_path_2"], BASE_URI);
await setCookie(
"non_session_expired_foo_path_1",
null,
"/foo",
EXPIRED_TIME,
FOO_PATH
);
await setCookie(
"non_session_expired_foo_path_2",
null,
"/foo",
EXPIRED_TIME,
FOO_PATH
);
verifyCookies(
[
"session_foo_path_5",
"session_foo_path_6",
"session_foo_path_7",
"non_session_expired_foo_path_1",
"non_session_expired_foo_path_2",
],
BASE_URI
);
// Check if expired cookies are evicted first.
await new Promise(resolve => do_timeout(EXPIRED_TIME * 1000, resolve));
await setCookie("session_foo_path_8", null, "/foo", null, FOO_PATH);
verifyCookies(["session_foo_path_6",
"session_foo_path_7",
"session_foo_path_8"], BASE_URI);
// Check if expired cookies are evicted first.
await new Promise(resolve => do_timeout(EXPIRED_TIME * 1000, resolve));
await setCookie("session_foo_path_8", null, "/foo", null, FOO_PATH);
verifyCookies(
["session_foo_path_6", "session_foo_path_7", "session_foo_path_8"],
BASE_URI
);
}
// Verify that the given cookie names exist, and are ordered from least to most recently accessed
function verifyCookies(names, uri) {
Assert.equal(cm.countCookiesFromHost(uri.host), names.length);
let actual_cookies = [];
for (let cookie of cm.getCookiesFromHost(uri.host, {})) {
actual_cookies.push(cookie);
}
if (names.length != actual_cookies.length) {
let left = names.filter(function(n) {
return actual_cookies.findIndex(function(c) {
return c.name == n;
}) == -1;
});
let right = actual_cookies.filter(function(c) {
return names.findIndex(function(n) {
return c.name == n;
}) == -1;
}).map(function(c) { return c.name; });
if (left.length) {
info("unexpected cookies: " + left);
}
if (right.length) {
info("expected cookies: " + right);
}
}
Assert.equal(names.length, actual_cookies.length);
actual_cookies.sort(function(a, b) {
if (a.lastAccessed < b.lastAccessed)
return -1;
if (a.lastAccessed > b.lastAccessed)
return 1;
return 0;
Assert.equal(cm.countCookiesFromHost(uri.host), names.length);
let actual_cookies = [];
for (let cookie of cm.getCookiesFromHost(uri.host, {})) {
actual_cookies.push(cookie);
}
if (names.length != actual_cookies.length) {
let left = names.filter(function(n) {
return (
actual_cookies.findIndex(function(c) {
return c.name == n;
}) == -1
);
});
for (var i = 0; i < names.length; i++) {
Assert.equal(names[i], actual_cookies[i].name);
Assert.equal(names[i].startsWith("session"), actual_cookies[i].isSession);
let right = actual_cookies
.filter(function(c) {
return (
names.findIndex(function(n) {
return c.name == n;
}) == -1
);
})
.map(function(c) {
return c.name;
});
if (left.length) {
info("unexpected cookies: " + left);
}
if (right.length) {
info("expected cookies: " + right);
}
}
Assert.equal(names.length, actual_cookies.length);
actual_cookies.sort(function(a, b) {
if (a.lastAccessed < b.lastAccessed) {
return -1;
}
if (a.lastAccessed > b.lastAccessed) {
return 1;
}
return 0;
});
for (var i = 0; i < names.length; i++) {
Assert.equal(names[i], actual_cookies[i].name);
Assert.equal(names[i].startsWith("session"), actual_cookies[i].isSession);
}
}
var lastValue = 0;
function setCookie(name, domain, path, maxAge, url) {
let value = name + "=" + ++lastValue;
var s = "setting cookie " + value;
if (domain) {
value += "; Domain=" + domain;
s += " (d=" + domain + ")";
}
if (path) {
value += "; Path=" + path;
s += " (p=" + path + ")";
}
if (maxAge) {
value += "; Max-Age=" + maxAge;
s += " (non-session)";
} else {
s += " (session)";
}
s += " for " + url.spec;
info(s);
cs.setCookieStringFromHttp(url, null, null, value, null, null);
return new Promise(function(resolve) {
// Windows XP has low precision timestamps that cause our cookie eviction
// algorithm to produce different results from other platforms. We work around
// this by ensuring that there's a clear gap between each cookie update.
do_timeout(10, resolve);
});
let value = name + "=" + ++lastValue;
var s = "setting cookie " + value;
if (domain) {
value += "; Domain=" + domain;
s += " (d=" + domain + ")";
}
if (path) {
value += "; Path=" + path;
s += " (p=" + path + ")";
}
if (maxAge) {
value += "; Max-Age=" + maxAge;
s += " (non-session)";
} else {
s += " (session)";
}
s += " for " + url.spec;
info(s);
cs.setCookieStringFromHttp(url, null, null, value, null, null);
return new Promise(function(resolve) {
// Windows XP has low precision timestamps that cause our cookie eviction
// algorithm to produce different results from other platforms. We work around
// this by ensuring that there's a clear gap between each cookie update.
do_timeout(10, resolve);
});
}

View file

@ -1,5 +1,5 @@
const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
function inChildProcess() {
return Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
@ -7,8 +7,9 @@ function inChildProcess() {
function run_test() {
// Allow all cookies if the pref service is available in this process.
if (!inChildProcess())
if (!inChildProcess()) {
Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
}
let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
@ -21,4 +22,3 @@ function run_test() {
let actual = cs.getCookieStringFromHttp(uri, null, null);
Assert.equal(actual, expected);
}

View file

@ -1,5 +1,5 @@
const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
function inChildProcess() {
return Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
@ -7,8 +7,9 @@ function inChildProcess() {
function run_test() {
// Allow all cookies if the pref service is available in this process.
if (!inChildProcess())
if (!inChildProcess()) {
Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
}
let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
@ -21,4 +22,3 @@ function run_test() {
let actual = cs.getCookieStringFromHttp(uri, null, null);
Assert.equal(actual, expected);
}

View file

@ -1,5 +1,5 @@
const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
function inChildProcess() {
return Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
@ -12,14 +12,16 @@ add_task(async _ => {
dbFile.append("cookies.sqlite");
let storage = Services.storage;
let properties = Cc["@mozilla.org/hash-property-bag;1"].
createInstance(Ci.nsIWritablePropertyBag);
let properties = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
Ci.nsIWritablePropertyBag
);
properties.setProperty("shared", true);
let conn = storage.openDatabase(dbFile);
conn.schemaVersion = 9;
conn.executeSimpleSQL("DROP TABLE IF EXISTS moz_cookies");
conn.executeSimpleSQL("CREATE TABLE moz_cookies (" +
conn.executeSimpleSQL(
"CREATE TABLE moz_cookies (" +
"id INTEGER PRIMARY KEY, " +
"baseDomain TEXT, " +
"originAttributes TEXT NOT NULL DEFAULT '', " +
@ -35,22 +37,32 @@ add_task(async _ => {
"inBrowserElement INTEGER DEFAULT 0, " +
"sameSite INTEGER DEFAULT 0, " +
"CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)" +
")");
")"
);
conn.close();
// Allow all cookies if the pref service is available in this process.
if (!inChildProcess()) {
Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
Services.prefs.setBoolPref("network.cookieSettings.unblocked_for_testing", true);
Services.prefs.setBoolPref(
"network.cookieSettings.unblocked_for_testing",
true
);
Services.prefs.setBoolPref("network.cookie.sameSite.laxByDefault", true);
Services.prefs.setBoolPref("network.cookie.sameSite.noneRequiresSecure", true);
Services.prefs.setBoolPref(
"network.cookie.sameSite.noneRequiresSecure",
true
);
}
let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
let uri = NetUtil.newURI("http://example.org/");
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
let principal = Services.scriptSecurityManager.createCodebasePrincipal(
uri,
{}
);
let channel = NetUtil.newChannel({
uri,
@ -60,18 +72,17 @@ add_task(async _ => {
});
let tests = [
{ cookie: "foo=b;max-age=3600, c=d;path=/; sameSite=strict",
{
cookie: "foo=b;max-age=3600, c=d;path=/; sameSite=strict",
sameSite: 2,
rawSameSite: 2,
},
{ cookie: "foo=b;max-age=3600, c=d;path=/; sameSite=lax",
{
cookie: "foo=b;max-age=3600, c=d;path=/; sameSite=lax",
sameSite: 1,
rawSameSite: 1,
},
{ cookie: "foo=b;max-age=3600, c=d;path=/",
sameSite: 1,
rawSameSite: 0,
},
{ cookie: "foo=b;max-age=3600, c=d;path=/", sameSite: 1, rawSameSite: 0 },
];
for (let i = 0; i < tests.length; ++i) {
@ -93,7 +104,9 @@ add_task(async _ => {
conn = storage.openDatabase(dbFile);
Assert.equal(conn.schemaVersion, 10);
let stmt = conn.createStatement("SELECT sameSite, rawSameSite FROM moz_cookies");
let stmt = conn.createStatement(
"SELECT sameSite, rawSameSite FROM moz_cookies"
);
let success = stmt.executeStep();
Assert.ok(success);

View file

@ -3,23 +3,29 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { AppConstants } = ChromeUtils.import(
"resource://gre/modules/AppConstants.jsm"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {MulticastDNS} = ChromeUtils.import(
(AppConstants.platform == "android" && !Services.prefs.getBoolPref("network.mdns.use_js_fallback"))
? "resource://gre/modules/MulticastDNSAndroid.jsm"
: "resource://gre/modules/MulticastDNS.jsm");
const { MulticastDNS } = ChromeUtils.import(
AppConstants.platform == "android" &&
!Services.prefs.getBoolPref("network.mdns.use_js_fallback")
? "resource://gre/modules/MulticastDNSAndroid.jsm"
: "resource://gre/modules/MulticastDNS.jsm"
);
const DNSSERVICEINFO_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-info;1";
const DNSSERVICEINFO_CONTRACT_ID =
"@mozilla.org/toolkit/components/mdnsresponder/dns-info;1";
function log(aMsg) {
dump("-*- nsDNSServiceDiscovery.js : " + aMsg + "\n");
}
function generateUuid() {
var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].
getService(Ci.nsIUUIDGenerator);
var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(
Ci.nsIUUIDGenerator
);
return uuidGenerator.generateUUID().toString();
}
@ -40,9 +46,17 @@ function ListenerWrapper(aListener, aMdns) {
ListenerWrapper.prototype = {
// Helper function for transforming an Object into nsIDNSServiceInfo.
makeServiceInfo(aServiceInfo) {
let serviceInfo = Cc[DNSSERVICEINFO_CONTRACT_ID].createInstance(Ci.nsIDNSServiceInfo);
let serviceInfo = Cc[DNSSERVICEINFO_CONTRACT_ID].createInstance(
Ci.nsIDNSServiceInfo
);
for (let name of ["host", "address", "port", "serviceName", "serviceType"]) {
for (let name of [
"host",
"address",
"port",
"serviceName",
"serviceType",
]) {
try {
serviceInfo[name] = aServiceInfo[name];
} catch (e) {
@ -54,10 +68,11 @@ ListenerWrapper.prototype = {
try {
attributes = _toPropertyBag2(aServiceInfo.attributes);
} catch (err) {
// Ignore unset attributes in object.
log("Caught unset attributes error: " + err + " - " + err.stack);
attributes = Cc["@mozilla.org/hash-property-bag;1"]
.createInstance(Ci.nsIWritablePropertyBag2);
// Ignore unset attributes in object.
log("Caught unset attributes error: " + err + " - " + err.stack);
attributes = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
Ci.nsIWritablePropertyBag2
);
}
serviceInfo.attributes = attributes;
@ -113,15 +128,24 @@ ListenerWrapper.prototype = {
log("onRegistrationFailed: (" + aErrorCode + ")");
this.registrationStarting = false;
this.stopRegistration = true;
this.listener.onRegistrationFailed(this.makeServiceInfo(aServiceInfo), aErrorCode);
this.listener.onRegistrationFailed(
this.makeServiceInfo(aServiceInfo),
aErrorCode
);
},
onUnregistrationFailed(aServiceInfo, aErrorCode) {
log("onUnregistrationFailed: (" + aErrorCode + ")");
this.listener.onUnregistrationFailed(this.makeServiceInfo(aServiceInfo), aErrorCode);
this.listener.onUnregistrationFailed(
this.makeServiceInfo(aServiceInfo),
aErrorCode
);
},
onResolveFailed(aServiceInfo, aErrorCode) {
log("onResolveFailed: (" + aErrorCode + ")");
this.listener.onResolveFailed(this.makeServiceInfo(aServiceInfo), aErrorCode);
this.listener.onResolveFailed(
this.makeServiceInfo(aServiceInfo),
aErrorCode
);
},
};
@ -131,7 +155,10 @@ function nsDNSServiceDiscovery() {
}
nsDNSServiceDiscovery.prototype = {
QueryInterface: ChromeUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIDNSServiceDiscovery]),
QueryInterface: ChromeUtils.generateQI([
Ci.nsISupportsWeakReference,
Ci.nsIDNSServiceDiscovery,
]),
startDiscovery(aServiceType, aListener) {
log("startDiscovery");
@ -141,13 +168,13 @@ nsDNSServiceDiscovery.prototype = {
return {
QueryInterface: ChromeUtils.generateQI([Ci.nsICancelable]),
cancel: (function() {
cancel: function() {
if (this.discoveryStarting || this.stopDiscovery) {
this.stopDiscovery = true;
return;
}
this.mdns.stopDiscovery(aServiceType, listener);
}).bind(listener),
}.bind(listener),
};
},
@ -159,13 +186,13 @@ nsDNSServiceDiscovery.prototype = {
return {
QueryInterface: ChromeUtils.generateQI([Ci.nsICancelable]),
cancel: (function() {
cancel: function() {
if (this.registrationStarting || this.stopRegistration) {
this.stopRegistration = true;
return;
}
this.mdns.unregisterService(aServiceInfo, listener);
}).bind(listener),
}.bind(listener),
};
},
@ -182,8 +209,9 @@ function _toPropertyBag2(obj) {
return obj.QueryInterface(Ci.nsIPropertyBag2);
}
let result = Cc["@mozilla.org/hash-property-bag;1"]
.createInstance(Ci.nsIWritablePropertyBag2);
let result = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
Ci.nsIWritablePropertyBag2
);
for (let name in obj) {
result.setPropertyAsAString(name, obj[name]);
}

View file

@ -7,14 +7,18 @@
var EXPORTED_SYMBOLS = ["MulticastDNS"];
const {EventDispatcher} = ChromeUtils.import("resource://gre/modules/Messaging.jsm");
const { EventDispatcher } = ChromeUtils.import(
"resource://gre/modules/Messaging.jsm"
);
const DEBUG = false;
var log = function(s) {};
if (DEBUG) {
log = ChromeUtils.import("resource://gre/modules/AndroidLog.jsm", {})
.AndroidLog.d.bind(null, "MulticastDNS");
log = ChromeUtils.import(
"resource://gre/modules/AndroidLog.jsm",
{}
).AndroidLog.d.bind(null, "MulticastDNS");
}
const FAILURE_INTERNAL_ERROR = -65537;
@ -28,18 +32,20 @@ function send(type, data, callback) {
for (let i in data) {
try {
msg[i] = data[i];
} catch (e) {
}
} catch (e) {}
}
EventDispatcher.instance.sendRequestForResult(msg)
.then(result => callback(result, null),
err => callback(null, typeof err === "number" ? err : FAILURE_INTERNAL_ERROR));
EventDispatcher.instance
.sendRequestForResult(msg)
.then(
result => callback(result, null),
err =>
callback(null, typeof err === "number" ? err : FAILURE_INTERNAL_ERROR)
);
}
// Receives service found/lost event from NsdManager
function ServiceManager() {
}
function ServiceManager() {}
ServiceManager.prototype = {
listeners: {},
@ -145,11 +151,11 @@ function parsePropertyBag2(bag) {
}
let attributes = [];
for (let {name} of bag.enumerator) {
for (let { name } of bag.enumerator) {
let value = bag.getPropertyAsACString(name);
attributes.push({
"name": name,
"value": value,
name,
value,
});
}

View file

@ -8,12 +8,20 @@
var EXPORTED_SYMBOLS = ["DNSPacket"];
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {DataReader} = ChromeUtils.import("resource://gre/modules/DataReader.jsm");
const {DataWriter} = ChromeUtils.import("resource://gre/modules/DataWriter.jsm");
const {DNSRecord} = ChromeUtils.import("resource://gre/modules/DNSRecord.jsm");
const {DNSResourceRecord} = ChromeUtils.import("resource://gre/modules/DNSResourceRecord.jsm");
const { DataReader } = ChromeUtils.import(
"resource://gre/modules/DataReader.jsm"
);
const { DataWriter } = ChromeUtils.import(
"resource://gre/modules/DataWriter.jsm"
);
const { DNSRecord } = ChromeUtils.import(
"resource://gre/modules/DNSRecord.jsm"
);
const { DNSResourceRecord } = ChromeUtils.import(
"resource://gre/modules/DNSResourceRecord.jsm"
);
const DEBUG = true;
@ -25,7 +33,7 @@ let DNS_PACKET_SECTION_TYPES = [
"QD", // Question
"AN", // Answer
"NS", // Authority
"AR", // Additional
"AR", // Additional
];
/**
@ -125,7 +133,7 @@ class DNSPacket {
this._flags = _valueToFlags(0x0000);
this._records = {};
DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
DNS_PACKET_SECTION_TYPES.forEach(sectionType => {
this._records[sectionType] = [];
});
}
@ -142,20 +150,24 @@ class DNSPacket {
let recordCounts = {};
// Parse the record counts.
DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
DNS_PACKET_SECTION_TYPES.forEach(sectionType => {
recordCounts[sectionType] = reader.getValue(2);
});
// Parse the actual records.
DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
DNS_PACKET_SECTION_TYPES.forEach(sectionType => {
let recordCount = recordCounts[sectionType];
for (let i = 0; i < recordCount; i++) {
if (sectionType === "QD") {
packet.addRecord(sectionType,
DNSRecord.parseFromPacketReader(reader));
packet.addRecord(
sectionType,
DNSRecord.parseFromPacketReader(reader)
);
} else {
packet.addRecord(sectionType,
DNSResourceRecord.parseFromPacketReader(reader));
packet.addRecord(
sectionType,
DNSResourceRecord.parseFromPacketReader(reader)
);
}
}
});
@ -182,7 +194,7 @@ class DNSPacket {
getRecords(sectionTypes, recordType) {
let records = [];
sectionTypes.forEach((sectionType) => {
sectionTypes.forEach(sectionType => {
records = records.concat(this._records[sectionType]);
});
@ -203,13 +215,13 @@ class DNSPacket {
writer.putValue(_flagsToValue(this._flags), 2);
// Write lengths of record sections (2 bytes each)
DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
DNS_PACKET_SECTION_TYPES.forEach(sectionType => {
writer.putValue(this._records[sectionType].length, 2);
});
// Write records
DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
this._records[sectionType].forEach((record) => {
DNS_PACKET_SECTION_TYPES.forEach(sectionType => {
this._records[sectionType].forEach(record => {
writer.putBytes(record.serialize());
});
});
@ -222,12 +234,12 @@ class DNSPacket {
}
toJSONObject() {
let result = {flags: this._flags};
DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
let result = { flags: this._flags };
DNS_PACKET_SECTION_TYPES.forEach(sectionType => {
result[sectionType] = [];
let records = this._records[sectionType];
records.forEach((record) => {
records.forEach(record => {
result[sectionType].push(record.toJSONObject());
});
});

View file

@ -8,22 +8,26 @@
var EXPORTED_SYMBOLS = ["DNSRecord"];
const {DataWriter} = ChromeUtils.import("resource://gre/modules/DataWriter.jsm");
const {DNS_CLASS_CODES, DNS_RECORD_TYPES} = ChromeUtils.import("resource://gre/modules/DNSTypes.jsm");
const { DataWriter } = ChromeUtils.import(
"resource://gre/modules/DataWriter.jsm"
);
const { DNS_CLASS_CODES, DNS_RECORD_TYPES } = ChromeUtils.import(
"resource://gre/modules/DNSTypes.jsm"
);
class DNSRecord {
constructor(properties = {}) {
this.name = properties.name || "";
this.name = properties.name || "";
this.recordType = properties.recordType || DNS_RECORD_TYPES.ANY;
this.classCode = properties.classCode || DNS_CLASS_CODES.IN;
this.classCode = properties.classCode || DNS_CLASS_CODES.IN;
this.cacheFlush = properties.cacheFlush || false;
}
static parseFromPacketReader(reader) {
let name = reader.getLabel();
let name = reader.getLabel();
let recordType = reader.getValue(2);
let classCode = reader.getValue(2);
let cacheFlush = !!((classCode & 0x8000));
let classCode = reader.getValue(2);
let cacheFlush = !!(classCode & 0x8000);
classCode &= 0xff;
return new this({

View file

@ -8,10 +8,18 @@
var EXPORTED_SYMBOLS = ["DNSResourceRecord"];
const {DataReader} = ChromeUtils.import("resource://gre/modules/DataReader.jsm");
const {DataWriter} = ChromeUtils.import("resource://gre/modules/DataWriter.jsm");
const {DNSRecord} = ChromeUtils.import("resource://gre/modules/DNSRecord.jsm");
const {DNS_RECORD_TYPES} = ChromeUtils.import("resource://gre/modules/DNSTypes.jsm");
const { DataReader } = ChromeUtils.import(
"resource://gre/modules/DataReader.jsm"
);
const { DataWriter } = ChromeUtils.import(
"resource://gre/modules/DataWriter.jsm"
);
const { DNSRecord } = ChromeUtils.import(
"resource://gre/modules/DNSRecord.jsm"
);
const { DNS_RECORD_TYPES } = ChromeUtils.import(
"resource://gre/modules/DNSTypes.jsm"
);
const DNS_RESOURCE_RECORD_DEFAULT_TTL = 120; // 120 seconds
@ -19,14 +27,14 @@ class DNSResourceRecord extends DNSRecord {
constructor(properties = {}) {
super(properties);
this.ttl = properties.ttl || DNS_RESOURCE_RECORD_DEFAULT_TTL;
this.ttl = properties.ttl || DNS_RESOURCE_RECORD_DEFAULT_TTL;
this.data = properties.data || {};
}
static parseFromPacketReader(reader) {
let record = super.parseFromPacketReader(reader);
let ttl = reader.getValue(4);
let ttl = reader.getValue(4);
let recordData = reader.getBytes(reader.getValue(2));
let packetData = reader.data;
@ -50,7 +58,7 @@ class DNSResourceRecord extends DNSRecord {
break;
}
record.ttl = ttl;
record.ttl = ttl;
record.data = data;
return record;
@ -137,7 +145,7 @@ function _parseTXT(recordData, packetData) {
let label = reader.getLabel(packetData);
if (label.length > 0) {
let parts = label.split(".");
parts.forEach((part) => {
parts.forEach(part => {
let [name] = part.split("=", 1);
let value = part.substr(name.length + 1);
result[name] = value;
@ -154,9 +162,9 @@ function _parseSRV(recordData, packetData) {
let reader = new DataReader(recordData);
let priority = reader.getValue(2);
let weight = reader.getValue(2);
let port = reader.getValue(2);
let target = reader.getLabel(packetData);
let weight = reader.getValue(2);
let port = reader.getValue(2);
let target = reader.getLabel(packetData);
return { priority, weight, port, target };
}

View file

@ -14,87 +14,87 @@ var EXPORTED_SYMBOLS = [
];
let DNS_QUERY_RESPONSE_CODES = {
QUERY: 0, // RFC 1035 - Query
RESPONSE: 1, // RFC 1035 - Reponse
QUERY: 0, // RFC 1035 - Query
RESPONSE: 1, // RFC 1035 - Reponse
};
let DNS_AUTHORITATIVE_ANSWER_CODES = {
NO: 0, // RFC 1035 - Not Authoritative
YES: 1, // RFC 1035 - Is Authoritative
NO: 0, // RFC 1035 - Not Authoritative
YES: 1, // RFC 1035 - Is Authoritative
};
let DNS_CLASS_CODES = {
IN: 0x01, // RFC 1035 - Internet
CS: 0x02, // RFC 1035 - CSNET
CH: 0x03, // RFC 1035 - CHAOS
HS: 0x04, // RFC 1035 - Hesiod
NONE: 0xfe, // RFC 2136 - None
ANY: 0xff, // RFC 1035 - Any
IN: 0x01, // RFC 1035 - Internet
CS: 0x02, // RFC 1035 - CSNET
CH: 0x03, // RFC 1035 - CHAOS
HS: 0x04, // RFC 1035 - Hesiod
NONE: 0xfe, // RFC 2136 - None
ANY: 0xff, // RFC 1035 - Any
};
let DNS_RECORD_TYPES = {
SIGZERO: 0, // RFC 2931
A: 1, // RFC 1035
NS: 2, // RFC 1035
MD: 3, // RFC 1035
MF: 4, // RFC 1035
CNAME: 5, // RFC 1035
SOA: 6, // RFC 1035
MB: 7, // RFC 1035
MG: 8, // RFC 1035
MR: 9, // RFC 1035
NULL: 10, // RFC 1035
WKS: 11, // RFC 1035
PTR: 12, // RFC 1035
HINFO: 13, // RFC 1035
MINFO: 14, // RFC 1035
MX: 15, // RFC 1035
TXT: 16, // RFC 1035
RP: 17, // RFC 1183
AFSDB: 18, // RFC 1183
X25: 19, // RFC 1183
ISDN: 20, // RFC 1183
RT: 21, // RFC 1183
NSAP: 22, // RFC 1706
NSAP_PTR: 23, // RFC 1348
SIG: 24, // RFC 2535
KEY: 25, // RFC 2535
PX: 26, // RFC 2163
GPOS: 27, // RFC 1712
AAAA: 28, // RFC 1886
LOC: 29, // RFC 1876
NXT: 30, // RFC 2535
EID: 31, // RFC ????
NIMLOC: 32, // RFC ????
SRV: 33, // RFC 2052
ATMA: 34, // RFC ????
NAPTR: 35, // RFC 2168
KX: 36, // RFC 2230
CERT: 37, // RFC 2538
DNAME: 39, // RFC 2672
OPT: 41, // RFC 2671
APL: 42, // RFC 3123
DS: 43, // RFC 4034
SSHFP: 44, // RFC 4255
IPSECKEY: 45, // RFC 4025
RRSIG: 46, // RFC 4034
NSEC: 47, // RFC 4034
DNSKEY: 48, // RFC 4034
DHCID: 49, // RFC 4701
NSEC3: 50, // RFC ????
NSEC3PARAM: 51, // RFC ????
HIP: 55, // RFC 5205
SPF: 99, // RFC 4408
UINFO: 100, // RFC ????
UID: 101, // RFC ????
GID: 102, // RFC ????
UNSPEC: 103, // RFC ????
TKEY: 249, // RFC 2930
TSIG: 250, // RFC 2931
IXFR: 251, // RFC 1995
AXFR: 252, // RFC 1035
MAILB: 253, // RFC 1035
MAILA: 254, // RFC 1035
ANY: 255, // RFC 1035
DLV: 32769, // RFC 4431
SIGZERO: 0, // RFC 2931
A: 1, // RFC 1035
NS: 2, // RFC 1035
MD: 3, // RFC 1035
MF: 4, // RFC 1035
CNAME: 5, // RFC 1035
SOA: 6, // RFC 1035
MB: 7, // RFC 1035
MG: 8, // RFC 1035
MR: 9, // RFC 1035
NULL: 10, // RFC 1035
WKS: 11, // RFC 1035
PTR: 12, // RFC 1035
HINFO: 13, // RFC 1035
MINFO: 14, // RFC 1035
MX: 15, // RFC 1035
TXT: 16, // RFC 1035
RP: 17, // RFC 1183
AFSDB: 18, // RFC 1183
X25: 19, // RFC 1183
ISDN: 20, // RFC 1183
RT: 21, // RFC 1183
NSAP: 22, // RFC 1706
NSAP_PTR: 23, // RFC 1348
SIG: 24, // RFC 2535
KEY: 25, // RFC 2535
PX: 26, // RFC 2163
GPOS: 27, // RFC 1712
AAAA: 28, // RFC 1886
LOC: 29, // RFC 1876
NXT: 30, // RFC 2535
EID: 31, // RFC ????
NIMLOC: 32, // RFC ????
SRV: 33, // RFC 2052
ATMA: 34, // RFC ????
NAPTR: 35, // RFC 2168
KX: 36, // RFC 2230
CERT: 37, // RFC 2538
DNAME: 39, // RFC 2672
OPT: 41, // RFC 2671
APL: 42, // RFC 3123
DS: 43, // RFC 4034
SSHFP: 44, // RFC 4255
IPSECKEY: 45, // RFC 4025
RRSIG: 46, // RFC 4034
NSEC: 47, // RFC 4034
DNSKEY: 48, // RFC 4034
DHCID: 49, // RFC 4701
NSEC3: 50, // RFC ????
NSEC3PARAM: 51, // RFC ????
HIP: 55, // RFC 5205
SPF: 99, // RFC 4408
UINFO: 100, // RFC ????
UID: 101, // RFC ????
GID: 102, // RFC ????
UNSPEC: 103, // RFC ????
TKEY: 249, // RFC 2930
TSIG: 250, // RFC 2931
IXFR: 251, // RFC 1995
AXFR: 252, // RFC 1035
MAILB: 253, // RFC 1035
MAILA: 254, // RFC 1035
ANY: 255, // RFC 1035
DLV: 32769, // RFC 4431
};

View file

@ -105,7 +105,9 @@ function _uint8ArrayToString(uint8Array) {
let results = [];
for (let i = 0; i < length; i += 1024) {
results.push(String.fromCharCode.apply(null, uint8Array.subarray(i, i + 1024)));
results.push(
String.fromCharCode.apply(null, uint8Array.subarray(i, i + 1024))
);
}
return results.join("");

View file

@ -66,7 +66,7 @@ class DataWriter {
// Eliminate any trailing '.'s in the label (valid in text representation).
label = label.replace(/\.$/, "");
let parts = label.split(".");
parts.forEach((part) => {
parts.forEach(part => {
this.putLengthString(part);
});
this.putValue(0);
@ -74,7 +74,7 @@ class DataWriter {
putLengthString(string) {
if (string.length > 0xff) {
throw new Error("String too long.");
throw new Error("String too long.");
}
this.putValue(string.length);
for (let i = 0; i < string.length; i++) {

View file

@ -8,33 +8,56 @@
var EXPORTED_SYMBOLS = ["MulticastDNS"];
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {clearTimeout, setTimeout} = ChromeUtils.import("resource://gre/modules/Timer.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { clearTimeout, setTimeout } = ChromeUtils.import(
"resource://gre/modules/Timer.jsm"
);
const {DNSPacket} = ChromeUtils.import("resource://gre/modules/DNSPacket.jsm");
const {DNSRecord} = ChromeUtils.import("resource://gre/modules/DNSRecord.jsm");
const {DNSResourceRecord} = ChromeUtils.import("resource://gre/modules/DNSResourceRecord.jsm");
const {DNS_AUTHORITATIVE_ANSWER_CODES, DNS_CLASS_CODES, DNS_QUERY_RESPONSE_CODES, DNS_RECORD_TYPES} = ChromeUtils.import("resource://gre/modules/DNSTypes.jsm");
const { DNSPacket } = ChromeUtils.import(
"resource://gre/modules/DNSPacket.jsm"
);
const { DNSRecord } = ChromeUtils.import(
"resource://gre/modules/DNSRecord.jsm"
);
const { DNSResourceRecord } = ChromeUtils.import(
"resource://gre/modules/DNSResourceRecord.jsm"
);
const {
DNS_AUTHORITATIVE_ANSWER_CODES,
DNS_CLASS_CODES,
DNS_QUERY_RESPONSE_CODES,
DNS_RECORD_TYPES,
} = ChromeUtils.import("resource://gre/modules/DNSTypes.jsm");
const NS_NETWORK_LINK_TOPIC = "network:link-status-changed";
let networkInfoService = Cc["@mozilla.org/network-info-service;1"]
.createInstance(Ci.nsINetworkInfoService);
let networkInfoService = Cc[
"@mozilla.org/network-info-service;1"
].createInstance(Ci.nsINetworkInfoService);
const DEBUG = true;
const MDNS_MULTICAST_GROUP = "224.0.0.251";
const MDNS_PORT = 5353;
const DEFAULT_TTL = 120;
const MDNS_PORT = 5353;
const DEFAULT_TTL = 120;
function debug(msg) {
dump("MulticastDNS: " + msg + "\n");
}
function ServiceKey(svc) {
return "" + svc.serviceType.length + "/" + svc.serviceType + "|" +
svc.serviceName.length + "/" + svc.serviceName + "|" +
svc.port;
return (
"" +
svc.serviceType.length +
"/" +
svc.serviceType +
"|" +
svc.serviceName.length +
"/" +
svc.serviceName +
"|" +
svc.port
);
}
function TryGet(obj, name) {
@ -77,9 +100,11 @@ class PublishedService {
}
equals(svc) {
return (this.port == svc.port) &&
(this.serviceName == svc.serviceName) &&
(this.serviceType == svc.serviceType);
return (
this.port == svc.port &&
this.serviceName == svc.serviceName &&
this.serviceType == svc.serviceType
);
}
generateKey() {
@ -87,7 +112,7 @@ class PublishedService {
}
ptrMatch(name) {
return name == (this.serviceType + "." + this.domainName);
return name == this.serviceType + "." + this.domainName;
}
clearAdvertiseTimer() {
@ -101,17 +126,23 @@ class PublishedService {
class MulticastDNS {
constructor() {
this._listeners = new Map();
this._sockets = new Map();
this._services = new Map();
this._discovered = new Map();
this._querySocket = undefined;
this._listeners = new Map();
this._sockets = new Map();
this._services = new Map();
this._discovered = new Map();
this._querySocket = undefined;
this._broadcastReceiverSocket = undefined;
this._broadcastTimer = undefined;
this._broadcastTimer = undefined;
this._networkLinkObserver = {
observe: (subject, topic, data) => {
DEBUG && debug(NS_NETWORK_LINK_TOPIC + "(" + data + "); Clearing list of previously discovered services");
DEBUG &&
debug(
NS_NETWORK_LINK_TOPIC +
"(" +
data +
"); Clearing list of previously discovered services"
);
this._discovered.clear();
},
};
@ -124,7 +155,10 @@ class MulticastDNS {
if (!this._isNetworkLinkObserverAttached) {
DEBUG && debug("Attaching observer " + NS_NETWORK_LINK_TOPIC);
Services.obs.addObserver(this._networkLinkObserver, NS_NETWORK_LINK_TOPIC);
Services.obs.addObserver(
this._networkLinkObserver,
NS_NETWORK_LINK_TOPIC
);
this._isNetworkLinkObserverAttached = true;
}
}
@ -137,7 +171,10 @@ class MulticastDNS {
this._networkLinkObserverTimeout = setTimeout(() => {
DEBUG && debug("Detaching observer " + NS_NETWORK_LINK_TOPIC);
Services.obs.removeObserver(this._networkLinkObserver, NS_NETWORK_LINK_TOPIC);
Services.obs.removeObserver(
this._networkLinkObserver,
NS_NETWORK_LINK_TOPIC
);
this._isNetworkLinkObserverAttached = false;
this._networkLinkObserverTimeout = null;
}, 5000);
@ -199,22 +236,32 @@ class MulticastDNS {
try {
publishedService = new PublishedService(aServiceInfo);
} catch (e) {
DEBUG && debug("Error constructing PublishedService: " + e + " - " + e.stack);
setTimeout(() => aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
DEBUG &&
debug("Error constructing PublishedService: " + e + " - " + e.stack);
setTimeout(() =>
aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE)
);
return;
}
// Ensure such a service does not already exist.
if (this._services.get(publishedService.key)) {
setTimeout(() => aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
setTimeout(() =>
aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE)
);
return;
}
// Make sure that the service addr is '0.0.0.0', or there is at least one
// socket open on the address the service is open on.
this._getSockets().then((sockets) => {
if (publishedService.address != "0.0.0.0" && !sockets.get(publishedService.address)) {
setTimeout(() => aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
this._getSockets().then(sockets => {
if (
publishedService.address != "0.0.0.0" &&
!sockets.get(publishedService.address)
) {
setTimeout(() =>
aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE)
);
return;
}
@ -237,13 +284,17 @@ class MulticastDNS {
try {
serviceKey = ServiceKey(aServiceInfo);
} catch (e) {
setTimeout(() => aListener.onUnregistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
setTimeout(() =>
aListener.onUnregistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE)
);
return;
}
let publishedService = this._services.get(serviceKey);
if (!publishedService) {
setTimeout(() => aListener.onUnregistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
setTimeout(() =>
aListener.onUnregistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE)
);
return;
}
@ -252,7 +303,9 @@ class MulticastDNS {
// Delete the service from the service map.
if (!this._services.delete(serviceKey)) {
setTimeout(() => aListener.onUnregistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
setTimeout(() =>
aListener.onUnregistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE)
);
return;
}
@ -268,8 +321,15 @@ class MulticastDNS {
_respondToQuery(serviceKey, message) {
let address = message.fromAddr.address;
let port = message.fromAddr.port;
DEBUG && debug("_respondToQuery(): key=" + serviceKey + ", fromAddr="
+ address + ":" + port);
DEBUG &&
debug(
"_respondToQuery(): key=" +
serviceKey +
", fromAddr=" +
address +
":" +
port
);
let publishedService = this._services.get(serviceKey);
if (!publishedService) {
@ -277,15 +337,20 @@ class MulticastDNS {
return;
}
DEBUG && debug("_respondToQuery(): key=" + serviceKey + ": SENDING RESPONSE");
this._advertiseServiceHelper(publishedService, {address, port});
DEBUG &&
debug("_respondToQuery(): key=" + serviceKey + ": SENDING RESPONSE");
this._advertiseServiceHelper(publishedService, { address, port });
}
_advertiseService(serviceKey, firstAdv) {
DEBUG && debug("_advertiseService(): key=" + serviceKey);
let publishedService = this._services.get(serviceKey);
if (!publishedService) {
debug("_advertiseService Could not find service to advertise (key=" + serviceKey + ")");
debug(
"_advertiseService Could not find service to advertise (key=" +
serviceKey +
")"
);
return;
}
@ -307,10 +372,10 @@ class MulticastDNS {
_advertiseServiceHelper(svc, target) {
if (!target) {
target = {address: MDNS_MULTICAST_GROUP, port: MDNS_PORT};
target = { address: MDNS_MULTICAST_GROUP, port: MDNS_PORT };
}
return this._getSockets().then((sockets) => {
return this._getSockets().then(sockets => {
sockets.forEach((socket, address) => {
if (svc.address == "0.0.0.0" || address == svc.address) {
let packet = this._makeServicePacket(svc, [address]);
@ -318,8 +383,10 @@ class MulticastDNS {
try {
socket.send(target.address, target.port, data);
} catch (err) {
DEBUG && debug("Failed to send packet to "
+ target.address + ":" + target.port);
DEBUG &&
debug(
"Failed to send packet to " + target.address + ":" + target.port
);
}
}
});
@ -355,14 +422,14 @@ class MulticastDNS {
let msSinceAdv = now - publishedService.lastAdvertised;
// If msSinceAdv is more than 90% of the way to the TTL, advertise now.
if (msSinceAdv > (DEFAULT_TTL * 1000 * 0.9)) {
if (msSinceAdv > DEFAULT_TTL * 1000 * 0.9) {
bcastServices.push(publishedService);
continue;
}
// Otherwise, calculate the next time to advertise for this service.
// We set that at 95% of the time to the TTL expiry.
let nextAdvWait = (DEFAULT_TTL * 1000 * 0.95) - msSinceAdv;
let nextAdvWait = DEFAULT_TTL * 1000 * 0.95 - msSinceAdv;
if (nextBcastWait === undefined || nextBcastWait > nextAdvWait) {
nextBcastWait = nextAdvWait;
}
@ -370,13 +437,21 @@ class MulticastDNS {
// Schedule an immediate advertisement of all services to be advertised now.
for (let svc of bcastServices) {
svc.advertiseTimer = setTimeout(() => this._advertiseService(svc.key));
svc.advertiseTimer = setTimeout(() => this._advertiseService(svc.key));
}
// Schedule next broadcast check for the next bcast time.
if (nextBcastWait !== undefined) {
DEBUG && debug("_checkStartBroadcastTimer(): Scheduling next check in " + nextBcastWait + "ms");
this._broadcastTimer = setTimeout(() => this._checkStartBroadcastTimer(), nextBcastWait);
DEBUG &&
debug(
"_checkStartBroadcastTimer(): Scheduling next check in " +
nextBcastWait +
"ms"
);
this._broadcastTimer = setTimeout(
() => this._checkStartBroadcastTimer(),
nextBcastWait
);
}
}
@ -386,12 +461,15 @@ class MulticastDNS {
packet.setFlag("QR", DNS_QUERY_RESPONSE_CODES.QUERY);
// PTR Record
packet.addRecord("QD", new DNSRecord({
name,
recordType: DNS_RECORD_TYPES.PTR,
classCode: DNS_CLASS_CODES.IN,
cacheFlush: true,
}));
packet.addRecord(
"QD",
new DNSRecord({
name,
recordType: DNS_RECORD_TYPES.PTR,
classCode: DNS_CLASS_CODES.IN,
cacheFlush: true,
})
);
let data = packet.serialize();
@ -400,7 +478,7 @@ class MulticastDNS {
// multicast queries/announcements on all interfaces.
this._getBroadcastReceiverSocket();
this._getQuerySocket().then((querySocket) => {
this._getQuerySocket().then(querySocket => {
DEBUG && debug('sending query on query socket ("' + name + '")');
querySocket.send(MDNS_MULTICAST_GROUP, MDNS_PORT, data);
});
@ -408,7 +486,8 @@ class MulticastDNS {
// Automatically announce previously-discovered
// services that match and haven't expired yet.
setTimeout(() => {
DEBUG && debug('announcing previously discovered services ("' + name + '")');
DEBUG &&
debug('announcing previously discovered services ("' + name + '")');
let { serviceType } = _parseServiceDomainName(name);
this._clearExpiredDiscoveries();
@ -419,7 +498,7 @@ class MulticastDNS {
}
let listeners = this._listeners.get(serviceInfo.serviceType) || [];
listeners.forEach((listener) => {
listeners.forEach(listener => {
listener.onServiceFound(serviceInfo);
});
});
@ -435,16 +514,20 @@ class MulticastDNS {
}
_handleQueryPacket(packet, message) {
packet.getRecords(["QD"]).forEach((record) => {
packet.getRecords(["QD"]).forEach(record => {
// Don't respond if the query's class code is not IN or ANY.
if (record.classCode !== DNS_CLASS_CODES.IN &&
record.classCode !== DNS_CLASS_CODES.ANY) {
if (
record.classCode !== DNS_CLASS_CODES.IN &&
record.classCode !== DNS_CLASS_CODES.ANY
) {
return;
}
// Don't respond if the query's record type is not PTR or ANY.
if (record.recordType !== DNS_RECORD_TYPES.PTR &&
record.recordType !== DNS_RECORD_TYPES.ANY) {
if (
record.recordType !== DNS_RECORD_TYPES.PTR &&
record.recordType !== DNS_RECORD_TYPES.ANY
) {
return;
}
@ -465,46 +548,59 @@ class MulticastDNS {
let host = service.host || _hostname;
// e.g.: foo-bar-service._http._tcp.local
let serviceDomainName = service.serviceName + "." + service.serviceType + ".local";
let serviceDomainName =
service.serviceName + "." + service.serviceType + ".local";
// PTR Record
packet.addRecord("AN", new DNSResourceRecord({
name: service.serviceType + ".local", // e.g.: _http._tcp.local
recordType: DNS_RECORD_TYPES.PTR,
data: serviceDomainName,
}));
packet.addRecord(
"AN",
new DNSResourceRecord({
name: service.serviceType + ".local", // e.g.: _http._tcp.local
recordType: DNS_RECORD_TYPES.PTR,
data: serviceDomainName,
})
);
// SRV Record
packet.addRecord("AR", new DNSResourceRecord({
name: serviceDomainName,
recordType: DNS_RECORD_TYPES.SRV,
classCode: DNS_CLASS_CODES.IN,
cacheFlush: true,
data: {
priority: 0,
weight: 0,
port: service.port,
target: host, // e.g.: My-Android-Phone.local
},
}));
packet.addRecord(
"AR",
new DNSResourceRecord({
name: serviceDomainName,
recordType: DNS_RECORD_TYPES.SRV,
classCode: DNS_CLASS_CODES.IN,
cacheFlush: true,
data: {
priority: 0,
weight: 0,
port: service.port,
target: host, // e.g.: My-Android-Phone.local
},
})
);
// A Records
for (let address of addresses) {
packet.addRecord("AR", new DNSResourceRecord({
packet.addRecord(
"AR",
new DNSResourceRecord({
name: host,
recordType: DNS_RECORD_TYPES.A,
data: address,
}));
})
);
}
// TXT Record
packet.addRecord("AR", new DNSResourceRecord({
name: serviceDomainName,
recordType: DNS_RECORD_TYPES.TXT,
classCode: DNS_CLASS_CODES.IN,
cacheFlush: true,
data: service.serviceAttrs || {},
}));
packet.addRecord(
"AR",
new DNSResourceRecord({
name: serviceDomainName,
recordType: DNS_RECORD_TYPES.TXT,
classCode: DNS_CLASS_CODES.IN,
cacheFlush: true,
data: service.serviceAttrs || {},
})
);
return packet;
}
@ -518,7 +614,7 @@ class MulticastDNS {
let ptrRecords = packet.getRecords(["AN", "AR"], DNS_RECORD_TYPES.PTR);
let aRecords = packet.getRecords(["AN", "AR"], DNS_RECORD_TYPES.A);
srvRecords.forEach((record) => {
srvRecords.forEach(record => {
let data = record.data || {};
services[record.name] = {
@ -528,7 +624,7 @@ class MulticastDNS {
};
});
txtRecords.forEach((record) => {
txtRecords.forEach(record => {
if (!services[record.name]) {
return;
}
@ -536,24 +632,26 @@ class MulticastDNS {
services[record.name].attributes = record.data;
});
aRecords.forEach((record) => {
aRecords.forEach(record => {
if (IsIpv4Address(record.data)) {
hosts[record.name] = record.data;
}
});
ptrRecords.forEach((record) => {
ptrRecords.forEach(record => {
let name = record.data;
if (!services[name]) {
return;
}
let {host, port} = services[name];
let { host, port } = services[name];
if (!host || !port) {
return;
}
let { serviceName, serviceType, domainName } = _parseServiceDomainName(name);
let { serviceName, serviceType, domainName } = _parseServiceDomainName(
name
);
if (!serviceName || !serviceType || !domainName) {
return;
}
@ -579,12 +677,17 @@ class MulticastDNS {
}
_onServiceFound(serviceInfo, ttl = 0) {
let expireTime = Date.now() + (ttl * 1000);
let key = serviceInfo.serviceName + "." +
serviceInfo.serviceType + "." +
serviceInfo.domainName + " @" +
serviceInfo.address + ":" +
serviceInfo.port;
let expireTime = Date.now() + ttl * 1000;
let key =
serviceInfo.serviceName +
"." +
serviceInfo.serviceType +
"." +
serviceInfo.domainName +
" @" +
serviceInfo.address +
":" +
serviceInfo.port;
// If this service was already discovered, just update
// its expiration time and don't re-emit it.
@ -599,7 +702,7 @@ class MulticastDNS {
});
let listeners = this._listeners.get(serviceInfo.serviceType) || [];
listeners.forEach((listener) => {
listeners.forEach(listener => {
listener.onServiceFound(serviceInfo);
});
@ -636,10 +739,15 @@ class MulticastDNS {
_getBroadcastReceiverSocket() {
return new Promise((resolve, reject) => {
if (!this._broadcastReceiverSocket) {
this._broadcastReceiverSocket = _openSocket("0.0.0.0", MDNS_PORT, {
onPacketReceived: this._onPacketReceived.bind(this),
onStopListening: this._onStopListening.bind(this),
}, /* multicastInterface = */ "0.0.0.0");
this._broadcastReceiverSocket = _openSocket(
"0.0.0.0",
MDNS_PORT,
{
onPacketReceived: this._onPacketReceived.bind(this),
onStopListening: this._onStopListening.bind(this),
},
/* multicastInterface = */ "0.0.0.0"
);
}
resolve(this._broadcastReceiverSocket);
});
@ -656,14 +764,14 @@ class MulticastDNS {
* already handling them.
*/
_getSockets() {
return new Promise((resolve) => {
return new Promise(resolve => {
if (this._sockets.size > 0) {
resolve(this._sockets);
return;
}
Promise.all([getAddresses(), getHostname()]).then(() => {
_addresses.forEach((address) => {
_addresses.forEach(address => {
let socket = _openSocket(address, MDNS_PORT, null);
this._sockets.set(address, socket);
});
@ -675,17 +783,20 @@ class MulticastDNS {
_checkCloseSockets() {
// Nothing to do if no sockets to close.
if (this._sockets.size == 0)
if (this._sockets.size == 0) {
return;
}
// Don't close sockets if discovery listeners are still present.
if (this._listeners.size > 0)
if (this._listeners.size > 0) {
return;
}
// Don't close sockets if advertised services are present.
// Since we need to listen for service queries and respond to them.
if (this._services.size > 0)
if (this._services.size > 0) {
return;
}
this._closeSockets();
}
@ -757,10 +868,12 @@ function getAddresses() {
networkInfoService.listNetworkAddresses({
onListedNetworkAddresses(aAddressArray) {
_addresses = aAddressArray.filter((address) => {
return !address.includes("%p2p") && // No WiFi Direct interfaces
!address.includes(":") && // XXX: No IPv6 for now
address != "127.0.0.1"; // No ipv4 loopback addresses.
_addresses = aAddressArray.filter(address => {
return (
!address.includes("%p2p") && // No WiFi Direct interfaces
!address.includes(":") && // XXX: No IPv6 for now
address != "127.0.0.1"
); // No ipv4 loopback addresses.
});
DEBUG && debug("getAddresses(): " + _addresses);
@ -781,7 +894,7 @@ let _hostname;
* @private
*/
function getHostname() {
return new Promise((resolve) => {
return new Promise(resolve => {
if (_hostname) {
resolve(_hostname);
return;
@ -848,8 +961,15 @@ function _propertyBagToObject(propBag) {
* @private
*/
function _openSocket(addr, port, handler, multicastInterface) {
let socket = Cc["@mozilla.org/network/udp-socket;1"].createInstance(Ci.nsIUDPSocket);
socket.init2(addr, port, Services.scriptSecurityManager.getSystemPrincipal(), true);
let socket = Cc["@mozilla.org/network/udp-socket;1"].createInstance(
Ci.nsIUDPSocket
);
socket.init2(
addr,
port,
Services.scriptSecurityManager.getSystemPrincipal(),
true
);
if (handler) {
socket.asyncListen({

View file

@ -4,8 +4,10 @@
"use strict";
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {UserAgentOverrides} = ChromeUtils.import("resource://gre/modules/UserAgentOverrides.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { UserAgentOverrides } = ChromeUtils.import(
"resource://gre/modules/UserAgentOverrides.jsm"
);
function UAOverridesBootstrapper() {
this.init();

View file

@ -4,36 +4,43 @@
"use strict";
var EXPORTED_SYMBOLS = [ "UserAgentOverrides" ];
var EXPORTED_SYMBOLS = ["UserAgentOverrides"];
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {UserAgentUpdates} = ChromeUtils.import("resource://gre/modules/UserAgentUpdates.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { UserAgentUpdates } = ChromeUtils.import(
"resource://gre/modules/UserAgentUpdates.jsm"
);
const PREF_OVERRIDES_ENABLED = "general.useragent.site_specific_overrides";
const MAX_OVERRIDE_FOR_HOST_CACHE_SIZE = 250;
// lazy load nsHttpHandler to improve startup performance.
XPCOMUtils.defineLazyGetter(this, "DEFAULT_UA", function() {
return Cc["@mozilla.org/network/protocol;1?name=http"]
.getService(Ci.nsIHttpProtocolHandler)
.userAgent;
return Cc["@mozilla.org/network/protocol;1?name=http"].getService(
Ci.nsIHttpProtocolHandler
).userAgent;
});
var gPrefBranch;
var gOverrides = new Map;
var gOverrides = new Map();
var gUpdatedOverrides;
var gOverrideForHostCache = new Map;
var gOverrideForHostCache = new Map();
var gInitialized = false;
var gOverrideFunctions = [
function(aHttpChannel) { return UserAgentOverrides.getOverrideForURI(aHttpChannel.URI); },
function(aHttpChannel) {
return UserAgentOverrides.getOverrideForURI(aHttpChannel.URI);
},
];
var gBuiltUAs = new Map;
var gBuiltUAs = new Map();
var UserAgentOverrides = {
init: function uao_init() {
if (gInitialized)
if (gInitialized) {
return;
}
gPrefBranch = Services.prefs.getBranch("general.useragent.override.");
gPrefBranch.addObserver("", buildOverrides);
@ -41,7 +48,10 @@ var UserAgentOverrides = {
Services.prefs.addObserver(PREF_OVERRIDES_ENABLED, buildOverrides);
try {
Services.obs.addObserver(HTTP_on_useragent_request, "http-on-useragent-request");
Services.obs.addObserver(
HTTP_on_useragent_request,
"http-on-useragent-request"
);
} catch (x) {
// The http-on-useragent-request notification is disallowed in content processes.
}
@ -53,7 +63,9 @@ var UserAgentOverrides = {
for (let domain in overrides) {
overrides[domain] = getUserAgentFromOverride(overrides[domain]);
}
overrides.get = function(key) { return this[key]; };
overrides.get = function(key) {
return this[key];
};
}
gUpdatedOverrides = overrides;
});
@ -75,15 +87,14 @@ var UserAgentOverrides = {
getOverrideForURI: function uao_getOverrideForURI(aURI) {
let host = aURI.asciiHost;
if (!gInitialized ||
(!gOverrides.size && !gUpdatedOverrides) ||
!(host)) {
if (!gInitialized || (!gOverrides.size && !gUpdatedOverrides) || !host) {
return null;
}
let override = gOverrideForHostCache.get(host);
if (override !== undefined)
if (override !== undefined) {
return override;
}
function findOverride(overrides) {
let searchHost = host;
@ -100,8 +111,9 @@ var UserAgentOverrides = {
return userAgent;
}
override = (gOverrides.size && findOverride(gOverrides))
|| (gUpdatedOverrides && findOverride(gUpdatedOverrides));
override =
(gOverrides.size && findOverride(gOverrides)) ||
(gUpdatedOverrides && findOverride(gUpdatedOverrides));
if (gOverrideForHostCache.size >= MAX_OVERRIDE_FOR_HOST_CACHE_SIZE) {
gOverrideForHostCache.clear();
@ -112,15 +124,19 @@ var UserAgentOverrides = {
},
uninit: function uao_uninit() {
if (!gInitialized)
if (!gInitialized) {
return;
}
gInitialized = false;
gPrefBranch.removeObserver("", buildOverrides);
Services.prefs.removeObserver(PREF_OVERRIDES_ENABLED, buildOverrides);
Services.obs.removeObserver(HTTP_on_useragent_request, "http-on-useragent-request");
Services.obs.removeObserver(
HTTP_on_useragent_request,
"http-on-useragent-request"
);
},
};
@ -143,8 +159,9 @@ function buildOverrides() {
gOverrides.clear();
gOverrideForHostCache.clear();
if (!Services.prefs.getBoolPref(PREF_OVERRIDES_ENABLED))
if (!Services.prefs.getBoolPref(PREF_OVERRIDES_ENABLED)) {
return;
}
let domains = gPrefBranch.getChildList("");

View file

@ -6,35 +6,50 @@
var EXPORTED_SYMBOLS = ["UserAgentUpdates"];
const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const { AppConstants } = ChromeUtils.import(
"resource://gre/modules/AppConstants.jsm"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
XPCOMUtils.defineLazyGlobalGetters(this, ["XMLHttpRequest"]);
ChromeUtils.defineModuleGetter(
this, "FileUtils", "resource://gre/modules/FileUtils.jsm");
this,
"FileUtils",
"resource://gre/modules/FileUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
this,
"NetUtil",
"resource://gre/modules/NetUtil.jsm"
);
ChromeUtils.defineModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
ChromeUtils.defineModuleGetter(
this, "OS", "resource://gre/modules/osfile.jsm");
ChromeUtils.defineModuleGetter(
this, "UpdateUtils", "resource://gre/modules/UpdateUtils.jsm");
this,
"UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm"
);
XPCOMUtils.defineLazyServiceGetter(
this, "gUpdateTimer", "@mozilla.org/updates/timer-manager;1", "nsIUpdateTimerManager");
XPCOMUtils.defineLazyGetter(this, "gDecoder",
function() { return new TextDecoder(); }
this,
"gUpdateTimer",
"@mozilla.org/updates/timer-manager;1",
"nsIUpdateTimerManager"
);
XPCOMUtils.defineLazyGetter(this, "gEncoder",
function() { return new TextEncoder(); }
);
XPCOMUtils.defineLazyGetter(this, "gDecoder", function() {
return new TextDecoder();
});
XPCOMUtils.defineLazyGetter(this, "gEncoder", function() {
return new TextEncoder();
});
const TIMER_ID = "user-agent-updates-timer";
@ -58,7 +73,10 @@ var gInitialized = false;
function readChannel(url) {
return new Promise((resolve, reject) => {
try {
let channel = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
let channel = NetUtil.newChannel({
uri: url,
loadUsingSystemPrincipal: true,
});
channel.contentType = "application/json";
NetUtil.asyncFetch(channel, (inputStream, status) => {
@ -73,8 +91,16 @@ function readChannel(url) {
resolve(data);
});
} catch (ex) {
reject(new Error("UserAgentUpdates: Could not fetch " + url + " " +
ex + "\n" + ex.stack));
reject(
new Error(
"UserAgentUpdates: Could not fetch " +
url +
" " +
ex +
"\n" +
ex.stack
)
);
}
});
}
@ -119,32 +145,40 @@ var UserAgentUpdates = {
// try loading from profile dir, then from app dir
let dirs = [KEY_PREFDIR, KEY_APPDIR];
dirs.reduce((prevLoad, dir) => {
let file = FileUtils.getFile(dir, [FILE_UPDATES], true).path;
// tryNext returns promise to read file under dir and parse it
let tryNext = () => OS.File.read(file).then(
(bytes) => {
let update = JSON.parse(gDecoder.decode(bytes));
if (!update) {
throw new Error("invalid update");
}
return update;
dirs
.reduce((prevLoad, dir) => {
let file = FileUtils.getFile(dir, [FILE_UPDATES], true).path;
// tryNext returns promise to read file under dir and parse it
let tryNext = () =>
OS.File.read(file).then(bytes => {
let update = JSON.parse(gDecoder.decode(bytes));
if (!update) {
throw new Error("invalid update");
}
return update;
});
// try to load next one if the previous load failed
return prevLoad ? prevLoad.catch(tryNext) : tryNext();
}, null)
.catch(ex => {
if (AppConstants.platform !== "android") {
// All previous (non-Android) load attempts have failed, so we bail.
throw new Error(
"UserAgentUpdates: Failed to load " +
FILE_UPDATES +
ex +
"\n" +
ex.stack
);
}
);
// try to load next one if the previous load failed
return prevLoad ? prevLoad.catch(tryNext) : tryNext();
}, null).catch((ex) => {
if (AppConstants.platform !== "android") {
// All previous (non-Android) load attempts have failed, so we bail.
throw new Error("UserAgentUpdates: Failed to load " + FILE_UPDATES +
ex + "\n" + ex.stack);
}
// Make one last attempt to read from the Fennec APK root.
return readChannel("resource://android/" + FILE_UPDATES);
}).then((update) => {
// Apply update if loading was successful
this._applyUpdate(update);
}).catch(Cu.reportError);
// Make one last attempt to read from the Fennec APK root.
return readChannel("resource://android/" + FILE_UPDATES);
})
.then(update => {
// Apply update if loading was successful
this._applyUpdate(update);
})
.catch(Cu.reportError);
this._scheduleUpdate();
},
@ -152,21 +186,22 @@ var UserAgentUpdates = {
let file = FileUtils.getFile(KEY_PREFDIR, [FILE_UPDATES], true);
let path = file.path;
let bytes = gEncoder.encode(JSON.stringify(update));
OS.File.writeAtomic(path, bytes, {tmpPath: path + ".tmp"}).then(
() => {
this._lastUpdated = Date.now();
Services.prefs.setCharPref(
PREF_UPDATES_LASTUPDATED, this._lastUpdated.toString());
},
Cu.reportError
);
OS.File.writeAtomic(path, bytes, { tmpPath: path + ".tmp" }).then(() => {
this._lastUpdated = Date.now();
Services.prefs.setCharPref(
PREF_UPDATES_LASTUPDATED,
this._lastUpdated.toString()
);
}, Cu.reportError);
},
_getPref(name, def) {
try {
switch (typeof def) {
case "number": return Services.prefs.getIntPref(name);
case "boolean": return Services.prefs.getBoolPref(name);
case "number":
return Services.prefs.getIntPref(name);
case "boolean":
return Services.prefs.getBoolPref(name);
}
return Services.prefs.getCharPref(name);
} catch (e) {
@ -176,15 +211,33 @@ var UserAgentUpdates = {
_getParameters() {
return {
"%DATE%": function() { return Date.now().toString(); },
"%PRODUCT%": function() { return Services.appinfo.name; },
"%APP_ID%": function() { return Services.appinfo.ID; },
"%APP_VERSION%": function() { return Services.appinfo.version; },
"%BUILD_ID%": function() { return Services.appinfo.appBuildID; },
"%OS%": function() { return Services.appinfo.OS; },
"%CHANNEL%": function() { return UpdateUtils.UpdateChannel; },
"%DISTRIBUTION%": function() { return this._getPref(PREF_APP_DISTRIBUTION, ""); },
"%DISTRIBUTION_VERSION%": function() { return this._getPref(PREF_APP_DISTRIBUTION_VERSION, ""); },
"%DATE%": function() {
return Date.now().toString();
},
"%PRODUCT%": function() {
return Services.appinfo.name;
},
"%APP_ID%": function() {
return Services.appinfo.ID;
},
"%APP_VERSION%": function() {
return Services.appinfo.version;
},
"%BUILD_ID%": function() {
return Services.appinfo.appBuildID;
},
"%OS%": function() {
return Services.appinfo.OS;
},
"%CHANNEL%": function() {
return UpdateUtils.UpdateChannel;
},
"%DISTRIBUTION%": function() {
return this._getPref(PREF_APP_DISTRIBUTION, "");
},
"%DISTRIBUTION_VERSION%": function() {
return this._getPref(PREF_APP_DISTRIBUTION_VERSION, "");
},
};
},
@ -216,21 +269,28 @@ var UserAgentUpdates = {
_update() {
let url = this._getUpdateURL();
url && this._fetchUpdate(url,
response => { // success
// apply update and save overrides to profile
this._applyUpdate(response);
this._saveToFile(response);
this._scheduleUpdate(); // cancel any retries
},
response => { // error
this._scheduleUpdate(true /* retry */);
});
url &&
this._fetchUpdate(
url,
response => {
// success
// apply update and save overrides to profile
this._applyUpdate(response);
this._saveToFile(response);
this._scheduleUpdate(); // cancel any retries
},
response => {
// error
this._scheduleUpdate(true /* retry */);
}
);
},
_scheduleUpdate(retry) {
// only schedule updates in the main process
if (Services.appinfo.processType !== Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
if (
Services.appinfo.processType !== Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
) {
return;
}
let interval = this._getPref(PREF_UPDATES_INTERVAL, 604800 /* 1 week */);
@ -257,7 +317,9 @@ var UserAgentUpdates = {
} else if (data === PREF_UPDATES_LASTUPDATED) {
// reload from file if there has been an update
let lastUpdated = parseInt(
this._getPref(PREF_UPDATES_LASTUPDATED, "0"), 0);
this._getPref(PREF_UPDATES_LASTUPDATED, "0"),
0
);
if (lastUpdated > this._lastUpdated) {
this._applySavedUpdate();
this._lastUpdated = lastUpdated;
@ -267,8 +329,5 @@ var UserAgentUpdates = {
}
},
QueryInterface: ChromeUtils.generateQI([
Ci.nsIObserver,
Ci.nsITimerCallback,
]),
QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver, Ci.nsITimerCallback]),
};

View file

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* 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/. */
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";

View file

@ -14,54 +14,74 @@ function test() {
}
function nextTest() {
if (tests.length)
if (tests.length) {
executeSoon(tests.shift());
else
} else {
executeSoon(finish);
}
}
var tests = [
test_asyncFetchBadCert,
];
var tests = [test_asyncFetchBadCert];
function test_asyncFetchBadCert() {
// Try a load from an untrusted cert, with errors supressed
NetUtil.asyncFetch({
uri: "https://untrusted.example.com",
loadUsingSystemPrincipal: true
}, function (aInputStream, aStatusCode, aRequest) {
ok(!Components.isSuccessCode(aStatusCode), "request failed");
ok(aRequest instanceof Ci.nsIHttpChannel, "request is an nsIHttpChannel");
// Now try again with a channel whose notificationCallbacks doesn't suprress errors
let channel = NetUtil.newChannel({
NetUtil.asyncFetch(
{
uri: "https://untrusted.example.com",
loadUsingSystemPrincipal: true});
channel.notificationCallbacks = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIProgressEventSink,
Ci.nsIInterfaceRequestor]),
getInterface (aIID) { return this.QueryInterface(aIID); },
onProgress () {},
onStatus () {}
};
NetUtil.asyncFetch(channel, function (aInputStream, aStatusCode, aRequest) {
loadUsingSystemPrincipal: true,
},
function(aInputStream, aStatusCode, aRequest) {
ok(!Components.isSuccessCode(aStatusCode), "request failed");
ok(aRequest instanceof Ci.nsIHttpChannel, "request is an nsIHttpChannel");
// Now try a valid request
NetUtil.asyncFetch({
uri: "https://example.com",
loadUsingSystemPrincipal: true
}, function (aInputStream, aStatusCode, aRequest) {
info("aStatusCode for valid request: " + aStatusCode);
ok(Components.isSuccessCode(aStatusCode), "request succeeded");
ok(aRequest instanceof Ci.nsIHttpChannel, "request is an nsIHttpChannel");
ok(aRequest.requestSucceeded, "HTTP request succeeded");
nextTest();
// Now try again with a channel whose notificationCallbacks doesn't suprress errors
let channel = NetUtil.newChannel({
uri: "https://untrusted.example.com",
loadUsingSystemPrincipal: true,
});
});
});
channel.notificationCallbacks = {
QueryInterface: ChromeUtils.generateQI([
Ci.nsIProgressEventSink,
Ci.nsIInterfaceRequestor,
]),
getInterface(aIID) {
return this.QueryInterface(aIID);
},
onProgress() {},
onStatus() {},
};
NetUtil.asyncFetch(channel, function(
aInputStream,
aStatusCode,
aRequest
) {
ok(!Components.isSuccessCode(aStatusCode), "request failed");
ok(
aRequest instanceof Ci.nsIHttpChannel,
"request is an nsIHttpChannel"
);
// Now try a valid request
NetUtil.asyncFetch(
{
uri: "https://example.com",
loadUsingSystemPrincipal: true,
},
function(aInputStream, aStatusCode, aRequest) {
info("aStatusCode for valid request: " + aStatusCode);
ok(Components.isSuccessCode(aStatusCode), "request succeeded");
ok(
aRequest instanceof Ci.nsIHttpChannel,
"request is an nsIHttpChannel"
);
ok(aRequest.requestSucceeded, "HTTP request succeeded");
nextTest();
}
);
});
}
);
}
function WindowListener(aURL, aCallback) {
@ -72,15 +92,20 @@ WindowListener.prototype = {
onOpenWindow(aXULWindow) {
var domwindow = aXULWindow.docShell.domWindow;
var self = this;
domwindow.addEventListener("load", function() {
if (domwindow.document.location.href != self.url)
return;
domwindow.addEventListener(
"load",
function() {
if (domwindow.document.location.href != self.url) {
return;
}
// Allow other window load listeners to execute before passing to callback
executeSoon(function() {
self.callback(domwindow);
});
}, {once: true});
// Allow other window load listeners to execute before passing to callback
executeSoon(function() {
self.callback(domwindow);
});
},
{ once: true }
);
},
onCloseWindow(aXULWindow) {},
}
};

View file

@ -4,28 +4,48 @@
* Open a dummy page, then open about:cache and verify the opened page shows up in the cache.
*/
add_task(async function() {
const kRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/",
"https://example.com/");
const kRoot = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content/",
"https://example.com/"
);
const kTestPage = kRoot + "dummy.html";
// Open the dummy page to get it cached.
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kTestPage, true);
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
kTestPage,
true
);
BrowserTestUtils.removeTab(tab);
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:cache", true);
tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:cache",
true
);
let expectedPageCheck = function(uri) {
info("Saw load for " + uri);
// Can't easily use searchParms and new URL() because it's an about: URI...
return uri.startsWith("about:cache?") && uri.includes("storage=disk");
};
let diskPageLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, expectedPageCheck);
let diskPageLoaded = BrowserTestUtils.browserLoaded(
tab.linkedBrowser,
false,
expectedPageCheck
);
await ContentTask.spawn(tab.linkedBrowser, null, function() {
ok(!content.document.nodePrincipal.isSystemPrincipal,
"about:cache should not have system principal");
ok(
!content.document.nodePrincipal.isSystemPrincipal,
"about:cache should not have system principal"
);
let principalURI = content.document.nodePrincipal.URI;
let channel = content.docShell.currentDocumentChannel;
ok(!channel.loadInfo.loadingPrincipal, "Loading principal should be null.");
is(principalURI && principalURI.spec, content.document.location.href, "Principal matches location");
let links = [... content.document.querySelectorAll("a[href*=disk]")];
is(
principalURI && principalURI.spec,
content.document.location.href,
"Principal matches location"
);
let links = [...content.document.querySelectorAll("a[href*=disk]")];
is(links.length, 1, "Should have 1 link to the disk entries");
links[0].click();
});
@ -37,35 +57,64 @@ add_task(async function() {
return uri.startsWith("about:cache-entry") && uri.includes("dummy.html");
};
let triggeringURISpec = tab.linkedBrowser.currentURI.spec;
let entryLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, expectedPageCheck);
let entryLoaded = BrowserTestUtils.browserLoaded(
tab.linkedBrowser,
false,
expectedPageCheck
);
await ContentTask.spawn(tab.linkedBrowser, kTestPage, function(kTestPage) {
ok(!content.document.nodePrincipal.isSystemPrincipal,
"about:cache with query params should still not have system principal");
ok(
!content.document.nodePrincipal.isSystemPrincipal,
"about:cache with query params should still not have system principal"
);
let principalURI = content.document.nodePrincipal.URI;
is(principalURI && principalURI.spec, content.document.location.href, "Principal matches location");
is(
principalURI && principalURI.spec,
content.document.location.href,
"Principal matches location"
);
let channel = content.docShell.currentDocumentChannel;
principalURI = channel.loadInfo.triggeringPrincipal.URI;
is(principalURI && principalURI.spec, "about:cache", "Triggering principal matches previous location");
is(
principalURI && principalURI.spec,
"about:cache",
"Triggering principal matches previous location"
);
ok(!channel.loadInfo.loadingPrincipal, "Loading principal should be null.");
let links = [... content.document.querySelectorAll("a[href*='" + kTestPage + "']")];
let links = [
...content.document.querySelectorAll("a[href*='" + kTestPage + "']"),
];
is(links.length, 1, "Should have 1 link to the entry for " + kTestPage);
links[0].click();
});
await entryLoaded;
info("about:cache entry loaded");
await ContentTask.spawn(tab.linkedBrowser, triggeringURISpec, function(triggeringURISpec) {
ok(!content.document.nodePrincipal.isSystemPrincipal,
"about:cache-entry should also not have system principal");
await ContentTask.spawn(tab.linkedBrowser, triggeringURISpec, function(
triggeringURISpec
) {
ok(
!content.document.nodePrincipal.isSystemPrincipal,
"about:cache-entry should also not have system principal"
);
let principalURI = content.document.nodePrincipal.URI;
is(principalURI && principalURI.spec, content.document.location.href, "Principal matches location");
is(
principalURI && principalURI.spec,
content.document.location.href,
"Principal matches location"
);
let channel = content.docShell.currentDocumentChannel;
principalURI = channel.loadInfo.triggeringPrincipal.URI;
is(principalURI && principalURI.spec, triggeringURISpec, "Triggering principal matches previous location");
is(
principalURI && principalURI.spec,
triggeringURISpec,
"Triggering principal matches previous location"
);
ok(!channel.loadInfo.loadingPrincipal, "Loading principal should be null.");
ok(content.document.querySelectorAll("th").length,
"Should have several table headers with data.");
ok(
content.document.querySelectorAll("th").length,
"Should have several table headers with data."
);
});
BrowserTestUtils.removeTab(tab);
});

View file

@ -2,10 +2,14 @@
add_task(_ => {
try {
Cc["@mozilla.org/network/effective-tld-service;1"]
.createInstance(Ci.nsISupports);
Cc["@mozilla.org/network/effective-tld-service;1"].createInstance(
Ci.nsISupports
);
} catch (e) {
is(e.result, Cr.NS_ERROR_XPC_CI_RETURNED_FAILURE,
"Component creation as an instance fails with expected code");
is(
e.result,
Cr.NS_ERROR_XPC_CI_RETURNED_FAILURE,
"Component creation as an instance fails with expected code"
);
}
});

View file

@ -8,21 +8,24 @@ const TEST_URL = "http://example.com/browser/netwerk/test/browser/dummy.html";
const expectedRemote = gMultiProcessBrowser ? "true" : "";
const resProtocol = Cc["@mozilla.org/network/protocol;1?name=resource"]
.getService(Ci.nsIResProtocolHandler);
const resProtocol = Cc[
"@mozilla.org/network/protocol;1?name=resource"
].getService(Ci.nsIResProtocolHandler);
function frameScript() {
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
let resProtocol = Cc["@mozilla.org/network/protocol;1?name=resource"]
.getService(Ci.nsIResProtocolHandler);
const { Services } = ChromeUtils.import(
"resource://gre/modules/Services.jsm"
);
let resProtocol = Cc[
"@mozilla.org/network/protocol;1?name=resource"
].getService(Ci.nsIResProtocolHandler);
addMessageListener("Test:ResolveURI", function({ data: uri }) {
uri = Services.io.newURI(uri);
try {
let resolved = resProtocol.resolveURI(uri);
sendAsyncMessage("Test:ResolvedURI", resolved);
}
catch (e) {
} catch (e) {
sendAsyncMessage("Test:ResolvedURI", null);
}
});
@ -30,7 +33,7 @@ function frameScript() {
function waitForEvent(obj, name, capturing, chromeEvent) {
info("Waiting for " + name);
return new Promise((resolve) => {
return new Promise(resolve => {
function listener(event) {
info("Saw " + name);
obj.removeEventListener(name, listener, capturing, chromeEvent);
@ -45,14 +48,13 @@ function resolveURI(uri) {
uri = Services.io.newURI(uri);
try {
return resProtocol.resolveURI(uri);
}
catch (e) {
} catch (e) {
return null;
}
}
function remoteResolveURI(uri) {
return new Promise((resolve) => {
return new Promise(resolve => {
let manager = gBrowser.selectedBrowser.messageManager;
function listener({ data: resolved }) {
@ -69,7 +71,10 @@ var loadTestTab = async function() {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TEST_URL);
let browser = gBrowser.selectedBrowser;
await BrowserTestUtils.browserLoaded(browser);
browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")();", true);
browser.messageManager.loadFrameScript(
"data:,(" + frameScript.toString() + ")();",
true
);
return browser;
};
@ -77,16 +82,24 @@ var loadTestTab = async function() {
var restart = async function() {
let browser = gBrowser.selectedBrowser;
// If the tab isn't remote this would crash the main process so skip it
if (browser.getAttribute("remote") != "true")
if (browser.getAttribute("remote") != "true") {
return browser;
}
await BrowserTestUtils.crashBrowser(browser);
browser.reload();
await BrowserTestUtils.browserLoaded(browser);
is(browser.getAttribute("remote"), expectedRemote, "Browser should be in the right process");
browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")();", true);
is(
browser.getAttribute("remote"),
expectedRemote,
"Browser should be in the right process"
);
browser.messageManager.loadFrameScript(
"data:,(" + frameScript.toString() + ")();",
true
);
return browser;
};
@ -95,7 +108,11 @@ add_task(async function() {
let browser = await loadTestTab();
// This must be loaded in the remote process for this test to be useful
is(browser.getAttribute("remote"), expectedRemote, "Browser should be in the right process");
is(
browser.getAttribute("remote"),
expectedRemote,
"Browser should be in the right process"
);
let local = resolveURI("resource://gre/modules/Services.jsm");
let remote = await remoteResolveURI("resource://gre/modules/Services.jsm");
@ -109,14 +126,28 @@ add_task(async function() {
let browser = await loadTestTab();
info("Set");
resProtocol.setSubstitution("testing", Services.io.newURI("chrome://global/content"));
resProtocol.setSubstitution(
"testing",
Services.io.newURI("chrome://global/content")
);
let local = resolveURI("resource://testing/test.js");
let remote = await remoteResolveURI("resource://testing/test.js");
is(local, "chrome://global/content/test.js", "Should resolve in main process");
is(remote, "chrome://global/content/test.js", "Should resolve in child process");
is(
local,
"chrome://global/content/test.js",
"Should resolve in main process"
);
is(
remote,
"chrome://global/content/test.js",
"Should resolve in child process"
);
info("Change");
resProtocol.setSubstitution("testing", Services.io.newURI("chrome://global/skin"));
resProtocol.setSubstitution(
"testing",
Services.io.newURI("chrome://global/skin")
);
local = resolveURI("resource://testing/test.js");
remote = await remoteResolveURI("resource://testing/test.js");
is(local, "chrome://global/skin/test.js", "Should resolve in main process");
@ -137,21 +168,43 @@ add_task(async function() {
let browser = await loadTestTab();
info("Set");
resProtocol.setSubstitution("testing", Services.io.newURI("chrome://global/content"));
resProtocol.setSubstitution(
"testing",
Services.io.newURI("chrome://global/content")
);
let local = resolveURI("resource://testing/test.js");
let remote = await remoteResolveURI("resource://testing/test.js");
is(local, "chrome://global/content/test.js", "Should resolve in main process");
is(remote, "chrome://global/content/test.js", "Should resolve in child process");
is(
local,
"chrome://global/content/test.js",
"Should resolve in main process"
);
is(
remote,
"chrome://global/content/test.js",
"Should resolve in child process"
);
await restart();
local = resolveURI("resource://testing/test.js");
remote = await remoteResolveURI("resource://testing/test.js");
is(local, "chrome://global/content/test.js", "Should resolve in main process");
is(remote, "chrome://global/content/test.js", "Should resolve in child process");
is(
local,
"chrome://global/content/test.js",
"Should resolve in main process"
);
is(
remote,
"chrome://global/content/test.js",
"Should resolve in child process"
);
info("Change");
resProtocol.setSubstitution("testing", Services.io.newURI("chrome://global/skin"));
resProtocol.setSubstitution(
"testing",
Services.io.newURI("chrome://global/skin")
);
await restart();
@ -178,19 +231,41 @@ add_task(async function() {
let browser = await loadTestTab();
info("Set");
resProtocol.setSubstitution("testing", Services.io.newURI("chrome://global/content"));
resProtocol.setSubstitution("testing2", Services.io.newURI("resource://testing"));
resProtocol.setSubstitution(
"testing",
Services.io.newURI("chrome://global/content")
);
resProtocol.setSubstitution(
"testing2",
Services.io.newURI("resource://testing")
);
let local = resolveURI("resource://testing2/test.js");
let remote = await remoteResolveURI("resource://testing2/test.js");
is(local, "chrome://global/content/test.js", "Should resolve in main process");
is(remote, "chrome://global/content/test.js", "Should resolve in child process");
is(
local,
"chrome://global/content/test.js",
"Should resolve in main process"
);
is(
remote,
"chrome://global/content/test.js",
"Should resolve in child process"
);
info("Clear");
resProtocol.setSubstitution("testing", null);
local = resolveURI("resource://testing2/test.js");
remote = await remoteResolveURI("resource://testing2/test.js");
is(local, "chrome://global/content/test.js", "Should resolve in main process");
is(remote, "chrome://global/content/test.js", "Should resolve in child process");
is(
local,
"chrome://global/content/test.js",
"Should resolve in main process"
);
is(
remote,
"chrome://global/content/test.js",
"Should resolve in child process"
);
resProtocol.setSubstitution("testing2", null);
local = resolveURI("resource://testing2/test.js");

View file

@ -8,14 +8,24 @@
add_task(async function() {
info("Make sure cookie changes in one process are visible in the other");
const kRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/",
"https://example.com/");
const kRoot = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content/",
"https://example.com/"
);
const kTestPage = kRoot + "dummy.html";
Services.cookies.removeAll();
let tab1 = await BrowserTestUtils.openNewForegroundTab({ gBrowser, url: kTestPage, forceNewProcess: true });
let tab2 = await BrowserTestUtils.openNewForegroundTab({ gBrowser, url: kTestPage, forceNewProcess: true });
let tab1 = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: kTestPage,
forceNewProcess: true,
});
let tab2 = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: kTestPage,
forceNewProcess: true,
});
let browser1 = gBrowser.getBrowserForTab(tab1);
let browser2 = gBrowser.getBrowserForTab(tab2);
@ -49,7 +59,11 @@ add_task(async function() {
});
await ContentTask.spawn(browser2, null, async function() {
is(content.document.cookie, "a1=other_test; a2=again", "Cookie should be set");
is(
content.document.cookie,
"a1=other_test; a2=again",
"Cookie should be set"
);
content.document.cookie = "a1=; expires=Thu, 01-Jan-1970 00:00:01 GMT;";
content.document.cookie = "a2=; expires=Thu, 01-Jan-1970 00:00:01 GMT;";
});

View file

@ -10,7 +10,12 @@ const gRegistrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
let gLoadedInProcess2Promise = null;
function _createProcessChooser(remoteTab, from, to, rejectPromise = false) {
let processChooser = new ProcessChooser(remoteTab, "example.com", "example.org", rejectPromise);
let processChooser = new ProcessChooser(
remoteTab,
"example.com",
"example.org",
rejectPromise
);
registerCleanupFunction(function() {
processChooser.unregister();
});
@ -90,21 +95,35 @@ ProcessChooser.prototype = {
// nsISupports
QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver]),
}
};
add_task(async function() {
info("Check that a redirect in process A may be correctly handled in process B");
info(
"Check that a redirect in process A may be correctly handled in process B"
);
const kRoot1 = getRootDirectory(gTestPath).replace("chrome://mochitests/content/",
"https://example.com/");
const kRoot2 = getRootDirectory(gTestPath).replace("chrome://mochitests/content/",
"https://example.org/");
const kRoot1 = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content/",
"https://example.com/"
);
const kRoot2 = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content/",
"https://example.org/"
);
const kRoot3 = getRootDirectory(gTestPath);
// This process will attempt to load the page that redirects to a different origin
let tab1 = await BrowserTestUtils.openNewForegroundTab({ gBrowser, url: kRoot1 + "dummy.html", forceNewProcess: true });
let tab1 = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: kRoot1 + "dummy.html",
forceNewProcess: true,
});
// This process will eventually receive the redirected channel.
let tab2 = await BrowserTestUtils.openNewForegroundTab({ gBrowser, url: kRoot2 + "dummy.html", forceNewProcess: true });
let tab2 = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
url: kRoot2 + "dummy.html",
forceNewProcess: true,
});
let browser1 = gBrowser.getBrowserForTab(tab1);
let browser2 = gBrowser.getBrowserForTab(tab2);
@ -112,7 +131,11 @@ add_task(async function() {
// This is for testing purposes only.
// This "process chooser" will direct the channel to be opened in the second
// tab, and thus in the second parent.
let processChooser = _createProcessChooser(browser2.frameLoader.remoteTab, "example.com", "example.org");
let processChooser = _createProcessChooser(
browser2.frameLoader.remoteTab,
"example.com",
"example.org"
);
info("Loading redirected URL");
// Open the URL in the first process. We expect it to wind up in the second
@ -120,18 +143,32 @@ add_task(async function() {
// Define the child listener in the new channel.
await ContentTask.spawn(browser2, null, async function(arg) {
function ChannelListener(childListener) { this.childListener = childListener; }
function ChannelListener(childListener) {
this.childListener = childListener;
}
ChannelListener.prototype = {
onStartRequest(aRequest) {
info("onStartRequest");
let channel = aRequest.QueryInterface(Ci.nsIChannel);
Assert.equal(channel.URI.spec, this.childListener.URI, "Make sure the channel has the proper URI");
Assert.equal(channel.originalURI.spec, this.childListener.originalURI, "Make sure the originalURI is correct");
Assert.equal(
channel.URI.spec,
this.childListener.URI,
"Make sure the channel has the proper URI"
);
Assert.equal(
channel.originalURI.spec,
this.childListener.originalURI,
"Make sure the originalURI is correct"
);
},
onStopRequest(aRequest, aStatusCode) {
info("onStopRequest");
Assert.equal(aStatusCode, Cr.NS_OK, "Check the status code");
Assert.equal(this.gotData, true, "Check that the channel received data");
Assert.equal(
this.gotData,
true,
"Check that the channel received data"
);
if (this.childListener.onComplete) {
this.childListener.onComplete();
}
@ -141,10 +178,17 @@ add_task(async function() {
this.gotData = true;
info("onDataAvailable");
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIStreamListener,Ci.nsIRequestObserver])
QueryInterface: ChromeUtils.generateQI([
Ci.nsIStreamListener,
Ci.nsIRequestObserver,
]),
};
function ChildListener(uri, originalURI, resolve) { this.URI = uri; this.originalURI = originalURI; this.resolve = resolve;}
function ChildListener(uri, originalURI, resolve) {
this.URI = uri;
this.originalURI = originalURI;
this.resolve = resolve;
}
ChildListener.prototype = {
// nsIChildProcessChannelListener
onChannelReady(aChildChannel, aIdentifier) {
@ -161,32 +205,54 @@ add_task(async function() {
},
lockFactory() {},
// nsISupports
QueryInterface: ChromeUtils.generateQI([Ci.nsIChildProcessChannelListener, Ci.nsIFactory]),
classID: Components.ID("{a6c142a9-eb38-4a09-a940-b71cdad479e1}")
}
QueryInterface: ChromeUtils.generateQI([
Ci.nsIChildProcessChannelListener,
Ci.nsIFactory,
]),
classID: Components.ID("{a6c142a9-eb38-4a09-a940-b71cdad479e1}"),
};
content.window.ChildListener = ChildListener;
});
// This promise instantiates a ChildListener and is resolved when the redirected
// channel is completed.
let loadedInProcess2Promise = ContentTask.spawn(browser2, { URI: kRoot2 + "dummy.html", originalURI: kRoot1 + "redirect.sjs?" + kRoot2 + "dummy.html"}, async function(arg) {
// We register the listener in process no. 2
return new Promise(resolve => {
var childListener = new content.window.ChildListener(arg.URI, arg.originalURI, resolve);
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
childListener.onComplete = () => {
registrar.unregisterFactory(childListener.classID, childListener);
}
registrar.registerFactory(childListener.classID, "",
"@mozilla.org/network/childProcessChannelListener;1",
childListener);
});
});
let loadedInProcess2Promise = ContentTask.spawn(
browser2,
{
URI: kRoot2 + "dummy.html",
originalURI: kRoot1 + "redirect.sjs?" + kRoot2 + "dummy.html",
},
async function(arg) {
// We register the listener in process no. 2
return new Promise(resolve => {
var childListener = new content.window.ChildListener(
arg.URI,
arg.originalURI,
resolve
);
var registrar = Components.manager.QueryInterface(
Ci.nsIComponentRegistrar
);
childListener.onComplete = () => {
registrar.unregisterFactory(childListener.classID, childListener);
};
registrar.registerFactory(
childListener.classID,
"",
"@mozilla.org/network/childProcessChannelListener;1",
childListener
);
});
}
);
let browser1LoadHasStopped = BrowserTestUtils.browserStopped(browser1);
await BrowserTestUtils.loadURI(browser1, kRoot1 + "redirect.sjs?" + kRoot2 + "dummy.html");
await BrowserTestUtils.loadURI(
browser1,
kRoot1 + "redirect.sjs?" + kRoot2 + "dummy.html"
);
// Check that the channel was delivered to process no. 2
await loadedInProcess2Promise;
@ -195,9 +261,17 @@ add_task(async function() {
await browser1LoadHasStopped;
// check that a rejected promise also works.
processChooser = _createProcessChooser(browser2.frameLoader.remoteTab, "example.com", "example.org", true);
processChooser = _createProcessChooser(
browser2.frameLoader.remoteTab,
"example.com",
"example.org",
true
);
let browser1LoadHasStoppedAgain = BrowserTestUtils.browserStopped(browser1);
await BrowserTestUtils.loadURI(browser1, kRoot1 + "redirect.sjs?" + kRoot2 + "dummy.html");
await BrowserTestUtils.loadURI(
browser1,
kRoot1 + "redirect.sjs?" + kRoot2 + "dummy.html"
);
await browser1LoadHasStoppedAgain;
info("this is done now");

View file

@ -17,8 +17,7 @@ const NORMAL_ACTION_URI = ACTION_BASE + "normal.html";
const UPLOAD_ACTION_URI = ACTION_BASE + "upload.html";
const POST_ACTION_URI = ACTION_BASE + "post.html";
function CustomProtocolHandler() {
}
function CustomProtocolHandler() {}
CustomProtocolHandler.prototype = {
/** nsIProtocolHandler */
get scheme() {
@ -28,8 +27,10 @@ CustomProtocolHandler.prototype = {
return -1;
},
get protocolFlags() {
return Ci.nsIProtocolHandler.URI_NORELATIVE |
Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE;
return (
Ci.nsIProtocolHandler.URI_NORELATIVE |
Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE
);
},
newChannel(aURI, aLoadInfo) {
return new CustomChannel(aURI, aLoadInfo);
@ -48,9 +49,11 @@ CustomProtocolHandler.prototype = {
lockFactory() {},
/** nsISupports */
QueryInterface: ChromeUtils.generateQI([Ci.nsIProtocolHandler,
Ci.nsIFactory]),
classID: Components.ID("{16d594bc-d9d8-47ae-a139-ea714dc0c35c}")
QueryInterface: ChromeUtils.generateQI([
Ci.nsIProtocolHandler,
Ci.nsIFactory,
]),
classID: Components.ID("{16d594bc-d9d8-47ae-a139-ea714dc0c35c}"),
};
function CustomChannel(aURI, aLoadInfo) {
@ -94,8 +97,7 @@ CustomChannel.prototype = {
get contentType() {
return "text/html";
},
set contentType(val) {
},
set contentType(val) {},
contentCharset: "UTF-8",
get contentLength() {
return -1;
@ -137,8 +139,9 @@ document.getElementById('form').submit();
var postData = "";
var headers = {};
if (this._uploadStream) {
var bstream = Cc["@mozilla.org/binaryinputstream;1"]
.createInstance(Ci.nsIBinaryInputStream);
var bstream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
Ci.nsIBinaryInputStream
);
bstream.setInputStream(this._uploadStream);
postData = bstream.readBytes(bstream.available());
@ -160,22 +163,23 @@ document.getElementById('form').submit();
</html>
`;
var stream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
var stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
stream.setData(data, data.length);
var runnable = {
run: () => {
try {
aListener.onStartRequest(this, null);
} catch(e) {}
} catch (e) {}
try {
aListener.onDataAvailable(this, stream, 0, stream.available());
} catch(e) {}
} catch (e) {}
try {
aListener.onStopRequest(this, null, Cr.NS_OK);
} catch(e) {}
}
} catch (e) {}
},
};
Services.tm.dispatchToMainThread(runnable);
},
@ -184,7 +188,7 @@ document.getElementById('form').submit();
get name() {
return this.uri.spec;
},
isPending () {
isPending() {
return false;
},
get status() {
@ -192,9 +196,10 @@ document.getElementById('form').submit();
},
cancel(status) {},
loadGroup: null,
loadFlags: Ci.nsIRequest.LOAD_NORMAL |
Ci.nsIRequest.INHIBIT_CACHING |
Ci.nsIRequest.LOAD_BYPASS_CACHE,
loadFlags:
Ci.nsIRequest.LOAD_NORMAL |
Ci.nsIRequest.INHIBIT_CACHING |
Ci.nsIRequest.LOAD_BYPASS_CACHE,
};
function frameScript() {
@ -203,11 +208,17 @@ function frameScript() {
if (content) {
var frame = content.document.getElementById("frame");
if (frame) {
var upload_stream = frame.contentDocument.getElementById("upload_stream");
var upload_stream = frame.contentDocument.getElementById(
"upload_stream"
);
var post_data = frame.contentDocument.getElementById("post_data");
var headers = frame.contentDocument.getElementById("upload_headers");
if (upload_stream && post_data && headers) {
sendAsyncMessage("Test:IFrameLoaded", [upload_stream.value, post_data.value, headers.value]);
sendAsyncMessage("Test:IFrameLoaded", [
upload_stream.value,
post_data.value,
headers.value,
]);
return;
}
}
@ -225,7 +236,10 @@ function loadTestTab(uri) {
var browser = gBrowser.selectedBrowser;
let manager = browser.messageManager;
browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")();", true);
browser.messageManager.loadFrameScript(
"data:,(" + frameScript.toString() + ")();",
true
);
return new Promise(resolve => {
function listener({ data: [hasUploadStream, postData, headers] }) {
@ -241,9 +255,12 @@ function loadTestTab(uri) {
add_task(async function() {
var handler = new CustomProtocolHandler();
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(handler.classID, "",
"@mozilla.org/network/protocol;1?name=" + handler.scheme,
handler);
registrar.registerFactory(
handler.classID,
"",
"@mozilla.org/network/protocol;1?name=" + handler.scheme,
handler
);
registerCleanupFunction(function() {
registrar.unregisterFactory(handler.classID, handler);
});
@ -267,8 +284,7 @@ add_task(async function() {
var [hasUploadStream, postData, headers] = await loadTestTab(POST_FORM_URI);
is(hasUploadStream, "yes", "post action should have uploadStream");
is(postData, "foo=bar\r\n",
"POST data is received correctly");
is(postData, "foo=bar\r\n", "POST data is received correctly");
is(headers["Content-Type"], "text/plain", "Content-Type header is correct");
is(headers["Content-Length"], undefined, "Content-Length header is correct");

View file

@ -2,7 +2,7 @@
* Tests for bug 1241100: Post to local file should not overwrite the file.
*/
const {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
async function createTestFile(filename, content) {
let path = OS.Path.join(OS.Constants.Path.tmpDir, filename);
@ -78,7 +78,10 @@ add_task(async function() {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, postURI);
let browser = gBrowser.selectedBrowser;
browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")();", true);
browser.messageManager.loadFrameScript(
"data:,(" + frameScript.toString() + ")();",
true
);
await new Promise(resolve => {
let manager = browser.messageManager;

View file

@ -8,46 +8,69 @@
add_task(async function() {
info("Make sure navigation through links in resource:// pages work");
await BrowserTestUtils.withNewTab({ gBrowser, url: "resource://gre/" }, async function(browser) {
// Following a directory link shall properly open the directory (bug 1224046)
await ContentTask.spawn(browser, {}, function() {
let link = Array.prototype.filter.call(content.document.getElementsByClassName('dir'), function(element) {
let name = element.textContent;
// Depending whether resource:// is backed by jar: or file://,
// directories either have a trailing slash or they don't.
if (name.endsWith("/")) {
name = name.slice(0, -1);
}
return name == "components";
})[0];
// First ensure the link is in the viewport
link.scrollIntoView();
// Then click on it.
link.click();
});
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "resource://gre/" },
async function(browser) {
// Following a directory link shall properly open the directory (bug 1224046)
await ContentTask.spawn(browser, {}, function() {
let link = Array.prototype.filter.call(
content.document.getElementsByClassName("dir"),
function(element) {
let name = element.textContent;
// Depending whether resource:// is backed by jar: or file://,
// directories either have a trailing slash or they don't.
if (name.endsWith("/")) {
name = name.slice(0, -1);
}
return name == "components";
}
)[0];
// First ensure the link is in the viewport
link.scrollIntoView();
// Then click on it.
link.click();
});
await BrowserTestUtils.browserLoaded(browser, undefined, "resource://gre/components/");
await BrowserTestUtils.browserLoaded(
browser,
undefined,
"resource://gre/components/"
);
// Following the parent link shall properly open the parent (bug 1366180)
await ContentTask.spawn(browser, {}, function() {
let link = content.document.getElementById('UI_goUp').getElementsByTagName('a')[0];
// The link should always be high enough in the page to be in the viewport.
link.click();
});
// Following the parent link shall properly open the parent (bug 1366180)
await ContentTask.spawn(browser, {}, function() {
let link = content.document
.getElementById("UI_goUp")
.getElementsByTagName("a")[0];
// The link should always be high enough in the page to be in the viewport.
link.click();
});
await BrowserTestUtils.browserLoaded(browser, undefined, "resource://gre/");
await BrowserTestUtils.browserLoaded(
browser,
undefined,
"resource://gre/"
);
// Following a link to a given file shall properly open the file.
await ContentTask.spawn(browser, {}, function() {
let link = Array.prototype.filter.call(content.document.getElementsByClassName('file'), function(element) {
return element.textContent == "greprefs.js";
})[0];
link.scrollIntoView();
link.click();
});
// Following a link to a given file shall properly open the file.
await ContentTask.spawn(browser, {}, function() {
let link = Array.prototype.filter.call(
content.document.getElementsByClassName("file"),
function(element) {
return element.textContent == "greprefs.js";
}
)[0];
link.scrollIntoView();
link.click();
});
await BrowserTestUtils.browserLoaded(browser, undefined, "resource://gre/greprefs.js");
await BrowserTestUtils.browserLoaded(
browser,
undefined,
"resource://gre/greprefs.js"
);
ok(true, "Got to the end of the test!");
});
ok(true, "Got to the end of the test!");
}
);
});

View file

@ -2,9 +2,13 @@
// domain. The cookie should be considered third party.
add_task(async function() {
const iconUrl = "http://example.org/browser/netwerk/test/browser/damonbowling.jpg";
const pageUrl = "http://example.com/browser/netwerk/test/browser/file_favicon.html";
await SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 1]]});
const iconUrl =
"http://example.org/browser/netwerk/test/browser/damonbowling.jpg";
const pageUrl =
"http://example.com/browser/netwerk/test/browser/file_favicon.html";
await SpecialPowers.pushPrefEnv({
set: [["network.cookie.cookieBehavior", 1]],
});
let promise = TestUtils.topicObserved("cookie-rejected", subject => {
let uri = subject.QueryInterface(Ci.nsIURI);

View file

@ -4,8 +4,10 @@
* 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 ROOT_URL = getRootDirectory(gTestPath).replace("chrome://mochitests/content/",
"https://example.com/");
const ROOT_URL = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content/",
"https://example.com/"
);
const TEST_URL = "about:license";
const TEST_URL2 = ROOT_URL + "ioactivity.html";
@ -15,34 +17,32 @@ var gotSqlite = false;
var gotEmptyData = false;
function processResults(results) {
for (let data of results) {
console.log(data.location);
gotEmptyData = data.rx == 0 && data.tx == 0 && !gotEmptyData
gotSocket = data.location.startsWith("socket://127.0.0.1:") || gotSocket;
gotFile = data.location.endsWith("aboutLicense.css") || gotFile;
gotSqlite = data.location.endsWith("places.sqlite") || gotSqlite;
}
};
for (let data of results) {
console.log(data.location);
gotEmptyData = data.rx == 0 && data.tx == 0 && !gotEmptyData;
gotSocket = data.location.startsWith("socket://127.0.0.1:") || gotSocket;
gotFile = data.location.endsWith("aboutLicense.css") || gotFile;
gotSqlite = data.location.endsWith("places.sqlite") || gotSqlite;
}
}
add_task(async function testRequestIOActivity() {
await SpecialPowers.pushPrefEnv({
"set": [
["io.activity.enabled", true],
]
});
waitForExplicitFinish();
Services.obs.notifyObservers(null, "profile-initial-state");
await SpecialPowers.pushPrefEnv({
set: [["io.activity.enabled", true]],
});
waitForExplicitFinish();
Services.obs.notifyObservers(null, "profile-initial-state");
await BrowserTestUtils.withNewTab(TEST_URL, async function(browser) {
await BrowserTestUtils.withNewTab(TEST_URL2, async function(browser) {
let results = await ChromeUtils.requestIOActivity();
processResults(results);
await BrowserTestUtils.withNewTab(TEST_URL, async function(browser) {
await BrowserTestUtils.withNewTab(TEST_URL2, async function(browser) {
let results = await ChromeUtils.requestIOActivity();
processResults(results);
ok(gotSocket, "A socket was used");
// test deactivated for now
// ok(gotFile, "A file was used");
ok(gotSqlite, "A sqlite DB was used");
ok(!gotEmptyData, "Every I/O event had data");
});
ok(gotSocket, "A socket was used");
// test deactivated for now
// ok(gotFile, "A file was used");
ok(gotSqlite, "A sqlite DB was used");
ok(!gotEmptyData, "Every I/O event had data");
});
});
});

File diff suppressed because it is too large Load diff

View file

@ -13,8 +13,10 @@ load(_HTTPD_JS_PATH.path);
// if these tests fail, we'll want the debug output
var linDEBUG = true;
var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
var {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
var { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
var { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
/**
* Constructs a new nsHttpServer instance. This function is intended to
@ -33,8 +35,10 @@ function createServer() {
* the URL of the channel to create
*/
function makeChannel(url) {
return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true})
.QueryInterface(Ci.nsIHttpChannel);
return NetUtil.newChannel({
uri: url,
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
}
/**
@ -47,7 +51,6 @@ function makeBIS(stream) {
return new BinaryInputStream(stream);
}
/**
* Returns the contents of the file as a string.
*
@ -58,8 +61,12 @@ function makeBIS(stream) {
*/
function fileContents(file) {
const PR_RDONLY = 0x01;
var fis = new FileInputStream(file, PR_RDONLY, 0o444,
Ci.nsIFileInputStream.CLOSE_ON_EOF);
var fis = new FileInputStream(
file,
PR_RDONLY,
0o444,
Ci.nsIFileInputStream.CLOSE_ON_EOF
);
var sis = new ScriptableInputStream(fis);
var contents = sis.read(file.fileSize);
sis.close();
@ -80,14 +87,14 @@ function* LineIterator(data) {
var index = 0;
do {
index = data.indexOf("\r\n");
if (index >= 0)
if (index >= 0) {
yield data.substring(0, index);
else
} else {
yield data;
}
data = data.substring(index + 2);
}
while (index >= 0);
} while (index >= 0);
}
/**
@ -103,14 +110,18 @@ function* LineIterator(data) {
function expectLines(iter, expectedLines) {
var index = 0;
for (var line of iter) {
if (expectedLines.length == index)
throw new Error(`Error: got more than ${expectedLines.length} expected lines!`);
if (expectedLines.length == index) {
throw new Error(
`Error: got more than ${expectedLines.length} expected lines!`
);
}
var expected = expectedLines[index++];
if (expected !== line)
if (expected !== line) {
throw new Error(`Error on line ${index}!
actual: '${line}',
expect: '${expected}'`);
}
}
if (expectedLines.length !== index) {
@ -148,8 +159,9 @@ function writeDetails(request, response) {
*/
function skipHeaders(iter) {
var line = iter.next().value;
while (line !== "")
while (line !== "") {
line = iter.next().value;
}
}
/**
@ -162,8 +174,9 @@ function skipHeaders(iter) {
* the expected exception
*/
function isException(e, code) {
if (e !== code && e.result !== code)
if (e !== code && e.result !== code) {
do_throw("unexpected error: " + e);
}
}
/**
@ -180,7 +193,6 @@ function callLater(msecs, callback) {
do_timeout(msecs, callback);
}
/** *****************************************************
* SIMPLE SUPPORT FOR LOADING/TESTING A SERIES OF URLS *
*******************************************************/
@ -192,7 +204,9 @@ function callLater(msecs, callback) {
function testComplete(srv) {
return function complete() {
do_test_pending();
srv.stop(function quit() { do_test_finished(); });
srv.stop(function quit() {
do_test_finished();
});
};
}
@ -218,7 +232,7 @@ function testComplete(srv) {
* nothing needs to be done
*/
function Test(path, initChannel, onStartRequest, onStopRequest) {
function nil() { }
function nil() {}
this.path = path;
this.initChannel = initChannel || nil;
@ -254,7 +268,10 @@ function runHttpTests(testArray, done) {
test.initChannel(ch);
} catch (e) {
try {
do_report_unexpected_exception(e, "testArray[" + testIndex + "].initChannel(ch)");
do_report_unexpected_exception(
e,
"testArray[" + testIndex + "].initChannel(ch)"
);
} catch (x) {
/* swallow and let tests continue */
}
@ -268,65 +285,74 @@ function runHttpTests(testArray, done) {
var testIndex = -1;
/** Stream listener for the channels. */
var listener =
{
/** Current channel being observed by this. */
_channel: null,
/** Array of bytes of data in body of response. */
_data: [],
var listener = {
/** Current channel being observed by this. */
_channel: null,
/** Array of bytes of data in body of response. */
_data: [],
onStartRequest(request) {
Assert.ok(request === this._channel);
var ch = request.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
onStartRequest(request) {
Assert.ok(request === this._channel);
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
this._data.length = 0;
this._data.length = 0;
try {
try {
try {
testArray[testIndex].onStartRequest(ch);
} catch (e) {
do_report_unexpected_exception(e, "testArray[" + testIndex + "].onStartRequest");
}
testArray[testIndex].onStartRequest(ch);
} catch (e) {
do_note_exception(e, "!!! swallowing onStartRequest exception so onStopRequest is " +
"called...");
do_report_unexpected_exception(
e,
"testArray[" + testIndex + "].onStartRequest"
);
}
},
onDataAvailable(request, inputStream, offset, count) {
var quantum = 262144; // just above half the argument-count limit
var bis = makeBIS(inputStream);
for (var start = 0; start < count; start += quantum) {
var newData = bis.readByteArray(Math.min(quantum, count - start));
Array.prototype.push.apply(this._data, newData);
}
},
onStopRequest(request, status) {
this._channel = null;
} catch (e) {
do_note_exception(
e,
"!!! swallowing onStartRequest exception so onStopRequest is " +
"called..."
);
}
},
onDataAvailable(request, inputStream, offset, count) {
var quantum = 262144; // just above half the argument-count limit
var bis = makeBIS(inputStream);
for (var start = 0; start < count; start += quantum) {
var newData = bis.readByteArray(Math.min(quantum, count - start));
Array.prototype.push.apply(this._data, newData);
}
},
onStopRequest(request, status) {
this._channel = null;
var ch = request.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
// NB: The onStopRequest callback must run before performNextTest here,
// because the latter runs the next test's initChannel callback, and
// we want one test to be sequentially processed before the next
// one.
// NB: The onStopRequest callback must run before performNextTest here,
// because the latter runs the next test's initChannel callback, and
// we want one test to be sequentially processed before the next
// one.
try {
testArray[testIndex].onStopRequest(ch, status, this._data);
} finally {
try {
testArray[testIndex].onStopRequest(ch, status, this._data);
performNextTest();
} finally {
try {
performNextTest();
} finally {
do_test_finished();
}
do_test_finished();
}
},
QueryInterface: ChromeUtils.generateQI(["nsIStreamListener", "nsIRequestObserver"]),
};
}
},
QueryInterface: ChromeUtils.generateQI([
"nsIStreamListener",
"nsIRequestObserver",
]),
};
performNextTest();
}
/** **************************************
* RAW REQUEST FORMAT TESTING FUNCTIONS *
****************************************/
@ -350,16 +376,24 @@ function runHttpTests(testArray, done) {
* environment between tests
*/
function RawTest(host, port, data, responseCheck) {
if (0 > port || 65535 < port || port % 1 !== 0)
if (0 > port || 65535 < port || port % 1 !== 0) {
throw new Error("bad port");
if (!(data instanceof Array))
}
if (!(data instanceof Array)) {
data = [data];
if (data.length <= 0)
}
if (data.length <= 0) {
throw new Error("bad data length");
}
// eslint-disable-next-line no-control-regex
if (!data.every(function(v) { return /^[\x00-\xff]*$/.test(v); }))
if (
!data.every(function(v) {
return /^[\x00-\xff]*$/.test(v);
})
) {
throw new Error("bad data contained non-byte-valued character");
}
this.host = host;
this.port = port;
@ -380,12 +414,12 @@ function RawTest(host, port, data, responseCheck) {
function runRawTests(testArray, done, beforeTestCallback) {
do_test_pending();
var sts = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Ci.nsISocketTransportService);
var sts = Cc["@mozilla.org/network/socket-transport-service;1"].getService(
Ci.nsISocketTransportService
);
var currentThread = Cc["@mozilla.org/thread-manager;1"]
.getService()
.currentThread;
var currentThread = Cc["@mozilla.org/thread-manager;1"].getService()
.currentThread;
/** Kicks off running the next test in the array. */
function performNextTest() {
@ -402,16 +436,17 @@ function runRawTests(testArray, done, beforeTestCallback) {
if (beforeTestCallback) {
try {
beforeTestCallback(testIndex);
} catch (e) { /* We don't care if this call fails */ }
} catch (e) {
/* We don't care if this call fails */
}
}
var rawTest = testArray[testIndex];
var transport =
sts.createTransport([], rawTest.host, rawTest.port, null);
var transport = sts.createTransport([], rawTest.host, rawTest.port, null);
var inStream = transport.openInputStream(0, 0, 0);
var outStream = transport.openOutputStream(0, 0, 0);
var outStream = transport.openOutputStream(0, 0, 0);
// reset
dataIndex = 0;
@ -432,8 +467,12 @@ function runRawTests(testArray, done, beforeTestCallback) {
// guarantee that 'stream' passed in here been QIed to nsIAsyncOutputStream
// since the last GC.
stream = stream.QueryInterface(Ci.nsIAsyncOutputStream);
stream.asyncWait(writer, 0, testArray[testIndex].data[dataIndex].length,
currentThread);
stream.asyncWait(
writer,
0,
testArray[testIndex].data[dataIndex].length,
currentThread
);
}
/** Index of the test being run. */
@ -449,80 +488,80 @@ function runRawTests(testArray, done, beforeTestCallback) {
var received = "";
/** Reads data from the socket. */
var reader =
{
onInputStreamReady(stream) {
Assert.ok(stream === this.stream);
var reader = {
onInputStreamReady(stream) {
Assert.ok(stream === this.stream);
try {
var bis = new BinaryInputStream(stream);
var av = 0;
try {
var bis = new BinaryInputStream(stream);
av = bis.available();
} catch (e) {
/* default to 0 */
do_note_exception(e);
}
var av = 0;
try {
av = bis.available();
} catch (e) {
/* default to 0 */
do_note_exception(e);
if (av > 0) {
var quantum = 262144;
for (var start = 0; start < av; start += quantum) {
var bytes = bis.readByteArray(Math.min(quantum, av - start));
received += String.fromCharCode.apply(null, bytes);
}
waitForMoreInput(stream);
return;
}
} catch (e) {
do_report_unexpected_exception(e);
}
if (av > 0) {
var quantum = 262144;
for (var start = 0; start < av; start += quantum) {
var bytes = bis.readByteArray(Math.min(quantum, av - start));
received += String.fromCharCode.apply(null, bytes);
}
waitForMoreInput(stream);
return;
}
var rawTest = testArray[testIndex];
try {
rawTest.responseCheck(received);
} catch (e) {
do_report_unexpected_exception(e);
} finally {
try {
stream.close();
performNextTest();
} catch (e) {
do_report_unexpected_exception(e);
}
var rawTest = testArray[testIndex];
try {
rawTest.responseCheck(received);
} catch (e) {
do_report_unexpected_exception(e);
} finally {
try {
stream.close();
performNextTest();
} catch (e) {
do_report_unexpected_exception(e);
}
}
},
};
}
},
};
/** Writes data to the socket. */
var writer =
{
onOutputStreamReady(stream) {
var str = testArray[testIndex].data[dataIndex];
var writer = {
onOutputStreamReady(stream) {
var str = testArray[testIndex].data[dataIndex];
var written = 0;
try {
written = stream.write(str, str.length);
if (written == str.length)
dataIndex++;
else
testArray[testIndex].data[dataIndex] = str.substring(written);
} catch (e) {
do_note_exception(e);
/* stream could have been closed, just ignore */
var written = 0;
try {
written = stream.write(str, str.length);
if (written == str.length) {
dataIndex++;
} else {
testArray[testIndex].data[dataIndex] = str.substring(written);
}
} catch (e) {
do_note_exception(e);
/* stream could have been closed, just ignore */
}
try {
// Keep writing data while we can write and
// until there's no more data to read
if (written > 0 && dataIndex < testArray[testIndex].data.length)
waitToWriteOutput(stream);
else
stream.close();
} catch (e) {
do_report_unexpected_exception(e);
try {
// Keep writing data while we can write and
// until there's no more data to read
if (written > 0 && dataIndex < testArray[testIndex].data.length) {
waitToWriteOutput(stream);
} else {
stream.close();
}
},
};
} catch (e) {
do_report_unexpected_exception(e);
}
},
};
performNextTest();
}

File diff suppressed because it is too large Load diff

View file

@ -14,14 +14,30 @@ XPCOMUtils.defineLazyGetter(this, "port", function() {
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test("http://localhost:" + port + "/objHandler",
null, start_objHandler, null),
new Test("http://localhost:" + port + "/functionHandler",
null, start_functionHandler, null),
new Test("http://localhost:" + port + "/nonexistent-path",
null, start_non_existent_path, null),
new Test("http://localhost:" + port + "/lotsOfHeaders",
null, start_lots_of_headers, null),
new Test(
"http://localhost:" + port + "/objHandler",
null,
start_objHandler,
null
),
new Test(
"http://localhost:" + port + "/functionHandler",
null,
start_functionHandler,
null
),
new Test(
"http://localhost:" + port + "/nonexistent-path",
null,
start_non_existent_path,
null
),
new Test(
"http://localhost:" + port + "/lotsOfHeaders",
null,
start_lots_of_headers,
null
),
];
});
@ -66,11 +82,13 @@ function start_objHandler(ch) {
Assert.equal(ch.getResponseHeader("content-type"), "text/plain");
Assert.equal(ch.responseStatusText, "OK");
var reqMin = {}, reqMaj = {}, respMin = {}, respMaj = {};
var reqMin = {},
reqMaj = {},
respMin = {},
respMaj = {};
ch.getRequestVersion(reqMaj, reqMin);
ch.getResponseVersion(respMaj, respMin);
Assert.ok(reqMaj.value == respMaj.value &&
reqMin.value == respMin.value);
Assert.ok(reqMaj.value == respMaj.value && reqMin.value == respMin.value);
}
function start_functionHandler(ch) {
@ -81,7 +99,10 @@ function start_functionHandler(ch) {
Assert.equal(ch.getResponseHeader("foopy"), "quux-baz");
Assert.equal(ch.responseStatusText, "Page Not Found");
var reqMin = {}, reqMaj = {}, respMin = {}, respMaj = {};
var reqMin = {},
reqMaj = {},
respMin = {},
respMaj = {};
ch.getRequestVersion(reqMaj, reqMin);
ch.getResponseVersion(respMaj, respMin);
Assert.ok(reqMaj.value == 1 && reqMin.value == 1);
@ -101,41 +122,41 @@ function start_lots_of_headers(ch) {
Assert.equal(ch.responseStatus, 200);
Assert.ok(ch.requestSucceeded);
for (var i = 0; i < HEADER_COUNT; i++)
for (var i = 0; i < HEADER_COUNT; i++) {
Assert.equal(ch.getResponseHeader("X-Header-" + i), "value " + i);
}
}
// PATH HANDLERS
// /objHandler
var objHandler =
{
handle(metadata, response) {
response.setStatusLine(metadata.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/plain", false);
var objHandler = {
handle(metadata, response) {
response.setStatusLine(metadata.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/plain", false);
var body = "Request (slightly reformatted):\n\n";
body += metadata.method + " " + metadata.path;
var body = "Request (slightly reformatted):\n\n";
body += metadata.method + " " + metadata.path;
Assert.equal(metadata.port, port);
Assert.equal(metadata.port, port);
if (metadata.queryString)
body += "?" + metadata.queryString;
if (metadata.queryString) {
body += "?" + metadata.queryString;
}
body += " HTTP/" + metadata.httpVersion + "\n";
body += " HTTP/" + metadata.httpVersion + "\n";
var headEnum = metadata.headers;
while (headEnum.hasMoreElements()) {
var fieldName = headEnum.getNext()
.QueryInterface(Ci.nsISupportsString)
.data;
body += fieldName + ": " + metadata.getHeader(fieldName) + "\n";
}
var headEnum = metadata.headers;
while (headEnum.hasMoreElements()) {
var fieldName = headEnum.getNext().QueryInterface(Ci.nsISupportsString)
.data;
body += fieldName + ": " + metadata.getHeader(fieldName) + "\n";
}
response.bodyOutputStream.write(body, body.length);
},
QueryInterface: ChromeUtils.generateQI(["nsIHttpRequestHandler"]),
};
response.bodyOutputStream.write(body, body.length);
},
QueryInterface: ChromeUtils.generateQI(["nsIHttpRequestHandler"]),
};
// /functionHandler
function functionHandler(metadata, response) {
@ -154,6 +175,7 @@ function functionHandler(metadata, response) {
function lotsOfHeadersHandler(request, response) {
response.setHeader("Content-Type", "text/plain", false);
for (var i = 0; i < HEADER_COUNT; i++)
for (var i = 0; i < HEADER_COUNT; i++) {
response.setHeader("X-Header-" + i, "value " + i, false);
}
}

View file

@ -30,8 +30,9 @@ function contentLength(request, response) {
var avail;
var data = "";
while ((avail = body.available()) > 0)
while ((avail = body.available()) > 0) {
data += body.read(avail);
}
Assert.equal(data, REQUEST_DATA);
}
@ -42,18 +43,24 @@ function contentLength(request, response) {
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test("http://localhost:" + srv.identity.primaryPort + "/content-length",
init_content_length),
new Test(
"http://localhost:" + srv.identity.primaryPort + "/content-length",
init_content_length
),
];
});
function init_content_length(ch) {
var content = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
var content = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
content.data = REQUEST_DATA;
ch.QueryInterface(Ci.nsIUploadChannel)
.setUploadStream(content, "text/plain", REQUEST_DATA.length);
ch.QueryInterface(Ci.nsIUploadChannel).setUploadStream(
content,
"text/plain",
REQUEST_DATA.length
);
// Override the values implicitly set by setUploadStream above.
ch.requestMethod = "POST";

View file

@ -14,35 +14,66 @@ XPCOMUtils.defineLazyGetter(this, "PREFIX", function() {
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test(PREFIX + "/range.txt",
init_byterange, start_byterange, stop_byterange),
new Test(PREFIX + "/range.txt",
init_byterange2, start_byterange2),
new Test(PREFIX + "/range.txt",
init_byterange3, start_byterange3, stop_byterange3),
new Test(PREFIX + "/range.txt",
init_byterange4, start_byterange4),
new Test(PREFIX + "/range.txt",
init_byterange5, start_byterange5, stop_byterange5),
new Test(PREFIX + "/range.txt",
init_byterange6, start_byterange6, stop_byterange6),
new Test(PREFIX + "/range.txt",
init_byterange7, start_byterange7, stop_byterange7),
new Test(PREFIX + "/range.txt",
init_byterange8, start_byterange8, stop_byterange8),
new Test(PREFIX + "/range.txt",
init_byterange9, start_byterange9, stop_byterange9),
new Test(PREFIX + "/range.txt",
init_byterange10, start_byterange10),
new Test(PREFIX + "/range.txt",
init_byterange11, start_byterange11, stop_byterange11),
new Test(PREFIX + "/empty.txt",
null, start_byterange12, stop_byterange12),
new Test(PREFIX + "/headers.txt",
init_byterange13, start_byterange13, null),
new Test(PREFIX + "/range.txt",
null, start_normal, stop_normal),
];
new Test(
PREFIX + "/range.txt",
init_byterange,
start_byterange,
stop_byterange
),
new Test(PREFIX + "/range.txt", init_byterange2, start_byterange2),
new Test(
PREFIX + "/range.txt",
init_byterange3,
start_byterange3,
stop_byterange3
),
new Test(PREFIX + "/range.txt", init_byterange4, start_byterange4),
new Test(
PREFIX + "/range.txt",
init_byterange5,
start_byterange5,
stop_byterange5
),
new Test(
PREFIX + "/range.txt",
init_byterange6,
start_byterange6,
stop_byterange6
),
new Test(
PREFIX + "/range.txt",
init_byterange7,
start_byterange7,
stop_byterange7
),
new Test(
PREFIX + "/range.txt",
init_byterange8,
start_byterange8,
stop_byterange8
),
new Test(
PREFIX + "/range.txt",
init_byterange9,
start_byterange9,
stop_byterange9
),
new Test(PREFIX + "/range.txt", init_byterange10, start_byterange10),
new Test(
PREFIX + "/range.txt",
init_byterange11,
start_byterange11,
stop_byterange11
),
new Test(PREFIX + "/empty.txt", null, start_byterange12, stop_byterange12),
new Test(
PREFIX + "/headers.txt",
init_byterange13,
start_byterange13,
null
),
new Test(PREFIX + "/range.txt", null, start_normal, stop_normal),
];
});
function run_test() {

View file

@ -13,16 +13,26 @@ XPCOMUtils.defineLazyGetter(this, "PREFIX", function() {
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test(PREFIX + "/test_both.html",
null, start_testBoth, null),
new Test(PREFIX + "/test_ctype_override.txt",
null, start_test_ctype_override_txt, null),
new Test(PREFIX + "/test_status_override.html",
null, start_test_status_override_html, null),
new Test(PREFIX + "/test_status_override_nodesc.txt",
null, start_test_status_override_nodesc_txt, null),
new Test(PREFIX + "/caret_test.txt^",
null, start_caret_test_txt_, null),
new Test(PREFIX + "/test_both.html", null, start_testBoth, null),
new Test(
PREFIX + "/test_ctype_override.txt",
null,
start_test_ctype_override_txt,
null
),
new Test(
PREFIX + "/test_status_override.html",
null,
start_test_status_override_html,
null
),
new Test(
PREFIX + "/test_status_override_nodesc.txt",
null,
start_test_status_override_nodesc_txt,
null
),
new Test(PREFIX + "/caret_test.txt^", null, start_caret_test_txt_, null),
];
});
@ -37,7 +47,6 @@ function run_test() {
runHttpTests(tests, testComplete(srv));
}
// TEST DATA
function start_testBoth(ch) {

View file

@ -28,7 +28,9 @@ function run_test() {
function done() {
do_test_pending();
destroyTestDirectory();
srv.stop(function() { do_test_finished(); });
srv.stop(function() {
do_test_finished();
});
}
runHttpTests(tests, done);
@ -77,7 +79,6 @@ function destroyTestDirectory() {
dir.remove(true);
}
/** ***********
* UTILITIES *
*************/
@ -115,8 +116,10 @@ function hiddenDataCheck(bytes, uri, path) {
var top = Services.io.newURI(uri);
// N.B. No ERROR_IF_SEE_THIS.txt^ file!
var dirEntries = [{name: "file.txt", isDirectory: false},
{name: "SHOULD_SEE_THIS.txt^", isDirectory: false}];
var dirEntries = [
{ name: "file.txt", isDirectory: false },
{ name: "SHOULD_SEE_THIS.txt^", isDirectory: false },
];
for (var i = 0; i < items.length; i++) {
var link = items[i].childNodes[0];
@ -202,8 +205,10 @@ function makeFile(name, isDirectory, parentDir, lst) {
try {
file.append(name);
file.create(type, 0o755);
lst.push({name, isDirectory});
} catch (e) { /* OS probably doesn't like file name, skip */ }
lst.push({ name, isDirectory });
} catch (e) {
/* OS probably doesn't like file name, skip */
}
}
/** *******
@ -214,7 +219,12 @@ XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test(BASE_URL, null, start, stopRootDirectory),
new Test(BASE_URL + "foo/", null, start, stopFooDirectory),
new Test(BASE_URL + "bar/folder^/", null, start, stopTrailingCaretDirectory),
new Test(
BASE_URL + "bar/folder^/",
null,
start,
stopTrailingCaretDirectory
),
];
});

View file

@ -11,10 +11,18 @@ var srv;
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test("http://localhost:" + srv.identity.primaryPort + "/empty-body-unwritten",
null, ensureEmpty, null),
new Test("http://localhost:" + srv.identity.primaryPort + "/empty-body-written",
null, ensureEmpty, null),
new Test(
"http://localhost:" + srv.identity.primaryPort + "/empty-body-unwritten",
null,
ensureEmpty,
null
),
new Test(
"http://localhost:" + srv.identity.primaryPort + "/empty-body-written",
null,
ensureEmpty,
null
),
];
});

View file

@ -9,14 +9,28 @@
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test("http://localhost:" + srv.identity.primaryPort + "/throws/exception",
null, start_throws_exception, succeeded),
new Test("http://localhost:" + srv.identity.primaryPort +
"/this/file/does/not/exist/and/404s",
null, start_nonexistent_404_fails_so_400, succeeded),
new Test("http://localhost:" + srv.identity.primaryPort +
"/attempts/404/fails/so/400/fails/so/500s",
register400Handler, start_multiple_exceptions_500, succeeded),
new Test(
"http://localhost:" + srv.identity.primaryPort + "/throws/exception",
null,
start_throws_exception,
succeeded
),
new Test(
"http://localhost:" +
srv.identity.primaryPort +
"/this/file/does/not/exist/and/404s",
null,
start_nonexistent_404_fails_so_400,
succeeded
),
new Test(
"http://localhost:" +
srv.identity.primaryPort +
"/attempts/404/fails/so/400/fails/so/500s",
register400Handler,
start_multiple_exceptions_500,
succeeded
),
];
});
@ -33,14 +47,20 @@ function run_test() {
runHttpTests(tests, testComplete(srv));
}
// TEST DATA
function checkStatusLine(channel, httpMaxVer, httpMinVer, httpCode, statusText) {
function checkStatusLine(
channel,
httpMaxVer,
httpMinVer,
httpCode,
statusText
) {
Assert.equal(channel.responseStatus, httpCode);
Assert.equal(channel.responseStatusText, statusText);
var respMaj = {}, respMin = {};
var respMaj = {},
respMin = {};
channel.getResponseVersion(respMaj, respMin);
Assert.equal(respMaj.value, httpMaxVer);
Assert.equal(respMin.value, httpMinVer);
@ -66,7 +86,6 @@ function register400Handler(ch) {
srv.registerErrorHandler(400, throwsException);
}
// PATH HANDLERS
// /throws/exception (and also a 404 and 400 error handler)

View file

@ -18,7 +18,6 @@ function run_test() {
runHttpTests(tests, testComplete(srv));
}
/** **********
* HANDLERS *
************/
@ -47,8 +46,11 @@ function pathHandler(request, response) {
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test("http://localhost:" + srv.identity.primaryPort + "/path-handler",
null, check),
new Test(
"http://localhost:" + srv.identity.primaryPort + "/path-handler",
null,
check
),
];
});

View file

@ -8,7 +8,6 @@
// structure and is not to be used directly outside of httpd.js itself except
// for testing purposes
/**
* Ensures that a fieldname-fieldvalue combination is a valid header.
*
@ -40,14 +39,16 @@ function assertValidHeader(fieldName, fieldValue, headers) {
function assertInvalidHeader(fieldName, fieldValue, headers) {
try {
headers.setHeader(fieldName, fieldValue, false);
throw new Error(`Setting (${fieldName}, ${fieldValue}) as header succeeded!`);
throw new Error(
`Setting (${fieldName}, ${fieldValue}) as header succeeded!`
);
} catch (e) {
if (e.result !== Cr.NS_ERROR_INVALID_ARG)
if (e.result !== Cr.NS_ERROR_INVALID_ARG) {
do_throw("Unexpected exception thrown: " + e);
}
}
}
function run_test() {
testHeaderValidity();
testGetHeader();
@ -65,7 +66,7 @@ function testHeaderValidity() {
assertInvalidHeader("@xml", "bar", headers);
assertInvalidHeader("fiz(", "bar", headers);
assertInvalidHeader("HTTP/1.1", "bar", headers);
assertInvalidHeader("b\"b", "bar", headers);
assertInvalidHeader('b"b', "bar", headers);
assertInvalidHeader("ascsd\t", "bar", headers);
assertInvalidHeader("{fds", "bar", headers);
assertInvalidHeader("baz?", "bar", headers);
@ -106,31 +107,33 @@ function testGetHeader() {
headers.getHeader(":");
throw new Error("Failed to throw for invalid header");
} catch (e) {
if (e.result !== Cr.NS_ERROR_INVALID_ARG)
if (e.result !== Cr.NS_ERROR_INVALID_ARG) {
do_throw("headers.getHeader(':') must throw invalid arg");
}
}
try {
headers.getHeader("valid");
throw new Error("header doesn't exist");
} catch (e) {
if (e.result !== Cr.NS_ERROR_NOT_AVAILABLE)
if (e.result !== Cr.NS_ERROR_NOT_AVAILABLE) {
do_throw("shouldn't be a header named 'valid' in headers!");
}
}
}
function testHeaderEnumerator() {
var headers = new nsHttpHeaders();
var heads =
{
"foo": "17",
"baz": "two six niner",
"decaf": "class Program { int .7; int main(){ .7 = 5; return 7 - .7; } }",
};
var heads = {
foo: "17",
baz: "two six niner",
decaf: "class Program { int .7; int main(){ .7 = 5; return 7 - .7; } }",
};
for (var i in heads)
for (var i in heads) {
headers.setHeader(i, heads[i], false);
}
var en = headers.enumerator;
while (en.hasMoreElements()) {
@ -159,7 +162,8 @@ function testHasHeader() {
headers.hasHeader(":");
throw new Error("failed to throw");
} catch (e) {
if (e.result !== Cr.NS_ERROR_INVALID_ARG)
if (e.result !== Cr.NS_ERROR_INVALID_ARG) {
do_throw(".hasHeader for an invalid name should throw");
}
}
}

View file

@ -24,8 +24,10 @@ add_task(async function run_test1() {
srv.registerPathHandler("/http/1.0-request", http10Request);
srv.registerPathHandler("/http/1.1-good-host", http11goodHost);
srv.registerPathHandler("/http/1.1-good-host-wacky-port",
http11goodHostWackyPort);
srv.registerPathHandler(
"/http/1.1-good-host-wacky-port",
http11goodHostWackyPort
);
srv.registerPathHandler("/http/1.1-ip-host", http11ipHost);
srv.start(FAKE_PORT_ONE);
@ -180,13 +182,14 @@ add_task(async function run_test_3() {
// Okay, finally done with identity testing. Our primary location is the one
// we want it to be, so we're off!
await new Promise(resolve => runRawTests(tests, resolve, (idx) => dump(`running test no ${idx}`)));
await new Promise(resolve =>
runRawTests(tests, resolve, idx => dump(`running test no ${idx}`))
);
// Finally shut down the server.
await new Promise(resolve => srv.stop(resolve));
});
/** *******************
* UTILITY FUNCTIONS *
*********************/
@ -235,7 +238,6 @@ function check400(aData) {
Assert.equal(firstLine.substring(0, HTTP_400_LEADER_LENGTH), HTTP_400_LEADER);
}
/** *************
* BEGIN TESTS *
***************/
@ -252,8 +254,7 @@ function http10Request(request, response) {
writeDetails(request, response);
response.setStatusLine("1.0", 200, "TEST PASSED");
}
data = "GET /http/1.0-request HTTP/1.0\r\n" +
"\r\n";
data = "GET /http/1.0-request HTTP/1.0\r\n" + "\r\n";
function check10(aData) {
let iter = LineIterator(aData);
@ -263,94 +264,84 @@ function check10(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
"Method: GET",
"Path: /http/1.0-request",
"Query: ",
"Version: 1.0",
"Scheme: http",
"Host: localhost",
"Port: 4444",
];
let body = [
"Method: GET",
"Path: /http/1.0-request",
"Query: ",
"Version: 1.0",
"Scheme: http",
"Host: localhost",
"Port: 4444",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check10);
tests.push(test);
// HTTP/1.1 request, no Host header, expect a 400 response
data = "GET /http/1.1-request HTTP/1.1\r\n" +
"\r\n";
data = "GET /http/1.1-request HTTP/1.1\r\n" + "\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, wrong host, expect a 400 response
data = "GET /http/1.1-request HTTP/1.1\r\n" +
"Host: not-localhost\r\n" +
"\r\n";
data =
"GET /http/1.1-request HTTP/1.1\r\n" + "Host: not-localhost\r\n" + "\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, wrong host/right port, expect a 400 response
data = "GET /http/1.1-request HTTP/1.1\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
data =
"GET /http/1.1-request HTTP/1.1\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, Host header has host but no port, expect a 400 response
data = "GET /http/1.1-request HTTP/1.1\r\n" +
"Host: 127.0.0.1\r\n" +
"\r\n";
data = "GET /http/1.1-request HTTP/1.1\r\n" + "Host: 127.0.0.1\r\n" + "\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, Request-URI has wrong port, expect a 400 response
data = "GET http://127.0.0.1/http/1.1-request HTTP/1.1\r\n" +
"Host: 127.0.0.1\r\n" +
"\r\n";
data =
"GET http://127.0.0.1/http/1.1-request HTTP/1.1\r\n" +
"Host: 127.0.0.1\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, Request-URI has wrong port, expect a 400 response
data = "GET http://localhost:31337/http/1.1-request HTTP/1.1\r\n" +
"Host: localhost:31337\r\n" +
"\r\n";
data =
"GET http://localhost:31337/http/1.1-request HTTP/1.1\r\n" +
"Host: localhost:31337\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, Request-URI has wrong scheme, expect a 400 response
data = "GET https://localhost:4444/http/1.1-request HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
data =
"GET https://localhost:4444/http/1.1-request HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, correct Host header, expect handler's response
function http11goodHost(request, response) {
writeDetails(request, response);
response.setStatusLine("1.1", 200, "TEST PASSED");
}
data = "GET /http/1.1-good-host HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
data =
"GET /http/1.1-good-host HTTP/1.1\r\n" + "Host: localhost:4444\r\n" + "\r\n";
function check11goodHost(aData) {
let iter = LineIterator(aData);
@ -360,32 +351,29 @@ function check11goodHost(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
"Method: GET",
"Path: /http/1.1-good-host",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: 4444",
];
let body = [
"Method: GET",
"Path: /http/1.1-good-host",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: 4444",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.1 request, Host header is secondary identity
function http11ipHost(request, response) {
writeDetails(request, response);
response.setStatusLine("1.1", 200, "TEST PASSED");
}
data = "GET /http/1.1-ip-host HTTP/1.1\r\n" +
"Host: 127.0.0.1:4444\r\n" +
"\r\n";
data =
"GET /http/1.1-ip-host HTTP/1.1\r\n" + "Host: 127.0.0.1:4444\r\n" + "\r\n";
function check11ipHost(aData) {
let iter = LineIterator(aData);
@ -395,63 +383,62 @@ function check11ipHost(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
"Method: GET",
"Path: /http/1.1-ip-host",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: 127.0.0.1",
"Port: 4444",
];
let body = [
"Method: GET",
"Path: /http/1.1-ip-host",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: 127.0.0.1",
"Port: 4444",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check11ipHost);
tests.push(test);
// HTTP/1.1 request, absolute path, accurate Host header
// reusing previous request handler so not defining a new one
data = "GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
data =
"GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.1 request, absolute path, inaccurate Host header
// reusing previous request handler so not defining a new one
data = "GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: localhost:1234\r\n" +
"\r\n";
data =
"GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: localhost:1234\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.1 request, absolute path, different inaccurate Host header
// reusing previous request handler so not defining a new one
data = "GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
data =
"GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.1 request, absolute path, yet another inaccurate Host header
// reusing previous request handler so not defining a new one
data = "GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: yippity-skippity\r\n" +
"\r\n";
data =
"GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: yippity-skippity\r\n" +
"\r\n";
function checkInaccurate(aData) {
check11goodHost(aData);
@ -461,14 +448,14 @@ function checkInaccurate(aData) {
test = new RawTest("localhost", PORT, data, checkInaccurate);
tests.push(test);
// HTTP/1.0 request, absolute path, different inaccurate Host header
// reusing previous request handler so not defining a new one
data = "GET /http/1.0-request HTTP/1.0\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
data =
"GET /http/1.0-request HTTP/1.0\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
function check10ip(aData) {
let iter = LineIterator(aData);
@ -478,32 +465,31 @@ function check10ip(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
"Method: GET",
"Path: /http/1.0-request",
"Query: ",
"Version: 1.0",
"Scheme: http",
"Host: 127.0.0.1",
"Port: 4444",
];
let body = [
"Method: GET",
"Path: /http/1.0-request",
"Query: ",
"Version: 1.0",
"Scheme: http",
"Host: 127.0.0.1",
"Port: 4444",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check10ip);
tests.push(test);
// HTTP/1.1 request, Host header with implied port
function http11goodHostWackyPort(request, response) {
writeDetails(request, response);
response.setStatusLine("1.1", 200, "TEST PASSED");
}
data = "GET /http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n";
data =
"GET /http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n";
function check11goodHostWackyPort(aData) {
let iter = LineIterator(aData);
@ -513,108 +499,104 @@ function check11goodHostWackyPort(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
"Method: GET",
"Path: /http/1.1-good-host-wacky-port",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: 80",
];
let body = [
"Method: GET",
"Path: /http/1.1-good-host-wacky-port",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: 80",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, Host header with wacky implied port
data = "GET /http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost:\r\n" +
"\r\n";
data =
"GET /http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost:\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, absolute URI with implied port
data = "GET http://localhost/http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n";
data =
"GET http://localhost/http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, absolute URI with wacky implied port
data = "GET http://localhost:/http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n";
data =
"GET http://localhost:/http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, absolute URI with explicit implied port, ignored Host
data = "GET http://localhost:80/http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: who-cares\r\n" +
"\r\n";
data =
"GET http://localhost:80/http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: who-cares\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, a malformed Request-URI
data = "GET is-this-the-real-life-is-this-just-fantasy HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
data =
"GET is-this-the-real-life-is-this-just-fantasy HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, a malformed Host header
data = "GET /http/1.1-request HTTP/1.1\r\n" +
"Host: la la la\r\n" +
"\r\n";
data = "GET /http/1.1-request HTTP/1.1\r\n" + "Host: la la la\r\n" + "\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, a malformed Host header but absolute URI, 5.2 sez fine
data = "GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: la la la\r\n" +
"\r\n";
data =
"GET http://localhost:4444/http/1.1-good-host HTTP/1.1\r\n" +
"Host: la la la\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.0 request, absolute URI, but those aren't valid in HTTP/1.0
data = "GET http://localhost:4444/http/1.1-request HTTP/1.0\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
data =
"GET http://localhost:4444/http/1.1-request HTTP/1.0\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, absolute URI with unrecognized host
data = "GET http://not-localhost:4444/http/1.1-request HTTP/1.1\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
data =
"GET http://not-localhost:4444/http/1.1-request HTTP/1.1\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, absolute URI with unrecognized host (but not in Host)
data = "GET http://not-localhost:4444/http/1.1-request HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
data =
"GET http://not-localhost:4444/http/1.1-request HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);

View file

@ -1,5 +1,5 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
*/
*/
/* 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/. */

View file

@ -5,7 +5,9 @@
* Ensure httpd.js can be imported as a module and that a server starts.
*/
function run_test() {
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import(
"resource://testing-common/httpd.js"
);
let server = new HttpServer();
server.start(-1);

View file

@ -16,36 +16,43 @@ XPCOMUtils.defineLazyGetter(this, "PREFIX", function() {
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test(PREFIX + "/bar.html^",
null, start_bar_html_, null),
new Test(PREFIX + "/foo.html^",
null, start_foo_html_, null),
new Test(PREFIX + "/normal-file.txt",
null, start_normal_file_txt, null),
new Test(PREFIX + "/folder^/file.txt",
null, start_folder__file_txt, null),
new Test(PREFIX + "/bar.html^", null, start_bar_html_, null),
new Test(PREFIX + "/foo.html^", null, start_foo_html_, null),
new Test(PREFIX + "/normal-file.txt", null, start_normal_file_txt, null),
new Test(PREFIX + "/folder^/file.txt", null, start_folder__file_txt, null),
new Test(PREFIX + "/foo/bar.html^",
null, start_bar_html_, null),
new Test(PREFIX + "/foo/foo.html^",
null, start_foo_html_, null),
new Test(PREFIX + "/foo/normal-file.txt",
null, start_normal_file_txt, null),
new Test(PREFIX + "/foo/folder^/file.txt",
null, start_folder__file_txt, null),
new Test(PREFIX + "/foo/bar.html^", null, start_bar_html_, null),
new Test(PREFIX + "/foo/foo.html^", null, start_foo_html_, null),
new Test(
PREFIX + "/foo/normal-file.txt",
null,
start_normal_file_txt,
null
),
new Test(
PREFIX + "/foo/folder^/file.txt",
null,
start_folder__file_txt,
null
),
new Test(PREFIX + "/end-caret^/bar.html^",
null, start_bar_html_, null),
new Test(PREFIX + "/end-caret^/foo.html^",
null, start_foo_html_, null),
new Test(PREFIX + "/end-caret^/normal-file.txt",
null, start_normal_file_txt, null),
new Test(PREFIX + "/end-caret^/folder^/file.txt",
null, start_folder__file_txt, null),
];
new Test(PREFIX + "/end-caret^/bar.html^", null, start_bar_html_, null),
new Test(PREFIX + "/end-caret^/foo.html^", null, start_foo_html_, null),
new Test(
PREFIX + "/end-caret^/normal-file.txt",
null,
start_normal_file_txt,
null
),
new Test(
PREFIX + "/end-caret^/folder^/file.txt",
null,
start_folder__file_txt,
null
),
];
});
function run_test() {
srv = createServer();
@ -61,7 +68,6 @@ function run_test() {
runHttpTests(tests, testComplete(srv));
}
// TEST DATA
function start_bar_html_(ch) {

View file

@ -4,7 +4,6 @@
* 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/. */
/*
* Tests for correct behavior of asynchronous responses.
*/
@ -17,14 +16,14 @@ var srv;
function run_test() {
srv = createServer();
for (var path in handlers)
for (var path in handlers) {
srv.registerPathHandler(path, handlers[path]);
}
srv.start(-1);
runHttpTests(tests, testComplete(srv));
}
/** *************
* BEGIN TESTS *
***************/
@ -32,12 +31,24 @@ function run_test() {
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test(PREPATH + "/handleSync", null, start_handleSync, null),
new Test(PREPATH + "/handleAsync1", null, start_handleAsync1,
stop_handleAsync1),
new Test(PREPATH + "/handleAsync2", init_handleAsync2, start_handleAsync2,
stop_handleAsync2),
new Test(PREPATH + "/handleAsyncOrdering", null, null,
stop_handleAsyncOrdering),
new Test(
PREPATH + "/handleAsync1",
null,
start_handleAsync1,
stop_handleAsync1
),
new Test(
PREPATH + "/handleAsync2",
init_handleAsync2,
start_handleAsync2,
stop_handleAsync2
),
new Test(
PREPATH + "/handleAsyncOrdering",
null,
null,
stop_handleAsyncOrdering
),
];
});
@ -171,14 +182,19 @@ handlers["/handleAsync2"] = handleAsync2;
var startTime_handleAsync2;
function init_handleAsync2(ch) {
var now = startTime_handleAsync2 = Date.now();
var now = (startTime_handleAsync2 = Date.now());
dumpn("*** init_HandleAsync2: start time " + now);
}
function start_handleAsync2(ch) {
var now = Date.now();
dumpn("*** start_handleAsync2: onStartRequest time " + now + ", " +
(now - startTime_handleAsync2) + "ms after start time");
dumpn(
"*** start_handleAsync2: onStartRequest time " +
now +
", " +
(now - startTime_handleAsync2) +
"ms after start time"
);
Assert.ok(now >= startTime_handleAsync2 + startToHeaderDelay);
Assert.equal(ch.responseStatus, 200);
@ -188,8 +204,13 @@ function start_handleAsync2(ch) {
function stop_handleAsync2(ch, status, data) {
var now = Date.now();
dumpn("*** stop_handleAsync2: onStopRequest time " + now + ", " +
(now - startTime_handleAsync2) + "ms after header time");
dumpn(
"*** stop_handleAsync2: onStopRequest time " +
now +
", " +
(now - startTime_handleAsync2) +
"ms after header time"
);
Assert.ok(now >= startTime_handleAsync2 + startToFinishedDelay);
Assert.equal(String.fromCharCode.apply(null, data), "BODY");
@ -206,30 +227,30 @@ function handleAsyncOrdering(request, response) {
var out = new BinaryOutputStream(response.bodyOutputStream);
var data = [];
for (var i = 0; i < 65536; i++)
for (var i = 0; i < 65536; i++) {
data[i] = 0;
}
var count = 20;
var writeData =
{
run() {
if (count-- === 0) {
response.finish();
return;
}
var writeData = {
run() {
if (count-- === 0) {
response.finish();
return;
}
try {
out.writeByteArray(data, data.length);
step();
} catch (e) {
try {
out.writeByteArray(data, data.length);
step();
} catch (e) {
try {
do_throw("error writing data: " + e);
} finally {
response.finish();
}
do_throw("error writing data: " + e);
} finally {
response.finish();
}
},
};
}
},
};
function step() {
// Use gThreadManager here because it's expedient, *not* because it's
// intended for public use! If you do this in client code, expect me to
@ -244,7 +265,8 @@ handlers["/handleAsyncOrdering"] = handleAsyncOrdering;
function stop_handleAsyncOrdering(ch, status, data) {
Assert.equal(data.length, 20 * 65536);
data.forEach(function(v, index) {
if (v !== 0)
if (v !== 0) {
do_throw("value " + v + " at index " + index + " should be zero");
}
});
}

View file

@ -13,10 +13,18 @@
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test("http://localhost:" + srv.identity.primaryPort + "/test",
null, start_test, null),
new Test("http://localhost:" + srv.identity.primaryPort + "/sjs/qi.sjs",
null, start_sjs_qi, null),
new Test(
"http://localhost:" + srv.identity.primaryPort + "/test",
null,
start_test,
null
),
new Test(
"http://localhost:" + srv.identity.primaryPort + "/sjs/qi.sjs",
null,
start_sjs_qi,
null
),
];
});
@ -41,7 +49,6 @@ function run_test() {
runHttpTests(tests, testComplete(srv));
}
// TEST DATA
function start_test(ch) {
@ -54,7 +61,6 @@ function start_sjs_qi(ch) {
Assert.equal(ch.responseStatus, 200);
}
function testHandler(request, response) {
var exstr;
var qid;
@ -67,8 +73,11 @@ function testHandler(request, response) {
passed = qid === request;
} catch (e) {
exstr = ("" + e).split(/[\x09\x20-\x7f\x81-\xff]+/)[0];
response.setStatusLine(request.httpVersion, 500,
"request doesn't QI: " + exstr);
response.setStatusLine(
request.httpVersion,
500,
"request doesn't QI: " + exstr
);
return;
}
if (!passed) {
@ -82,8 +91,11 @@ function testHandler(request, response) {
passed = qid === response;
} catch (e) {
exstr = ("" + e).split(/[\x09\x20-\x7f\x81-\xff]+/)[0];
response.setStatusLine(request.httpVersion, 500,
"response doesn't QI: " + exstr);
response.setStatusLine(
request.httpVersion,
500,
"response doesn't QI: " + exstr
);
return;
}
if (!passed) {

View file

@ -10,7 +10,6 @@ XPCOMUtils.defineLazyGetter(this, "BASE", function() {
return "http://localhost:" + srv.identity.primaryPort;
});
function nocache(ch) {
ch.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; // important!
}
@ -38,186 +37,222 @@ function checkFile(ch, status, data) {
var actualFile = serverBasePath.clone();
actualFile.append("test_registerdirectory.js");
Assert.equal(ch.getResponseHeader("Content-Length"),
actualFile.fileSize.toString());
Assert.equal(data.map(v => String.fromCharCode(v)).join(""),
fileContents(actualFile));
Assert.equal(
ch.getResponseHeader("Content-Length"),
actualFile.fileSize.toString()
);
Assert.equal(
data.map(v => String.fromCharCode(v)).join(""),
fileContents(actualFile)
);
}
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
/** *********************
* without a base path *
***********************/
new Test(BASE + "/test_registerdirectory.js", nocache, notFound, null),
/** *********************
* without a base path *
***********************/
new Test(BASE + "/test_registerdirectory.js",
nocache, notFound, null),
/** ******************
* with a base path *
********************/
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = testsDirectory.clone();
srv.registerDirectory("/", serverBasePath);
},
null,
checkFile
),
/** ******************
* with a base path *
********************/
new Test(BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = testsDirectory.clone();
srv.registerDirectory("/", serverBasePath);
},
null,
checkFile),
/** ***************************
* without a base path again *
*****************************/
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = null;
srv.registerDirectory("/", serverBasePath);
},
notFound,
null
),
/** ***************************
* without a base path again *
*****************************/
new Test(BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = null;
srv.registerDirectory("/", serverBasePath);
},
notFound,
null),
/** *************************
* registered path handler *
***************************/
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerPathHandler(
"/test_registerdirectory.js",
override_test_registerdirectory
);
},
checkOverride,
null
),
/** *************************
* registered path handler *
***************************/
new Test(BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js",
override_test_registerdirectory);
},
checkOverride,
null),
/** **********************
* removed path handler *
************************/
new Test(
BASE + "/test_registerdirectory.js",
function init_registerDirectory6(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js", null);
},
notFound,
null
),
/** **********************
* removed path handler *
************************/
new Test(BASE + "/test_registerdirectory.js",
function init_registerDirectory6(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js", null);
},
notFound,
null),
/** ******************
* with a base path *
********************/
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
/** ******************
* with a base path *
********************/
new Test(BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
// set the base path again
serverBasePath = testsDirectory.clone();
srv.registerDirectory("/", serverBasePath);
},
null,
checkFile
),
// set the base path again
serverBasePath = testsDirectory.clone();
srv.registerDirectory("/", serverBasePath);
},
null,
checkFile),
/** ***********************
* ...and a path handler *
*************************/
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerPathHandler(
"/test_registerdirectory.js",
override_test_registerdirectory
);
},
checkOverride,
null
),
/** ***********************
* ...and a path handler *
*************************/
new Test(BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js",
override_test_registerdirectory);
},
checkOverride,
null),
/** **********************
* removed base handler *
************************/
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = null;
srv.registerDirectory("/", serverBasePath);
},
checkOverride,
null
),
/** **********************
* removed base handler *
************************/
new Test(BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = null;
srv.registerDirectory("/", serverBasePath);
},
checkOverride,
null),
/** **********************
* removed path handler *
************************/
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js", null);
},
notFound,
null
),
/** **********************
* removed path handler *
************************/
new Test(BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js", null);
},
notFound,
null),
/** ***********************
* mapping set up, works *
*************************/
new Test(
BASE + "/foo/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = testsDirectory.clone();
srv.registerDirectory("/foo/", serverBasePath);
},
check200,
null
),
/** ***********************
* mapping set up, works *
*************************/
new Test(BASE + "/foo/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = testsDirectory.clone();
srv.registerDirectory("/foo/", serverBasePath);
},
check200,
null),
/** *******************
* no mapping, fails *
*********************/
new Test(
BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
nocache,
notFound,
null
),
/** *******************
* no mapping, fails *
*********************/
new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
nocache,
notFound,
null),
/** ****************
* mapping, works *
******************/
new Test(
BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerDirectory(
"/foo/test_registerdirectory.js/",
serverBasePath
);
},
null,
checkFile
),
/** ****************
* mapping, works *
******************/
new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerDirectory("/foo/test_registerdirectory.js/",
serverBasePath);
},
null,
checkFile),
/** **********************************
* two mappings set up, still works *
************************************/
new Test(BASE + "/foo/test_registerdirectory.js", nocache, null, checkFile),
/** **********************************
* two mappings set up, still works *
************************************/
new Test(BASE + "/foo/test_registerdirectory.js",
nocache, null, checkFile),
/** ************************
* remove topmost mapping *
**************************/
new Test(
BASE + "/foo/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerDirectory("/foo/", null);
},
notFound,
null
),
/** ************************
* remove topmost mapping *
**************************/
new Test(BASE + "/foo/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerDirectory("/foo/", null);
},
notFound,
null),
/** ************************************
* lower mapping still present, works *
**************************************/
new Test(
BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
nocache,
null,
checkFile
),
/** ************************************
* lower mapping still present, works *
**************************************/
new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
nocache, null, checkFile),
/** *****************
* mapping removed *
*******************/
new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerDirectory("/foo/test_registerdirectory.js/", null);
},
notFound,
null),
/** *****************
* mapping removed *
*******************/
new Test(
BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerDirectory("/foo/test_registerdirectory.js/", null);
},
notFound,
null
),
];
});
var srv;
var serverBasePath;
var testsDirectory;
@ -231,7 +266,6 @@ function run_test() {
runHttpTests(tests, testComplete(srv));
}
// PATH HANDLERS
// override of /test_registerdirectory.js

View file

@ -20,25 +20,41 @@ function notFound(ch) {
}
function makeCheckOverride(magic) {
return (function checkOverride(ch) {
return function checkOverride(ch) {
Assert.equal(ch.responseStatus, 200);
Assert.equal(ch.responseStatusText, "OK");
Assert.ok(ch.requestSucceeded);
Assert.equal(ch.getResponseHeader("Override-Succeeded"), magic);
});
};
}
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test(BASE + "/prefix/dummy", prefixHandler, null,
makeCheckOverride("prefix")),
new Test(BASE + "/prefix/dummy", pathHandler, null,
makeCheckOverride("path")),
new Test(BASE + "/prefix/subpath/dummy", longerPrefixHandler, null,
makeCheckOverride("subpath")),
new Test(
BASE + "/prefix/dummy",
prefixHandler,
null,
makeCheckOverride("prefix")
),
new Test(
BASE + "/prefix/dummy",
pathHandler,
null,
makeCheckOverride("path")
),
new Test(
BASE + "/prefix/subpath/dummy",
longerPrefixHandler,
null,
makeCheckOverride("subpath")
),
new Test(BASE + "/prefix/dummy", removeHandlers, null, notFound),
new Test(BASE + "/prefix/subpath/dummy", newPrefixHandler, null,
makeCheckOverride("subpath")),
new Test(
BASE + "/prefix/subpath/dummy",
newPrefixHandler,
null,
makeCheckOverride("subpath")
),
];
});
@ -105,11 +121,11 @@ function run_test() {
// generate an override
function makeOverride(magic) {
return (function override(metadata, response) {
return function override(metadata, response) {
response.setStatusLine("1.1", 200, "OK");
response.setHeader("Override-Succeeded", magic, false);
var body = "success!";
response.bodyOutputStream.write(body, body.length);
});
};
}

View file

@ -15,15 +15,15 @@ srv.start(-1);
const PORT = srv.identity.primaryPort;
function run_test() {
srv.registerPathHandler("/lots-of-leading-blank-lines",
lotsOfLeadingBlankLines);
srv.registerPathHandler("/very-long-request-line",
veryLongRequestLine);
srv.registerPathHandler(
"/lots-of-leading-blank-lines",
lotsOfLeadingBlankLines
);
srv.registerPathHandler("/very-long-request-line", veryLongRequestLine);
runRawTests(tests, testComplete(srv));
}
/** *************
* BEGIN TESTS *
***************/
@ -31,7 +31,6 @@ function run_test() {
var test, gData, str;
var tests = [];
function veryLongRequestLine(request, response) {
writeDetails(request, response);
response.setStatusLine(request.httpVersion, 200, "TEST PASSED");
@ -46,14 +45,21 @@ reallyLong = reallyLong + reallyLong + reallyLong + reallyLong; // 8192
reallyLong = reallyLong + reallyLong + reallyLong + reallyLong; // 32768
reallyLong = reallyLong + reallyLong + reallyLong + reallyLong; // 131072
reallyLong = reallyLong + reallyLong + reallyLong + reallyLong; // 524288
if (reallyLong.length !== 524288)
if (reallyLong.length !== 524288) {
throw new TypeError("generated length not as long as expected");
str = "GET /very-long-request-line?" + reallyLong + " HTTP/1.1\r\n" +
"Host: localhost:" + PORT + "\r\n" +
"\r\n";
}
str =
"GET /very-long-request-line?" +
reallyLong +
" HTTP/1.1\r\n" +
"Host: localhost:" +
PORT +
"\r\n" +
"\r\n";
gData = [];
for (let i = 0; i < str.length; i += 16384)
for (let i = 0; i < str.length; i += 16384) {
gData.push(str.substr(i, 16384));
}
function checkVeryLongRequestLine(data) {
var iter = LineIterator(data);
@ -67,38 +73,41 @@ function checkVeryLongRequestLine(data) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
var body =
[
"Method: GET",
"Path: /very-long-request-line",
"Query: " + reallyLong,
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: " + PORT,
];
var body = [
"Method: GET",
"Path: /very-long-request-line",
"Query: " + reallyLong,
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: " + PORT,
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, gData, checkVeryLongRequestLine);
tests.push(test);
function lotsOfLeadingBlankLines(request, response) {
writeDetails(request, response);
response.setStatusLine(request.httpVersion, 200, "TEST PASSED");
}
var blankLines = "\r\n";
for (let i = 0; i < 14; i++)
for (let i = 0; i < 14; i++) {
blankLines += blankLines;
str = blankLines +
"GET /lots-of-leading-blank-lines HTTP/1.1\r\n" +
"Host: localhost:" + PORT + "\r\n" +
"\r\n";
}
str =
blankLines +
"GET /lots-of-leading-blank-lines HTTP/1.1\r\n" +
"Host: localhost:" +
PORT +
"\r\n" +
"\r\n";
gData = [];
for (let i = 0; i < str.length; i += 100)
for (let i = 0; i < str.length; i += 100) {
gData.push(str.substr(i, 100));
}
function checkLotsOfLeadingBlankLines(data) {
var iter = LineIterator(data);
@ -112,16 +121,15 @@ function checkLotsOfLeadingBlankLines(data) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
var body =
[
"Method: GET",
"Path: /lots-of-leading-blank-lines",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: " + PORT,
];
var body = [
"Method: GET",
"Path: /lots-of-leading-blank-lines",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: " + PORT,
];
expectLines(iter, body);
}

View file

@ -8,10 +8,18 @@
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test("http://localhost:" + srv.identity.primaryPort + "/writeString",
null, check_1234, succeeded),
new Test("http://localhost:" + srv.identity.primaryPort + "/writeInt",
null, check_1234, succeeded),
new Test(
"http://localhost:" + srv.identity.primaryPort + "/writeString",
null,
check_1234,
succeeded
),
new Test(
"http://localhost:" + srv.identity.primaryPort + "/writeInt",
null,
check_1234,
succeeded
),
];
});
@ -27,7 +35,6 @@ function run_test() {
runHttpTests(tests, testComplete(srv));
}
// TEST DATA
function succeeded(ch, status, data) {

View file

@ -28,13 +28,13 @@ function run_test() {
runRawTests(tests, testComplete(srv));
}
function checkException(fun, err, msg) {
try {
fun();
} catch (e) {
if (e !== err && e.result !== err)
if (e !== err && e.result !== err) {
do_throw(msg);
}
return;
}
do_throw(msg);
@ -48,7 +48,6 @@ function callASAPLater(fun) {
});
}
/** ***************
* PATH HANDLERS *
*****************/
@ -65,33 +64,50 @@ function handleTooLate(request, response) {
response.seizePower();
if (response.bodyOutputStream !== output)
if (response.bodyOutputStream !== output) {
response.write("bodyOutputStream changed!");
else
} else {
response.write("too-late passed");
}
response.finish();
}
function handleExceptions(request, response) {
response.seizePower();
checkException(function() { response.setStatusLine("1.0", 500, "ISE"); },
Cr.NS_ERROR_NOT_AVAILABLE,
"setStatusLine should throw not-available after seizePower");
checkException(function() { response.setHeader("X-Fail", "FAIL", false); },
Cr.NS_ERROR_NOT_AVAILABLE,
"setHeader should throw not-available after seizePower");
checkException(function() { response.processAsync(); },
Cr.NS_ERROR_NOT_AVAILABLE,
"processAsync should throw not-available after seizePower");
checkException(
function() {
response.setStatusLine("1.0", 500, "ISE");
},
Cr.NS_ERROR_NOT_AVAILABLE,
"setStatusLine should throw not-available after seizePower"
);
checkException(
function() {
response.setHeader("X-Fail", "FAIL", false);
},
Cr.NS_ERROR_NOT_AVAILABLE,
"setHeader should throw not-available after seizePower"
);
checkException(
function() {
response.processAsync();
},
Cr.NS_ERROR_NOT_AVAILABLE,
"processAsync should throw not-available after seizePower"
);
var out = response.bodyOutputStream;
var data = "exceptions test passed";
out.write(data, data.length);
response.seizePower(); // idempotency test of seizePower
response.finish();
response.finish(); // idempotency test of finish after seizePower
checkException(function() { response.seizePower(); },
Cr.NS_ERROR_UNEXPECTED,
"seizePower should throw unexpected after finish");
checkException(
function() {
response.seizePower();
},
Cr.NS_ERROR_UNEXPECTED,
"seizePower should throw unexpected after finish"
);
}
function handleAsyncSeizure(request, response) {
@ -108,15 +124,18 @@ function handleAsyncSeizure(request, response) {
function handleSeizeAfterAsync(request, response) {
response.setStatusLine(request.httpVersion, 200, "async seizure pass");
response.processAsync();
checkException(function() { response.seizePower(); },
Cr.NS_ERROR_NOT_AVAILABLE,
"seizePower should throw not-available after processAsync");
checkException(
function() {
response.seizePower();
},
Cr.NS_ERROR_NOT_AVAILABLE,
"seizePower should throw not-available after processAsync"
);
callLater(1, function() {
response.finish();
});
}
/** *************
* BEGIN TESTS *
***************/
@ -131,32 +150,30 @@ XPCOMUtils.defineLazyGetter(this, "tests", function() {
];
});
var data0 = "GET /raw-data HTTP/1.0\r\n" +
"\r\n";
var data0 = "GET /raw-data HTTP/1.0\r\n" + "\r\n";
function checkRawData(data) {
Assert.equal(data, "Raw data!");
}
var data1 = "GET /called-too-late HTTP/1.0\r\n" +
"\r\n";
var data1 = "GET /called-too-late HTTP/1.0\r\n" + "\r\n";
function checkTooLate(data) {
Assert.equal(LineIterator(data).next().value, "too-late passed");
}
var data2 = "GET /exceptions HTTP/1.0\r\n" +
"\r\n";
var data2 = "GET /exceptions HTTP/1.0\r\n" + "\r\n";
function checkExceptions(data) {
Assert.equal("exceptions test passed", data);
}
var data3 = "GET /async-seizure HTTP/1.0\r\n" +
"\r\n";
var data3 = "GET /async-seizure HTTP/1.0\r\n" + "\r\n";
function checkAsyncSeizure(data) {
Assert.equal(data, "async seizure passed");
}
var data4 = "GET /seize-after-async HTTP/1.0\r\n" +
"\r\n";
var data4 = "GET /seize-after-async HTTP/1.0\r\n" + "\r\n";
function checkSeizeAfterAsync(data) {
Assert.equal(LineIterator(data).next().value, "HTTP/1.0 200 async seizure pass");
Assert.equal(
LineIterator(data).next().value,
"HTTP/1.0 200 async seizure pass"
);
}

View file

@ -30,22 +30,27 @@ function run_test() {
runHttpTests(tests, testComplete(srv));
}
/** ***********
* UTILITIES *
*************/
function checkStatusLine(channel, httpMaxVer, httpMinVer, httpCode, statusText) {
function checkStatusLine(
channel,
httpMaxVer,
httpMinVer,
httpCode,
statusText
) {
Assert.equal(channel.responseStatus, httpCode);
Assert.equal(channel.responseStatusText, statusText);
var respMaj = {}, respMin = {};
var respMaj = {},
respMin = {};
channel.getResponseVersion(respMaj, respMin);
Assert.equal(respMaj.value, httpMaxVer);
Assert.equal(respMin.value, httpMinVer);
}
/** *******
* TESTS *
*********/
@ -63,10 +68,8 @@ XPCOMUtils.defineLazyGetter(this, "tests", function() {
];
});
// /no/setstatusline
function noSetstatusline(metadata, response) {
}
function noSetstatusline(metadata, response) {}
function startNoSetStatusLine(ch) {
checkStatusLine(ch, 1, 1, 200, "OK");
}
@ -74,7 +77,6 @@ function stop(ch, status, data) {
Assert.ok(Components.isSuccessCode(status));
}
// /http1_0
function http1_0(metadata, response) {
response.setStatusLine("1.0", 200, "OK");
@ -83,7 +85,6 @@ function startHttp1_0(ch) {
checkStatusLine(ch, 1, 0, 200, "OK");
}
// /http1_1
function http1_1(metadata, response) {
response.setStatusLine("1.1", 200, "OK");
@ -92,7 +93,6 @@ function startHttp1_1(ch) {
checkStatusLine(ch, 1, 1, 200, "OK");
}
// /invalidVersion
function invalidVersion(metadata, response) {
try {
@ -106,7 +106,6 @@ function startPassedTrue(ch) {
Assert.equal(ch.getResponseHeader("Passed"), "true");
}
// /invalidStatus
function invalidStatus(metadata, response) {
try {
@ -116,7 +115,6 @@ function invalidStatus(metadata, response) {
}
}
// /invalidDescription
function invalidDescription(metadata, response) {
try {
@ -126,7 +124,6 @@ function invalidDescription(metadata, response) {
}
}
// /crazyCode
function crazyCode(metadata, response) {
response.setStatusLine("1.1", 617, "Crazy");
@ -135,7 +132,6 @@ function startCrazy(ch) {
checkStatusLine(ch, 1, 1, 617, "Crazy");
}
// /nullVersion
function nullVersion(metadata, response) {
response.setStatusLine(null, 255, "NULL");

View file

@ -20,20 +20,22 @@ const BASE = "http://localhost:" + PORT;
var test;
var tests = [];
/** *******************
* UTILITY FUNCTIONS *
*********************/
function bytesToString(bytes) {
return bytes.map(function(v) { return String.fromCharCode(v); }).join("");
return bytes
.map(function(v) {
return String.fromCharCode(v);
})
.join("");
}
function skipCache(ch) {
ch.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
}
/** ******************
* DEFINE THE TESTS *
********************/
@ -61,7 +63,6 @@ function setupTests(throwing) {
test = new Test(TEST_URL, setupFile, null, verifyRawText);
tests.push(test);
// add mapping, => interpreted
function addTypeMapping(ch) {
@ -79,14 +80,14 @@ function setupTests(throwing) {
}
function checkContents(ch, status, data) {
if (!throwing)
if (!throwing) {
Assert.equal("PASS", bytesToString(data));
}
}
test = new Test(TEST_URL, addTypeMapping, checkType, checkContents);
tests.push(test);
// remove file/type mapping, map containing directory => raw text
function setupDirectoryAndRemoveType(ch) {
@ -100,7 +101,6 @@ function setupTests(throwing) {
test = new Test(TEST_URL, setupDirectoryAndRemoveType, null, verifyRawText);
tests.push(test);
// add mapping, => interpreted
function contentAndCleanup(ch, status, data) {
@ -119,7 +119,6 @@ function setupTests(throwing) {
// after the two sets will almost certainly fail.
}
/** ***************
* ADD THE TESTS *
*****************/
@ -157,34 +156,54 @@ function rangeInit(expectedRangeHeader) {
function checkRangeResult(ch) {
try {
var val = ch.getResponseHeader("Content-Range");
} catch (e) { /* IDL doesn't specify a particular exception to require */ }
} catch (e) {
/* IDL doesn't specify a particular exception to require */
}
if (val !== undefined) {
do_throw("should not have gotten a Content-Range header, but got one " +
"with this value: " + val);
do_throw(
"should not have gotten a Content-Range header, but got one " +
"with this value: " +
val
);
}
Assert.equal(200, ch.responseStatus);
Assert.equal("OK", ch.responseStatusText);
}
test = new Test(BASE + "/range-checker.sjs",
rangeInit("not-a-bytes-equals-specifier"),
checkRangeResult, null);
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("not-a-bytes-equals-specifier"),
checkRangeResult,
null
);
tests.push(test);
test = new Test(BASE + "/range-checker.sjs",
rangeInit("bytes=-"),
checkRangeResult, null);
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("bytes=-"),
checkRangeResult,
null
);
tests.push(test);
test = new Test(BASE + "/range-checker.sjs",
rangeInit("bytes=1000000-"),
checkRangeResult, null);
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("bytes=1000000-"),
checkRangeResult,
null
);
tests.push(test);
test = new Test(BASE + "/range-checker.sjs",
rangeInit("bytes=1-4"),
checkRangeResult, null);
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("bytes=1-4"),
checkRangeResult,
null
);
tests.push(test);
test = new Test(BASE + "/range-checker.sjs",
rangeInit("bytes=-4"),
checkRangeResult, null);
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("bytes=-4"),
checkRangeResult,
null
);
tests.push(test);
// One last test: for file mappings, the content-type is determined by the
@ -206,7 +225,6 @@ function onStop(ch, status, data) {
test = new Test(BASE + "/script.html", setupFileMapping, onStart, onStop);
tests.push(test);
/** ***************
* RUN THE TESTS *
*****************/
@ -215,7 +233,9 @@ function run_test() {
// Test for a content-type which isn't a field-value
try {
srv.registerContentType("foo", "bar\nbaz");
throw new Error("this server throws on content-types which aren't field-values");
throw new Error(
"this server throws on content-types which aren't field-values"
);
} catch (e) {
isException(e, Cr.NS_ERROR_INVALID_ARG);
}

View file

@ -8,7 +8,6 @@
* Tests that the object-state-preservation mechanism works correctly.
*/
XPCOMUtils.defineLazyGetter(this, "PATH", function() {
return "http://localhost:" + srv.identity.primaryPort + "/object-state.sjs";
});
@ -60,32 +59,46 @@ var initialStarted = false;
function initialStart(ch) {
dumpn("*** initialStart");
if (initialStarted)
if (initialStarted) {
do_throw("initialStart: initialStarted is true?!?!");
}
initialStarted = true;
new HTTPTestLoader(PATH + "?state=intermediate",
intermediateStart, intermediateStop);
new HTTPTestLoader(
PATH + "?state=intermediate",
intermediateStart,
intermediateStop
);
}
var initialStopped = false;
function initialStop(ch, status, data) {
dumpn("*** initialStop");
Assert.equal(data.map(function(v) { return String.fromCharCode(v); }).join(""),
"done");
Assert.equal(
data
.map(function(v) {
return String.fromCharCode(v);
})
.join(""),
"done"
);
Assert.equal(srv.getObjectState("object-state-test"), null);
if (!initialStarted)
if (!initialStarted) {
do_throw("initialStop: initialStarted is false?!?!");
if (initialStopped)
}
if (initialStopped) {
do_throw("initialStop: initialStopped is true?!?!");
if (!intermediateStarted)
}
if (!intermediateStarted) {
do_throw("initialStop: intermediateStarted is false?!?!");
if (!intermediateStopped)
}
if (!intermediateStopped) {
do_throw("initialStop: intermediateStopped is false?!?!");
}
initialStopped = true;
@ -98,10 +111,12 @@ function intermediateStart(ch) {
Assert.notEqual(srv.getObjectState("object-state-test"), null);
if (!initialStarted)
if (!initialStarted) {
do_throw("intermediateStart: initialStarted is false?!?!");
if (intermediateStarted)
}
if (intermediateStarted) {
do_throw("intermediateStart: intermediateStarted is true?!?!");
}
intermediateStarted = true;
}
@ -110,36 +125,48 @@ var intermediateStopped = false;
function intermediateStop(ch, status, data) {
dumpn("*** intermediateStop");
Assert.equal(data.map(function(v) { return String.fromCharCode(v); }).join(""),
"intermediate");
Assert.equal(
data
.map(function(v) {
return String.fromCharCode(v);
})
.join(""),
"intermediate"
);
Assert.notEqual(srv.getObjectState("object-state-test"), null);
if (!initialStarted)
if (!initialStarted) {
do_throw("intermediateStop: initialStarted is false?!?!");
if (!intermediateStarted)
}
if (!intermediateStarted) {
do_throw("intermediateStop: intermediateStarted is false?!?!");
if (intermediateStopped)
}
if (intermediateStopped) {
do_throw("intermediateStop: intermediateStopped is true?!?!");
}
intermediateStopped = true;
new HTTPTestLoader(PATH + "?state=trigger", triggerStart,
triggerStop);
new HTTPTestLoader(PATH + "?state=trigger", triggerStart, triggerStop);
}
var triggerStarted = false;
function triggerStart(ch) {
dumpn("*** triggerStart");
if (!initialStarted)
if (!initialStarted) {
do_throw("triggerStart: initialStarted is false?!?!");
if (!intermediateStarted)
}
if (!intermediateStarted) {
do_throw("triggerStart: intermediateStarted is false?!?!");
if (!intermediateStopped)
}
if (!intermediateStopped) {
do_throw("triggerStart: intermediateStopped is false?!?!");
if (triggerStarted)
}
if (triggerStarted) {
do_throw("triggerStart: triggerStarted is true?!?!");
}
triggerStarted = true;
}
@ -148,19 +175,30 @@ var triggerStopped = false;
function triggerStop(ch, status, data) {
dumpn("*** triggerStop");
Assert.equal(data.map(function(v) { return String.fromCharCode(v); }).join(""),
"trigger");
Assert.equal(
data
.map(function(v) {
return String.fromCharCode(v);
})
.join(""),
"trigger"
);
if (!initialStarted)
if (!initialStarted) {
do_throw("triggerStop: initialStarted is false?!?!");
if (!intermediateStarted)
}
if (!intermediateStarted) {
do_throw("triggerStop: intermediateStarted is false?!?!");
if (!intermediateStopped)
}
if (!intermediateStopped) {
do_throw("triggerStop: intermediateStopped is false?!?!");
if (!triggerStarted)
}
if (!triggerStarted) {
do_throw("triggerStop: triggerStarted is false?!?!");
if (triggerStopped)
}
if (triggerStopped) {
do_throw("triggerStop: triggerStopped is false?!?!");
}
triggerStopped = true;
@ -183,21 +221,24 @@ function checkForFinish() {
try {
Assert.equal(srv.getObjectState("object-state-test"), null);
if (!initialStarted)
if (!initialStarted) {
do_throw("checkForFinish: initialStarted is false?!?!");
if (!intermediateStarted)
}
if (!intermediateStarted) {
do_throw("checkForFinish: intermediateStarted is false?!?!");
if (!intermediateStopped)
}
if (!intermediateStopped) {
do_throw("checkForFinish: intermediateStopped is false?!?!");
if (!triggerStarted)
}
if (!triggerStarted) {
do_throw("checkForFinish: triggerStarted is false?!?!");
}
} finally {
srv.stop(do_test_finished);
}
}
}
/** *******************************
* UTILITY OBSERVABLE URL LOADER *
*********************************/
@ -219,38 +260,46 @@ function HTTPTestLoader(path, start, stop) {
var channel = makeChannel(path);
channel.asyncOpen(this);
}
HTTPTestLoader.prototype =
{
onStartRequest(request) {
dumpn("*** HTTPTestLoader.onStartRequest for " + this._path);
HTTPTestLoader.prototype = {
onStartRequest(request) {
dumpn("*** HTTPTestLoader.onStartRequest for " + this._path);
var ch = request.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
try {
try {
try {
this._start(ch);
} catch (e) {
do_throw(this._path + ": error in onStartRequest: " + e);
}
this._start(ch);
} catch (e) {
dumpn("!!! swallowing onStartRequest exception so onStopRequest is " +
"called...");
do_throw(this._path + ": error in onStartRequest: " + e);
}
},
onDataAvailable(request, inputStream, offset, count) {
dumpn("*** HTTPTestLoader.onDataAvailable for " + this._path);
} catch (e) {
dumpn(
"!!! swallowing onStartRequest exception so onStopRequest is " +
"called..."
);
}
},
onDataAvailable(request, inputStream, offset, count) {
dumpn("*** HTTPTestLoader.onDataAvailable for " + this._path);
Array.prototype.push.apply(this._data,
makeBIS(inputStream).readByteArray(count));
},
onStopRequest(request, status) {
dumpn("*** HTTPTestLoader.onStopRequest for " + this._path);
Array.prototype.push.apply(
this._data,
makeBIS(inputStream).readByteArray(count)
);
},
onStopRequest(request, status) {
dumpn("*** HTTPTestLoader.onStopRequest for " + this._path);
var ch = request.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
this._stop(ch, status, this._data);
},
QueryInterface: ChromeUtils.generateQI(["nsIStreamListener", "nsIRequestObserver"]),
};
this._stop(ch, status, this._data);
},
QueryInterface: ChromeUtils.generateQI([
"nsIStreamListener",
"nsIRequestObserver",
]),
};

View file

@ -22,20 +22,21 @@ function run_test() {
function done() {
Assert.equal(srv.getSharedState("shared-value"), "done!");
Assert.equal(srv.getState("/path-handler", "private-value"),
"pathHandlerPrivate2");
Assert.equal(srv.getState("/state1.sjs", "private-value"),
"");
Assert.equal(srv.getState("/state2.sjs", "private-value"),
"newPrivate5");
Assert.equal(
srv.getState("/path-handler", "private-value"),
"pathHandlerPrivate2"
);
Assert.equal(srv.getState("/state1.sjs", "private-value"), "");
Assert.equal(srv.getState("/state2.sjs", "private-value"), "newPrivate5");
do_test_pending();
srv.stop(function() { do_test_finished(); });
srv.stop(function() {
do_test_finished();
});
}
runHttpTests(tests, done);
}
/** **********
* HANDLERS *
************/
@ -45,10 +46,16 @@ var firstTime = true;
function pathHandler(request, response) {
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("X-Old-Shared-Value", srv.getSharedState("shared-value"),
false);
response.setHeader("X-Old-Private-Value", srv.getState("/path-handler", "private-value"),
false);
response.setHeader(
"X-Old-Shared-Value",
srv.getSharedState("shared-value"),
false
);
response.setHeader(
"X-Old-Private-Value",
srv.getState("/path-handler", "private-value"),
false
);
var privateValue, sharedValue;
if (firstTime) {
@ -67,38 +74,56 @@ function pathHandler(request, response) {
response.setHeader("X-New-Shared-Value", sharedValue, false);
}
/** *************
* BEGIN TESTS *
***************/
XPCOMUtils.defineLazyGetter(this, "tests", function() {
return [
new Test(URL + "/state1.sjs?" +
"newShared=newShared&newPrivate=newPrivate",
null, start_initial, null),
new Test(URL + "/state1.sjs?" +
"newShared=newShared2&newPrivate=newPrivate2",
null, start_overwrite, null),
new Test(URL + "/state1.sjs?" +
"newShared=&newPrivate=newPrivate3",
null, start_remove, null),
new Test(URL + "/path-handler",
null, start_handler, null),
new Test(URL + "/path-handler",
null, start_handler_again, null),
new Test(URL + "/state2.sjs?" +
"newShared=newShared4&newPrivate=newPrivate4",
null, start_other_initial, null),
new Test(URL + "/state2.sjs?" +
"newShared=",
null, start_other_remove_ignore, null),
new Test(URL + "/state2.sjs?" +
"newShared=newShared5&newPrivate=newPrivate5",
null, start_other_set_new, null),
new Test(URL + "/state1.sjs?" +
"newShared=done!&newPrivate=",
null, start_set_remove_original, null),
new Test(
URL + "/state1.sjs?" + "newShared=newShared&newPrivate=newPrivate",
null,
start_initial,
null
),
new Test(
URL + "/state1.sjs?" + "newShared=newShared2&newPrivate=newPrivate2",
null,
start_overwrite,
null
),
new Test(
URL + "/state1.sjs?" + "newShared=&newPrivate=newPrivate3",
null,
start_remove,
null
),
new Test(URL + "/path-handler", null, start_handler, null),
new Test(URL + "/path-handler", null, start_handler_again, null),
new Test(
URL + "/state2.sjs?" + "newShared=newShared4&newPrivate=newPrivate4",
null,
start_other_initial,
null
),
new Test(
URL + "/state2.sjs?" + "newShared=",
null,
start_other_remove_ignore,
null
),
new Test(
URL + "/state2.sjs?" + "newShared=newShared5&newPrivate=newPrivate5",
null,
start_other_set_new,
null
),
new Test(
URL + "/state1.sjs?" + "newShared=done!&newPrivate=",
null,
start_set_remove_original,
null
),
];
});
@ -108,8 +133,9 @@ function getHeaderFunction(ch) {
try {
return ch.getResponseHeader(name);
} catch (e) {
if (e.result !== Cr.NS_ERROR_NOT_AVAILABLE)
if (e.result !== Cr.NS_ERROR_NOT_AVAILABLE) {
throw e;
}
}
return "";
}
@ -127,7 +153,7 @@ function expectValues(ch, oldShared, newShared, oldPrivate, newPrivate) {
}
function start_initial(ch) {
dumpn("XXX start_initial");
dumpn("XXX start_initial");
expectValues(ch, "", "newShared", "", "newPrivate");
}
@ -144,8 +170,13 @@ function start_handler(ch) {
}
function start_handler_again(ch) {
expectValues(ch, "pathHandlerShared", "",
"pathHandlerPrivate", "pathHandlerPrivate2");
expectValues(
ch,
"pathHandlerShared",
"",
"pathHandlerPrivate",
"pathHandlerPrivate2"
);
}
function start_other_initial(ch) {

View file

@ -25,7 +25,9 @@ function run_test() {
function done() {
do_test_pending();
srv.stop(function() { do_test_finished(); });
srv.stop(function() {
do_test_finished();
});
Assert.equal(gStartCount, TEST_RUNS);
Assert.ok(lastPassed);
}
@ -46,8 +48,9 @@ const TEST_RUNS = 250;
XPCOMUtils.defineLazyGetter(this, "tests", function() {
var _tests = new Array(TEST_RUNS + 1);
var _test = new Test(URL + "/thrower.sjs?throw", null, start_thrower);
for (var i = 0; i < TEST_RUNS; i++)
for (var i = 0; i < TEST_RUNS; i++) {
_tests[i] = _test;
}
// ...and don't forget to stop!
_tests[TEST_RUNS] = new Test(URL + "/thrower.sjs", null, start_last);
return _tests;

View file

@ -20,8 +20,10 @@ var srv, srv2;
function run_test() {
if (mozinfo.os == "win") {
dumpn("*** not running test_start_stop.js on Windows for now, because " +
"Windows is dumb");
dumpn(
"*** not running test_start_stop.js on Windows for now, because " +
"Windows is dumb"
);
return;
}
@ -65,15 +67,16 @@ function run_test_2() {
do_test_pending();
try {
srv.stop({onStopped() {
try {
do_test_pending();
run_test_3();
} finally {
do_test_finished();
}
},
});
srv.stop({
onStopped() {
try {
do_test_pending();
run_test_3();
} finally {
do_test_finished();
}
},
});
} catch (e) {
do_throw("error stopping with an object: " + e);
}
@ -123,11 +126,11 @@ function run_test_5() {
dumpn("*** run_test_5");
testsComplete = true;
if (stopped)
if (stopped) {
do_test_finished();
}
}
const INTERVAL = 500;
function handle(request, response) {
@ -157,6 +160,7 @@ var stopped = false;
function serverStopped() {
dumpn("*** server really, fully shut down now");
stopped = true;
if (testsComplete)
if (testsComplete) {
do_test_finished();
}
}

View file

@ -1,4 +1,4 @@
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
var observer = {
@ -8,15 +8,15 @@ var observer = {
sendAsyncMessage("cookieName", cookie.name + "=" + cookie.value);
sendAsyncMessage("cookieOperation", data);
}
}
},
};
addMessageListener("createObserver" , function(e) {
addMessageListener("createObserver", function(e) {
Services.obs.addObserver(observer, "cookie-changed");
sendAsyncMessage("createObserver:return");
});
addMessageListener("removeObserver" , function(e) {
addMessageListener("removeObserver", function(e) {
Services.obs.removeObserver(observer, "cookie-changed");
sendAsyncMessage("removeObserver:return");
});

View file

@ -1,10 +1,10 @@
let cs = Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager);
let cs = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
addMessageListener("getCookieCountAndClear", () => {
let count = 0;
for (let cookie of cs.enumerator)
for (let cookie of cs.enumerator) {
++count;
}
cs.removeAll();
sendAsyncMessage("getCookieCountAndClear:return", { count });

View file

@ -1,6 +1,5 @@
function getCookieService() {
return Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager);
return Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
}
function getCookies(cs) {

View file

@ -13,9 +13,10 @@ function setupTest(uri, cookies, loads) {
SimpleTest.waitForExplicitFinish();
var prefSet = new Promise(resolve => {
SpecialPowers.pushPrefEnv({ set: [
["network.cookie.cookieBehavior", 1],
]}, resolve);
SpecialPowers.pushPrefEnv(
{ set: [["network.cookie.cookieBehavior", 1]] },
resolve
);
});
gScript = SpecialPowers.loadChromeScript(SCRIPT_URL);
@ -28,7 +29,7 @@ function setupTest(uri, cookies, loads) {
prefSet.then(() => {
// load a window which contains an iframe; each will attempt to set
// cookies from their respective domains.
gPopup = window.open(uri, 'hai', 'width=100,height=100');
gPopup = window.open(uri, "hai", "width=100,height=100");
});
}

View file

@ -1,4 +1,6 @@
const SCRIPT_URL = SimpleTest.getTestFileURL('file_testloadflags_chromescript.js');
const SCRIPT_URL = SimpleTest.getTestFileURL(
"file_testloadflags_chromescript.js"
);
var gExpectedCookies;
var gExpectedHeaders;
@ -12,13 +14,26 @@ var gLoads = 0;
// setupTest() is run from 'onload='.
function setupTest(uri, domain, cookies, loads, headers) {
info("setupTest uri: " + uri + " domain: " + domain + " cookies: " + cookies +
" loads: " + loads + " headers: " + headers);
info(
"setupTest uri: " +
uri +
" domain: " +
domain +
" cookies: " +
cookies +
" loads: " +
loads +
" headers: " +
headers
);
SimpleTest.waitForExplicitFinish();
var prefSet = new Promise(resolve => {
SpecialPowers.pushPrefEnv({ set: [["network.cookie.cookieBehavior", 1]] }, resolve);
SpecialPowers.pushPrefEnv(
{ set: [["network.cookie.cookieBehavior", 1]] },
resolve
);
});
gExpectedCookies = cookies;
@ -29,8 +44,11 @@ function setupTest(uri, domain, cookies, loads, headers) {
gScript.addMessageListener("info", ({ str }) => info(str));
gScript.addMessageListener("ok", ({ c, m }) => ok(c, m));
gScript.addMessageListener("observer:gotCookie", ({ cookie, uri }) => {
isnot(cookie.indexOf("oh=hai"), -1,
"cookie 'oh=hai' is in header for " + uri);
isnot(
cookie.indexOf("oh=hai"),
-1,
"cookie 'oh=hai' is in header for " + uri
);
++gHeaders;
});
@ -42,15 +60,14 @@ function setupTest(uri, domain, cookies, loads, headers) {
// Listen for MessageEvents.
window.addEventListener("message", messageReceiver);
Promise.all([ prefSet, scriptReady ]).then(() => {
Promise.all([prefSet, scriptReady]).then(() => {
// load a window which contains an iframe; each will attempt to set
// cookies from their respective domains.
gPopup = window.open(uri, 'hai', 'width=100,height=100');
gPopup = window.open(uri, "hai", "width=100,height=100");
});
}
function finishTest()
{
function finishTest() {
gScript.addMessageListener("shutdown:return", () => {
gScript.destroy();
SimpleTest.finish();
@ -60,10 +77,11 @@ function finishTest()
/** Receives MessageEvents to this window. */
// Count and check loads.
function messageReceiver(evt)
{
ok(evt.data == "f_lf_i msg data img" || evt.data == "f_lf_i msg data page",
"message data received from popup");
function messageReceiver(evt) {
ok(
evt.data == "f_lf_i msg data img" || evt.data == "f_lf_i msg data page",
"message data received from popup"
);
if (evt.data == "f_lf_i msg data img") {
info("message data received from popup for image");
}

View file

@ -16,8 +16,9 @@ function is(a, b, m) {
function obs() {
info("adding observer");
this.os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
this.os = Cc["@mozilla.org/observer-service;1"].getService(
Ci.nsIObserverService
);
this.os.addObserver(this, "http-on-modify-request");
}
@ -35,21 +36,26 @@ obs.prototype = {
channel.visitRequestHeaders({
visitHeader(aHeader, aValue) {
info(aHeader + ": " + aValue);
}});
},
});
} catch (err) {
ok(false, "catch error " + err);
}
// Ignore notifications we don't care about (like favicons)
if (!channel.URI.spec.includes(
"http://example.org/tests/netwerk/test/mochitests/")) {
if (
!channel.URI.spec.includes(
"http://example.org/tests/netwerk/test/mochitests/"
)
) {
info("ignoring this one");
return;
}
sendAsyncMessage("observer:gotCookie",
{ cookie: channel.getRequestHeader("Cookie"),
uri: channel.URI.spec });
sendAsyncMessage("observer:gotCookie", {
cookie: channel.getRequestHeader("Cookie"),
uri: channel.URI.spec,
});
},
remove() {
@ -57,15 +63,27 @@ obs.prototype = {
this.os.removeObserver(this, "http-on-modify-request");
this.os = null;
}
}
},
};
function getCookieCount(cs) {
let count = 0;
for (let cookie of cs.enumerator) {
info("cookie: " + cookie);
info("cookie host " + cookie.host + " path " + cookie.path + " name " + cookie.name +
" value " + cookie.value + " isSecure " + cookie.isSecure + " expires " + cookie.expires);
info(
"cookie host " +
cookie.host +
" path " +
cookie.path +
" name " +
cookie.name +
" value " +
cookie.value +
" isSecure " +
cookie.isSecure +
" expires " +
cookie.expires
);
++count;
}
@ -73,8 +91,7 @@ function getCookieCount(cs) {
}
addMessageListener("init", ({ domain }) => {
let cs = Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager);
let cs = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
info("we are going to remove these cookies");
@ -82,17 +99,30 @@ addMessageListener("init", ({ domain }) => {
info(count + " cookies");
cs.removeAll();
cs.add(domain, "", "oh", "hai", false, false, true, Math.pow(2, 62), {},
Ci.nsICookie.SAMESITE_NONE);
is(cs.countCookiesFromHost(domain), 1, "number of cookies for domain " + domain);
cs.add(
domain,
"",
"oh",
"hai",
false,
false,
true,
Math.pow(2, 62),
{},
Ci.nsICookie.SAMESITE_NONE
);
is(
cs.countCookiesFromHost(domain),
1,
"number of cookies for domain " + domain
);
gObs = new obs();
sendAsyncMessage("init:return");
});
addMessageListener("getCookieCount", () => {
let cs = Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager);
let cs = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
let count = getCookieCount(cs);
cs.removeAll();
@ -102,8 +132,7 @@ addMessageListener("getCookieCount", () => {
addMessageListener("shutdown", () => {
gObs.remove();
let cs = Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager);
let cs = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
cs.removeAll();
sendAsyncMessage("shutdown:return");
});

View file

@ -3,11 +3,13 @@
// 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 { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
var Prompter = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIPrompt]),
alert() {} // Do nothing when asked to show an alert
alert() {}, // Do nothing when asked to show an alert
};
function WindowWatcherService() {}
@ -17,9 +19,7 @@ WindowWatcherService.prototype = {
getNewPrompter() {
return Prompter;
}
},
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
WindowWatcherService
]);
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WindowWatcherService]);

View file

@ -1,20 +1,23 @@
var {XPCOMUtils} = ChromeUtils.import('resource://gre/modules/XPCOMUtils.jsm');
var {Services} = ChromeUtils.import('resource://gre/modules/Services.jsm');
var { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
var _CSvc;
function get_cache_service() {
if (_CSvc)
if (_CSvc) {
return _CSvc;
}
return _CSvc = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
return (_CSvc = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(
Ci.nsICacheStorageService
));
}
function evict_cache_entries(where)
{
var clearDisk = (!where || where == "disk" || where == "all");
var clearMem = (!where || where == "memory" || where == "all");
var clearAppCache = (where == "appcache");
function evict_cache_entries(where) {
var clearDisk = !where || where == "disk" || where == "all";
var clearMem = !where || where == "memory" || where == "all";
var clearAppCache = where == "appcache";
var svc = get_cache_service();
var storage;
@ -35,72 +38,79 @@ function evict_cache_entries(where)
}
}
function createURI(urispec)
{
var ioServ = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
function createURI(urispec) {
var ioServ = Cc["@mozilla.org/network/io-service;1"].getService(
Ci.nsIIOService
);
return ioServ.newURI(urispec);
}
function getCacheStorage(where, lci, appcache)
{
if (!lci) lci = Services.loadContextInfo.default;
function getCacheStorage(where, lci, appcache) {
if (!lci) {
lci = Services.loadContextInfo.default;
}
var svc = get_cache_service();
switch (where) {
case "disk": return svc.diskCacheStorage(lci, false);
case "memory": return svc.memoryCacheStorage(lci);
case "appcache": return svc.appCacheStorage(lci, appcache);
case "pin": return svc.pinningCacheStorage(lci);
case "disk":
return svc.diskCacheStorage(lci, false);
case "memory":
return svc.memoryCacheStorage(lci);
case "appcache":
return svc.appCacheStorage(lci, appcache);
case "pin":
return svc.pinningCacheStorage(lci);
}
return null;
}
function asyncOpenCacheEntry(key, where, flags, lci, callback, appcache)
{
function asyncOpenCacheEntry(key, where, flags, lci, callback, appcache) {
key = createURI(key);
function CacheListener() { }
function CacheListener() {}
CacheListener.prototype = {
_appCache: appcache,
QueryInterface: ChromeUtils.generateQI(["nsICacheEntryOpenCallback"]),
onCacheEntryCheck(entry, appCache) {
if (typeof callback === "object")
if (typeof callback === "object") {
return callback.onCacheEntryCheck(entry, appCache);
}
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
},
onCacheEntryAvailable (entry, isnew, appCache, status) {
onCacheEntryAvailable(entry, isnew, appCache, status) {
if (typeof callback === "object") {
// Root us at the callback
callback.__cache_listener_root = this;
callback.onCacheEntryAvailable(entry, isnew, appCache, status);
}
else
} else {
callback(status, entry, appCache);
}
},
run () {
run() {
var storage = getCacheStorage(where, lci, this._appCache);
storage.asyncOpenURI(key, "", flags, this);
}
},
};
(new CacheListener()).run();
new CacheListener().run();
}
function syncWithCacheIOThread(callback, force)
{
function syncWithCacheIOThread(callback, force) {
if (force) {
asyncOpenCacheEntry(
"http://nonexistententry/", "disk", Ci.nsICacheStorage.OPEN_READONLY, null,
"http://nonexistententry/",
"disk",
Ci.nsICacheStorage.OPEN_READONLY,
null,
function(status, entry) {
Assert.equal(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
callback();
});
}
else {
}
);
} else {
callback();
}
}
@ -113,7 +123,7 @@ function get_device_entry_count(where, lci, continuation) {
}
var visitor = {
onCacheStorageInfo (entryCount, consumption) {
onCacheStorageInfo(entryCount, consumption) {
executeSoon(function() {
continuation(entryCount, consumption);
});
@ -124,19 +134,32 @@ function get_device_entry_count(where, lci, continuation) {
storage.asyncVisitStorage(visitor, false);
}
function asyncCheckCacheEntryPresence(key, where, shouldExist, continuation, appCache)
{
asyncOpenCacheEntry(key, where, Ci.nsICacheStorage.OPEN_READONLY, null,
function asyncCheckCacheEntryPresence(
key,
where,
shouldExist,
continuation,
appCache
) {
asyncOpenCacheEntry(
key,
where,
Ci.nsICacheStorage.OPEN_READONLY,
null,
function(status, entry) {
if (shouldExist) {
dump("TEST-INFO | checking cache key " + key + " exists @ " + where);
Assert.equal(status, Cr.NS_OK);
Assert.ok(!!entry);
} else {
dump("TEST-INFO | checking cache key " + key + " doesn't exist @ " + where);
dump(
"TEST-INFO | checking cache key " + key + " doesn't exist @ " + where
);
Assert.equal(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
Assert.equal(null, entry);
}
continuation();
}, appCache);
},
appCache
);
}

View file

@ -1,91 +1,100 @@
var callbacks = new Array();
// Expect an existing entry
const NORMAL = 0;
const NORMAL = 0;
// Expect a new entry
const NEW = 1 << 0;
const NEW = 1 << 0;
// Return early from onCacheEntryCheck and set the callback to state it expects onCacheEntryCheck to happen
const NOTVALID = 1 << 1;
const NOTVALID = 1 << 1;
// Throw from onCacheEntryAvailable
const THROWAVAIL = 1 << 2;
const THROWAVAIL = 1 << 2;
// Open entry for reading-only
const READONLY = 1 << 3;
const READONLY = 1 << 3;
// Expect the entry to not be found
const NOTFOUND = 1 << 4;
const NOTFOUND = 1 << 4;
// Return ENTRY_NEEDS_REVALIDATION from onCacheEntryCheck
const REVAL = 1 << 5;
const REVAL = 1 << 5;
// Return ENTRY_PARTIAL from onCacheEntryCheck, in combo with NEW or RECREATE bypasses check for emptiness of the entry
const PARTIAL = 1 << 6
const PARTIAL = 1 << 6;
// Expect the entry is doomed, i.e. the output stream should not be possible to open
const DOOMED = 1 << 7;
const DOOMED = 1 << 7;
// Don't trigger the go-on callback until the entry is written
const WAITFORWRITE = 1 << 8;
const WAITFORWRITE = 1 << 8;
// Don't write data (i.e. don't open output stream)
const METAONLY = 1 << 9;
const METAONLY = 1 << 9;
// Do recreation of an existing cache entry
const RECREATE = 1 << 10;
const RECREATE = 1 << 10;
// Do not give me the entry
const NOTWANTED = 1 << 11;
const NOTWANTED = 1 << 11;
// Tell the cache to wait for the entry to be completely written first
const COMPLETE = 1 << 12;
const COMPLETE = 1 << 12;
// Don't write meta/data and don't set valid in the callback, consumer will do it manually
const DONTFILL = 1 << 13;
const DONTFILL = 1 << 13;
// Used in combination with METAONLY, don't call setValid() on the entry after metadata has been set
const DONTSETVALID = 1 << 14;
const DONTSETVALID = 1 << 14;
// Notify before checking the data, useful for proper callback ordering checks
const NOTIFYBEFOREREAD = 1 << 15;
// It's allowed to not get an existing entry (result of opening is undetermined)
const MAYBE_NEW = 1 << 16;
const MAYBE_NEW = 1 << 16;
var log_c2 = true;
function LOG_C2(o, m)
{
if (!log_c2) return;
if (!m)
function LOG_C2(o, m) {
if (!log_c2) {
return;
}
if (!m) {
dump("TEST-INFO | CACHE2: " + o + "\n");
else
dump("TEST-INFO | CACHE2: callback #" + o.order + "(" + (o.workingData ? o.workingData.substr(0, 10) : "---") + ") " + m + "\n");
} else {
dump(
"TEST-INFO | CACHE2: callback #" +
o.order +
"(" +
(o.workingData ? o.workingData.substr(0, 10) : "---") +
") " +
m +
"\n"
);
}
}
function pumpReadStream(inputStream, goon)
{
function pumpReadStream(inputStream, goon) {
if (inputStream.isNonBlocking()) {
// non-blocking stream, must read via pump
var pump = Cc["@mozilla.org/network/input-stream-pump;1"]
.createInstance(Ci.nsIInputStreamPump);
var pump = Cc["@mozilla.org/network/input-stream-pump;1"].createInstance(
Ci.nsIInputStreamPump
);
pump.init(inputStream, 0, 0, true);
var data = "";
pump.asyncRead({
onStartRequest (aRequest) { },
onDataAvailable (aRequest, aInputStream, aOffset, aCount)
pump.asyncRead(
{
var wrapper = Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
wrapper.init(aInputStream);
var str = wrapper.read(wrapper.available());
LOG_C2("reading data '" + str.substring(0,5) + "'");
data += str;
onStartRequest(aRequest) {},
onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
var wrapper = Cc[
"@mozilla.org/scriptableinputstream;1"
].createInstance(Ci.nsIScriptableInputStream);
wrapper.init(aInputStream);
var str = wrapper.read(wrapper.available());
LOG_C2("reading data '" + str.substring(0, 5) + "'");
data += str;
},
onStopRequest(aRequest, aStatusCode) {
LOG_C2("done reading data: " + aStatusCode);
Assert.equal(aStatusCode, Cr.NS_OK);
goon(data);
},
},
onStopRequest (aRequest, aStatusCode)
{
LOG_C2("done reading data: " + aStatusCode);
Assert.equal(aStatusCode, Cr.NS_OK);
goon(data);
},
}, null);
}
else {
null
);
} else {
// blocking stream
var data = read_stream(inputStream, inputStream.available());
goon(data);
}
}
OpenCallback.prototype =
{
OpenCallback.prototype = {
QueryInterface: ChromeUtils.generateQI(["nsICacheEntryOpenCallback"]),
onCacheEntryCheck(entry, appCache)
{
onCacheEntryCheck(entry, appCache) {
LOG_C2(this, "onCacheEntryCheck");
Assert.ok(!this.onCheckPassed);
this.onCheckPassed = true;
@ -103,15 +112,18 @@ OpenCallback.prototype =
Assert.equal(entry.getMetaDataElement("meto"), this.workingMetadata);
// check for sane flag combination
Assert.notEqual(this.behavior & (REVAL|PARTIAL), REVAL|PARTIAL);
Assert.notEqual(this.behavior & (REVAL | PARTIAL), REVAL | PARTIAL);
if (this.behavior & (REVAL|PARTIAL)) {
if (this.behavior & (REVAL | PARTIAL)) {
LOG_C2(this, "onCacheEntryCheck DONE, return ENTRY_NEEDS_REVALIDATION");
return Ci.nsICacheEntryOpenCallback.ENTRY_NEEDS_REVALIDATION;
}
if (this.behavior & COMPLETE) {
LOG_C2(this, "onCacheEntryCheck DONE, return RECHECK_AFTER_WRITE_FINISHED");
LOG_C2(
this,
"onCacheEntryCheck DONE, return RECHECK_AFTER_WRITE_FINISHED"
);
// Specific to the new backend because of concurrent read/write:
// when a consumer returns RECHECK_AFTER_WRITE_FINISHED from onCacheEntryCheck
// the cache calls this callback again after the entry write has finished.
@ -127,9 +139,8 @@ OpenCallback.prototype =
LOG_C2(this, "onCacheEntryCheck DONE, return ENTRY_WANTED");
return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
},
onCacheEntryAvailable(entry, isnew, appCache, status)
{
if ((this.behavior & MAYBE_NEW) && isnew) {
onCacheEntryAvailable(entry, isnew, appCache, status) {
if (this.behavior & MAYBE_NEW && isnew) {
this.behavior |= NEW;
}
@ -139,14 +150,14 @@ OpenCallback.prototype =
Assert.equal(isnew, !!(this.behavior & NEW));
if (this.behavior & (NOTFOUND|NOTWANTED)) {
if (this.behavior & (NOTFOUND | NOTWANTED)) {
Assert.equal(status, Cr.NS_ERROR_CACHE_KEY_NOT_FOUND);
Assert.ok(!entry);
if (this.behavior & THROWAVAIL)
if (this.behavior & THROWAVAIL) {
this.throwAndNotify(entry);
}
this.goon(entry);
}
else if (this.behavior & (NEW|RECREATE)) {
} else if (this.behavior & (NEW | RECREATE)) {
Assert.ok(!!entry);
if (this.behavior & RECREATE) {
@ -154,18 +165,19 @@ OpenCallback.prototype =
Assert.ok(!!entry);
}
if (this.behavior & THROWAVAIL)
if (this.behavior & THROWAVAIL) {
this.throwAndNotify(entry);
}
if (!(this.behavior & WAITFORWRITE))
if (!(this.behavior & WAITFORWRITE)) {
this.goon(entry);
}
if (!(this.behavior & PARTIAL)) {
try {
entry.getMetaDataElement("meto");
Assert.ok(false);
}
catch (ex) {}
} catch (ex) {}
}
if (this.behavior & DONTFILL) {
@ -174,21 +186,25 @@ OpenCallback.prototype =
}
var self = this;
executeSoon(function() { // emulate network latency
executeSoon(function() {
// emulate network latency
entry.setMetaDataElement("meto", self.workingMetadata);
entry.metaDataReady();
if (self.behavior & METAONLY) {
// Since forcing GC/CC doesn't trigger OnWriterClosed, we have to set the entry valid manually :(
if (!(self.behavior & DONTSETVALID))
if (!(self.behavior & DONTSETVALID)) {
entry.setValid();
}
entry.close();
if (self.behavior & WAITFORWRITE)
if (self.behavior & WAITFORWRITE) {
self.goon(entry);
}
return;
}
executeSoon(function() { // emulate more network latency
executeSoon(function() {
// emulate more network latency
if (self.behavior & DOOMED) {
LOG_C2(self, "checking doom state");
try {
@ -200,37 +216,40 @@ OpenCallback.prototype =
} catch (ex) {
Assert.ok(true);
}
if (self.behavior & WAITFORWRITE)
if (self.behavior & WAITFORWRITE) {
self.goon(entry);
}
return;
}
var offset = (self.behavior & PARTIAL)
? entry.dataSize
: 0;
var offset = self.behavior & PARTIAL ? entry.dataSize : 0;
LOG_C2(self, "openOutputStream @ " + offset);
var os = entry.openOutputStream(offset, -1);
LOG_C2(self, "writing data");
var wrt = os.write(self.workingData, self.workingData.length);
Assert.equal(wrt, self.workingData.length);
os.close();
if (self.behavior & WAITFORWRITE)
if (self.behavior & WAITFORWRITE) {
self.goon(entry);
}
entry.close();
})
})
}
else { // NORMAL
});
});
} else {
// NORMAL
Assert.ok(!!entry);
Assert.equal(entry.getMetaDataElement("meto"), this.workingMetadata);
if (this.behavior & THROWAVAIL)
if (this.behavior & THROWAVAIL) {
this.throwAndNotify(entry);
if (this.behavior & NOTIFYBEFOREREAD)
}
if (this.behavior & NOTIFYBEFOREREAD) {
this.goon(entry, true);
}
var wrapper = Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
var wrapper = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
Ci.nsIScriptableInputStream
);
var self = this;
pumpReadStream(entry.openInputStream(0), function(data) {
Assert.equal(data, self.workingData);
@ -241,16 +260,14 @@ OpenCallback.prototype =
});
}
},
selfCheck()
{
selfCheck() {
LOG_C2(this, "selfCheck");
Assert.ok(this.onCheckPassed || (this.behavior & MAYBE_NEW));
Assert.ok(this.onCheckPassed || this.behavior & MAYBE_NEW);
Assert.ok(this.onAvailPassed);
Assert.ok(this.onDataCheckPassed || (this.behavior & MAYBE_NEW));
Assert.ok(this.onDataCheckPassed || this.behavior & MAYBE_NEW);
},
throwAndNotify(entry)
{
throwAndNotify(entry) {
LOG_C2(this, "Throwing");
var self = this;
executeSoon(function() {
@ -258,47 +275,59 @@ OpenCallback.prototype =
self.goon(entry);
});
throw Cr.NS_ERROR_FAILURE;
}
},
};
function OpenCallback(behavior, workingMetadata, workingData, goon)
{
function OpenCallback(behavior, workingMetadata, workingData, goon) {
this.behavior = behavior;
this.workingMetadata = workingMetadata;
this.workingData = workingData;
this.goon = goon;
this.onCheckPassed = (!!(behavior & (NEW|RECREATE)) || !workingMetadata) && !(behavior & NOTVALID);
this.onCheckPassed =
(!!(behavior & (NEW | RECREATE)) || !workingMetadata) &&
!(behavior & NOTVALID);
this.onAvailPassed = false;
this.onDataCheckPassed = !!(behavior & (NEW|RECREATE|NOTWANTED)) || !workingMetadata;
this.onDataCheckPassed =
!!(behavior & (NEW | RECREATE | NOTWANTED)) || !workingMetadata;
callbacks.push(this);
this.order = callbacks.length;
}
VisitCallback.prototype =
{
VisitCallback.prototype = {
QueryInterface: ChromeUtils.generateQI(["nsICacheStorageVisitor"]),
onCacheStorageInfo(num, consumption)
{
onCacheStorageInfo(num, consumption) {
LOG_C2(this, "onCacheStorageInfo: num=" + num + ", size=" + consumption);
Assert.equal(this.num, num);
Assert.equal(this.consumption, consumption);
if (!this.entries)
if (!this.entries) {
this.notify();
}
},
onCacheEntryInfo(aURI, aIdEnhance, aDataSize, aFetchCount, aLastModifiedTime, aExpirationTime,
aPinned, aInfo)
{
var key = (aIdEnhance ? (aIdEnhance + ":") : "") + aURI.asciiSpec;
onCacheEntryInfo(
aURI,
aIdEnhance,
aDataSize,
aFetchCount,
aLastModifiedTime,
aExpirationTime,
aPinned,
aInfo
) {
var key = (aIdEnhance ? aIdEnhance + ":" : "") + aURI.asciiSpec;
LOG_C2(this, "onCacheEntryInfo: key=" + key);
function findCacheIndex(element) {
if (typeof(element) === "string") {
if (typeof element === "string") {
return element === key;
} else if (typeof(element) === "object") {
return element.uri === key &&
element.lci.isAnonymous === aInfo.isAnonymous &&
ChromeUtils.isOriginAttributesEqual(element.lci.originAttributes,
aInfo.originAttributes);
} else if (typeof element === "object") {
return (
element.uri === key &&
element.lci.isAnonymous === aInfo.isAnonymous &&
ChromeUtils.isOriginAttributesEqual(
element.lci.originAttributes,
aInfo.originAttributes
)
);
}
return false;
@ -311,28 +340,25 @@ VisitCallback.prototype =
this.entries.splice(index, 1);
},
onCacheEntryVisitCompleted()
{
onCacheEntryVisitCompleted() {
LOG_C2(this, "onCacheEntryVisitCompleted");
if (this.entries)
if (this.entries) {
Assert.equal(this.entries.length, 0);
}
this.notify();
},
notify()
{
notify() {
Assert.ok(!!this.goon);
var goon = this.goon;
this.goon = null;
executeSoon(goon);
},
selfCheck()
{
selfCheck() {
Assert.ok(!this.entries || !this.entries.length);
}
},
};
function VisitCallback(num, consumption, entries, goon)
{
function VisitCallback(num, consumption, entries, goon) {
this.num = num;
this.consumption = consumption;
this.entries = entries;
@ -341,64 +367,61 @@ function VisitCallback(num, consumption, entries, goon)
this.order = callbacks.length;
}
EvictionCallback.prototype =
{
EvictionCallback.prototype = {
QueryInterface: ChromeUtils.generateQI(["nsICacheEntryDoomCallback"]),
onCacheEntryDoomed(result)
{
onCacheEntryDoomed(result) {
Assert.equal(this.expectedSuccess, result == Cr.NS_OK);
this.goon();
},
selfCheck() {}
}
selfCheck() {},
};
function EvictionCallback(success, goon)
{
function EvictionCallback(success, goon) {
this.expectedSuccess = success;
this.goon = goon;
callbacks.push(this);
this.order = callbacks.length;
}
MultipleCallbacks.prototype =
{
fired()
{
if (--this.pending == 0)
{
MultipleCallbacks.prototype = {
fired() {
if (--this.pending == 0) {
var self = this;
if (this.delayed)
executeSoon(function() { self.goon(); });
else
if (this.delayed) {
executeSoon(function() {
self.goon();
});
} else {
this.goon();
}
}
},
add()
{
add() {
++this.pending;
}
}
},
};
function MultipleCallbacks(number, goon, delayed)
{
function MultipleCallbacks(number, goon, delayed) {
this.pending = number;
this.goon = goon;
this.delayed = delayed;
}
function wait_for_cache_index(continue_func)
{
function wait_for_cache_index(continue_func) {
// This callback will not fire before the index is in the ready state. nsICacheStorage.exists() will
// no longer throw after this point.
get_cache_service().asyncGetDiskConsumption({
onNetworkCacheDiskConsumption() { continue_func(); },
onNetworkCacheDiskConsumption() {
continue_func();
},
// eslint-disable-next-line mozilla/use-chromeutils-generateqi
QueryInterface() { return this; }
QueryInterface() {
return this;
},
});
}
function finish_cache2_test()
{
function finish_cache2_test() {
callbacks.forEach(function(callback, index) {
callback.selfCheck();
});

View file

@ -3,9 +3,9 @@
*/
function read_stream(stream, count) {
/* assume stream has non-ASCII data */
var wrapper =
Cc["@mozilla.org/binaryinputstream;1"]
.createInstance(Ci.nsIBinaryInputStream);
var wrapper = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
Ci.nsIBinaryInputStream
);
wrapper.setInputStream(stream);
/* JS methods can be called with a maximum of 65535 arguments, and input
streams don't have to return all the data they make .available() when
@ -15,10 +15,11 @@ function read_stream(stream, count) {
var bytes = wrapper.readByteArray(Math.min(65535, count));
data.push(String.fromCharCode.apply(null, bytes));
count -= bytes.length;
if (bytes.length == 0)
if (bytes.length == 0) {
do_throw("Nothing read from input stream!");
}
}
return data.join('');
return data.join("");
}
const CL_EXPECT_FAILURE = 0x1;
@ -64,50 +65,64 @@ ChannelListener.prototype = {
_contentLen: -1,
_lastEvent: 0,
QueryInterface: ChromeUtils.generateQI(["nsIStreamListener", "nsIRequestObserver"]),
QueryInterface: ChromeUtils.generateQI([
"nsIStreamListener",
"nsIRequestObserver",
]),
onStartRequest(request) {
try {
if (this._got_onstartrequest)
if (this._got_onstartrequest) {
do_throw("Got second onStartRequest event!");
}
this._got_onstartrequest = true;
this._lastEvent = Date.now();
try {
this._isFromCache = request.QueryInterface(Ci.nsICacheInfoChannel).isFromCache();
this._isFromCache = request
.QueryInterface(Ci.nsICacheInfoChannel)
.isFromCache();
} catch (e) {}
var thrown = false;
try {
this._cacheEntryId = request.QueryInterface(Ci.nsICacheInfoChannel).getCacheEntryId();
this._cacheEntryId = request
.QueryInterface(Ci.nsICacheInfoChannel)
.getCacheEntryId();
} catch (e) {
thrown = true;
}
if (this._isFromCache && thrown)
if (this._isFromCache && thrown) {
do_throw("Should get a CacheEntryId");
else if (!this._isFromCache && !thrown)
} else if (!this._isFromCache && !thrown) {
do_throw("Shouldn't get a CacheEntryId");
}
request.QueryInterface(Ci.nsIChannel);
try {
this._contentLen = request.contentLength;
}
catch (ex) {
if (!(this._flags & (CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL)))
} catch (ex) {
if (!(this._flags & (CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL))) {
do_throw("Could not get contentLength");
}
}
if (!request.isPending())
if (!request.isPending()) {
do_throw("request reports itself as not pending from onStartRequest!");
if (this._contentLen == -1 && !(this._flags & (CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL)))
}
if (
this._contentLen == -1 &&
!(this._flags & (CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL))
) {
do_throw("Content length is unknown in onStartRequest!");
}
if ((this._flags & CL_FROM_CACHE)) {
if (this._flags & CL_FROM_CACHE) {
request.QueryInterface(Ci.nsICachingChannel);
if (!request.isFromCache()) {
do_throw("Response is not from the cache (CL_FROM_CACHE)");
}
}
if ((this._flags & CL_NOT_FROM_CACHE)) {
if (this._flags & CL_NOT_FROM_CACHE) {
request.QueryInterface(Ci.nsICachingChannel);
if (request.isFromCache()) {
do_throw("Response is from the cache (CL_NOT_FROM_CACHE)");
@ -116,7 +131,9 @@ ChannelListener.prototype = {
if (this._flags & CL_SUSPEND) {
request.suspend();
do_timeout(SUSPEND_DELAY, function() { request.resume(); });
do_timeout(SUSPEND_DELAY, function() {
request.resume();
});
}
} catch (ex) {
do_throw("Error in onStartRequest: " + ex);
@ -127,24 +144,35 @@ ChannelListener.prototype = {
try {
let current = Date.now();
if (!this._got_onstartrequest)
if (!this._got_onstartrequest) {
do_throw("onDataAvailable without onStartRequest event!");
if (this._got_onstoprequest)
}
if (this._got_onstoprequest) {
do_throw("onDataAvailable after onStopRequest event!");
if (!request.isPending())
}
if (!request.isPending()) {
do_throw("request reports itself as not pending from onDataAvailable!");
if (this._flags & CL_EXPECT_FAILURE)
}
if (this._flags & CL_EXPECT_FAILURE) {
do_throw("Got data despite expecting a failure");
}
if (current - this._lastEvent >= SUSPEND_DELAY &&
!(this._flags & CL_EXPECT_3S_DELAY))
do_throw("Data received after significant unexpected delay");
else if (current - this._lastEvent < SUSPEND_DELAY &&
this._flags & CL_EXPECT_3S_DELAY)
if (
current - this._lastEvent >= SUSPEND_DELAY &&
!(this._flags & CL_EXPECT_3S_DELAY)
) {
do_throw("Data received after significant unexpected delay");
} else if (
current - this._lastEvent < SUSPEND_DELAY &&
this._flags & CL_EXPECT_3S_DELAY
) {
do_throw("Data received sooner than expected");
else if (current - this._lastEvent >= SUSPEND_DELAY &&
this._flags & CL_EXPECT_3S_DELAY)
this._flags &= ~CL_EXPECT_3S_DELAY; // No more delays expected
} else if (
current - this._lastEvent >= SUSPEND_DELAY &&
this._flags & CL_EXPECT_3S_DELAY
) {
this._flags &= ~CL_EXPECT_3S_DELAY;
} // No more delays expected
this._buffer = this._buffer.concat(read_stream(stream, count));
this._lastEvent = current;
@ -156,43 +184,65 @@ ChannelListener.prototype = {
onStopRequest(request, status) {
try {
var success = Components.isSuccessCode(status);
if (!this._got_onstartrequest)
if (!this._got_onstartrequest) {
do_throw("onStopRequest without onStartRequest event!");
if (this._got_onstoprequest)
}
if (this._got_onstoprequest) {
do_throw("Got second onStopRequest event!");
}
this._got_onstoprequest = true;
if ((this._flags & (CL_EXPECT_FAILURE | CL_EXPECT_LATE_FAILURE)) && success)
do_throw("Should have failed to load URL (status is " + status.toString(16) + ")");
else if (!(this._flags & (CL_EXPECT_FAILURE | CL_EXPECT_LATE_FAILURE)) && !success)
if (
this._flags & (CL_EXPECT_FAILURE | CL_EXPECT_LATE_FAILURE) &&
success
) {
do_throw(
"Should have failed to load URL (status is " +
status.toString(16) +
")"
);
} else if (
!(this._flags & (CL_EXPECT_FAILURE | CL_EXPECT_LATE_FAILURE)) &&
!success
) {
do_throw("Failed to load URL: " + status.toString(16));
if (status != request.status)
}
if (status != request.status) {
do_throw("request.status does not match status arg to onStopRequest!");
if (request.isPending())
}
if (request.isPending()) {
do_throw("request reports itself as pending from onStopRequest!");
if (!(this._flags & (CL_EXPECT_FAILURE | CL_EXPECT_LATE_FAILURE | CL_IGNORE_CL)) &&
!(this._flags & CL_EXPECT_GZIP) &&
this._contentLen != -1)
Assert.equal(this._buffer.length, this._contentLen)
}
if (
!(
this._flags &
(CL_EXPECT_FAILURE | CL_EXPECT_LATE_FAILURE | CL_IGNORE_CL)
) &&
!(this._flags & CL_EXPECT_GZIP) &&
this._contentLen != -1
) {
Assert.equal(this._buffer.length, this._contentLen);
}
} catch (ex) {
do_throw("Error in onStopRequest: " + ex);
}
try {
this._closure(request,
this._buffer,
this._closurectx,
this._isFromCache,
this._cacheEntryId);
this._closure(
request,
this._buffer,
this._closurectx,
this._isFromCache,
this._cacheEntryId
);
this._closurectx = null;
} catch (ex) {
do_throw("Error in closure function: " + ex);
}
}
},
};
var ES_ABORT_REDIRECT = 0x01;
function ChannelEventSink(flags)
{
function ChannelEventSink(flags) {
this._flags = flags;
}
@ -200,17 +250,19 @@ ChannelEventSink.prototype = {
QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor"]),
getInterface(iid) {
if (iid.equals(Ci.nsIChannelEventSink))
if (iid.equals(Ci.nsIChannelEventSink)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
},
asyncOnChannelRedirect(oldChannel, newChannel, flags, callback) {
if (this._flags & ES_ABORT_REDIRECT)
if (this._flags & ES_ABORT_REDIRECT) {
throw Cr.NS_BINDING_ABORTED;
}
callback.onRedirectVerifyCallback(Cr.NS_OK);
}
},
};
/**
@ -222,12 +274,13 @@ function OriginAttributes(inIsolatedMozBrowser, privateId) {
}
OriginAttributes.prototype = {
inIsolatedMozBrowser: false,
privateBrowsingId: 0
privateBrowsingId: 0,
};
function readFile(file) {
let fstream = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
Ci.nsIFileInputStream
);
fstream.init(file, -1, 0, 0);
let data = NetUtil.readInputStreamToString(fstream, fstream.available());
fstream.close();
@ -237,9 +290,8 @@ function readFile(file) {
function addCertFromFile(certdb, filename, trustString) {
let certFile = do_get_file(filename, false);
let pem = readFile(certFile)
.replace(/-----BEGIN CERTIFICATE-----/, "")
.replace(/-----END CERTIFICATE-----/, "")
.replace(/[\r\n]/g, "");
.replace(/-----BEGIN CERTIFICATE-----/, "")
.replace(/-----END CERTIFICATE-----/, "")
.replace(/[\r\n]/g, "");
certdb.addCertFromBase64(pem, trustString);
}

View file

@ -2,37 +2,46 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyServiceGetter(Services, "cookies",
"@mozilla.org/cookieService;1",
"nsICookieService");
XPCOMUtils.defineLazyServiceGetter(Services, "cookiemgr",
"@mozilla.org/cookiemanager;1",
"nsICookieManager");
XPCOMUtils.defineLazyServiceGetter(
Services,
"cookies",
"@mozilla.org/cookieService;1",
"nsICookieService"
);
XPCOMUtils.defineLazyServiceGetter(
Services,
"cookiemgr",
"@mozilla.org/cookiemanager;1",
"nsICookieManager"
);
XPCOMUtils.defineLazyServiceGetter(Services, "etld",
"@mozilla.org/network/effective-tld-service;1",
"nsIEffectiveTLDService");
XPCOMUtils.defineLazyServiceGetter(
Services,
"etld",
"@mozilla.org/network/effective-tld-service;1",
"nsIEffectiveTLDService"
);
function do_check_throws(f, result, stack)
{
if (!stack)
function do_check_throws(f, result, stack) {
if (!stack) {
stack = Components.stack.caller;
}
try {
f();
} catch (exc) {
if (exc.result == result)
if (exc.result == result) {
return;
}
do_throw("expected result " + result + ", caught " + exc, stack);
}
do_throw("expected result " + result + ", none thrown", stack);
}
// Helper to step a generator function and catch a StopIteration exception.
function do_run_generator(generator)
{
function do_run_generator(generator) {
try {
generator.next();
} catch (e) {
@ -41,8 +50,7 @@ function do_run_generator(generator)
}
// Helper to finish a generator function test.
function do_finish_generator_test(generator)
{
function do_finish_generator_test(generator) {
executeSoon(function() {
generator.return();
do_test_finished();
@ -57,19 +65,20 @@ function _observer(generator, topic) {
}
_observer.prototype = {
observe (subject, topic, data) {
observe(subject, topic, data) {
Assert.equal(this.topic, topic);
Services.obs.removeObserver(this, this.topic);
// Continue executing the generator function.
if (this.generator)
if (this.generator) {
do_run_generator(this.generator);
}
this.generator = null;
this.topic = null;
}
}
},
};
// Close the cookie database. If a generator is supplied, it will be invoked
// once the close is complete.
@ -96,7 +105,14 @@ function do_load_profile(generator) {
// Set a single session cookie using http and test the cookie count
// against 'expected'
function do_set_single_http_cookie(uri, channel, expected) {
Services.cookies.setCookieStringFromHttp(uri, null, null, "foo=bar", null, channel);
Services.cookies.setCookieStringFromHttp(
uri,
null,
null,
"foo=bar",
null,
channel
);
Assert.equal(Services.cookiemgr.countCookiesFromHost(uri.host), expected);
}
@ -112,10 +128,24 @@ function do_set_cookies(uri, channel, session, expected) {
Services.cookies.setCookieString(uri, null, "can=has" + suffix, channel);
Assert.equal(Services.cookiemgr.countCookiesFromHost(uri.host), expected[1]);
// without channel, from http
Services.cookies.setCookieStringFromHttp(uri, null, null, "cheez=burger" + suffix, null, null);
Services.cookies.setCookieStringFromHttp(
uri,
null,
null,
"cheez=burger" + suffix,
null,
null
);
Assert.equal(Services.cookiemgr.countCookiesFromHost(uri.host), expected[2]);
// with channel, from http
Services.cookies.setCookieStringFromHttp(uri, null, null, "hot=dog" + suffix, null, channel);
Services.cookies.setCookieStringFromHttp(
uri,
null,
null,
"hot=dog" + suffix,
null,
channel
);
Assert.equal(Services.cookiemgr.countCookiesFromHost(uri.host), expected[3]);
}
@ -133,17 +163,18 @@ function do_count_cookies() {
}
// Helper object to store cookie data.
function Cookie(name,
value,
host,
path,
expiry,
lastAccessed,
creationTime,
isSession,
isSecure,
isHttpOnly)
{
function Cookie(
name,
value,
host,
path,
expiry,
lastAccessed,
creationTime,
isSession,
isSecure,
isHttpOnly
) {
this.name = name;
this.value = value;
this.host = host;
@ -155,33 +186,35 @@ function Cookie(name,
this.isSecure = isSecure;
this.isHttpOnly = isHttpOnly;
let strippedHost = host.charAt(0) == '.' ? host.slice(1) : host;
let strippedHost = host.charAt(0) == "." ? host.slice(1) : host;
try {
this.baseDomain = Services.etld.getBaseDomainFromHost(strippedHost);
} catch (e) {
if (e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS ||
e.result == Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS)
if (
e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS ||
e.result == Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
) {
this.baseDomain = strippedHost;
}
}
}
// Object representing a database connection and associated statements. The
// implementation varies depending on schema version.
function CookieDatabaseConnection(file, schema)
{
function CookieDatabaseConnection(file, schema) {
// Manually generate a cookies.sqlite file with appropriate rows, columns,
// and schema version. If it already exists, just set up our statements.
let exists = file.exists();
this.db = Services.storage.openDatabase(file);
this.schema = schema;
if (!exists)
if (!exists) {
this.db.schemaVersion = schema;
}
switch (schema) {
case 1:
{
case 1: {
if (!exists) {
this.db.executeSimpleSQL(
"CREATE TABLE moz_cookies ( \
@ -192,7 +225,8 @@ function CookieDatabaseConnection(file, schema)
path TEXT, \
expiry INTEGER, \
isSecure INTEGER, \
isHttpOnly INTEGER)");
isHttpOnly INTEGER)"
);
}
this.stmtInsert = this.db.createStatement(
@ -213,16 +247,17 @@ function CookieDatabaseConnection(file, schema)
:path, \
:expiry, \
:isSecure, \
:isHttpOnly)");
:isHttpOnly)"
);
this.stmtDelete = this.db.createStatement(
"DELETE FROM moz_cookies WHERE id = :id");
"DELETE FROM moz_cookies WHERE id = :id"
);
break;
}
case 2:
{
case 2: {
if (!exists) {
this.db.executeSimpleSQL(
"CREATE TABLE moz_cookies ( \
@ -234,7 +269,8 @@ function CookieDatabaseConnection(file, schema)
expiry INTEGER, \
lastAccessed INTEGER, \
isSecure INTEGER, \
isHttpOnly INTEGER)");
isHttpOnly INTEGER)"
);
}
this.stmtInsert = this.db.createStatement(
@ -257,19 +293,21 @@ function CookieDatabaseConnection(file, schema)
:expiry, \
:lastAccessed, \
:isSecure, \
:isHttpOnly)");
:isHttpOnly)"
);
this.stmtDelete = this.db.createStatement(
"DELETE FROM moz_cookies WHERE id = :id");
"DELETE FROM moz_cookies WHERE id = :id"
);
this.stmtUpdate = this.db.createStatement(
"UPDATE moz_cookies SET lastAccessed = :lastAccessed WHERE id = :id");
"UPDATE moz_cookies SET lastAccessed = :lastAccessed WHERE id = :id"
);
break;
}
case 3:
{
case 3: {
if (!exists) {
this.db.executeSimpleSQL(
"CREATE TABLE moz_cookies ( \
@ -282,10 +320,12 @@ function CookieDatabaseConnection(file, schema)
expiry INTEGER, \
lastAccessed INTEGER, \
isSecure INTEGER, \
isHttpOnly INTEGER)");
isHttpOnly INTEGER)"
);
this.db.executeSimpleSQL(
"CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)");
"CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)"
);
}
this.stmtInsert = this.db.createStatement(
@ -310,19 +350,21 @@ function CookieDatabaseConnection(file, schema)
:expiry, \
:lastAccessed, \
:isSecure, \
:isHttpOnly)");
:isHttpOnly)"
);
this.stmtDelete = this.db.createStatement(
"DELETE FROM moz_cookies WHERE id = :id");
"DELETE FROM moz_cookies WHERE id = :id"
);
this.stmtUpdate = this.db.createStatement(
"UPDATE moz_cookies SET lastAccessed = :lastAccessed WHERE id = :id");
"UPDATE moz_cookies SET lastAccessed = :lastAccessed WHERE id = :id"
);
break;
}
case 4:
{
case 4: {
if (!exists) {
this.db.executeSimpleSQL(
"CREATE TABLE moz_cookies ( \
@ -337,13 +379,14 @@ function CookieDatabaseConnection(file, schema)
creationTime INTEGER, \
isSecure INTEGER, \
isHttpOnly INTEGER \
CONSTRAINT moz_uniqueid UNIQUE (name, host, path))");
CONSTRAINT moz_uniqueid UNIQUE (name, host, path))"
);
this.db.executeSimpleSQL(
"CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)");
"CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)"
);
this.db.executeSimpleSQL(
"PRAGMA journal_mode = WAL");
this.db.executeSimpleSQL("PRAGMA journal_mode = WAL");
}
this.stmtInsert = this.db.createStatement(
@ -368,162 +411,160 @@ function CookieDatabaseConnection(file, schema)
:lastAccessed, \
:creationTime, \
:isSecure, \
:isHttpOnly)");
:isHttpOnly)"
);
this.stmtDelete = this.db.createStatement(
"DELETE FROM moz_cookies \
WHERE name = :name AND host = :host AND path = :path");
WHERE name = :name AND host = :host AND path = :path"
);
this.stmtUpdate = this.db.createStatement(
"UPDATE moz_cookies SET lastAccessed = :lastAccessed \
WHERE name = :name AND host = :host AND path = :path");
WHERE name = :name AND host = :host AND path = :path"
);
break;
}
default:
do_throw("unrecognized schemaVersion!");
default:
do_throw("unrecognized schemaVersion!");
}
}
CookieDatabaseConnection.prototype =
{
insertCookie(cookie)
{
if (!(cookie instanceof Cookie))
CookieDatabaseConnection.prototype = {
insertCookie(cookie) {
if (!(cookie instanceof Cookie)) {
do_throw("not a cookie");
}
switch (this.schema)
{
case 1:
this.stmtInsert.bindByName("id", cookie.creationTime);
this.stmtInsert.bindByName("name", cookie.name);
this.stmtInsert.bindByName("value", cookie.value);
this.stmtInsert.bindByName("host", cookie.host);
this.stmtInsert.bindByName("path", cookie.path);
this.stmtInsert.bindByName("expiry", cookie.expiry);
this.stmtInsert.bindByName("isSecure", cookie.isSecure);
this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
break;
switch (this.schema) {
case 1:
this.stmtInsert.bindByName("id", cookie.creationTime);
this.stmtInsert.bindByName("name", cookie.name);
this.stmtInsert.bindByName("value", cookie.value);
this.stmtInsert.bindByName("host", cookie.host);
this.stmtInsert.bindByName("path", cookie.path);
this.stmtInsert.bindByName("expiry", cookie.expiry);
this.stmtInsert.bindByName("isSecure", cookie.isSecure);
this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
break;
case 2:
this.stmtInsert.bindByName("id", cookie.creationTime);
this.stmtInsert.bindByName("name", cookie.name);
this.stmtInsert.bindByName("value", cookie.value);
this.stmtInsert.bindByName("host", cookie.host);
this.stmtInsert.bindByName("path", cookie.path);
this.stmtInsert.bindByName("expiry", cookie.expiry);
this.stmtInsert.bindByName("lastAccessed", cookie.lastAccessed);
this.stmtInsert.bindByName("isSecure", cookie.isSecure);
this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
break;
case 2:
this.stmtInsert.bindByName("id", cookie.creationTime);
this.stmtInsert.bindByName("name", cookie.name);
this.stmtInsert.bindByName("value", cookie.value);
this.stmtInsert.bindByName("host", cookie.host);
this.stmtInsert.bindByName("path", cookie.path);
this.stmtInsert.bindByName("expiry", cookie.expiry);
this.stmtInsert.bindByName("lastAccessed", cookie.lastAccessed);
this.stmtInsert.bindByName("isSecure", cookie.isSecure);
this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
break;
case 3:
this.stmtInsert.bindByName("id", cookie.creationTime);
this.stmtInsert.bindByName("baseDomain", cookie.baseDomain);
this.stmtInsert.bindByName("name", cookie.name);
this.stmtInsert.bindByName("value", cookie.value);
this.stmtInsert.bindByName("host", cookie.host);
this.stmtInsert.bindByName("path", cookie.path);
this.stmtInsert.bindByName("expiry", cookie.expiry);
this.stmtInsert.bindByName("lastAccessed", cookie.lastAccessed);
this.stmtInsert.bindByName("isSecure", cookie.isSecure);
this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
break;
case 3:
this.stmtInsert.bindByName("id", cookie.creationTime);
this.stmtInsert.bindByName("baseDomain", cookie.baseDomain);
this.stmtInsert.bindByName("name", cookie.name);
this.stmtInsert.bindByName("value", cookie.value);
this.stmtInsert.bindByName("host", cookie.host);
this.stmtInsert.bindByName("path", cookie.path);
this.stmtInsert.bindByName("expiry", cookie.expiry);
this.stmtInsert.bindByName("lastAccessed", cookie.lastAccessed);
this.stmtInsert.bindByName("isSecure", cookie.isSecure);
this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
break;
case 4:
this.stmtInsert.bindByName("baseDomain", cookie.baseDomain);
this.stmtInsert.bindByName("name", cookie.name);
this.stmtInsert.bindByName("value", cookie.value);
this.stmtInsert.bindByName("host", cookie.host);
this.stmtInsert.bindByName("path", cookie.path);
this.stmtInsert.bindByName("expiry", cookie.expiry);
this.stmtInsert.bindByName("lastAccessed", cookie.lastAccessed);
this.stmtInsert.bindByName("creationTime", cookie.creationTime);
this.stmtInsert.bindByName("isSecure", cookie.isSecure);
this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
break;
case 4:
this.stmtInsert.bindByName("baseDomain", cookie.baseDomain);
this.stmtInsert.bindByName("name", cookie.name);
this.stmtInsert.bindByName("value", cookie.value);
this.stmtInsert.bindByName("host", cookie.host);
this.stmtInsert.bindByName("path", cookie.path);
this.stmtInsert.bindByName("expiry", cookie.expiry);
this.stmtInsert.bindByName("lastAccessed", cookie.lastAccessed);
this.stmtInsert.bindByName("creationTime", cookie.creationTime);
this.stmtInsert.bindByName("isSecure", cookie.isSecure);
this.stmtInsert.bindByName("isHttpOnly", cookie.isHttpOnly);
break;
default:
do_throw("unrecognized schemaVersion!");
default:
do_throw("unrecognized schemaVersion!");
}
do_execute_stmt(this.stmtInsert);
},
deleteCookie(cookie)
{
if (!(cookie instanceof Cookie))
deleteCookie(cookie) {
if (!(cookie instanceof Cookie)) {
do_throw("not a cookie");
}
switch (this.db.schemaVersion)
{
case 1:
case 2:
case 3:
this.stmtDelete.bindByName("id", cookie.creationTime);
break;
switch (this.db.schemaVersion) {
case 1:
case 2:
case 3:
this.stmtDelete.bindByName("id", cookie.creationTime);
break;
case 4:
this.stmtDelete.bindByName("name", cookie.name);
this.stmtDelete.bindByName("host", cookie.host);
this.stmtDelete.bindByName("path", cookie.path);
break;
case 4:
this.stmtDelete.bindByName("name", cookie.name);
this.stmtDelete.bindByName("host", cookie.host);
this.stmtDelete.bindByName("path", cookie.path);
break;
default:
do_throw("unrecognized schemaVersion!");
default:
do_throw("unrecognized schemaVersion!");
}
do_execute_stmt(this.stmtDelete);
},
updateCookie(cookie)
{
if (!(cookie instanceof Cookie))
updateCookie(cookie) {
if (!(cookie instanceof Cookie)) {
do_throw("not a cookie");
}
switch (this.db.schemaVersion)
{
case 1:
do_throw("can't update a schema 1 cookie!");
switch (this.db.schemaVersion) {
case 1:
do_throw("can't update a schema 1 cookie!");
case 2:
case 3:
this.stmtUpdate.bindByName("id", cookie.creationTime);
this.stmtUpdate.bindByName("lastAccessed", cookie.lastAccessed);
break;
case 2:
case 3:
this.stmtUpdate.bindByName("id", cookie.creationTime);
this.stmtUpdate.bindByName("lastAccessed", cookie.lastAccessed);
break;
case 4:
this.stmtDelete.bindByName("name", cookie.name);
this.stmtDelete.bindByName("host", cookie.host);
this.stmtDelete.bindByName("path", cookie.path);
this.stmtUpdate.bindByName("lastAccessed", cookie.lastAccessed);
break;
case 4:
this.stmtDelete.bindByName("name", cookie.name);
this.stmtDelete.bindByName("host", cookie.host);
this.stmtDelete.bindByName("path", cookie.path);
this.stmtUpdate.bindByName("lastAccessed", cookie.lastAccessed);
break;
default:
do_throw("unrecognized schemaVersion!");
default:
do_throw("unrecognized schemaVersion!");
}
do_execute_stmt(this.stmtUpdate);
},
close()
{
close() {
this.stmtInsert.finalize();
this.stmtDelete.finalize();
if (this.stmtUpdate)
if (this.stmtUpdate) {
this.stmtUpdate.finalize();
}
this.db.close();
this.stmtInsert = null;
this.stmtDelete = null;
this.stmtUpdate = null;
this.db = null;
}
}
},
};
function do_get_cookie_file(profile)
{
function do_get_cookie_file(profile) {
let file = profile.clone();
file.append("cookies.sqlite");
return file;
@ -531,16 +572,15 @@ function do_get_cookie_file(profile)
// Count the cookies from 'host' in a database. If 'host' is null, count all
// cookies.
function do_count_cookies_in_db(connection, host)
{
function do_count_cookies_in_db(connection, host) {
let select = null;
if (host) {
select = connection.createStatement(
"SELECT COUNT(1) FROM moz_cookies WHERE host = :host");
"SELECT COUNT(1) FROM moz_cookies WHERE host = :host"
);
select.bindByName("host", host);
} else {
select = connection.createStatement(
"SELECT COUNT(1) FROM moz_cookies");
select = connection.createStatement("SELECT COUNT(1) FROM moz_cookies");
}
select.executeStep();
@ -551,8 +591,7 @@ function do_count_cookies_in_db(connection, host)
}
// Execute 'stmt', ensuring that we reset it if it throws.
function do_execute_stmt(stmt)
{
function do_execute_stmt(stmt) {
try {
stmt.executeStep();
stmt.reset();

View file

@ -1,40 +1,58 @@
var CC = Components.Constructor;
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream");
const ProtocolProxyService = CC("@mozilla.org/network/protocol-proxy-service;1",
"nsIProtocolProxyService");
var sts = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Ci.nsISocketTransportService);
const BinaryInputStream = CC(
"@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream"
);
const ProtocolProxyService = CC(
"@mozilla.org/network/protocol-proxy-service;1",
"nsIProtocolProxyService"
);
var sts = Cc["@mozilla.org/network/socket-transport-service;1"].getService(
Ci.nsISocketTransportService
);
function launchConnection(socks_vers, socks_port, dest_host, dest_port, dns)
{
function launchConnection(socks_vers, socks_port, dest_host, dest_port, dns) {
var pi_flags = 0;
if (dns == 'remote')
if (dns == "remote") {
pi_flags = Ci.nsIProxyInfo.TRANSPARENT_PROXY_RESOLVES_HOST;
}
var pps = new ProtocolProxyService();
var pi = pps.newProxyInfo(socks_vers, 'localhost', socks_port, '', '',
pi_flags, -1, null);
var pi = pps.newProxyInfo(
socks_vers,
"localhost",
socks_port,
"",
"",
pi_flags,
-1,
null
);
var trans = sts.createTransport([], dest_host, dest_port, pi);
var input = trans.openInputStream(Ci.nsITransport.OPEN_BLOCKING,0,0);
var output = trans.openOutputStream(Ci.nsITransport.OPEN_BLOCKING,0,0);
var input = trans.openInputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);
var output = trans.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);
var bin = new BinaryInputStream(input);
var data = bin.readBytes(5);
if (data == 'PING!') {
print('client: got ping, sending pong.');
output.write('PONG!', 5);
if (data == "PING!") {
print("client: got ping, sending pong.");
output.write("PONG!", 5);
} else {
print('client: wrong data from server:', data);
output.write('Error: wrong data received.', 27);
print("client: wrong data from server:", data);
output.write("Error: wrong data received.", 27);
}
output.close();
}
for (var arg of arguments) {
print('client: running test', arg);
test = arg.split('|');
launchConnection(test[0], parseInt(test[1]), test[2],
parseInt(test[3]), test[4]);
print("client: running test", arg);
test = arg.split("|");
launchConnection(
test[0],
parseInt(test[1]),
test[2],
parseInt(test[3]),
test[4]
);
}

View file

@ -1,30 +1,42 @@
// Test based on submitted one from Peter B Shalimoff
var test = function(s, funcName){
function Arg(){};
Arg.prototype.toString = function(){
info("Testing " + funcName + " with null args");
return this.value;
};
// create a generic arg lits of null, -1, and 10 nulls
var args = [s, -1];
for (var i = 0; i < 10; ++i) {
args.push(new Arg());
}
var up = Cc["@mozilla.org/network/url-parser;1?auth=maybe"].getService(Ci.nsIURLParser);
try {
up[funcName].apply(up, args);
return args;
} catch (x) {
Assert.ok(true); // make sure it throws an exception instead of crashing
return x;
}
// should always have an exception to catch
Assert.ok(false);
var test = function(s, funcName) {
function Arg() {}
Arg.prototype.toString = function() {
info("Testing " + funcName + " with null args");
return this.value;
};
// create a generic arg lits of null, -1, and 10 nulls
var args = [s, -1];
for (var i = 0; i < 10; ++i) {
args.push(new Arg());
}
var up = Cc["@mozilla.org/network/url-parser;1?auth=maybe"].getService(
Ci.nsIURLParser
);
try {
up[funcName].apply(up, args);
return args;
} catch (x) {
Assert.ok(true); // make sure it throws an exception instead of crashing
return x;
}
// should always have an exception to catch
Assert.ok(false);
};
var s = null;
var funcs = ["parseAuthority", "parseFileName", "parseFilePath", "parsePath", "parseServerInfo", "parseURL", "parseUserInfo"];
var funcs = [
"parseAuthority",
"parseFileName",
"parseFilePath",
"parsePath",
"parseServerInfo",
"parseURL",
"parseUserInfo",
];
function run_test() {
funcs.forEach(function(f){test(s, f);});
funcs.forEach(function(f) {
test(s, f);
});
}

View file

@ -1,7 +1,7 @@
"use strict";
// https://bugzilla.mozilla.org/show_bug.cgi?id=761228
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
XPCOMUtils.defineLazyGetter(this, "URL", function() {
return "http://localhost:" + httpServer.identity.primaryPort;
@ -19,20 +19,22 @@ const unexpected304 = "unexpected304";
const existingCached304 = "existingCached304";
function make_uri(url) {
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
return ios.newURI(url);
}
function make_channel(url) {
return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true})
.QueryInterface(Ci.nsIHttpChannel);
return NetUtil.newChannel({
uri: url,
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
}
function clearCache() {
var service = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Ci.nsICacheStorageService);
service.clear();
var service = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(
Ci.nsICacheStorageService
);
service.clear();
}
function alwaysReturn304Handler(metadata, response) {
@ -44,10 +46,14 @@ function run_test() {
evict_cache_entries();
httpServer = new HttpServer();
httpServer.registerPathHandler(basePath + unexpected304,
alwaysReturn304Handler);
httpServer.registerPathHandler(basePath + existingCached304,
alwaysReturn304Handler);
httpServer.registerPathHandler(
basePath + unexpected304,
alwaysReturn304Handler
);
httpServer.registerPathHandler(
basePath + existingCached304,
alwaysReturn304Handler
);
httpServer.start(-1);
run_next_test();
}
@ -74,12 +80,16 @@ add_test(function test_unexpected_304() {
// the cache.
add_test(function test_304_stored_in_cache() {
asyncOpenCacheEntry(
baseURI + existingCached304, "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
function (entryStatus, cacheEntry) {
baseURI + existingCached304,
"disk",
Ci.nsICacheStorage.OPEN_NORMALLY,
null,
function(entryStatus, cacheEntry) {
cacheEntry.setMetaDataElement("request-method", "GET");
cacheEntry.setMetaDataElement("response-head",
"HTTP/1.1 304 Not Modified\r\n" +
"\r\n");
cacheEntry.setMetaDataElement(
"response-head",
"HTTP/1.1 304 Not Modified\r\n" + "\r\n"
);
cacheEntry.metaDataReady();
cacheEntry.close();
@ -90,5 +100,6 @@ add_test(function test_304_stored_in_cache() {
chan.setRequestHeader("If-None-Match", '"foo"', false);
chan.asyncOpen(new ChannelListener(consume304, null));
});
}
);
});

View file

@ -1,4 +1,4 @@
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
XPCOMUtils.defineLazyGetter(this, "URL", function() {
return "http://localhost:" + httpserver.identity.primaryPort;
@ -15,75 +15,80 @@ XPCOMUtils.defineLazyGetter(this, "noRedirectURI", function() {
var httpserver = null;
function make_channel(url) {
return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
}
const requestBody = "request body";
function redirectHandler(metadata, response)
{
function redirectHandler(metadata, response) {
response.setStatusLine(metadata.httpVersion, 307, "Moved Temporarily");
response.setHeader("Location", noRedirectURI, false);
}
function contentHandler(metadata, response)
{
function contentHandler(metadata, response) {
response.setHeader("Content-Type", "text/plain");
response.bodyOutputStream.writeFrom(metadata.bodyInputStream,
metadata.bodyInputStream.available());
response.bodyOutputStream.writeFrom(
metadata.bodyInputStream,
metadata.bodyInputStream.available()
);
}
function noRedirectStreamObserver(request, buffer)
{
function noRedirectStreamObserver(request, buffer) {
Assert.equal(buffer, requestBody);
var chan = make_channel(uri);
var uploadStream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
var uploadStream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
uploadStream.setData(requestBody, requestBody.length);
chan.QueryInterface(Ci.nsIUploadChannel).setUploadStream(uploadStream,
"text/plain",
-1);
chan
.QueryInterface(Ci.nsIUploadChannel)
.setUploadStream(uploadStream, "text/plain", -1);
chan.asyncOpen(new ChannelListener(noHeaderStreamObserver, null));
}
function noHeaderStreamObserver(request, buffer)
{
function noHeaderStreamObserver(request, buffer) {
Assert.equal(buffer, requestBody);
var chan = make_channel(uri);
var uploadStream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
var streamBody = "Content-Type: text/plain\r\n" +
"Content-Length: " + requestBody.length + "\r\n\r\n" +
requestBody;
var uploadStream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
var streamBody =
"Content-Type: text/plain\r\n" +
"Content-Length: " +
requestBody.length +
"\r\n\r\n" +
requestBody;
uploadStream.setData(streamBody, streamBody.length);
chan.QueryInterface(Ci.nsIUploadChannel).setUploadStream(uploadStream, "", -1);
chan
.QueryInterface(Ci.nsIUploadChannel)
.setUploadStream(uploadStream, "", -1);
chan.asyncOpen(new ChannelListener(headerStreamObserver, null));
}
function headerStreamObserver(request, buffer)
{
function headerStreamObserver(request, buffer) {
Assert.equal(buffer, requestBody);
httpserver.stop(do_test_finished);
}
function run_test()
{
function run_test() {
httpserver = new HttpServer();
httpserver.registerPathHandler("/redirect", redirectHandler);
httpserver.registerPathHandler("/content", contentHandler);
httpserver.start(-1);
var prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(
Ci.nsIPrefBranch
);
prefs.setBoolPref("network.http.prompt-temp-redirect", false);
var chan = make_channel(noRedirectURI);
var uploadStream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
var uploadStream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
uploadStream.setData(requestBody, requestBody.length);
chan.QueryInterface(Ci.nsIUploadChannel).setUploadStream(uploadStream,
"text/plain",
-1);
chan
.QueryInterface(Ci.nsIUploadChannel)
.setUploadStream(uploadStream, "text/plain", -1);
chan.asyncOpen(new ChannelListener(noRedirectStreamObserver, null));
do_test_pending();
}

View file

@ -1,4 +1,4 @@
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
XPCOMUtils.defineLazyGetter(this, "URL", function() {
return "http://localhost:" + httpserver.identity.primaryPort;
@ -25,7 +25,10 @@ function setup_test() {
}
function setupChannel(path) {
var chan = NetUtil.newChannel({uri: URL + path, loadUsingSystemPrincipal: true});
var chan = NetUtil.newChannel({
uri: URL + path,
loadUsingSystemPrincipal: true,
});
chan.QueryInterface(Ci.nsIHttpChannel);
chan.requestMethod = "GET";
return chan;

File diff suppressed because it is too large Load diff

View file

@ -8,15 +8,15 @@
* This file tests the methods on NetUtil.jsm.
*/
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
// We need the profile directory so the test harness will clean up our test
// files.
do_get_profile();
const OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/file-output-stream;1";
const SAFE_OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/safe-file-output-stream;1";
const SAFE_OUTPUT_STREAM_CONTRACT_ID =
"@mozilla.org/network/safe-file-output-stream;1";
////////////////////////////////////////////////////////////////////////////////
//// Helper Methods
@ -28,25 +28,25 @@ const SAFE_OUTPUT_STREAM_CONTRACT_ID = "@mozilla.org/network/safe-file-output-st
* The file to return from.
* @return the contents of the file in the form of a string.
*/
function getFileContents(aFile)
{
function getFileContents(aFile) {
"use strict";
let fstream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
Ci.nsIFileInputStream
);
fstream.init(aFile, -1, 0, 0);
let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].
createInstance(Ci.nsIConverterInputStream);
let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(
Ci.nsIConverterInputStream
);
cstream.init(fstream, "UTF-8", 0, 0);
let string = {};
let string = {};
cstream.readString(-1, string);
cstream.close();
return string.value;
}
/**
* Tests asynchronously writing a file using NetUtil.asyncCopy.
*
@ -55,25 +55,30 @@ function getFileContents(aFile)
* @param aDeferOpen
* Whether to use DEFER_OPEN in the output stream.
*/
function async_write_file(aContractId, aDeferOpen)
{
function async_write_file(aContractId, aDeferOpen) {
do_test_pending();
// First, we need an output file to write to.
let file = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).
get("ProfD", Ci.nsIFile);
let file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
file.append("NetUtil-async-test-file.tmp");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
// Then, we need an output stream to our output file.
let ostream = Cc[aContractId].createInstance(Ci.nsIFileOutputStream);
ostream.init(file, -1, -1, aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0);
ostream.init(
file,
-1,
-1,
aDeferOpen ? Ci.nsIFileOutputStream.DEFER_OPEN : 0
);
// Finally, we need an input stream to take data from.
const TEST_DATA = "this is a test string";
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
istream.setData(TEST_DATA, TEST_DATA.length);
NetUtil.asyncCopy(istream, ostream, function(aResult) {
@ -93,8 +98,7 @@ function async_write_file(aContractId, aDeferOpen)
//// Tests
// Test NetUtil.asyncCopy for all possible buffering scenarios
function test_async_copy()
{
function test_async_copy() {
// Create a data sample
function make_sample(text) {
let data = [];
@ -108,27 +112,30 @@ function test_async_copy()
function make_input(isBuffered, data) {
if (isBuffered) {
// String input streams are buffered
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
istream.setData(data, data.length);
return istream;
}
// File input streams are not buffered, so let's create a file
let file = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).
get("ProfD", Ci.nsIFile);
let file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
file.append("NetUtil-asyncFetch-test-file.tmp");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
let ostream = Cc[
"@mozilla.org/network/file-output-stream;1"
].createInstance(Ci.nsIFileOutputStream);
ostream.init(file, -1, -1, 0);
ostream.write(data, data.length);
ostream.close();
let istream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
let istream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
Ci.nsIFileInputStream
);
istream.init(file, -1, 0, 0);
return istream;
@ -136,37 +143,40 @@ function test_async_copy()
// Create an output buffer holding some data
function make_output(isBuffered) {
let file = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).
get("ProfD", Ci.nsIFile);
let file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
file.append("NetUtil-asyncFetch-test-file.tmp");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
let ostream = Cc[
"@mozilla.org/network/file-output-stream;1"
].createInstance(Ci.nsIFileOutputStream);
ostream.init(file, -1, -1, 0);
if (!isBuffered) {
return {file, sink: ostream};
return { file, sink: ostream };
}
let bstream = Cc["@mozilla.org/network/buffered-output-stream;1"].
createInstance(Ci.nsIBufferedOutputStream);
let bstream = Cc[
"@mozilla.org/network/buffered-output-stream;1"
].createInstance(Ci.nsIBufferedOutputStream);
bstream.init(ostream, 256);
return {file, sink: bstream};
return { file, sink: bstream };
}
(async function() {
do_test_pending();
for (let bufferedInput of [true, false]) {
for (let bufferedOutput of [true, false]) {
let text = "test_async_copy with "
+ (bufferedInput?"buffered input":"unbuffered input")
+ ", "
+ (bufferedOutput?"buffered output":"unbuffered output");
let text =
"test_async_copy with " +
(bufferedInput ? "buffered input" : "unbuffered input") +
", " +
(bufferedOutput ? "buffered output" : "unbuffered output");
info(text);
let TEST_DATA = "[" + make_sample(text) + "]";
let source = make_input(bufferedInput, TEST_DATA);
let {file, sink} = make_output(bufferedOutput);
let { file, sink } = make_output(bufferedOutput);
let result = await new Promise(resolve => {
NetUtil.asyncCopy(source, sink, resolve);
});
@ -202,21 +212,18 @@ function test_async_write_file_safe_deferred() {
async_write_file(SAFE_OUTPUT_STREAM_CONTRACT_ID, true);
}
function test_newURI_no_spec_throws()
{
function test_newURI_no_spec_throws() {
try {
NetUtil.newURI();
do_throw("should throw!");
}
catch (e) {
} catch (e) {
Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
}
function test_newURI()
{
function test_newURI() {
let ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
// Check that we get the same URI back from the IO service and the utility
@ -229,14 +236,13 @@ function test_newURI()
run_next_test();
}
function test_newURI_takes_nsIFile()
{
function test_newURI_takes_nsIFile() {
let ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
// Create a test file that we can pass into NetUtil.newURI
let file = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).
get("ProfD", Ci.nsIFile);
let file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
file.append("NetUtil-test-file.tmp");
// Check that we get the same URI back from the IO service and the utility
@ -248,34 +254,29 @@ function test_newURI_takes_nsIFile()
run_next_test();
}
function test_asyncFetch_no_channel()
{
function test_asyncFetch_no_channel() {
try {
NetUtil.asyncFetch(null, function() { });
NetUtil.asyncFetch(null, function() {});
do_throw("should throw!");
}
catch (e) {
} catch (e) {
Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
}
function test_asyncFetch_no_callback()
{
function test_asyncFetch_no_callback() {
try {
NetUtil.asyncFetch({ });
NetUtil.asyncFetch({});
do_throw("should throw!");
}
catch (e) {
} catch (e) {
Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
}
function test_asyncFetch_with_nsIChannel()
{
function test_asyncFetch_with_nsIChannel() {
const TEST_DATA = "this is a test string";
// Start the http server, and register our handler.
@ -300,8 +301,9 @@ function test_asyncFetch_with_nsIChannel()
// Check that we got the right data.
Assert.equal(aInputStream.available(), TEST_DATA.length);
let is = Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
Ci.nsIScriptableInputStream
);
is.init(aInputStream);
let result = is.read(TEST_DATA.length);
Assert.equal(TEST_DATA, result);
@ -310,8 +312,7 @@ function test_asyncFetch_with_nsIChannel()
});
}
function test_asyncFetch_with_nsIURI()
{
function test_asyncFetch_with_nsIURI() {
const TEST_DATA = "this is a test string";
// Start the http server, and register our handler.
@ -324,36 +325,40 @@ function test_asyncFetch_with_nsIURI()
server.start(-1);
// Create our URI.
let uri = NetUtil.newURI("http://localhost:" +
server.identity.primaryPort + "/test");
let uri = NetUtil.newURI(
"http://localhost:" + server.identity.primaryPort + "/test"
);
// Open our URI asynchronously.
NetUtil.asyncFetch({
uri,
loadUsingSystemPrincipal: true,
}, function(aInputStream, aResult) {
// Check that we had success.
Assert.ok(Components.isSuccessCode(aResult));
NetUtil.asyncFetch(
{
uri,
loadUsingSystemPrincipal: true,
},
function(aInputStream, aResult) {
// Check that we had success.
Assert.ok(Components.isSuccessCode(aResult));
// Check that we got the right data.
Assert.equal(aInputStream.available(), TEST_DATA.length);
let is = Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
is.init(aInputStream);
let result = is.read(TEST_DATA.length);
Assert.equal(TEST_DATA, result);
// Check that we got the right data.
Assert.equal(aInputStream.available(), TEST_DATA.length);
let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
Ci.nsIScriptableInputStream
);
is.init(aInputStream);
let result = is.read(TEST_DATA.length);
Assert.equal(TEST_DATA, result);
server.stop(run_next_test);
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
server.stop(run_next_test);
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER
);
}
function test_asyncFetch_with_string()
{
function test_asyncFetch_with_string() {
const TEST_DATA = "this is a test string";
// Start the http server, and register our handler.
@ -366,44 +371,48 @@ function test_asyncFetch_with_string()
server.start(-1);
// Open our location asynchronously.
NetUtil.asyncFetch({
uri: "http://localhost:" + server.identity.primaryPort + "/test",
loadUsingSystemPrincipal: true,
}, function(aInputStream, aResult) {
// Check that we had success.
Assert.ok(Components.isSuccessCode(aResult));
NetUtil.asyncFetch(
{
uri: "http://localhost:" + server.identity.primaryPort + "/test",
loadUsingSystemPrincipal: true,
},
function(aInputStream, aResult) {
// Check that we had success.
Assert.ok(Components.isSuccessCode(aResult));
// Check that we got the right data.
Assert.equal(aInputStream.available(), TEST_DATA.length);
let is = Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
is.init(aInputStream);
let result = is.read(TEST_DATA.length);
Assert.equal(TEST_DATA, result);
// Check that we got the right data.
Assert.equal(aInputStream.available(), TEST_DATA.length);
let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
Ci.nsIScriptableInputStream
);
is.init(aInputStream);
let result = is.read(TEST_DATA.length);
Assert.equal(TEST_DATA, result);
server.stop(run_next_test);
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
server.stop(run_next_test);
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER
);
}
function test_asyncFetch_with_nsIFile()
{
function test_asyncFetch_with_nsIFile() {
const TEST_DATA = "this is a test string";
// First we need a file to read from.
let file = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties).
get("ProfD", Ci.nsIFile);
let file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
file.append("NetUtil-asyncFetch-test-file.tmp");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
// Write the test data to the file.
let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
let ostream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
Ci.nsIFileOutputStream
);
ostream.init(file, -1, -1, 0);
ostream.write(TEST_DATA, TEST_DATA.length);
@ -412,58 +421,66 @@ function test_asyncFetch_with_nsIFile()
// Open our file asynchronously.
// Note that this causes main-tread I/O and should be avoided in production.
NetUtil.asyncFetch({
uri: NetUtil.newURI(file),
loadUsingSystemPrincipal: true,
}, function(aInputStream, aResult) {
// Check that we had success.
Assert.ok(Components.isSuccessCode(aResult));
NetUtil.asyncFetch(
{
uri: NetUtil.newURI(file),
loadUsingSystemPrincipal: true,
},
function(aInputStream, aResult) {
// Check that we had success.
Assert.ok(Components.isSuccessCode(aResult));
// Check that we got the right data.
Assert.equal(aInputStream.available(), TEST_DATA.length);
let is = Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
is.init(aInputStream);
let result = is.read(TEST_DATA.length);
Assert.equal(TEST_DATA, result);
// Check that we got the right data.
Assert.equal(aInputStream.available(), TEST_DATA.length);
let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
Ci.nsIScriptableInputStream
);
is.init(aInputStream);
let result = is.read(TEST_DATA.length);
Assert.equal(TEST_DATA, result);
run_next_test();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
run_next_test();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER
);
}
function test_asyncFetch_with_nsIInputString()
{
function test_asyncFetch_with_nsIInputString() {
const TEST_DATA = "this is a test string";
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
istream.setData(TEST_DATA, TEST_DATA.length);
// Read the input stream asynchronously.
NetUtil.asyncFetch(istream, function(aInputStream, aResult) {
// Check that we had success.
Assert.ok(Components.isSuccessCode(aResult));
NetUtil.asyncFetch(
istream,
function(aInputStream, aResult) {
// Check that we had success.
Assert.ok(Components.isSuccessCode(aResult));
// Check that we got the right data.
Assert.equal(aInputStream.available(), TEST_DATA.length);
Assert.equal(NetUtil.readInputStreamToString(aInputStream, TEST_DATA.length),
TEST_DATA);
// Check that we got the right data.
Assert.equal(aInputStream.available(), TEST_DATA.length);
Assert.equal(
NetUtil.readInputStreamToString(aInputStream, TEST_DATA.length),
TEST_DATA
);
run_next_test();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
run_next_test();
},
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER
);
}
function test_asyncFetch_does_not_block()
{
function test_asyncFetch_does_not_block() {
// Create our channel that has no data.
let channel = NetUtil.newChannel({
uri: "data:text/plain,",
@ -477,14 +494,14 @@ function test_asyncFetch_does_not_block()
// Check that reading a byte throws that the stream was closed (as opposed
// saying it would block).
let is = Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
let is = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
Ci.nsIScriptableInputStream
);
is.init(aInputStream);
try {
is.read(1);
do_throw("should throw!");
}
catch (e) {
} catch (e) {
Assert.equal(e.result, Cr.NS_BASE_STREAM_CLOSED);
}
@ -492,97 +509,101 @@ function test_asyncFetch_does_not_block()
});
}
function test_newChannel_no_specifier()
{
function test_newChannel_no_specifier() {
try {
NetUtil.newChannel();
do_throw("should throw!");
}
catch (e) {
} catch (e) {
Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
}
function test_newChannel_with_string()
{
function test_newChannel_with_string() {
const TEST_SPEC = "http://mozilla.org";
// Check that we get the same URI back from channel the IO service creates and
// the channel the utility method creates.
let ios = Services.io
let iosChannel = ios.newChannel(TEST_SPEC,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
let ios = Services.io;
let iosChannel = ios.newChannel(
TEST_SPEC,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER
);
let NetUtilChannel = NetUtil.newChannel({
uri: TEST_SPEC,
loadUsingSystemPrincipal: true
loadUsingSystemPrincipal: true,
});
Assert.ok(iosChannel.URI.equals(NetUtilChannel.URI));
run_next_test();
}
function test_newChannel_with_nsIURI()
{
function test_newChannel_with_nsIURI() {
const TEST_SPEC = "http://mozilla.org";
// Check that we get the same URI back from channel the IO service creates and
// the channel the utility method creates.
let uri = NetUtil.newURI(TEST_SPEC);
let iosChannel = Services.io.newChannelFromURI(uri,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
let iosChannel = Services.io.newChannelFromURI(
uri,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER
);
let NetUtilChannel = NetUtil.newChannel({
uri,
loadUsingSystemPrincipal: true
loadUsingSystemPrincipal: true,
});
Assert.ok(iosChannel.URI.equals(NetUtilChannel.URI));
run_next_test();
}
function test_newChannel_with_options()
{
function test_newChannel_with_options() {
let uri = "data:text/plain,";
let iosChannel = Services.io.newChannelFromURI(NetUtil.newURI(uri),
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
let iosChannel = Services.io.newChannelFromURI(
NetUtil.newURI(uri),
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER
);
function checkEqualToIOSChannel(channel) {
Assert.ok(iosChannel.URI.equals(channel.URI));
Assert.ok(iosChannel.URI.equals(channel.URI));
}
checkEqualToIOSChannel(NetUtil.newChannel({
uri,
loadingPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
}));
checkEqualToIOSChannel(
NetUtil.newChannel({
uri,
loadingPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
})
);
checkEqualToIOSChannel(NetUtil.newChannel({
uri,
loadUsingSystemPrincipal: true,
}));
checkEqualToIOSChannel(
NetUtil.newChannel({
uri,
loadUsingSystemPrincipal: true,
})
);
run_next_test();
}
function test_newChannel_with_wrong_options()
{
function test_newChannel_with_wrong_options() {
let uri = "data:text/plain,";
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
@ -628,136 +649,137 @@ function test_newChannel_with_wrong_options()
run_next_test();
}
function test_readInputStreamToString()
{
function test_readInputStreamToString() {
const TEST_DATA = "this is a test string\0 with an embedded null";
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsISupportsCString);
let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsISupportsCString
);
istream.data = TEST_DATA;
Assert.equal(NetUtil.readInputStreamToString(istream, TEST_DATA.length),
TEST_DATA);
Assert.equal(
NetUtil.readInputStreamToString(istream, TEST_DATA.length),
TEST_DATA
);
run_next_test();
}
function test_readInputStreamToString_no_input_stream()
{
function test_readInputStreamToString_no_input_stream() {
try {
NetUtil.readInputStreamToString("hi", 2);
do_throw("should throw!");
}
catch (e) {
} catch (e) {
Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
}
function test_readInputStreamToString_no_bytes_arg()
{
function test_readInputStreamToString_no_bytes_arg() {
const TEST_DATA = "this is a test string";
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
istream.setData(TEST_DATA, TEST_DATA.length);
try {
NetUtil.readInputStreamToString(istream);
do_throw("should throw!");
}
catch (e) {
} catch (e) {
Assert.equal(e.result, Cr.NS_ERROR_INVALID_ARG);
}
run_next_test();
}
function test_readInputStreamToString_blocking_stream()
{
function test_readInputStreamToString_blocking_stream() {
let pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
pipe.init(true, true, 0, 0, null);
try {
NetUtil.readInputStreamToString(pipe.inputStream, 10);
do_throw("should throw!");
}
catch (e) {
} catch (e) {
Assert.equal(e.result, Cr.NS_BASE_STREAM_WOULD_BLOCK);
}
run_next_test();
}
function test_readInputStreamToString_too_many_bytes()
{
function test_readInputStreamToString_too_many_bytes() {
const TEST_DATA = "this is a test string";
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
istream.setData(TEST_DATA, TEST_DATA.length);
try {
NetUtil.readInputStreamToString(istream, TEST_DATA.length + 10);
do_throw("should throw!");
}
catch (e) {
} catch (e) {
Assert.equal(e.result, Cr.NS_ERROR_FAILURE);
}
run_next_test();
}
function test_readInputStreamToString_with_charset()
{
function test_readInputStreamToString_with_charset() {
const TEST_DATA = "\uff10\uff11\uff12\uff13";
const TEST_DATA_UTF8 = "\xef\xbc\x90\xef\xbc\x91\xef\xbc\x92\xef\xbc\x93";
const TEST_DATA_SJIS = "\x82\x4f\x82\x50\x82\x51\x82\x52";
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
istream.setData(TEST_DATA_UTF8, TEST_DATA_UTF8.length);
Assert.equal(NetUtil.readInputStreamToString(istream,
TEST_DATA_UTF8.length,
{ charset: "UTF-8"}),
TEST_DATA);
Assert.equal(
NetUtil.readInputStreamToString(istream, TEST_DATA_UTF8.length, {
charset: "UTF-8",
}),
TEST_DATA
);
istream.setData(TEST_DATA_SJIS, TEST_DATA_SJIS.length);
Assert.equal(NetUtil.readInputStreamToString(istream,
TEST_DATA_SJIS.length,
{ charset: "Shift_JIS"}),
TEST_DATA);
Assert.equal(
NetUtil.readInputStreamToString(istream, TEST_DATA_SJIS.length, {
charset: "Shift_JIS",
}),
TEST_DATA
);
run_next_test();
}
function test_readInputStreamToString_invalid_sequence()
{
function test_readInputStreamToString_invalid_sequence() {
const TEST_DATA = "\ufffd\ufffd\ufffd\ufffd";
const TEST_DATA_UTF8 = "\xaa\xaa\xaa\xaa";
let istream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
Ci.nsIStringInputStream
);
istream.setData(TEST_DATA_UTF8, TEST_DATA_UTF8.length);
try {
NetUtil.readInputStreamToString(istream,
TEST_DATA_UTF8.length,
{ charset: "UTF-8" });
NetUtil.readInputStreamToString(istream, TEST_DATA_UTF8.length, {
charset: "UTF-8",
});
do_throw("should throw!");
} catch (e) {
Assert.equal(e.result, Cr.NS_ERROR_ILLEGAL_INPUT);
}
istream.setData(TEST_DATA_UTF8, TEST_DATA_UTF8.length);
Assert.equal(NetUtil.readInputStreamToString(istream,
TEST_DATA_UTF8.length, {
charset: "UTF-8",
replacement: Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER}),
TEST_DATA);
Assert.equal(
NetUtil.readInputStreamToString(istream, TEST_DATA_UTF8.length, {
charset: "UTF-8",
replacement: Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER,
}),
TEST_DATA
);
run_next_test();
}
////////////////////////////////////////////////////////////////////////////////
//// Test Runner
@ -792,4 +814,3 @@ function test_readInputStreamToString_invalid_sequence()
test_readInputStreamToString_invalid_sequence,
].forEach(f => add_test(f));
var index = 0;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -4,8 +4,10 @@
// etc--see HttpBaseChannel::IsSafeMethod). Since no prompting is possible
// in xpcshell, we get an error for prompts, and the request fails.
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const {Preferences} = ChromeUtils.import("resource://gre/modules/Preferences.jsm");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
const { Preferences } = ChromeUtils.import(
"resource://gre/modules/Preferences.jsm"
);
Cu.importGlobalProperties(["XMLHttpRequest"]);
@ -23,15 +25,13 @@ XPCOMUtils.defineLazyGetter(this, "pOther", function() {
return sOther.identity.primaryPort;
});
function createXHR(async, method, path)
{
function createXHR(async, method, path) {
var xhr = new XMLHttpRequest();
xhr.open(method, "http://localhost:" + pSame + path, async);
return xhr;
}
function checkResults(xhr, method, status, unsafe)
{
function checkResults(xhr, method, status, unsafe) {
if (unsafe) {
if (sRedirectPromptPref) {
// The method is null if we prompt for unsafe redirects
@ -42,8 +42,9 @@ function checkResults(xhr, method, status, unsafe)
}
}
if (xhr.readyState != 4)
if (xhr.readyState != 4) {
return false;
}
Assert.equal(xhr.status, status);
if (status == 200) {
@ -59,18 +60,48 @@ function run_test() {
sSame = new HttpServer();
// same-origin redirects
sSame.registerPathHandler("/bug" + BUGID + "-redirect301", bug676059redirect301);
sSame.registerPathHandler("/bug" + BUGID + "-redirect302", bug676059redirect302);
sSame.registerPathHandler("/bug" + BUGID + "-redirect303", bug676059redirect303);
sSame.registerPathHandler("/bug" + BUGID + "-redirect307", bug676059redirect307);
sSame.registerPathHandler("/bug" + BUGID + "-redirect308", bug676059redirect308);
sSame.registerPathHandler(
"/bug" + BUGID + "-redirect301",
bug676059redirect301
);
sSame.registerPathHandler(
"/bug" + BUGID + "-redirect302",
bug676059redirect302
);
sSame.registerPathHandler(
"/bug" + BUGID + "-redirect303",
bug676059redirect303
);
sSame.registerPathHandler(
"/bug" + BUGID + "-redirect307",
bug676059redirect307
);
sSame.registerPathHandler(
"/bug" + BUGID + "-redirect308",
bug676059redirect308
);
// cross-origin redirects
sSame.registerPathHandler("/bug" + OTHERBUGID + "-redirect301", bug696849redirect301);
sSame.registerPathHandler("/bug" + OTHERBUGID + "-redirect302", bug696849redirect302);
sSame.registerPathHandler("/bug" + OTHERBUGID + "-redirect303", bug696849redirect303);
sSame.registerPathHandler("/bug" + OTHERBUGID + "-redirect307", bug696849redirect307);
sSame.registerPathHandler("/bug" + OTHERBUGID + "-redirect308", bug696849redirect308);
sSame.registerPathHandler(
"/bug" + OTHERBUGID + "-redirect301",
bug696849redirect301
);
sSame.registerPathHandler(
"/bug" + OTHERBUGID + "-redirect302",
bug696849redirect302
);
sSame.registerPathHandler(
"/bug" + OTHERBUGID + "-redirect303",
bug696849redirect303
);
sSame.registerPathHandler(
"/bug" + OTHERBUGID + "-redirect307",
bug696849redirect307
);
sSame.registerPathHandler(
"/bug" + OTHERBUGID + "-redirect308",
bug696849redirect308
);
// same-origin target
sSame.registerPathHandler("/bug" + BUGID + "-target", echoMethod);
@ -86,10 +117,10 @@ function run_test() {
// methodToSend is the HTTP method to send
// redirectedMethod is the method to use for the redirect, if any
// finalStatus is 200 when the redirect takes place, redirectType otherwise
// Note that unsafe methods should not follow the redirect automatically
// Of the methods below, DELETE, POST and PUT are unsafe
sRedirectPromptPref = Preferences.get("network.http.prompt-temp-redirect");
// Following Bug 677754 we don't prompt for unsafe redirects
@ -136,49 +167,56 @@ function run_test() {
var othertests = tests; // for now these have identical results
var xhr;
for (var i = 0; i < tests.length; ++i) {
dump("Testing " + tests[i] + "\n");
xhr = createXHR(false, tests[i][1], "/bug" + BUGID + "-redirect" + tests[i][0]);
xhr = createXHR(
false,
tests[i][1],
"/bug" + BUGID + "-redirect" + tests[i][0]
);
xhr.send(null);
checkResults(xhr, tests[i][2], tests[i][3], tests[i][4]);
}
}
for (var i = 0; i < othertests.length; ++i) {
dump("Testing " + othertests[i] + " (cross-origin)\n");
xhr = createXHR(false, othertests[i][1], "/bug" + OTHERBUGID + "-redirect" + othertests[i][0]);
xhr = createXHR(
false,
othertests[i][1],
"/bug" + OTHERBUGID + "-redirect" + othertests[i][0]
);
xhr.send(null);
checkResults(xhr, othertests[i][2], tests[i][3], tests[i][4]);
}
}
sSame.stop(do_test_finished);
sOther.stop(do_test_finished);
}
function redirect(metadata, response, status, port, bugid) {
// set a proper reason string to avoid confusion when looking at the
// HTTP messages
var reason;
if (status == 301) {
reason = "Moved Permanently";
}
else if (status == 302) {
} else if (status == 302) {
reason = "Found";
}
else if (status == 303) {
} else if (status == 303) {
reason = "See Other";
}
else if (status == 307) {
} else if (status == 307) {
reason = "Temporary Redirect";
}
else if (status == 308) {
} else if (status == 308) {
reason = "Permanent Redirect";
}
response.setStatusLine(metadata.httpVersion, status, reason);
response.setHeader("Location", "http://localhost:" + port + "/bug" + bugid + "-target");
}
response.setHeader(
"Location",
"http://localhost:" + port + "/bug" + bugid + "-target"
);
}
// PATH HANDLER FOR /bug676059-redirect301
function bug676059redirect301(metadata, response) {
redirect(metadata, response, 301, pSame, BUGID);

View file

@ -3,13 +3,15 @@
* 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 {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
const gDashboard = Cc['@mozilla.org/network/dashboard;1']
.getService(Ci.nsIDashboard);
const gDashboard = Cc["@mozilla.org/network/dashboard;1"].getService(
Ci.nsIDashboard
);
const gServerSocket = Cc["@mozilla.org/network/server-socket;1"]
.createInstance(Ci.nsIServerSocket);
const gServerSocket = Cc["@mozilla.org/network/server-socket;1"].createInstance(
Ci.nsIServerSocket
);
const gHttpServer = new HttpServer();
add_test(function test_http() {
@ -46,12 +48,17 @@ add_test(function test_dns() {
});
add_test(function test_sockets() {
let sts = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Ci.nsISocketTransportService);
let sts = Cc["@mozilla.org/network/socket-transport-service;1"].getService(
Ci.nsISocketTransportService
);
let threadManager = Cc["@mozilla.org/thread-manager;1"].getService();
let transport = sts.createTransport([], "127.0.0.1",
gServerSocket.port, null);
let transport = sts.createTransport(
[],
"127.0.0.1",
gServerSocket.port,
null
);
let listener = {
onTransportStatus(aTransport, aStatus, aProgress, aProgressMax) {
if (aStatus == Ci.nsISocketTransport.STATUS_CONNECTED_TO) {
@ -69,7 +76,7 @@ add_test(function test_sockets() {
run_next_test();
});
}
}
},
};
transport.setEventSink(listener, threadManager.currentThread);
@ -77,15 +84,21 @@ add_test(function test_sockets() {
});
function run_test() {
Services.prefs.setBoolPref("network.cookieSettings.unblocked_for_testing", true);
Services.prefs.setBoolPref(
"network.cookieSettings.unblocked_for_testing",
true
);
let ioService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
let ioService = Cc["@mozilla.org/network/io-service;1"].getService(
Ci.nsIIOService
);
gHttpServer.start(-1);
let uri = ioService.newURI("http://localhost:" + gHttpServer.identity.primaryPort);
let channel = NetUtil.newChannel({uri, loadUsingSystemPrincipal: true});
let uri = ioService.newURI(
"http://localhost:" + gHttpServer.identity.primaryPort
);
let channel = NetUtil.newChannel({ uri, loadUsingSystemPrincipal: true });
channel.open();
@ -93,4 +106,3 @@ function run_test() {
run_next_test();
}

View file

@ -2,43 +2,54 @@
* 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/. */
var unsafeAboutModule = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIAboutModule]),
newChannel (aURI, aLoadInfo) {
newChannel(aURI, aLoadInfo) {
var uri = Services.io.newURI("about:blank");
let chan = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo);
chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
return chan;
},
getURIFlags (aURI) {
getURIFlags(aURI) {
return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT;
}
},
};
var factory = {
createInstance(aOuter, aIID) {
if (aOuter)
if (aOuter) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return unsafeAboutModule.QueryInterface(aIID);
},
lockFactory(aLock) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIFactory])
QueryInterface: ChromeUtils.generateQI([Ci.nsIFactory]),
};
function run_test() {
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
let classID = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID();
registrar.registerFactory(classID, "", "@mozilla.org/network/protocol/about;1?what=unsafe", factory);
let classID = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator)
.generateUUID();
registrar.registerFactory(
classID,
"",
"@mozilla.org/network/protocol/about;1?what=unsafe",
factory
);
let aboutUnsafeChan = NetUtil.newChannel({
uri: "about:unsafe",
loadUsingSystemPrincipal: true
loadUsingSystemPrincipal: true,
});
Assert.equal(null, aboutUnsafeChan.owner, "URI_SAFE_FOR_UNTRUSTED_CONTENT channel has no owner");
Assert.equal(
null,
aboutUnsafeChan.owner,
"URI_SAFE_FOR_UNTRUSTED_CONTENT channel has no owner"
);
registrar.unregisterFactory(classID, factory);
}

View file

@ -1,4 +1,3 @@
function run_test() {
var base = NetUtil.newURI("http://www.example.com");
var about1 = NetUtil.newURI("about:blank");
@ -6,19 +5,18 @@ function run_test() {
var chan1 = NetUtil.newChannel({
uri: about1,
loadUsingSystemPrincipal: true
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIPropertyBag2);
var chan2 = NetUtil.newChannel({
uri: about2,
loadUsingSystemPrincipal: true
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIPropertyBag2);
var haveProp = false;
var propVal = null;
try {
propVal = chan1.getPropertyAsInterface("baseURI",
Ci.nsIURI);
propVal = chan1.getPropertyAsInterface("baseURI", Ci.nsIURI);
haveProp = true;
} catch (e) {
if (e.result != Cr.NS_ERROR_NOT_AVAILABLE) {
@ -28,7 +26,5 @@ function run_test() {
}
Assert.equal(propVal, null);
Assert.equal(haveProp, false);
Assert.equal(chan2.getPropertyAsInterface("baseURI",
Ci.nsIURI),
base);
Assert.equal(chan2.getPropertyAsInterface("baseURI", Ci.nsIURI), base);
}

View file

@ -4,12 +4,13 @@
var CC = Components.Constructor;
const ServerSocket = CC("@mozilla.org/network/server-socket;1",
"nsIServerSocket",
"init");
const ServerSocket = CC(
"@mozilla.org/network/server-socket;1",
"nsIServerSocket",
"init"
);
function testAddrInUse()
{
function testAddrInUse() {
// Windows lets us have as many sockets listening on the same address as
// we like, evidently.
if (mozinfo.os == "win") {
@ -22,11 +23,12 @@ function testAddrInUse()
Assert.ok(listener instanceof Ci.nsIServerSocket);
// Try to create another listening socket on the same port, whatever that was.
do_check_throws_nsIException(() => ServerSocket(listener.port, true, -1),
"NS_ERROR_SOCKET_ADDRESS_IN_USE");
do_check_throws_nsIException(
() => ServerSocket(listener.port, true, -1),
"NS_ERROR_SOCKET_ADDRESS_IN_USE"
);
}
function run_test()
{
function run_test() {
testAddrInUse();
}

View file

@ -10,7 +10,7 @@
* - again we receive the data from the server.
*/
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
XPCOMUtils.defineLazyGetter(this, "URL", function() {
return "http://localhost:" + httpServer.identity.primaryPort + "/content";
@ -19,21 +19,24 @@ XPCOMUtils.defineLazyGetter(this, "URL", function() {
var httpServer = null;
// needs to be rooted
var cacheFlushObserver = cacheFlushObserver = { observe() {
cacheFlushObserver = null;
readServerContentAgain();
}};
var cacheFlushObserver = (cacheFlushObserver = {
observe() {
cacheFlushObserver = null;
readServerContentAgain();
},
});
var currentThread = null;
function make_channel(url, callback, ctx) {
return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
}
function inChildProcess() {
return Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULRuntime)
.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
return (
Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
);
}
const responseContent = "response body";
@ -46,15 +49,14 @@ var shouldPassRevalidation = true;
var cache_storage = null;
function contentHandler(metadata, response)
{
function contentHandler(metadata, response) {
response.setHeader("Content-Type", "text/plain");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("ETag", "test-etag1");
try {
var etag = metadata.getHeader("If-None-Match");
} catch(ex) {
} catch (ex) {
var etag = "";
}
@ -67,8 +69,7 @@ function contentHandler(metadata, response)
}
}
function check_has_alt_data_in_index(aHasAltData)
{
function check_has_alt_data_in_index(aHasAltData) {
if (inChildProcess()) {
return;
}
@ -77,8 +78,7 @@ function check_has_alt_data_in_index(aHasAltData)
Assert.equal(hasAltData.value, aHasAltData);
}
function run_test()
{
function run_test() {
do_get_profile();
httpServer = new HttpServer();
httpServer.registerPathHandler("/content", contentHandler);
@ -86,15 +86,14 @@ function run_test()
do_test_pending();
if (!inChildProcess()) {
cache_storage = getCacheStorage("disk") ;
cache_storage = getCacheStorage("disk");
wait_for_cache_index(asyncOpen);
} else {
asyncOpen();
}
}
function asyncOpen()
{
function asyncOpen() {
var chan = make_channel(URL);
var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
@ -103,8 +102,7 @@ function asyncOpen()
chan.asyncOpen(new ChannelListener(readServerContent, null));
}
function readServerContent(request, buffer)
{
function readServerContent(request, buffer) {
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
Assert.equal(buffer, responseContent);
@ -119,23 +117,29 @@ function readServerContent(request, buffer)
var os = cc.openAlternativeOutputStream(altContentType, altContent.length);
var aos = os.QueryInterface(Ci.nsIAsyncOutputStream);
aos.asyncWait(_ => {
os.write(altContent, altContent.length);
aos.closeWithStatus(Cr.NS_ERROR_FAILURE);
executeSoon(flushAndReadServerContentAgain);
}, 0, 0, currentThread);
aos.asyncWait(
_ => {
os.write(altContent, altContent.length);
aos.closeWithStatus(Cr.NS_ERROR_FAILURE);
executeSoon(flushAndReadServerContentAgain);
},
0,
0,
currentThread
);
});
}
function flushAndReadServerContentAgain()
{
function flushAndReadServerContentAgain() {
// We need to do a GC pass to ensure the cache entry has been freed.
gc();
if (!inChildProcess()) {
Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver);
Services.cache2
.QueryInterface(Ci.nsICacheTesting)
.flush(cacheFlushObserver);
} else {
do_send_remote_message('flush');
do_await_remote_message('flushed').then(() => {
do_send_remote_message("flush");
do_await_remote_message("flushed").then(() => {
readServerContentAgain();
});
}
@ -151,8 +155,7 @@ function readServerContentAgain() {
chan.asyncOpen(new ChannelListener(readServerContentAgainCB, null));
}
function readServerContentAgainCB(request, buffer)
{
function readServerContentAgainCB(request, buffer) {
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
Assert.equal(buffer, responseContent);

View file

@ -9,7 +9,7 @@
* - this time the alt data must arive
*/
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
XPCOMUtils.defineLazyGetter(this, "URL", function() {
return "http://localhost:" + httpServer.identity.primaryPort + "/content";
@ -18,13 +18,14 @@ XPCOMUtils.defineLazyGetter(this, "URL", function() {
var httpServer = null;
function make_channel(url, callback, ctx) {
return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
}
function inChildProcess() {
return Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULRuntime)
.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
return (
Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
);
}
const responseContent = "response body";
@ -37,15 +38,14 @@ var shouldPassRevalidation = true;
var cache_storage = null;
function contentHandler(metadata, response)
{
function contentHandler(metadata, response) {
response.setHeader("Content-Type", "text/plain");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("ETag", "test-etag1");
try {
var etag = metadata.getHeader("If-None-Match");
} catch(ex) {
} catch (ex) {
var etag = "";
}
@ -58,8 +58,7 @@ function contentHandler(metadata, response)
}
}
function check_has_alt_data_in_index(aHasAltData)
{
function check_has_alt_data_in_index(aHasAltData) {
if (inChildProcess()) {
return;
}
@ -68,8 +67,7 @@ function check_has_alt_data_in_index(aHasAltData)
Assert.equal(hasAltData.value, aHasAltData);
}
function run_test()
{
function run_test() {
httpServer = new HttpServer();
httpServer.registerPathHandler("/content", contentHandler);
httpServer.start(-1);
@ -78,8 +76,7 @@ function run_test()
asyncOpen();
}
function asyncOpen()
{
function asyncOpen() {
var chan = make_channel(URL);
var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
@ -88,8 +85,7 @@ function asyncOpen()
chan.asyncOpen(new ChannelListener(readServerContent, null));
}
function readServerContent(request, buffer)
{
function readServerContent(request, buffer) {
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
Assert.equal(buffer, responseContent);
@ -105,12 +101,11 @@ function readServerContent(request, buffer)
});
}
function flushAndOpenAltChannel()
{
function flushAndOpenAltChannel() {
// We need to do a GC pass to ensure the cache entry has been freed.
gc();
do_send_remote_message('flush');
do_await_remote_message('flushed').then(() => {
do_send_remote_message("flush");
do_await_remote_message("flushed").then(() => {
openAltChannel();
});
}
@ -123,8 +118,7 @@ function openAltChannel() {
chan.asyncOpen(new ChannelListener(readAltContent, null));
}
function readAltContent(request, buffer)
{
function readAltContent(request, buffer) {
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
Assert.equal(servedNotModified, true);
@ -132,8 +126,8 @@ function readAltContent(request, buffer)
Assert.equal(buffer, altContent);
// FINISH
do_send_remote_message('done');
do_await_remote_message('finish').then(() => {
do_send_remote_message("done");
do_await_remote_message("finish").then(() => {
httpServer.stop(do_test_finished);
});
}

View file

@ -12,7 +12,7 @@
* - readAltContent3 checks that it gets back the newly saved alt-data
*/
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
XPCOMUtils.defineLazyGetter(this, "URL", function() {
return "http://localhost:" + httpServer.identity.primaryPort + "/content";
@ -21,7 +21,7 @@ XPCOMUtils.defineLazyGetter(this, "URL", function() {
let httpServer = null;
function make_and_open_channel(url, altContentType, callback) {
let chan = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
let chan = NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
if (altContentType) {
let cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
cc.preferAlternativeDataType(altContentType, "", true);
@ -37,15 +37,14 @@ const altContentType2 = "text/binary2";
let servedNotModified = false;
function contentHandler(metadata, response)
{
function contentHandler(metadata, response) {
response.setHeader("Content-Type", "text/plain");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("ETag", "test-etag1");
let etag = ""
let etag = "";
try {
etag = metadata.getHeader("If-None-Match");
} catch(ex) {
} catch (ex) {
etag = "";
}
@ -58,8 +57,7 @@ function contentHandler(metadata, response)
}
}
function run_test()
{
function run_test() {
do_get_profile();
httpServer = new HttpServer();
httpServer.registerPathHandler("/content", contentHandler);
@ -69,8 +67,7 @@ function run_test()
make_and_open_channel(URL, altContentType, readServerContent);
}
function readServerContent(request, buffer)
{
function readServerContent(request, buffer) {
let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
Assert.equal(buffer, responseContent);
@ -85,26 +82,26 @@ function readServerContent(request, buffer)
});
}
function flushAndOpenAltChannel()
{
function flushAndOpenAltChannel() {
// We need to do a GC pass to ensure the cache entry has been freed.
Cu.forceShrinkingGC();
Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver);
}
// needs to be rooted
let cacheFlushObserver = { observe() {
if (!cacheFlushObserver) {
info("ignoring cacheFlushObserver\n");
return;
}
cacheFlushObserver = null;
Cu.forceShrinkingGC();
make_and_open_channel(URL, altContentType, readAltContent);
}};
let cacheFlushObserver = {
observe() {
if (!cacheFlushObserver) {
info("ignoring cacheFlushObserver\n");
return;
}
cacheFlushObserver = null;
Cu.forceShrinkingGC();
make_and_open_channel(URL, altContentType, readAltContent);
},
};
function readAltContent(request, buffer, closure, fromCache)
{
function readAltContent(request, buffer, closure, fromCache) {
Cu.forceShrinkingGC();
let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
@ -115,8 +112,7 @@ function readAltContent(request, buffer, closure, fromCache)
make_and_open_channel(URL, "dummy/null", readServerContent2);
}
function readServerContent2(request, buffer, closure, fromCache)
{
function readServerContent2(request, buffer, closure, fromCache) {
Cu.forceShrinkingGC();
let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
@ -133,26 +129,26 @@ function readServerContent2(request, buffer, closure, fromCache)
});
}
function flushAndOpenAltChannel2()
{
function flushAndOpenAltChannel2() {
// We need to do a GC pass to ensure the cache entry has been freed.
Cu.forceShrinkingGC();
Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver2);
}
// needs to be rooted
let cacheFlushObserver2 = { observe() {
if (!cacheFlushObserver2) {
info("ignoring cacheFlushObserver2\n");
return;
}
cacheFlushObserver2 = null;
Cu.forceShrinkingGC();
make_and_open_channel(URL, altContentType, readAltContent2);
}};
let cacheFlushObserver2 = {
observe() {
if (!cacheFlushObserver2) {
info("ignoring cacheFlushObserver2\n");
return;
}
cacheFlushObserver2 = null;
Cu.forceShrinkingGC();
make_and_open_channel(URL, altContentType, readAltContent2);
},
};
function readAltContent2(request, buffer, closure, fromCache)
{
function readAltContent2(request, buffer, closure, fromCache) {
Cu.forceShrinkingGC();
let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
@ -163,7 +159,10 @@ function readAltContent2(request, buffer, closure, fromCache)
executeSoon(() => {
Cu.forceShrinkingGC();
info("writing other content\n");
let os = cc.openAlternativeOutputStream(altContentType2, altContent2.length);
let os = cc.openAlternativeOutputStream(
altContentType2,
altContent2.length
);
os.write(altContent2, altContent2.length);
os.close();
@ -171,28 +170,27 @@ function readAltContent2(request, buffer, closure, fromCache)
});
}
function flushAndOpenAltChannel3()
{
function flushAndOpenAltChannel3() {
// We need to do a GC pass to ensure the cache entry has been freed.
Cu.forceShrinkingGC();
Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver3);
}
// needs to be rooted
let cacheFlushObserver3 = { observe() {
if (!cacheFlushObserver3) {
info("ignoring cacheFlushObserver3\n");
return;
}
let cacheFlushObserver3 = {
observe() {
if (!cacheFlushObserver3) {
info("ignoring cacheFlushObserver3\n");
return;
}
cacheFlushObserver3 = null;
Cu.forceShrinkingGC();
make_and_open_channel(URL, altContentType2, readAltContent3);
}};
cacheFlushObserver3 = null;
Cu.forceShrinkingGC();
make_and_open_channel(URL, altContentType2, readAltContent3);
},
};
function readAltContent3(request, buffer, closure, fromCache)
{
function readAltContent3(request, buffer, closure, fromCache) {
let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
Assert.equal(servedNotModified || fromCache, true);

View file

@ -9,7 +9,7 @@
* - this time the alt data must arive
*/
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
XPCOMUtils.defineLazyGetter(this, "URL", function() {
return "http://localhost:" + httpServer.identity.primaryPort + "/content";
@ -18,13 +18,14 @@ XPCOMUtils.defineLazyGetter(this, "URL", function() {
var httpServer = null;
function make_channel(url, callback, ctx) {
return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
}
function inChildProcess() {
return Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULRuntime)
.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
return (
Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
);
}
const responseContent = "response body";
@ -37,15 +38,14 @@ var shouldPassRevalidation = true;
var cache_storage = null;
function contentHandler(metadata, response)
{
function contentHandler(metadata, response) {
response.setHeader("Content-Type", "text/plain");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("ETag", "test-etag1");
try {
var etag = metadata.getHeader("If-None-Match");
} catch(ex) {
} catch (ex) {
var etag = "";
}
@ -58,8 +58,7 @@ function contentHandler(metadata, response)
}
}
function check_has_alt_data_in_index(aHasAltData)
{
function check_has_alt_data_in_index(aHasAltData) {
if (inChildProcess()) {
return;
}
@ -68,8 +67,7 @@ function check_has_alt_data_in_index(aHasAltData)
Assert.equal(hasAltData.value, aHasAltData);
}
function run_test()
{
function run_test() {
do_get_profile();
httpServer = new HttpServer();
httpServer.registerPathHandler("/content", contentHandler);
@ -77,15 +75,14 @@ function run_test()
do_test_pending();
if (!inChildProcess()) {
cache_storage = getCacheStorage("disk") ;
cache_storage = getCacheStorage("disk");
wait_for_cache_index(asyncOpen);
} else {
asyncOpen();
}
}
function asyncOpen()
{
function asyncOpen() {
var chan = make_channel(URL);
var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
@ -94,8 +91,7 @@ function asyncOpen()
chan.asyncOpen(new ChannelListener(readServerContent, null));
}
function readServerContent(request, buffer)
{
function readServerContent(request, buffer) {
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
Assert.equal(buffer, responseContent);
@ -112,20 +108,23 @@ function readServerContent(request, buffer)
}
// needs to be rooted
var cacheFlushObserver = cacheFlushObserver = { observe() {
cacheFlushObserver = null;
openAltChannel();
}};
var cacheFlushObserver = (cacheFlushObserver = {
observe() {
cacheFlushObserver = null;
openAltChannel();
},
});
function flushAndOpenAltChannel()
{
function flushAndOpenAltChannel() {
// We need to do a GC pass to ensure the cache entry has been freed.
gc();
if (!inChildProcess()) {
Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver);
Services.cache2
.QueryInterface(Ci.nsICacheTesting)
.flush(cacheFlushObserver);
} else {
do_send_remote_message('flush');
do_await_remote_message('flushed').then(() => {
do_send_remote_message("flush");
do_await_remote_message("flushed").then(() => {
openAltChannel();
});
}
@ -141,8 +140,7 @@ function openAltChannel() {
chan.asyncOpen(new ChannelListener(readAltContent, null));
}
function readAltContent(request, buffer)
{
function readAltContent(request, buffer) {
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
Assert.equal(servedNotModified, true);
@ -153,12 +151,11 @@ function readAltContent(request, buffer)
cc.getOriginalInputStream({
onInputStreamReady(aInputStream) {
executeSoon(() => readOriginalInputStream(aInputStream));
}
},
});
}
function readOriginalInputStream(aInputStream)
{
function readOriginalInputStream(aInputStream) {
// We expect the async stream length to match the expected content.
// If the test times out, it's probably because of this.
try {
@ -171,8 +168,7 @@ function readOriginalInputStream(aInputStream)
}
}
function requestAgain()
{
function requestAgain() {
shouldPassRevalidation = false;
var chan = make_channel(URL);
var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
@ -180,8 +176,7 @@ function requestAgain()
chan.asyncOpen(new ChannelListener(readEmptyAltContent, null));
}
function readEmptyAltContent(request, buffer)
{
function readEmptyAltContent(request, buffer) {
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
// the cache is overwrite and the alt-data is reset

View file

@ -11,7 +11,7 @@
*
*/
const {HttpServer} = ChromeUtils.import("resource://testing-common/httpd.js");
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
XPCOMUtils.defineLazyGetter(this, "URL", function() {
return "http://localhost:" + httpServer.identity.primaryPort + "/content";
@ -20,36 +20,35 @@ XPCOMUtils.defineLazyGetter(this, "URL", function() {
var httpServer = null;
function make_channel(url) {
return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
}
const responseContent = "response body";
// We need a large content in order to make sure that the IPDL stream is cut
// into several different chunks.
// We fill each chunk with a different character for easy debugging.
const altContent = "a".repeat(128*1024) +
"b".repeat(128*1024) +
"c".repeat(128*1024) +
"d".repeat(128*1024) +
"e".repeat(128*1024) +
"f".repeat(128*1024) +
"g".repeat(128*1024) +
"h".repeat(128*1024) +
"i".repeat(13); // Just so the chunk size doesn't match exactly.
const altContent =
"a".repeat(128 * 1024) +
"b".repeat(128 * 1024) +
"c".repeat(128 * 1024) +
"d".repeat(128 * 1024) +
"e".repeat(128 * 1024) +
"f".repeat(128 * 1024) +
"g".repeat(128 * 1024) +
"h".repeat(128 * 1024) +
"i".repeat(13); // Just so the chunk size doesn't match exactly.
const firstChunkSize = Math.floor(altContent.length / 4);
const altContentType = "text/binary";
function contentHandler(metadata, response)
{
function contentHandler(metadata, response) {
response.setHeader("Content-Type", "text/plain");
response.setHeader("Cache-Control", "max-age=86400");
response.bodyOutputStream.write(responseContent, responseContent.length);
}
function run_test()
{
function run_test() {
do_get_profile();
httpServer = new HttpServer();
httpServer.registerPathHandler("/content", contentHandler);
@ -67,8 +66,7 @@ function run_test()
// Output stream used to write alt-data to the cache entry.
var os;
function readServerContent(request, buffer)
{
function readServerContent(request, buffer) {
var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
Assert.equal(buffer, responseContent);
@ -83,8 +81,7 @@ function readServerContent(request, buffer)
});
}
function openAltChannel()
{
function openAltChannel() {
var chan = make_channel(URL);
var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
cc.preferAlternativeDataType(altContentType, "", true);
@ -94,7 +91,7 @@ function openAltChannel()
var altDataListener = {
buffer: "",
onStartRequest(request) { },
onStartRequest(request) {},
onDataAvailable(request, stream, offset, count) {
let string = NetUtil.readInputStreamToString(stream, count);
this.buffer += string;
@ -104,7 +101,10 @@ var altDataListener = {
// data in the first chunk.
if (this.buffer.length == firstChunkSize) {
// write the rest of the content
os.write(altContent.substring(firstChunkSize, altContent.length), altContent.length - firstChunkSize);
os.write(
altContent.substring(firstChunkSize, altContent.length),
altContent.length - firstChunkSize
);
os.close();
}
},
@ -117,8 +117,7 @@ var altDataListener = {
},
};
function openAltChannelWithOriginalContent()
{
function openAltChannelWithOriginalContent() {
var chan = make_channel(URL);
var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
cc.preferAlternativeDataType(altContentType, "", false);
@ -128,7 +127,7 @@ function openAltChannelWithOriginalContent()
var originalListener = {
buffer: "",
onStartRequest(request) { },
onStartRequest(request) {},
onDataAvailable(request, stream, offset, count) {
let string = NetUtil.readInputStreamToString(stream, count);
this.buffer += string;
@ -142,12 +141,11 @@ var originalListener = {
},
};
function testAltDataStream(cc)
{
function testAltDataStream(cc) {
cc.getAltDataInputStream(altContentType, {
onInputStreamReady(aInputStream) {
Assert.ok(!!aInputStream);
httpServer.stop(do_test_finished);
}
},
});
}

Some files were not shown because too many files have changed in this diff Show more