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
@ -19,8 +17,11 @@ const PR_UINT32_MAX = 0xffffffff;
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
@ -43,8 +44,7 @@ var NetUtil = {
* can be used to cancel the copying). The consumer can ignore the
* return value if desired.
*/
asyncCopy: function NetUtil_asyncCopy(aSource, aSink,
aCallback = null) {
asyncCopy: function NetUtil_asyncCopy(aSource, aSink, aCallback = null) {
if (!aSource || !aSink) {
let exception = new Components.Exception(
"Must have a source and a sink",
@ -55,12 +55,17 @@ var NetUtil = {
}
// make a stream copier
var copier = Cc["@mozilla.org/network/async-stream-copier;1"].
createInstance(Ci.nsIAsyncStreamCopier2);
copier.init(aSource, aSink,
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 */);
true,
true /* Auto-close */
);
var observer;
if (aCallback) {
@ -109,13 +114,13 @@ var NetUtil = {
// 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);
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);
let listener = Cc[
"@mozilla.org/network/simple-stream-listener;1"
].createInstance(Ci.nsISimpleStreamListener);
listener.init(pipe.outputStream, {
onStartRequest(aRequest) {},
onStopRequest(aRequest, aStatusCode) {
@ -126,8 +131,9 @@ var NetUtil = {
// 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);
let pump = Cc["@mozilla.org/network/input-stream-pump;1"].createInstance(
Ci.nsIInputStreamPump
);
pump.init(aSource, 0, 0, true);
pump.asyncRead(listener, null);
return;
@ -226,13 +232,15 @@ var NetUtil = {
);
}
let { uri,
let {
uri,
loadingNode,
loadingPrincipal,
loadUsingSystemPrincipal,
triggeringPrincipal,
securityFlags,
contentPolicyType } = aWhatToLoad;
contentPolicyType,
} = aWhatToLoad;
if (!uri) {
throw new Components.Exception(
@ -266,8 +274,7 @@ var NetUtil = {
Components.stack.caller
);
}
loadingPrincipal = Services.scriptSecurityManager
.getSystemPrincipal();
loadingPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
} else if (loadUsingSystemPrincipal !== undefined) {
throw new Components.Exception(
"newChannel requires the 'loadUsingSystemPrincipal'" +
@ -301,12 +308,14 @@ var NetUtil = {
contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
}
return Services.io.newChannelFromURI(uri,
return Services.io.newChannelFromURI(
uri,
loadingNode || null,
loadingPrincipal || null,
triggeringPrincipal || null,
securityFlags,
contentPolicyType);
contentPolicyType
);
},
/**
@ -332,9 +341,11 @@ var NetUtil = {
* aCount amount of data.
* @throws NS_ERROR_ILLEGAL_INPUT if aInputStream has invalid sequences
*/
readInputStreamToString: function NetUtil_readInputStreamToString(aInputStream,
readInputStreamToString: function NetUtil_readInputStreamToString(
aInputStream,
aCount,
aOptions) {
aOptions
) {
if (!(aInputStream instanceof Ci.nsIInputStream)) {
let exception = new Components.Exception(
"First argument should be an nsIInputStream",
@ -354,8 +365,9 @@ var NetUtil = {
}
if (aOptions && "charset" in aOptions) {
let cis = Cc["@mozilla.org/intl/converter-input-stream;1"].
createInstance(Ci.nsIConverterInputStream);
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.
@ -366,28 +378,36 @@ var NetUtil = {
aOptions.replacement = 0;
}
cis.init(aInputStream, aOptions.charset, aCount,
aOptions.replacement);
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);
throw new Components.Exception(
e.message,
e.result,
Components.stack.caller,
e.data
);
}
}
let sis = Cc["@mozilla.org/scriptableinputstream;1"].
createInstance(Ci.nsIScriptableInputStream);
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);
throw new Components.Exception(
e.message,
e.result,
Components.stack.caller,
e.data
);
}
},

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,15 +2,25 @@ 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 => {
await content
.fetch("server.sjs")
.then(r => r.text())
.then(text => {
is(text, "cookie-present", "We should have cookies");
});
@ -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 => {
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 => {
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

@ -30,9 +30,10 @@ async function openTabInUserContext(uri, userContextId) {
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
);
});
});
@ -43,13 +44,15 @@ add_task(async function test() {
// open our tab in the given user context
let { tab, browser } = await openTabInUserContext(TEST_URL, userContextId);
await ContentTask.spawn(browser,
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);
@ -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;
}

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(
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));
_ => {
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,7 +20,8 @@ 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,
this._createTest(
testName,
config.cookieJarAccessAllowed,
config.cookieJarAccessDenied,
config.prefs,
@ -29,10 +30,12 @@ this.CookiePolicyHelper = {
toBehavior: BEHAVIOR_REJECT,
fromPermission: PERM_DEFAULT,
toPermission: PERM_DEFAULT,
});
}
);
// Testing blocked to allowed by cookie behavior
this._createTest(testName,
this._createTest(
testName,
config.cookieJarAccessDenied,
config.cookieJarAccessAllowed,
config.prefs,
@ -41,10 +44,12 @@ this.CookiePolicyHelper = {
toBehavior: BEHAVIOR_ACCEPT,
fromPermission: PERM_DEFAULT,
toPermission: PERM_DEFAULT,
});
}
);
// Testing allowed to blocked by cookie permission
this._createTest(testName,
this._createTest(
testName,
config.cookieJarAccessAllowed,
config.cookieJarAccessDenied,
config.prefs,
@ -53,10 +58,12 @@ this.CookiePolicyHelper = {
toBehavior: BEHAVIOR_REJECT,
fromPermission: PERM_ALLOW,
toPermission: PERM_DEFAULT,
});
}
);
// Testing blocked to allowed by cookie permission
this._createTest(testName,
this._createTest(
testName,
config.cookieJarAccessDenied,
config.cookieJarAccessAllowed,
config.prefs,
@ -65,7 +72,8 @@ this.CookiePolicyHelper = {
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,8 +113,14 @@ 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,
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});})();`;
@ -116,17 +129,24 @@ this.CookiePolicyHelper = {
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,
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});})();`;
@ -135,7 +155,8 @@ this.CookiePolicyHelper = {
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,
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 |
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, ___ => {
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

@ -2,8 +2,7 @@ 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

@ -7,14 +7,16 @@ 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 (" +
conn.executeSimpleSQL(
"CREATE TABLE moz_cookies (" +
"id INTEGER PRIMARY KEY, " +
"baseDomain TEXT, " +
"originAttributes TEXT NOT NULL DEFAULT '', " +
@ -30,29 +32,41 @@ conn.executeSimpleSQL("CREATE TABLE moz_cookies (" +
"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 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(" +
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 +
", " +
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 " +
let stmt = conn.createStatement(
"SELECT sql FROM sqlite_master " +
"WHERE type = 'table' AND " +
" name = 'moz_cookies'");
" 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 " +
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 " +
" expiry = " +
now +
" AND " +
" lastAccessed = " +
now +
" AND " +
" creationTime = " +
now +
" AND " +
" isSecure = 1 AND " +
" isHttpOnly = 1");
" isHttpOnly = 1"
);
try {
Assert.ok(stmt.executeStep());
} finally {

View file

@ -23,4 +23,3 @@ function run_test() {
actual = cs.getCookieString(uri, null, null);
Assert.equal(actual, expected);
}

View file

@ -29,50 +29,80 @@ async function test_basic_eviction(base_host) {
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",
verifyCookies(
[
"session_foo_path_1",
"session_foo_path_2",
"session_foo_path_3",
"session_foo_path_4",
"session_foo_path_5"], BASE_URI);
"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);
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);
verifyCookies(["session_foo_path_4",
verifyCookies(
[
"session_foo_path_4",
"session_foo_path_5",
"session_foo_path_6",
"session_bar_path_1",
"session_bar_path_2"], BASE_URI);
"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);
verifyCookies(
["session_foo_path_5", "session_foo_path_6", "session_foo_path_7"],
BASE_URI
);
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",
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);
"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);
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
@ -84,15 +114,23 @@ function verifyCookies(names, uri) {
}
if (names.length != actual_cookies.length) {
let left = names.filter(function(n) {
return actual_cookies.findIndex(function(c) {
return (
actual_cookies.findIndex(function(c) {
return c.name == n;
}) == -1;
}) == -1
);
});
let right = actual_cookies.filter(function(c) {
return names.findIndex(function(n) {
let right = actual_cookies
.filter(function(c) {
return (
names.findIndex(function(n) {
return c.name == n;
}) == -1;
}).map(function(c) { return c.name; });
}) == -1
);
})
.map(function(c) {
return c.name;
});
if (left.length) {
info("unexpected cookies: " + left);
}
@ -102,10 +140,12 @@ function verifyCookies(names, uri) {
}
Assert.equal(names.length, actual_cookies.length);
actual_cookies.sort(function(a, b) {
if (a.lastAccessed < b.lastAccessed)
if (a.lastAccessed < b.lastAccessed) {
return -1;
if (a.lastAccessed > b.lastAccessed)
}
if (a.lastAccessed > b.lastAccessed) {
return 1;
}
return 0;
});
for (var i = 0; i < names.length; i++) {

View file

@ -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

@ -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

@ -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 { 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"))
AppConstants.platform == "android" &&
!Services.prefs.getBoolPref("network.mdns.use_js_fallback")
? "resource://gre/modules/MulticastDNSAndroid.jsm"
: "resource://gre/modules/MulticastDNS.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) {
@ -56,8 +70,9 @@ ListenerWrapper.prototype = {
} 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);
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: {},
@ -148,8 +154,8 @@ function parsePropertyBag2(bag) {
for (let { name } of bag.enumerator) {
let value = bag.getPropertyAsACString(name);
attributes.push({
"name": name,
"value": value,
name,
value,
});
}

View file

@ -10,10 +10,18 @@ var EXPORTED_SYMBOLS = ["DNSPacket"];
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;
@ -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());
});
});
@ -223,11 +235,11 @@ class DNSPacket {
toJSONObject() {
let result = { flags: this._flags };
DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
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,8 +8,12 @@
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 = {}) {
@ -23,7 +27,7 @@ class DNSRecord {
let name = reader.getLabel();
let recordType = reader.getValue(2);
let classCode = reader.getValue(2);
let cacheFlush = !!((classCode & 0x8000));
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
@ -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;

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);

View file

@ -9,17 +9,31 @@
var EXPORTED_SYMBOLS = ["MulticastDNS"];
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {clearTimeout, setTimeout} = ChromeUtils.import("resource://gre/modules/Timer.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;
@ -32,9 +46,18 @@ function debug(msg) {
}
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() {
@ -111,7 +136,13 @@ class MulticastDNS {
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,7 +337,8 @@ class MulticastDNS {
return;
}
DEBUG && debug("_respondToQuery(): key=" + serviceKey + ": SENDING RESPONSE");
DEBUG &&
debug("_respondToQuery(): key=" + serviceKey + ": SENDING RESPONSE");
this._advertiseServiceHelper(publishedService, { address, port });
}
@ -285,7 +346,11 @@ class MulticastDNS {
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;
}
@ -310,7 +375,7 @@ class MulticastDNS {
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;
}
@ -375,8 +442,16 @@ class MulticastDNS {
// 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({
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,17 +548,23 @@ 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({
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({
packet.addRecord(
"AR",
new DNSResourceRecord({
name: serviceDomainName,
recordType: DNS_RECORD_TYPES.SRV,
classCode: DNS_CLASS_CODES.IN,
@ -486,25 +575,32 @@ class MulticastDNS {
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({
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,13 +632,13 @@ 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;
@ -553,7 +649,9 @@ class MulticastDNS {
return;
}
let { serviceName, serviceType, domainName } = _parseServiceDomainName(name);
let { serviceName, serviceType, domainName } = _parseServiceDomainName(
name
);
if (!serviceName || !serviceType || !domainName) {
return;
}
@ -579,11 +677,16 @@ class MulticastDNS {
}
_onServiceFound(serviceInfo, ttl = 0) {
let expireTime = Date.now() + (ttl * 1000);
let key = serviceInfo.serviceName + "." +
serviceInfo.serviceType + "." +
serviceInfo.domainName + " @" +
serviceInfo.address + ":" +
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
@ -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, {
this._broadcastReceiverSocket = _openSocket(
"0.0.0.0",
MDNS_PORT,
{
onPacketReceived: this._onPacketReceived.bind(this),
onStopListening: this._onStopListening.bind(this),
}, /* multicastInterface = */ "0.0.0.0");
},
/* 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
_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.
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

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

View file

@ -6,34 +6,41 @@
var EXPORTED_SYMBOLS = ["UserAgentOverrides"];
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.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 { 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 { 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 { 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) => {
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 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) => {
}, 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);
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) => {
})
.then(update => {
// Apply update if loading was successful
this._applyUpdate(update);
}).catch(Cu.reportError);
})
.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(
() => {
OS.File.writeAtomic(path, bytes, { tmpPath: path + ".tmp" }).then(() => {
this._lastUpdated = Date.now();
Services.prefs.setCharPref(
PREF_UPDATES_LASTUPDATED, this._lastUpdated.toString());
},
Cu.reportError
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
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
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

@ -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({
NetUtil.asyncFetch(
{
uri: "https://untrusted.example.com",
loadUsingSystemPrincipal: true
}, 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 again with a channel whose notificationCallbacks doesn't suprress errors
let channel = NetUtil.newChannel({
uri: "https://untrusted.example.com",
loadUsingSystemPrincipal: true});
loadUsingSystemPrincipal: true,
});
channel.notificationCallbacks = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIProgressEventSink,
Ci.nsIInterfaceRequestor]),
getInterface (aIID) { return this.QueryInterface(aIID); },
QueryInterface: ChromeUtils.generateQI([
Ci.nsIProgressEventSink,
Ci.nsIInterfaceRequestor,
]),
getInterface(aIID) {
return this.QueryInterface(aIID);
},
onProgress() {},
onStatus () {}
onStatus() {},
};
NetUtil.asyncFetch(channel, function (aInputStream, aStatusCode, aRequest) {
NetUtil.asyncFetch(channel, function(
aInputStream,
aStatusCode,
aRequest
) {
ok(!Components.isSuccessCode(aStatusCode), "request failed");
ok(aRequest instanceof Ci.nsIHttpChannel, "request is an nsIHttpChannel");
ok(
aRequest instanceof Ci.nsIHttpChannel,
"request is an nsIHttpChannel"
);
// Now try a valid request
NetUtil.asyncFetch({
NetUtil.asyncFetch(
{
uri: "https://example.com",
loadUsingSystemPrincipal: true
}, function (aInputStream, aStatusCode, aRequest) {
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 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)
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});
},
{ once: true }
);
},
onCloseWindow(aXULWindow) {},
}
};

View file

@ -4,27 +4,47 @@
* 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");
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) {
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);
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, "",
};
registrar.registerFactory(
childListener.classID,
"",
"@mozilla.org/network/childProcessChannelListener;1",
childListener);
});
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,8 +163,9 @@ 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 = {
@ -175,7 +179,7 @@ document.getElementById('form').submit();
try {
aListener.onStopRequest(this, null, Cr.NS_OK);
} catch (e) {}
}
},
};
Services.tm.dispatchToMainThread(runnable);
},
@ -192,7 +196,8 @@ document.getElementById('form').submit();
},
cancel(status) {},
loadGroup: null,
loadFlags: Ci.nsIRequest.LOAD_NORMAL |
loadFlags:
Ci.nsIRequest.LOAD_NORMAL |
Ci.nsIRequest.INHIBIT_CACHING |
Ci.nsIRequest.LOAD_BYPASS_CACHE,
};
@ -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, "",
registrar.registerFactory(
handler.classID,
"",
"@mozilla.org/network/protocol;1?name=" + handler.scheme,
handler);
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

@ -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,10 +8,14 @@
add_task(async function() {
info("Make sure navigation through links in resource:// pages work");
await BrowserTestUtils.withNewTab({ gBrowser, url: "resource://gre/" }, async function(browser) {
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 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.
@ -19,35 +23,54 @@ add_task(async function() {
name = name.slice(0, -1);
}
return name == "components";
})[0];
}
)[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];
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) {
let link = Array.prototype.filter.call(
content.document.getElementsByClassName("file"),
function(element) {
return element.textContent == "greprefs.js";
})[0];
}
)[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!");
});
}
);
});

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";
@ -17,18 +19,16 @@ var gotEmptyData = false;
function processResults(results) {
for (let data of results) {
console.log(data.location);
gotEmptyData = data.rx == 0 && data.tx == 0 && !gotEmptyData
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],
]
set: [["io.activity.enabled", true]],
});
waitForExplicitFinish();
Services.obs.notifyObservers(null, "profile-initial-state");

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,9 @@ 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 { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
var { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
/**
@ -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,15 +110,19 @@ 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) {
throw new Error(
@ -148,9 +159,10 @@ function writeDetails(request, response) {
*/
function skipHeaders(iter) {
var line = iter.next().value;
while (line !== "")
while (line !== "") {
line = iter.next().value;
}
}
/**
* Checks that the exception e (which may be an XPConnect-created exception
@ -162,9 +174,10 @@ 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);
}
}
/**
* Calls the given function at least the specified number of milliseconds later.
@ -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();
});
};
}
@ -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,8 +285,7 @@ function runHttpTests(testArray, done) {
var testIndex = -1;
/** Stream listener for the channels. */
var listener =
{
var listener = {
/** Current channel being observed by this. */
_channel: null,
/** Array of bytes of data in body of response. */
@ -277,7 +293,8 @@ function runHttpTests(testArray, done) {
onStartRequest(request) {
Assert.ok(request === this._channel);
var ch = request.QueryInterface(Ci.nsIHttpChannel)
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
this._data.length = 0;
@ -285,11 +302,17 @@ function runHttpTests(testArray, done) {
try {
testArray[testIndex].onStartRequest(ch);
} catch (e) {
do_report_unexpected_exception(e, "testArray[" + testIndex + "].onStartRequest");
do_report_unexpected_exception(
e,
"testArray[" + testIndex + "].onStartRequest"
);
}
} catch (e) {
do_note_exception(e, "!!! swallowing onStartRequest exception so onStopRequest is " +
"called...");
do_note_exception(
e,
"!!! swallowing onStartRequest exception so onStopRequest is " +
"called..."
);
}
},
onDataAvailable(request, inputStream, offset, count) {
@ -303,7 +326,8 @@ function runHttpTests(testArray, done) {
onStopRequest(request, status) {
this._channel = null;
var ch = request.QueryInterface(Ci.nsIHttpChannel)
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
// NB: The onStopRequest callback must run before performNextTest here,
@ -320,13 +344,15 @@ function runHttpTests(testArray, done) {
}
}
},
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,11 +414,11 @@ 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()
var currentThread = Cc["@mozilla.org/thread-manager;1"].getService()
.currentThread;
/** Kicks off running the next test in the array. */
@ -402,13 +436,14 @@ 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);
@ -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,8 +488,7 @@ function runRawTests(testArray, done, beforeTestCallback) {
var received = "";
/** Reads data from the socket. */
var reader =
{
var reader = {
onInputStreamReady(stream) {
Assert.ok(stream === this.stream);
try {
@ -494,18 +532,18 @@ function runRawTests(testArray, done, beforeTestCallback) {
};
/** Writes data to the socket. */
var writer =
{
var writer = {
onOutputStreamReady(stream) {
var str = testArray[testIndex].data[dataIndex];
var written = 0;
try {
written = stream.write(str, str.length);
if (written == str.length)
if (written == str.length) {
dataIndex++;
else
} else {
testArray[testIndex].data[dataIndex] = str.substring(written);
}
} catch (e) {
do_note_exception(e);
/* stream could have been closed, just ignore */
@ -514,10 +552,11 @@ function runRawTests(testArray, done, beforeTestCallback) {
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)
if (written > 0 && dataIndex < testArray[testIndex].data.length) {
waitToWriteOutput(stream);
else
} else {
stream.close();
}
} catch (e) {
do_report_unexpected_exception(e);
}

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/. */
/*
* Ensures that data a request handler writes out in response is sent only as
* quickly as the client can receive it, without racing ahead and being forced
@ -22,9 +21,9 @@ gThreadManager = Cc["@mozilla.org/thread-manager;1"].createInstance();
function run_test() {
do_test_pending();
tests.push(function testsComplete(_) {
dumpn("******************\n" +
"* TESTS COMPLETE *\n" +
"******************");
dumpn(
"******************\n" + "* TESTS COMPLETE *\n" + "******************"
);
do_test_finished();
});
@ -40,13 +39,13 @@ function runNextTest() {
test(runNextTest);
} catch (e) {
var msg = "exception running test " + testIndex + ": " + e;
if (e && "stack" in e)
if (e && "stack" in e) {
msg += "\nstack follows:\n" + e.stack;
}
do_throw(msg);
}
}
/** ***********
* TEST DATA *
*************/
@ -76,13 +75,11 @@ const LATTER_HALF_THIRD_SEGMENT = [11, 12];
const TWO_HALF_SEGMENTS = [1, 2, 1, 2];
/** *******
* TESTS *
*********/
var tests =
[
var tests = [
sourceClosedWithoutWrite,
writeOneSegmentThenClose,
simpleWriteThenRead,
@ -149,8 +146,10 @@ function writeMultipleSegmentsThenRead(next) {
t.addToSource(TWO_SEGMENTS);
t.makeSourceReadable(TWO_SEGMENTS.length);
t.makeSinkWritableAndWaitFor(TWO_SEGMENTS.length,
[FIRST_SEGMENT, SECOND_SEGMENT]);
t.makeSinkWritableAndWaitFor(TWO_SEGMENTS.length, [
FIRST_SEGMENT,
SECOND_SEGMENT,
]);
t.closeSource(Cr.NS_OK);
t.expect(Cr.NS_OK, [TWO_SEGMENTS]);
}
@ -229,23 +228,28 @@ function partialWrite(next) {
t.addToSource(SEGMENT);
t.makeSourceReadable(SEGMENT.length);
t.makeSinkWritableByIncrementsAndWaitFor(SEGMENT.length,
[QUARTER_SEGMENT,
t.makeSinkWritableByIncrementsAndWaitFor(SEGMENT.length, [
QUARTER_SEGMENT,
MIDDLE_HALF_SEGMENT,
LAST_QUARTER_SEGMENT]);
LAST_QUARTER_SEGMENT,
]);
t.addToSource(SEGMENT);
t.makeSourceReadable(SEGMENT.length);
t.makeSinkWritableByIncrementsAndWaitFor(SEGMENT.length,
[HALF_SEGMENT, SECOND_HALF_SEGMENT]);
t.makeSinkWritableByIncrementsAndWaitFor(SEGMENT.length, [
HALF_SEGMENT,
SECOND_HALF_SEGMENT,
]);
t.addToSource(THREE_SEGMENTS);
t.makeSourceReadable(THREE_SEGMENTS.length);
t.makeSinkWritableByIncrementsAndWaitFor(THREE_SEGMENTS.length,
[HALF_SEGMENT, SECOND_HALF_SEGMENT,
t.makeSinkWritableByIncrementsAndWaitFor(THREE_SEGMENTS.length, [
HALF_SEGMENT,
SECOND_HALF_SEGMENT,
SECOND_SEGMENT,
HALF_THIRD_SEGMENT,
LATTER_HALF_THIRD_SEGMENT]);
LATTER_HALF_THIRD_SEGMENT,
]);
t.closeSource(Cr.NS_OK);
t.expect(Cr.NS_OK, [SEGMENT, SEGMENT, THREE_SEGMENTS]);
@ -317,7 +321,6 @@ function sinkAndSourceClosedWithPendingData(next) {
t.expect(Cr.NS_ERROR_UNEXPECTED, []);
}
/** ***********
* UTILITIES *
*************/
@ -325,8 +328,9 @@ function sinkAndSourceClosedWithPendingData(next) {
/** Returns the sum of the elements in arr. */
function sum(arr) {
var s = 0;
for (var i = 0, sz = arr.length; i < sz; i++)
for (var i = 0, sz = arr.length; i < sz; i++) {
s += arr[i];
}
return s;
}
@ -374,7 +378,6 @@ function note(m) {
dumpn(asterisks + "\n* " + m + " *\n" + asterisks);
}
/** *********
* MOCKERY *
***********/
@ -384,8 +387,12 @@ function note(m) {
* PUBLIC API! If you use any of these I will knowingly break your code by
* changing the names of variables and properties.
*/
var BinaryInputStream = function BIS(stream) { return stream; };
var BinaryOutputStream = function BOS(stream) { return stream; };
var BinaryInputStream = function BIS(stream) {
return stream;
};
var BinaryOutputStream = function BOS(stream) {
return stream;
};
Response.SEGMENT_SIZE = SEGMENT.length;
/**
@ -413,8 +420,7 @@ function CustomPipe(name) {
this._status = Cr.NS_OK;
/** The input end of this pipe. */
var input = this.inputStream =
{
var input = (this.inputStream = {
/** A name for this stream, used in debugging output. */
name: name + " input",
@ -452,12 +458,15 @@ function CustomPipe(name) {
interceptStreamReadyCallbacks(streamReadyInterceptCreator) {
dumpn("*** [" + this.name + "].interceptStreamReadyCallbacks");
Assert.ok(this._streamReadyInterceptCreator === null,
"intercepting twice");
Assert.ok(
this._streamReadyInterceptCreator === null,
"intercepting twice"
);
this._streamReadyInterceptCreator = streamReadyInterceptCreator;
if (this._waiter) {
this._waiter.callback =
new streamReadyInterceptCreator(this._waiter.callback);
this._waiter.callback = new streamReadyInterceptCreator(
this._waiter.callback
);
}
},
@ -468,11 +477,14 @@ function CustomPipe(name) {
removeStreamReadyInterceptor() {
dumpn("*** [" + this.name + "].removeStreamReadyInterceptor()");
Assert.ok(this._streamReadyInterceptCreator !== null,
"removing interceptor when none present?");
Assert.ok(
this._streamReadyInterceptCreator !== null,
"removing interceptor when none present?"
);
this._streamReadyInterceptCreator = null;
if (this._waiter)
if (this._waiter) {
this._waiter.callback = this._waiter.callback.wrappedCallback;
}
},
//
@ -486,15 +498,14 @@ function CustomPipe(name) {
var closureOnly =
(flags & Ci.nsIAsyncInputStream.WAIT_CLOSURE_ONLY) !== 0;
Assert.ok(this._waiter === null ||
(this._waiter.closureOnly && !closureOnly),
Assert.ok(
this._waiter === null || (this._waiter.closureOnly && !closureOnly),
"asyncWait already called with a non-closure-only " +
"callback? unexpected!");
"callback? unexpected!"
);
this._waiter =
{
callback:
this._streamReadyInterceptCreator
this._waiter = {
callback: this._streamReadyInterceptCreator
? new this._streamReadyInterceptCreator(callback)
: callback,
closureOnly,
@ -502,9 +513,12 @@ function CustomPipe(name) {
eventTarget: target,
};
if (!Components.isSuccessCode(self._status) ||
(!closureOnly && this._readable >= requestedCount &&
self._data.length >= requestedCount)) {
if (
!Components.isSuccessCode(self._status) ||
(!closureOnly &&
this._readable >= requestedCount &&
self._data.length >= requestedCount)
) {
this._notify();
}
},
@ -513,24 +527,32 @@ function CustomPipe(name) {
// see nsIAsyncInputStream.closeWithStatus
//
closeWithStatus: function closeWithStatus(status) {
dumpn("*** [" + this.name + "].closeWithStatus" +
"(" + status + ")");
dumpn("*** [" + this.name + "].closeWithStatus" + "(" + status + ")");
if (!Components.isSuccessCode(self._status)) {
dumpn("*** ignoring second closure of [input " + this.name + "] " +
"(status " + self._status + ")");
dumpn(
"*** ignoring second closure of [input " +
this.name +
"] " +
"(status " +
self._status +
")"
);
return;
}
if (Components.isSuccessCode(status))
if (Components.isSuccessCode(status)) {
status = Cr.NS_BASE_STREAM_CLOSED;
}
self._status = status;
if (this._waiter)
if (this._waiter) {
this._notify();
if (output._waiter)
}
if (output._waiter) {
output._notify();
}
},
//
@ -545,12 +567,14 @@ function CustomPipe(name) {
: self._status;
}
Assert.ok(this._readable <= self._data.length ||
this._readable === Infinity,
"consistency check");
Assert.ok(
this._readable <= self._data.length || this._readable === Infinity,
"consistency check"
);
if (this._readable < count || self._data.length < count)
if (this._readable < count || self._data.length < count) {
throw Cr.NS_BASE_STREAM_WOULD_BLOCK;
}
this._readable -= count;
return self._data.splice(0, count);
},
@ -569,9 +593,11 @@ function CustomPipe(name) {
dumpn("*** [" + this.name + "].makeReadable(" + count + ")");
Assert.ok(Components.isSuccessCode(self._status), "errant call");
Assert.ok(this._readable + count <= self._data.length ||
Assert.ok(
this._readable + count <= self._data.length ||
this._readable === Infinity,
"increasing readable beyond written amount");
"increasing readable beyond written amount"
);
this._readable += count;
@ -579,9 +605,10 @@ function CustomPipe(name) {
var waiter = this._waiter;
if (waiter !== null) {
if (waiter.requestedCount <= this._readable && !waiter.closureOnly)
if (waiter.requestedCount <= this._readable && !waiter.closureOnly) {
this._notify();
}
}
},
/**
@ -602,8 +629,9 @@ function CustomPipe(name) {
available: function available() {
dumpn("*** [" + this.name + "].available()");
if (self._data.length === 0 && !Components.isSuccessCode(self._status))
if (self._data.length === 0 && !Components.isSuccessCode(self._status)) {
throw self._status;
}
return Math.min(this._readable, self._data.length);
},
@ -625,8 +653,10 @@ function CustomPipe(name) {
Assert.ok(this._waiter !== null, "must be waiting now");
if (self._data.length > 0) {
dumpn("*** data still pending, normal notifications will signal " +
"completion");
dumpn(
"*** data still pending, normal notifications will signal " +
"completion"
);
return;
}
@ -651,30 +681,33 @@ function CustomPipe(name) {
Assert.ok(waiter !== null, "no waiter?");
if (this._event === null) {
var event = this._event =
{
var event = (this._event = {
run: function run() {
input._waiter = null;
input._event = null;
try {
Assert.ok(!Components.isSuccessCode(self._status) ||
input._readable >= waiter.requestedCount);
Assert.ok(
!Components.isSuccessCode(self._status) ||
input._readable >= waiter.requestedCount
);
waiter.callback.onInputStreamReady(input);
} catch (e) {
do_throw("error calling onInputStreamReady: " + e);
}
},
};
});
waiter.eventTarget.dispatch(event, Ci.nsIThread.DISPATCH_NORMAL);
}
},
QueryInterface: ChromeUtils.generateQI(["nsIAsyncInputStream", "nsIInputStream"]),
};
QueryInterface: ChromeUtils.generateQI([
"nsIAsyncInputStream",
"nsIInputStream",
]),
});
/** The output end of this pipe. */
var output = this.outputStream =
{
var output = (this.outputStream = {
/** A name for this stream, used in debugging output. */
name: name + " output",
@ -723,12 +756,15 @@ function CustomPipe(name) {
interceptStreamReadyCallbacks(streamReadyInterceptCreator) {
dumpn("*** [" + this.name + "].interceptStreamReadyCallbacks");
Assert.ok(this._streamReadyInterceptCreator !== null,
"intercepting onOutputStreamReady twice");
Assert.ok(
this._streamReadyInterceptCreator !== null,
"intercepting onOutputStreamReady twice"
);
this._streamReadyInterceptCreator = streamReadyInterceptCreator;
if (this._waiter) {
this._waiter.callback =
new streamReadyInterceptCreator(this._waiter.callback);
this._waiter.callback = new streamReadyInterceptCreator(
this._waiter.callback
);
}
},
@ -739,11 +775,14 @@ function CustomPipe(name) {
removeStreamReadyInterceptor() {
dumpn("*** [" + this.name + "].removeStreamReadyInterceptor()");
Assert.ok(this._streamReadyInterceptCreator !== null,
"removing interceptor when none present?");
Assert.ok(
this._streamReadyInterceptCreator !== null,
"removing interceptor when none present?"
);
this._streamReadyInterceptCreator = null;
if (this._waiter)
if (this._waiter) {
this._waiter.callback = this._waiter.callback.wrappedCallback;
}
},
//
@ -757,29 +796,36 @@ function CustomPipe(name) {
var closureOnly =
(flags & Ci.nsIAsyncInputStream.WAIT_CLOSURE_ONLY) !== 0;
Assert.ok(this._waiter === null ||
(this._waiter.closureOnly && !closureOnly),
Assert.ok(
this._waiter === null || (this._waiter.closureOnly && !closureOnly),
"asyncWait already called with a non-closure-only " +
"callback? unexpected!");
"callback? unexpected!"
);
this._waiter =
{
callback:
this._streamReadyInterceptCreator
this._waiter = {
callback: this._streamReadyInterceptCreator
? new this._streamReadyInterceptCreator(callback)
: callback,
closureOnly,
requestedCount,
eventTarget: target,
toString: function toString() {
return "waiter(" + (closureOnly ? "closure only, " : "") +
"requestedCount: " + requestedCount + ", target: " +
target + ")";
return (
"waiter(" +
(closureOnly ? "closure only, " : "") +
"requestedCount: " +
requestedCount +
", target: " +
target +
")"
);
},
};
if ((!closureOnly && this._writable >= requestedCount) ||
!Components.isSuccessCode(this.status)) {
if (
(!closureOnly && this._writable >= requestedCount) ||
!Components.isSuccessCode(this.status)
) {
this._notify();
}
},
@ -791,44 +837,69 @@ function CustomPipe(name) {
dumpn("*** [" + this.name + "].closeWithStatus(" + status + ")");
if (!Components.isSuccessCode(self._status)) {
dumpn("*** ignoring redundant closure of [input " + this.name + "] " +
"because it's already closed (status " + self._status + ")");
dumpn(
"*** ignoring redundant closure of [input " +
this.name +
"] " +
"because it's already closed (status " +
self._status +
")"
);
return;
}
if (Components.isSuccessCode(status))
if (Components.isSuccessCode(status)) {
status = Cr.NS_BASE_STREAM_CLOSED;
}
self._status = status;
if (input._waiter)
if (input._waiter) {
input._notify();
if (this._waiter)
}
if (this._waiter) {
this._notify();
}
},
//
// see nsIBinaryOutputStream.writeByteArray
//
writeByteArray: function writeByteArray(bytes, length) {
dumpn("*** [" + this.name + "].writeByteArray" +
"([" + bytes + "], " + length + ")");
dumpn(
"*** [" +
this.name +
"].writeByteArray" +
"([" +
bytes +
"], " +
length +
")"
);
Assert.equal(bytes.length, length, "sanity");
if (!Components.isSuccessCode(self._status))
if (!Components.isSuccessCode(self._status)) {
throw self._status;
}
Assert.equal(this._writableAmounts.length, 0,
"writeByteArray can't support specified-length writes");
Assert.equal(
this._writableAmounts.length,
0,
"writeByteArray can't support specified-length writes"
);
if (this._writable < length)
if (this._writable < length) {
throw Cr.NS_BASE_STREAM_WOULD_BLOCK;
}
self._data.push.apply(self._data, bytes);
this._writable -= length;
if (input._readable === Infinity && input._waiter &&
!input._waiter.closureOnly) {
if (
input._readable === Infinity &&
input._waiter &&
!input._waiter.closureOnly
) {
input._notify();
}
},
@ -840,32 +911,44 @@ function CustomPipe(name) {
dumpn("*** [" + this.name + "].write");
Assert.equal(str.length, length, "sanity");
if (!Components.isSuccessCode(self._status))
if (!Components.isSuccessCode(self._status)) {
throw self._status;
if (this._writable === 0)
}
if (this._writable === 0) {
throw Cr.NS_BASE_STREAM_WOULD_BLOCK;
}
var actualWritten;
if (this._writableAmounts.length === 0) {
actualWritten = Math.min(this._writable, length);
} else {
Assert.ok(this._writable >= this._writableAmounts[0],
"writable amounts value greater than writable data?");
Assert.equal(this._writable, sum(this._writableAmounts),
"total writable amount not equal to sum of writable " +
"increments");
Assert.ok(
this._writable >= this._writableAmounts[0],
"writable amounts value greater than writable data?"
);
Assert.equal(
this._writable,
sum(this._writableAmounts),
"total writable amount not equal to sum of writable " + "increments"
);
actualWritten = this._writableAmounts.shift();
}
var bytes = str.substring(0, actualWritten)
var bytes = str
.substring(0, actualWritten)
.split("")
.map(function(v) { return v.charCodeAt(0); });
.map(function(v) {
return v.charCodeAt(0);
});
self._data.push.apply(self._data, bytes);
this._writable -= actualWritten;
if (input._readable === Infinity && input._waiter &&
!input._waiter.closureOnly) {
if (
input._readable === Infinity &&
input._waiter &&
!input._waiter.closureOnly
) {
input._notify();
}
@ -887,8 +970,11 @@ function CustomPipe(name) {
this._writable += count;
var waiter = this._waiter;
if (waiter && !waiter.closureOnly &&
waiter.requestedCount <= this._writable) {
if (
waiter &&
!waiter.closureOnly &&
waiter.requestedCount <= this._writable
) {
this._notify();
}
},
@ -914,12 +1000,22 @@ function CustomPipe(name) {
* increments
*/
makeWritableByIncrements: function makeWritableByIncrements(increments) {
dumpn("*** [" + this.name + "].makeWritableByIncrements" +
"([" + increments.join(", ") + "])");
dumpn(
"*** [" +
this.name +
"].makeWritableByIncrements" +
"([" +
increments.join(", ") +
"])"
);
Assert.ok(increments.length > 0, "bad increments");
Assert.ok(increments.every(function(v) { return v > 0; }),
"zero increment?");
Assert.ok(
increments.every(function(v) {
return v > 0;
}),
"zero increment?"
);
Assert.ok(Components.isSuccessCode(self._status));
@ -927,8 +1023,11 @@ function CustomPipe(name) {
this._writableAmounts = increments;
var waiter = this._waiter;
if (waiter && !waiter.closureOnly &&
waiter.requestedCount <= this._writable) {
if (
waiter &&
!waiter.closureOnly &&
waiter.requestedCount <= this._writable
) {
this._notify();
}
},
@ -944,8 +1043,7 @@ function CustomPipe(name) {
Assert.ok(waiter !== null, "no waiter?");
if (this._event === null) {
var event = this._event =
{
var event = (this._event = {
run: function run() {
output._waiter = null;
output._event = null;
@ -956,13 +1054,16 @@ function CustomPipe(name) {
do_throw("error calling onOutputStreamReady: " + e);
}
},
};
});
waiter.eventTarget.dispatch(event, Ci.nsIThread.DISPATCH_NORMAL);
}
},
QueryInterface: ChromeUtils.generateQI(["nsIAsyncOutputStream", "nsIOutputStream"]),
};
QueryInterface: ChromeUtils.generateQI([
"nsIAsyncOutputStream",
"nsIOutputStream",
]),
});
}
/**
@ -1042,14 +1143,12 @@ function CopyTest(name, next) {
this._tasks = [];
/** The copier used by this test. */
this._copier =
new WriteThroughCopier(this._source, this._sink, this, null);
this._copier = new WriteThroughCopier(this._source, this._sink, this, null);
// Start watching for data written by the copier to the sink.
this._waitForWrittenData();
}
CopyTest.prototype =
{
CopyTest.prototype = {
/**
* Adds the given array of bytes to data in the copier's source.
*
@ -1098,23 +1197,30 @@ CopyTest.prototype =
* @param dataQuantums : [[uint]]
* array of byte arrays to expect to be written in sequence to the sink
*/
makeSinkWritableAndWaitFor:
function makeSinkWritableAndWaitFor(bytes, dataQuantums) {
makeSinkWritableAndWaitFor: function makeSinkWritableAndWaitFor(
bytes,
dataQuantums
) {
var self = this;
Assert.equal(bytes,
Assert.equal(
bytes,
dataQuantums.reduce(function(partial, current) {
return partial + current.length;
}, 0),
"bytes/quantums mismatch");
"bytes/quantums mismatch"
);
function increaseSinkSpaceTask() {
/* Now do the actual work to trigger the interceptor. */
self._sink.makeWritable(bytes);
}
this._waitForHelper("increaseSinkSpaceTask",
dataQuantums, increaseSinkSpaceTask);
this._waitForHelper(
"increaseSinkSpaceTask",
dataQuantums,
increaseSinkSpaceTask
);
},
/**
@ -1128,11 +1234,15 @@ CopyTest.prototype =
* @param dataQuantums : [[uint]]
* array of byte arrays to expect to be written in sequence to the sink
*/
makeSinkWritableByIncrementsAndWaitFor:
function makeSinkWritableByIncrementsAndWaitFor(bytes, dataQuantums) {
makeSinkWritableByIncrementsAndWaitFor: function makeSinkWritableByIncrementsAndWaitFor(
bytes,
dataQuantums
) {
var self = this;
var desiredAmounts = dataQuantums.map(function(v) { return v.length; });
var desiredAmounts = dataQuantums.map(function(v) {
return v.length;
});
Assert.equal(bytes, sum(desiredAmounts), "bytes/quantums mismatch");
function increaseSinkSpaceByIncrementsTask() {
@ -1140,8 +1250,11 @@ CopyTest.prototype =
self._sink.makeWritableByIncrements(desiredAmounts);
}
this._waitForHelper("increaseSinkSpaceByIncrementsTask",
dataQuantums, increaseSinkSpaceByIncrementsTask);
this._waitForHelper(
"increaseSinkSpaceByIncrementsTask",
dataQuantums,
increaseSinkSpaceByIncrementsTask
);
},
/**
@ -1174,20 +1287,33 @@ CopyTest.prototype =
* @param dataQuantums : [[uint]]
* array of byte arrays to expect to be written in sequence to the sink
*/
closeSourceAndWaitFor:
function closeSourceAndWaitFor(status, bytes, dataQuantums) {
closeSourceAndWaitFor: function closeSourceAndWaitFor(
status,
bytes,
dataQuantums
) {
var self = this;
Assert.equal(bytes, sum(dataQuantums.map(function(v) { return v.length; })),
"bytes/quantums mismatch");
Assert.equal(
bytes,
sum(
dataQuantums.map(function(v) {
return v.length;
})
),
"bytes/quantums mismatch"
);
function closeSourceAndWaitForTask() {
self._sink.makeWritable(bytes);
self._copyableDataStream.closeWithStatus(status);
}
this._waitForHelper("closeSourceAndWaitForTask",
dataQuantums, closeSourceAndWaitForTask);
this._waitForHelper(
"closeSourceAndWaitForTask",
dataQuantums,
closeSourceAndWaitForTask
);
},
/**
@ -1262,8 +1388,9 @@ CopyTest.prototype =
expect: function expect(expectedStatus, receivedData) {
this._expectedStatus = expectedStatus;
this._expectedData = [];
for (var i = 0, sz = receivedData.length; i < sz; i++)
for (var i = 0, sz = receivedData.length; i < sz; i++) {
this._expectedData.push.apply(this._expectedData, receivedData[i]);
}
this._stageNextTask();
},
@ -1295,11 +1422,14 @@ CopyTest.prototype =
* Intercept all data-available notifications so we can continue when all
* the ones we expect have been received.
*/
var streamReadyCallback =
{
var streamReadyCallback = {
onInputStreamReady: function wrapperOnInputStreamReady(input) {
dumpn("*** streamReadyCallback.onInputStreamReady" +
"(" + input.name + ")");
dumpn(
"*** streamReadyCallback.onInputStreamReady" +
"(" +
input.name +
")"
);
Assert.equal(this, streamReadyCallback, "sanity");
@ -1307,15 +1437,24 @@ CopyTest.prototype =
if (quantumIndex < dataQuantums.length) {
var quantum = dataQuantums[quantumIndex++];
var sz = quantum.length;
Assert.equal(self._lastQuantum.length, sz,
"different quantum lengths");
Assert.equal(
self._lastQuantum.length,
sz,
"different quantum lengths"
);
for (var i = 0; i < sz; i++) {
Assert.equal(self._lastQuantum[i], quantum[i],
"bad data at " + i);
Assert.equal(
self._lastQuantum[i],
quantum[i],
"bad data at " + i
);
}
dumpn("*** waiting to check remaining " +
(dataQuantums.length - quantumIndex) + " quantums...");
dumpn(
"*** waiting to check remaining " +
(dataQuantums.length - quantumIndex) +
" quantums..."
);
}
} finally {
if (quantumIndex === dataQuantums.length) {
@ -1327,8 +1466,10 @@ CopyTest.prototype =
},
};
var interceptor =
createStreamReadyInterceptor(streamReadyCallback, "onInputStreamReady");
var interceptor = createStreamReadyInterceptor(
streamReadyCallback,
"onInputStreamReady"
);
self._copiedDataStream.interceptStreamReadyCallbacks(interceptor);
/* Do the deed. */
@ -1349,15 +1490,17 @@ CopyTest.prototype =
dumpn("*** _waitForWrittenData (" + this.name + ")");
var self = this;
var outputWrittenWatcher =
{
var outputWrittenWatcher = {
onInputStreamReady: function onInputStreamReady(input) {
dumpn("*** outputWrittenWatcher.onInputStreamReady" +
"(" + input.name + ")");
dumpn(
"*** outputWrittenWatcher.onInputStreamReady" + "(" + input.name + ")"
);
if (self._allDataWritten) {
do_throw("ruh-roh! why are we getting notified of more data " +
"after we should have received all of it?");
do_throw(
"ruh-roh! why are we getting notified of more data " +
"after we should have received all of it?"
);
}
self._waitingForData = false;
@ -1367,18 +1510,23 @@ CopyTest.prototype =
} catch (e) {
dumpn("*** available() threw! error: " + e);
if (self._completed) {
dumpn("*** NB: this isn't a problem, because we've copied " +
dumpn(
"*** NB: this isn't a problem, because we've copied " +
"completely now, and this notify may have been expedited " +
"by maybeNotifyFinally such that we're being called when " +
"we can *guarantee* nothing is available any more");
"we can *guarantee* nothing is available any more"
);
}
avail = 0;
}
if (avail > 0) {
var data = input.readByteArray(avail);
Assert.equal(data.length, avail,
"readByteArray returned wrong number of bytes?");
Assert.equal(
data.length,
avail,
"readByteArray returned wrong number of bytes?"
);
self._lastQuantum = data;
self._receivedData.push.apply(self._receivedData, data);
}
@ -1402,8 +1550,12 @@ CopyTest.prototype =
},
};
this._copiedDataStream.asyncWait(outputWrittenWatcher, 0, 1,
gThreadManager.currentThread);
this._copiedDataStream.asyncWait(
outputWrittenWatcher,
0,
1,
gThreadManager.currentThread
);
this._waitingForData = true;
},
@ -1413,27 +1565,37 @@ CopyTest.prototype =
* this test was first created.
*/
_testComplete: function _testComplete() {
dumpn("*** CopyTest(" + this.name + ") complete! " +
"On to the next test...");
dumpn(
"*** CopyTest(" + this.name + ") complete! " + "On to the next test..."
);
try {
Assert.ok(this._allDataWritten, "expect all data written now!");
Assert.ok(this._copyingFinished, "expect copying finished now!");
Assert.equal(this._actualStatus, this._expectedStatus,
"wrong final status");
Assert.equal(
this._actualStatus,
this._expectedStatus,
"wrong final status"
);
var expected = this._expectedData, received = this._receivedData;
var expected = this._expectedData,
received = this._receivedData;
dumpn("received: [" + received + "], expected: [" + expected + "]");
Assert.equal(received.length, expected.length, "wrong data");
for (var i = 0, sz = expected.length; i < sz; i++)
for (var i = 0, sz = expected.length; i < sz; i++) {
Assert.equal(received[i], expected[i], "bad data at " + i);
}
} catch (e) {
dumpn("!!! ERROR PERFORMING FINAL " + this.name + " CHECKS! " + e);
throw e;
} finally {
dumpn("*** CopyTest(" + this.name + ") complete! " +
"Invoking test-completion callback...");
dumpn(
"*** CopyTest(" +
this.name +
") complete! " +
"Invoking test-completion callback..."
);
this._done();
}
},
@ -1448,8 +1610,7 @@ CopyTest.prototype =
}
var task = this._tasks[this._currentTask++];
var event =
{
var event = {
run: function run() {
try {
task();
@ -1508,8 +1669,9 @@ CopyTest.prototype =
*/
dumpn("*** not all data copied, waiting for that to happen...");
if (!this._waitingForData)
if (!this._waitingForData) {
this._waitForWrittenData();
}
this._copiedDataStream.maybeNotifyFinally();
}

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,15 +122,15 @@ 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 =
{
var objHandler = {
handle(metadata, response) {
response.setStatusLine(metadata.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/plain", false);
@ -119,15 +140,15 @@ var objHandler =
Assert.equal(metadata.port, port);
if (metadata.queryString)
if (metadata.queryString) {
body += "?" + metadata.queryString;
}
body += " HTTP/" + metadata.httpVersion + "\n";
var headEnum = metadata.headers;
while (headEnum.hasMoreElements()) {
var fieldName = headEnum.getNext()
.QueryInterface(Ci.nsISupportsString)
var fieldName = headEnum.getNext().QueryInterface(Ci.nsISupportsString)
.data;
body += fieldName + ": " + metadata.getHeader(fieldName) + "\n";
}
@ -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,34 +14,65 @@ 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),
];
});

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];
@ -203,7 +206,9 @@ function makeFile(name, isDirectory, parentDir, lst) {
file.append(name);
file.create(type, 0o755);
lst.push({ name, isDirectory });
} catch (e) { /* OS probably doesn't like file name, skip */ }
} 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 +
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 +
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),
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,13 +39,15 @@ 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();
@ -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,8 +264,7 @@ function check10(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
let body = [
"Method: GET",
"Path: /http/1.0-request",
"Query: ",
@ -279,78 +279,69 @@ function check10(aData) {
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" +
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" +
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";
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";
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" +
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" +
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,8 +351,7 @@ function check11goodHost(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
let body = [
"Method: GET",
"Path: /http/1.1-good-host",
"Query: ",
@ -376,16 +366,14 @@ function check11goodHost(aData) {
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,8 +383,7 @@ function check11ipHost(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
let body = [
"Method: GET",
"Path: /http/1.1-ip-host",
"Query: ",
@ -411,45 +398,45 @@ function check11ipHost(aData) {
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" +
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" +
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" +
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" +
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) {
@ -461,12 +448,12 @@ 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" +
data =
"GET /http/1.0-request HTTP/1.0\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
function check10ip(aData) {
@ -478,8 +465,7 @@ function check10ip(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
let body = [
"Method: GET",
"Path: /http/1.0-request",
"Query: ",
@ -494,14 +480,14 @@ function check10ip(aData) {
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" +
data =
"GET /http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n";
function check11goodHostWackyPort(aData) {
@ -513,8 +499,7 @@ function check11goodHostWackyPort(aData) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body =
[
let body = [
"Method: GET",
"Path: /http/1.1-good-host-wacky-port",
"Query: ",
@ -529,91 +514,88 @@ function check11goodHostWackyPort(aData) {
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" +
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" +
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" +
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" +
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" +
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" +
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" +
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" +
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" +
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);

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,12 +227,12 @@ 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 =
{
var writeData = {
run() {
if (count-- === 0) {
response.finish();
@ -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,72 +37,85 @@ 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),
new Test(BASE + "/test_registerdirectory.js", nocache, notFound, null),
/** ******************
* with a base path *
********************/
new Test(BASE + "/test_registerdirectory.js",
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = testsDirectory.clone();
srv.registerDirectory("/", serverBasePath);
},
null,
checkFile),
checkFile
),
/** ***************************
* without a base path again *
*****************************/
new Test(BASE + "/test_registerdirectory.js",
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = null;
srv.registerDirectory("/", serverBasePath);
},
notFound,
null),
null
),
/** *************************
* registered path handler *
***************************/
new Test(BASE + "/test_registerdirectory.js",
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js",
override_test_registerdirectory);
srv.registerPathHandler(
"/test_registerdirectory.js",
override_test_registerdirectory
);
},
checkOverride,
null),
null
),
/** **********************
* removed path handler *
************************/
new Test(BASE + "/test_registerdirectory.js",
new Test(
BASE + "/test_registerdirectory.js",
function init_registerDirectory6(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js", null);
},
notFound,
null),
null
),
/** ******************
* with a base path *
********************/
new Test(BASE + "/test_registerdirectory.js",
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
@ -112,112 +124,135 @@ XPCOMUtils.defineLazyGetter(this, "tests", function() {
srv.registerDirectory("/", serverBasePath);
},
null,
checkFile),
checkFile
),
/** ***********************
* ...and a path handler *
*************************/
new Test(BASE + "/test_registerdirectory.js",
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js",
override_test_registerdirectory);
srv.registerPathHandler(
"/test_registerdirectory.js",
override_test_registerdirectory
);
},
checkOverride,
null),
null
),
/** **********************
* removed base handler *
************************/
new Test(BASE + "/test_registerdirectory.js",
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = null;
srv.registerDirectory("/", serverBasePath);
},
checkOverride,
null),
null
),
/** **********************
* removed path handler *
************************/
new Test(BASE + "/test_registerdirectory.js",
new Test(
BASE + "/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerPathHandler("/test_registerdirectory.js", null);
},
notFound,
null),
null
),
/** ***********************
* mapping set up, works *
*************************/
new Test(BASE + "/foo/test_registerdirectory.js",
new Test(
BASE + "/foo/test_registerdirectory.js",
function(ch) {
nocache(ch);
serverBasePath = testsDirectory.clone();
srv.registerDirectory("/foo/", serverBasePath);
},
check200,
null),
null
),
/** *******************
* no mapping, fails *
*********************/
new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
new Test(
BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
nocache,
notFound,
null),
null
),
/** ****************
* mapping, works *
******************/
new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
new Test(
BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerDirectory("/foo/test_registerdirectory.js/",
serverBasePath);
srv.registerDirectory(
"/foo/test_registerdirectory.js/",
serverBasePath
);
},
null,
checkFile),
checkFile
),
/** **********************************
* two mappings set up, still works *
************************************/
new Test(BASE + "/foo/test_registerdirectory.js",
nocache, null, checkFile),
new Test(BASE + "/foo/test_registerdirectory.js", nocache, null, checkFile),
/** ************************
* remove topmost mapping *
**************************/
new Test(BASE + "/foo/test_registerdirectory.js",
new Test(
BASE + "/foo/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerDirectory("/foo/", null);
},
notFound,
null),
null
),
/** ************************************
* lower mapping still present, works *
**************************************/
new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
nocache, null, checkFile),
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",
new Test(
BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
function(ch) {
nocache(ch);
srv.registerDirectory("/foo/test_registerdirectory.js/", null);
},
notFound,
null),
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" +
}
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,8 +73,7 @@ function checkVeryLongRequestLine(data) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
var body =
[
var body = [
"Method: GET",
"Path: /very-long-request-line",
"Query: " + reallyLong,
@ -83,22 +88,26 @@ function checkVeryLongRequestLine(data) {
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 +
}
str =
blankLines +
"GET /lots-of-leading-blank-lines HTTP/1.1\r\n" +
"Host: localhost:" + PORT + "\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,8 +121,7 @@ function checkLotsOfLeadingBlankLines(data) {
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
var body =
[
var body = [
"Method: GET",
"Path: /lots-of-leading-blank-lines",
"Query: ",

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"); },
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); },
"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(); },
"setHeader should throw not-available after seizePower"
);
checkException(
function() {
response.processAsync();
},
Cr.NS_ERROR_NOT_AVAILABLE,
"processAsync should throw not-available after seizePower");
"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(); },
checkException(
function() {
response.seizePower();
},
Cr.NS_ERROR_UNEXPECTED,
"seizePower should throw unexpected after finish");
"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(); },
checkException(
function() {
response.seizePower();
},
Cr.NS_ERROR_NOT_AVAILABLE,
"seizePower should throw not-available after processAsync");
"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",
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("not-a-bytes-equals-specifier"),
checkRangeResult, null);
checkRangeResult,
null
);
tests.push(test);
test = new Test(BASE + "/range-checker.sjs",
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("bytes=-"),
checkRangeResult, null);
checkRangeResult,
null
);
tests.push(test);
test = new Test(BASE + "/range-checker.sjs",
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("bytes=1000000-"),
checkRangeResult, null);
checkRangeResult,
null
);
tests.push(test);
test = new Test(BASE + "/range-checker.sjs",
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("bytes=1-4"),
checkRangeResult, null);
checkRangeResult,
null
);
tests.push(test);
test = new Test(BASE + "/range-checker.sjs",
test = new Test(
BASE + "/range-checker.sjs",
rangeInit("bytes=-4"),
checkRangeResult, null);
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,12 +260,12 @@ function HTTPTestLoader(path, start, stop) {
var channel = makeChannel(path);
channel.asyncOpen(this);
}
HTTPTestLoader.prototype =
{
HTTPTestLoader.prototype = {
onStartRequest(request) {
dumpn("*** HTTPTestLoader.onStartRequest for " + this._path);
var ch = request.QueryInterface(Ci.nsIHttpChannel)
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
try {
@ -234,23 +275,31 @@ HTTPTestLoader.prototype =
do_throw(this._path + ": error in onStartRequest: " + e);
}
} catch (e) {
dumpn("!!! swallowing onStartRequest exception so onStopRequest is " +
"called...");
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));
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)
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
this._stop(ch, status, this._data);
},
QueryInterface: ChromeUtils.generateQI(["nsIStreamListener", "nsIRequestObserver"]),
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,9 +133,10 @@ 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 "";
}
return getHeader;
@ -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,7 +67,8 @@ function run_test_2() {
do_test_pending();
try {
srv.stop({onStopped() {
srv.stop({
onStopped() {
try {
do_test_pending();
run_test_3();
@ -123,10 +126,10 @@ function run_test_5() {
dumpn("*** run_test_5");
testsComplete = true;
if (stopped)
if (stopped) {
do_test_finished();
}
}
const INTERVAL = 500;
@ -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

@ -8,7 +8,7 @@ var observer = {
sendAsyncMessage("cookieName", cookie.name + "=" + cookie.value);
sendAsyncMessage("cookieOperation", data);
}
}
},
};
addMessageListener("createObserver", function(e) {

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;
});
@ -45,12 +63,11 @@ function setupTest(uri, domain, cookies, loads, headers) {
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);
}
function evict_cache_entries(where)
{
var clearDisk = (!where || where == "disk" || where == "all");
var clearMem = (!where || where == "memory" || where == "all");
var clearAppCache = (where == "appcache");
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";
var svc = get_cache_service();
var storage;
@ -35,28 +38,32 @@ 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() {}
@ -66,8 +73,9 @@ function asyncOpenCacheEntry(key, where, flags, lci, callback, 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;
},
@ -76,31 +84,33 @@ function asyncOpenCacheEntry(key, where, flags, lci, callback, appcache)
// Root us at the callback
callback.__cache_listener_root = this;
callback.onCacheEntryAvailable(entry, isnew, appCache, status);
}
else
} else {
callback(status, entry, appCache);
}
},
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();
}
}
@ -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

@ -15,7 +15,7 @@ const NOTFOUND = 1 << 4;
// Return ENTRY_NEEDS_REVALIDATION from onCacheEntryCheck
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;
// Don't trigger the go-on callback until the entry is written
@ -38,54 +38,63 @@ const NOTIFYBEFOREREAD = 1 << 15;
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);
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)
{
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;
@ -111,7 +120,10 @@ OpenCallback.prototype =
}
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;
}
@ -142,11 +153,11 @@ OpenCallback.prototype =
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)) {
this.goon(entry);
} 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 &&
} else if (typeof element === "object") {
return (
element.uri === key &&
element.lci.isAnonymous === aInfo.isAnonymous &&
ChromeUtils.isOriginAttributesEqual(element.lci.originAttributes,
aInfo.originAttributes);
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))
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)
} 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)) &&
}
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)
this._contentLen != -1
) {
Assert.equal(this._buffer.length, this._contentLen);
}
} catch (ex) {
do_throw("Error in onStopRequest: " + ex);
}
try {
this._closure(request,
this._closure(
request,
this._buffer,
this._closurectx,
this._isFromCache,
this._cacheEntryId);
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();
@ -242,4 +295,3 @@ function addCertFromFile(certdb, filename, trustString) {
.replace(/[\r\n]/g, "");
certdb.addCertFromBase64(pem, trustString);
}

View file

@ -4,35 +4,44 @@
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyServiceGetter(Services, "cookies",
XPCOMUtils.defineLazyServiceGetter(
Services,
"cookies",
"@mozilla.org/cookieService;1",
"nsICookieService");
XPCOMUtils.defineLazyServiceGetter(Services, "cookiemgr",
"nsICookieService"
);
XPCOMUtils.defineLazyServiceGetter(
Services,
"cookiemgr",
"@mozilla.org/cookiemanager;1",
"nsICookieManager");
"nsICookieManager"
);
XPCOMUtils.defineLazyServiceGetter(Services, "etld",
XPCOMUtils.defineLazyServiceGetter(
Services,
"etld",
"@mozilla.org/network/effective-tld-service;1",
"nsIEffectiveTLDService");
"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();
@ -63,13 +71,14 @@ _observer.prototype = {
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,7 +163,8 @@ function do_count_cookies() {
}
// Helper object to store cookie data.
function Cookie(name,
function Cookie(
name,
value,
host,
path,
@ -142,8 +173,8 @@ function Cookie(name,
creationTime,
isSession,
isSecure,
isHttpOnly)
{
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,15 +411,18 @@ 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;
}
@ -386,15 +432,13 @@ function CookieDatabaseConnection(file, schema)
}
}
CookieDatabaseConnection.prototype =
{
insertCookie(cookie)
{
if (!(cookie instanceof Cookie))
CookieDatabaseConnection.prototype = {
insertCookie(cookie) {
if (!(cookie instanceof Cookie)) {
do_throw("not a cookie");
}
switch (this.schema)
{
switch (this.schema) {
case 1:
this.stmtInsert.bindByName("id", cookie.creationTime);
this.stmtInsert.bindByName("name", cookie.name);
@ -451,13 +495,12 @@ CookieDatabaseConnection.prototype =
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)
{
switch (this.db.schemaVersion) {
case 1:
case 2:
case 3:
@ -477,13 +520,12 @@ CookieDatabaseConnection.prototype =
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)
{
switch (this.db.schemaVersion) {
case 1:
do_throw("can't update a schema 1 cookie!");
@ -507,23 +549,22 @@ CookieDatabaseConnection.prototype =
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",
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);
"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 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,7 +1,7 @@
// Test based on submitted one from Peter B Shalimoff
var test = function(s, funcName) {
function Arg(){};
function Arg() {}
Arg.prototype.toString = function() {
info("Testing " + funcName + " with null args");
return this.value;
@ -11,7 +11,9 @@ var test = function(s, funcName){
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);
var up = Cc["@mozilla.org/network/url-parser;1?auth=maybe"].getService(
Ci.nsIURLParser
);
try {
up[funcName].apply(up, args);
return args;
@ -23,8 +25,18 @@ var test = function(s, funcName){
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

@ -19,19 +19,21 @@ 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);
var service = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(
Ci.nsICacheStorageService
);
service.clear();
}
@ -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,
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

@ -20,70 +20,75 @@ function make_channel(url) {
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" +
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

@ -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;

View file

@ -5,7 +5,7 @@
* See also https://bugzilla.mozilla.org/show_bug.cgi?id=609667
*/
var BS = '\\';
var BS = "\\";
var DQUOTE = '"';
// Test array:
@ -23,257 +23,358 @@ var DQUOTE = '"';
var tests = [
// No filename parameter: return nothing
["attachment;",
"attachment", Cr.NS_ERROR_INVALID_ARG],
["attachment;", "attachment", Cr.NS_ERROR_INVALID_ARG],
// basic
["attachment; filename=basic",
"attachment", "basic"],
["attachment; filename=basic", "attachment", "basic"],
// extended
["attachment; filename*=UTF-8''extended",
"attachment", "extended"],
["attachment; filename*=UTF-8''extended", "attachment", "extended"],
// prefer extended to basic (bug 588781)
["attachment; filename=basic; filename*=UTF-8''extended",
"attachment", "extended"],
[
"attachment; filename=basic; filename*=UTF-8''extended",
"attachment",
"extended",
],
// prefer extended to basic (bug 588781)
["attachment; filename*=UTF-8''extended; filename=basic",
"attachment", "extended"],
[
"attachment; filename*=UTF-8''extended; filename=basic",
"attachment",
"extended",
],
// use first basic value (invalid; error recovery)
["attachment; filename=first; filename=wrong",
"attachment", "first"],
["attachment; filename=first; filename=wrong", "attachment", "first"],
// old school bad HTTP servers: missing 'attachment' or 'inline'
// (invalid; error recovery)
["filename=old",
"filename=old", "old"],
["filename=old", "filename=old", "old"],
["attachment; filename*=UTF-8''extended",
"attachment", "extended"],
["attachment; filename*=UTF-8''extended", "attachment", "extended"],
// continuations not part of RFC 5987 (bug 610054)
["attachment; filename*0=foo; filename*1=bar",
"attachment", "foobar",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */],
[
"attachment; filename*0=foo; filename*1=bar",
"attachment",
"foobar",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */
],
// Return first continuation (invalid; error recovery)
["attachment; filename*0=first; filename*0=wrong; filename=basic",
"attachment", "first",
/* "attachment", "basic" */],
[
"attachment; filename*0=first; filename*0=wrong; filename=basic",
"attachment",
"first",
/* "attachment", "basic" */
],
// Only use correctly ordered continuations (invalid; error recovery)
["attachment; filename*0=first; filename*1=second; filename*0=wrong",
"attachment", "firstsecond",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */],
[
"attachment; filename*0=first; filename*1=second; filename*0=wrong",
"attachment",
"firstsecond",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */
],
// prefer continuation to basic (unless RFC 5987)
["attachment; filename=basic; filename*0=foo; filename*1=bar",
"attachment", "foobar",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0=foo; filename*1=bar",
"attachment",
"foobar",
/* "attachment", "basic" */
],
// Prefer extended to basic and/or (broken or not) continuation
// (invalid; error recovery)
["attachment; filename=basic; filename*0=first; filename*0=wrong; filename*=UTF-8''extended",
"attachment", "extended"],
[
"attachment; filename=basic; filename*0=first; filename*0=wrong; filename*=UTF-8''extended",
"attachment",
"extended",
],
// RFC 2231 not clear on correct outcome: we prefer non-continued extended
// (invalid; error recovery)
["attachment; filename=basic; filename*=UTF-8''extended; filename*0=foo; filename*1=bar",
"attachment", "extended"],
[
"attachment; filename=basic; filename*=UTF-8''extended; filename*0=foo; filename*1=bar",
"attachment",
"extended",
],
// Gaps should result in returning only value until gap hit
// (invalid; error recovery)
["attachment; filename*0=foo; filename*2=bar",
"attachment", "foo",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */],
[
"attachment; filename*0=foo; filename*2=bar",
"attachment",
"foo",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */
],
// Don't allow leading 0's (*01) (invalid; error recovery)
["attachment; filename*0=foo; filename*01=bar",
"attachment", "foo",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */],
[
"attachment; filename*0=foo; filename*01=bar",
"attachment",
"foo",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */
],
// continuations should prevail over non-extended (unless RFC 5987)
["attachment; filename=basic; filename*0*=UTF-8''multi;\r\n"
+ " filename*1=line;\r\n"
+ " filename*2*=%20extended",
"attachment", "multiline extended",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''multi;\r\n" +
" filename*1=line;\r\n" +
" filename*2*=%20extended",
"attachment",
"multiline extended",
/* "attachment", "basic" */
],
// Gaps should result in returning only value until gap hit
// (invalid; error recovery)
["attachment; filename=basic; filename*0*=UTF-8''multi;\r\n"
+ " filename*1=line;\r\n"
+ " filename*3*=%20extended",
"attachment", "multiline",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''multi;\r\n" +
" filename*1=line;\r\n" +
" filename*3*=%20extended",
"attachment",
"multiline",
/* "attachment", "basic" */
],
// First series, only please, and don't slurp up higher elements (*2 in this
// case) from later series into earlier one (invalid; error recovery)
["attachment; filename=basic; filename*0*=UTF-8''multi;\r\n"
+ " filename*1=line;\r\n"
+ " filename*0*=UTF-8''wrong;\r\n"
+ " filename*1=bad;\r\n"
+ " filename*2=evil",
"attachment", "multiline",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''multi;\r\n" +
" filename*1=line;\r\n" +
" filename*0*=UTF-8''wrong;\r\n" +
" filename*1=bad;\r\n" +
" filename*2=evil",
"attachment",
"multiline",
/* "attachment", "basic" */
],
// RFC 2231 not clear on correct outcome: we prefer non-continued extended
// (invalid; error recovery)
["attachment; filename=basic; filename*0=UTF-8''multi\r\n;"
+ " filename*=UTF-8''extended;\r\n"
+ " filename*1=line;\r\n"
+ " filename*2*=%20extended",
"attachment", "extended"],
[
"attachment; filename=basic; filename*0=UTF-8''multi\r\n;" +
" filename*=UTF-8''extended;\r\n" +
" filename*1=line;\r\n" +
" filename*2*=%20extended",
"attachment",
"extended",
],
// sneaky: if unescaped, make sure we leave UTF-8'' in value
["attachment; filename*0=UTF-8''unescaped;\r\n"
+ " filename*1*=%20so%20includes%20UTF-8''%20in%20value",
"attachment", "UTF-8''unescaped so includes UTF-8'' in value",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */],
[
"attachment; filename*0=UTF-8''unescaped;\r\n" +
" filename*1*=%20so%20includes%20UTF-8''%20in%20value",
"attachment",
"UTF-8''unescaped so includes UTF-8'' in value",
/* "attachment", Cr.NS_ERROR_INVALID_ARG */
],
// sneaky: if unescaped, make sure we leave UTF-8'' in value
["attachment; filename=basic; filename*0=UTF-8''unescaped;\r\n"
+ " filename*1*=%20so%20includes%20UTF-8''%20in%20value",
"attachment", "UTF-8''unescaped so includes UTF-8'' in value",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0=UTF-8''unescaped;\r\n" +
" filename*1*=%20so%20includes%20UTF-8''%20in%20value",
"attachment",
"UTF-8''unescaped so includes UTF-8'' in value",
/* "attachment", "basic" */
],
// Prefer basic over invalid continuation
// (invalid; error recovery)
["attachment; filename=basic; filename*1=multi;\r\n"
+ " filename*2=line;\r\n"
+ " filename*3*=%20extended",
"attachment", "basic"],
[
"attachment; filename=basic; filename*1=multi;\r\n" +
" filename*2=line;\r\n" +
" filename*3*=%20extended",
"attachment",
"basic",
],
// support digits over 10
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n"
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n"
+ " filename*11=b; filename*12=c;filename*13=d;filename*14=e;filename*15=f\r\n",
"attachment", "0123456789abcdef",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''0;\r\n" +
" filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n" +
" filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n" +
" filename*11=b; filename*12=c;filename*13=d;filename*14=e;filename*15=f\r\n",
"attachment",
"0123456789abcdef",
/* "attachment", "basic" */
],
// support digits over 10 (detect gaps)
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n"
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n"
+ " filename*11=b; filename*12=c;filename*14=e\r\n",
"attachment", "0123456789abc",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''0;\r\n" +
" filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n" +
" filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n" +
" filename*11=b; filename*12=c;filename*14=e\r\n",
"attachment",
"0123456789abc",
/* "attachment", "basic" */
],
// return nothing: invalid
// (invalid; error recovery)
["attachment; filename*1=multi;\r\n"
+ " filename*2=line;\r\n"
+ " filename*3*=%20extended",
"attachment", Cr.NS_ERROR_INVALID_ARG],
[
"attachment; filename*1=multi;\r\n" +
" filename*2=line;\r\n" +
" filename*3*=%20extended",
"attachment",
Cr.NS_ERROR_INVALID_ARG,
],
// Bug 272541: Empty disposition type treated as "attachment"
// sanity check
["attachment; filename=foo.html",
"attachment", "foo.html",
"attachment", "foo.html"],
[
"attachment; filename=foo.html",
"attachment",
"foo.html",
"attachment",
"foo.html",
],
// the actual bug
["; filename=foo.html",
Cr.NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY, "foo.html",
Cr.NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY, "foo.html"],
[
"; filename=foo.html",
Cr.NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY,
"foo.html",
Cr.NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY,
"foo.html",
],
// regression check, but see bug 671204
["filename=foo.html",
"filename=foo.html", "foo.html",
"filename=foo.html", "foo.html"],
[
"filename=foo.html",
"filename=foo.html",
"foo.html",
"filename=foo.html",
"foo.html",
],
// Bug 384571: RFC 2231 parameters not decoded when appearing in reversed order
// check ordering
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n"
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n"
+ " filename*11=b; filename*12=c;filename*13=d;filename*15=f;filename*14=e;\r\n",
"attachment", "0123456789abcdef",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''0;\r\n" +
" filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n" +
" filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n" +
" filename*11=b; filename*12=c;filename*13=d;filename*15=f;filename*14=e;\r\n",
"attachment",
"0123456789abcdef",
/* "attachment", "basic" */
],
// check non-digits in sequence numbers
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
+ " filename*1a=1\r\n",
"attachment", "0",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''0;\r\n" +
" filename*1a=1\r\n",
"attachment",
"0",
/* "attachment", "basic" */
],
// check duplicate sequence numbers
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
+ " filename*0=bad; filename*1=1;\r\n",
"attachment", "0",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''0;\r\n" +
" filename*0=bad; filename*1=1;\r\n",
"attachment",
"0",
/* "attachment", "basic" */
],
// check overflow
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
+ " filename*11111111111111111111111111111111111111111111111111111111111=1",
"attachment", "0",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''0;\r\n" +
" filename*11111111111111111111111111111111111111111111111111111111111=1",
"attachment",
"0",
/* "attachment", "basic" */
],
// check underflow
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
+ " filename*-1=1",
"attachment", "0",
/* "attachment", "basic" */],
[
"attachment; filename=basic; filename*0*=UTF-8''0;\r\n" + " filename*-1=1",
"attachment",
"0",
/* "attachment", "basic" */
],
// check mixed token/quoted-string
["attachment; filename=basic; filename*0=\"0\";\r\n"
+ " filename*1=1;\r\n"
+ " filename*2*=%32",
"attachment", "012",
/* "attachment", "basic" */],
[
'attachment; filename=basic; filename*0="0";\r\n' +
" filename*1=1;\r\n" +
" filename*2*=%32",
"attachment",
"012",
/* "attachment", "basic" */
],
// check empty sequence number
["attachment; filename=basic; filename**=UTF-8''0\r\n",
"attachment", "basic",
"attachment", "basic"],
[
"attachment; filename=basic; filename**=UTF-8''0\r\n",
"attachment",
"basic",
"attachment",
"basic",
],
// Bug 419157: ensure that a MIME parameter with no charset information
// fallbacks to Latin-1
["attachment;filename=IT839\x04\xB5(m8)2.pdf;",
"attachment", "IT839\u0004\u00b5(m8)2.pdf"],
[
"attachment;filename=IT839\x04\xB5(m8)2.pdf;",
"attachment",
"IT839\u0004\u00b5(m8)2.pdf",
],
// Bug 588389: unescaping backslashes in quoted string parameters
// '\"', should be parsed as '"'
["attachment; filename=" + DQUOTE + (BS + DQUOTE) + DQUOTE,
"attachment", DQUOTE],
[
"attachment; filename=" + DQUOTE + (BS + DQUOTE) + DQUOTE,
"attachment",
DQUOTE,
],
// 'a\"b', should be parsed as 'a"b'
["attachment; filename=" + DQUOTE + 'a' + (BS + DQUOTE) + 'b' + DQUOTE,
"attachment", "a" + DQUOTE + "b"],
[
"attachment; filename=" + DQUOTE + "a" + (BS + DQUOTE) + "b" + DQUOTE,
"attachment",
"a" + DQUOTE + "b",
],
// '\x', should be parsed as 'x'
["attachment; filename=" + DQUOTE + (BS + "x") + DQUOTE,
"attachment", "x"],
["attachment; filename=" + DQUOTE + (BS + "x") + DQUOTE, "attachment", "x"],
// test empty param (quoted-string)
["attachment; filename=" + DQUOTE + DQUOTE,
"attachment", ""],
["attachment; filename=" + DQUOTE + DQUOTE, "attachment", ""],
// test empty param
["attachment; filename=",
"attachment", ""],
["attachment; filename=", "attachment", ""],
// Bug 601933: RFC 2047 does not apply to parameters (at least in HTTP)
["attachment; filename==?ISO-8859-1?Q?foo-=E4.html?=",
"attachment", "foo-\u00e4.html",
/* "attachment", "=?ISO-8859-1?Q?foo-=E4.html?=" */],
[
"attachment; filename==?ISO-8859-1?Q?foo-=E4.html?=",
"attachment",
"foo-\u00e4.html",
/* "attachment", "=?ISO-8859-1?Q?foo-=E4.html?=" */
],
["attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"",
"attachment", "foo-\u00e4.html",
/* "attachment", "=?ISO-8859-1?Q?foo-=E4.html?=" */],
[
'attachment; filename="=?ISO-8859-1?Q?foo-=E4.html?="',
"attachment",
"foo-\u00e4.html",
/* "attachment", "=?ISO-8859-1?Q?foo-=E4.html?=" */
],
// format sent by GMail as of 2012-07-23 (5987 overrides 2047)
["attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"; filename*=UTF-8''5987",
"attachment", "5987"],
[
"attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"; filename*=UTF-8''5987",
"attachment",
"5987",
],
// Bug 651185: double quotes around 2231/5987 encoded param
// Change reverted to backwards compat issues with various web services,
@ -281,12 +382,14 @@ var tests = [
// is tried again in the future, email probably needs to be special-cased.
// sanity check
["attachment; filename*=utf-8''%41",
"attachment", "A"],
["attachment; filename*=utf-8''%41", "attachment", "A"],
// the actual bug
["attachment; filename*=" + DQUOTE + "utf-8''%41" + DQUOTE,
"attachment", "A"],
[
"attachment; filename*=" + DQUOTE + "utf-8''%41" + DQUOTE,
"attachment",
"A",
],
// previously with the fix for 651185:
// "attachment", Cr.NS_ERROR_INVALID_ARG],
@ -294,52 +397,51 @@ var tests = [
// in params
// sanity check
["attachment; filename*=UTF-8''foo-%41.html",
"attachment", "foo-A.html"],
["attachment; filename*=UTF-8''foo-%41.html", "attachment", "foo-A.html"],
// the actual bug
["attachment; filename *=UTF-8''foo-%41.html",
"attachment", Cr.NS_ERROR_INVALID_ARG],
[
"attachment; filename *=UTF-8''foo-%41.html",
"attachment",
Cr.NS_ERROR_INVALID_ARG,
],
// the actual bug, without 2231/5987 encoding
["attachment; filename X",
"attachment", Cr.NS_ERROR_INVALID_ARG],
["attachment; filename X", "attachment", Cr.NS_ERROR_INVALID_ARG],
// sanity check with WS on both sides
["attachment; filename = foo-A.html",
"attachment", "foo-A.html"],
["attachment; filename = foo-A.html", "attachment", "foo-A.html"],
// Bug 685192: in RFC2231/5987 encoding, a missing charset field should be
// treated as error
// the actual bug
["attachment; filename*=''foo",
"attachment", "foo"],
["attachment; filename*=''foo", "attachment", "foo"],
// previously with the fix for 692574:
// "attachment", Cr.NS_ERROR_INVALID_ARG],
// sanity check
["attachment; filename*=a''foo",
"attachment", "foo"],
["attachment; filename*=a''foo", "attachment", "foo"],
// Bug 692574: RFC2231/5987 decoding should not tolerate missing single
// quotes
// one missing
["attachment; filename*=UTF-8'foo-%41.html",
"attachment", "foo-A.html"],
["attachment; filename*=UTF-8'foo-%41.html", "attachment", "foo-A.html"],
// previously with the fix for 692574:
// "attachment", Cr.NS_ERROR_INVALID_ARG],
// both missing
["attachment; filename*=foo-%41.html",
"attachment","foo-A.html"],
["attachment; filename*=foo-%41.html", "attachment", "foo-A.html"],
// previously with the fix for 692574:
// "attachment", Cr.NS_ERROR_INVALID_ARG],
// make sure fallback works
["attachment; filename*=UTF-8'foo-%41.html; filename=bar.html",
"attachment", "foo-A.html"],
[
"attachment; filename*=UTF-8'foo-%41.html; filename=bar.html",
"attachment",
"foo-A.html",
],
// previously with the fix for 692574:
// "attachment", "bar.html"],
@ -347,134 +449,209 @@ var tests = [
// as authoritative
// UTF-8 labeled ISO-8859-1
["attachment; filename*=ISO-8859-1''%c3%a4",
"attachment", "\u00c3\u00a4"],
["attachment; filename*=ISO-8859-1''%c3%a4", "attachment", "\u00c3\u00a4"],
// UTF-8 labeled ISO-8859-1, but with octets not allowed in ISO-8859-1
// accepts x82, understands it as Win1252, maps it to Unicode \u20a1
["attachment; filename*=ISO-8859-1''%e2%82%ac",
"attachment", "\u00e2\u201a\u00ac"],
[
"attachment; filename*=ISO-8859-1''%e2%82%ac",
"attachment",
"\u00e2\u201a\u00ac",
],
// defective UTF-8
["attachment; filename*=UTF-8''A%e4B",
"attachment", Cr.NS_ERROR_INVALID_ARG],
["attachment; filename*=UTF-8''A%e4B", "attachment", Cr.NS_ERROR_INVALID_ARG],
// defective UTF-8, with fallback
["attachment; filename*=UTF-8''A%e4B; filename=fallback",
"attachment", "fallback"],
[
"attachment; filename*=UTF-8''A%e4B; filename=fallback",
"attachment",
"fallback",
],
// defective UTF-8 (continuations), with fallback
["attachment; filename*0*=UTF-8''A%e4B; filename=fallback",
"attachment", "fallback"],
[
"attachment; filename*0*=UTF-8''A%e4B; filename=fallback",
"attachment",
"fallback",
],
// check that charsets aren't mixed up
["attachment; filename*0*=ISO-8859-15''euro-sign%3d%a4; filename*=ISO-8859-1''currency-sign%3d%a4",
"attachment", "currency-sign=\u00a4"],
[
"attachment; filename*0*=ISO-8859-15''euro-sign%3d%a4; filename*=ISO-8859-1''currency-sign%3d%a4",
"attachment",
"currency-sign=\u00a4",
],
// same as above, except reversed
["attachment; filename*=ISO-8859-1''currency-sign%3d%a4; filename*0*=ISO-8859-15''euro-sign%3d%a4",
"attachment", "currency-sign=\u00a4"],
[
"attachment; filename*=ISO-8859-1''currency-sign%3d%a4; filename*0*=ISO-8859-15''euro-sign%3d%a4",
"attachment",
"currency-sign=\u00a4",
],
// Bug 704989: add workaround for broken Outlook Web App (OWA)
// attachment handling
["attachment; filename*=\"a%20b\"",
"attachment", "a b"],
['attachment; filename*="a%20b"', "attachment", "a b"],
// Bug 717121: crash nsMIMEHeaderParamImpl::DoParameterInternal
["attachment; filename=\"",
"attachment", ""],
['attachment; filename="', "attachment", ""],
// We used to read past string if last param w/o = and ;
// Note: was only detected on windows PGO builds
["attachment; filename=foo; trouble",
"attachment", "foo"],
["attachment; filename=foo; trouble", "attachment", "foo"],
// Same, followed by space, hits another case
["attachment; filename=foo; trouble ",
"attachment", "foo"],
["attachment; filename=foo; trouble ", "attachment", "foo"],
["attachment",
"attachment", Cr.NS_ERROR_INVALID_ARG],
["attachment", "attachment", Cr.NS_ERROR_INVALID_ARG],
// Bug 730574: quoted-string in RFC2231-continuations not handled
['attachment; filename=basic; filename*0="foo"; filename*1="\\b\\a\\r.html"',
"attachment", "foobar.html",
/* "attachment", "basic" */],
[
'attachment; filename=basic; filename*0="foo"; filename*1="\\b\\a\\r.html"',
"attachment",
"foobar.html",
/* "attachment", "basic" */
],
// unmatched escape char
['attachment; filename=basic; filename*0="foo"; filename*1="\\b\\a\\',
"attachment", "fooba\\",
/* "attachment", "basic" */],
[
'attachment; filename=basic; filename*0="foo"; filename*1="\\b\\a\\',
"attachment",
"fooba\\",
/* "attachment", "basic" */
],
// Bug 732369: Content-Disposition parser does not require presence of ";" between params
// optimally, this would not even return the disposition type "attachment"
["attachment; extension=bla filename=foo",
"attachment", Cr.NS_ERROR_INVALID_ARG],
[
"attachment; extension=bla filename=foo",
"attachment",
Cr.NS_ERROR_INVALID_ARG,
],
["attachment; filename=foo extension=bla",
"attachment", "foo"],
["attachment; filename=foo extension=bla", "attachment", "foo"],
["attachment filename=foo",
"attachment", Cr.NS_ERROR_INVALID_ARG],
["attachment filename=foo", "attachment", Cr.NS_ERROR_INVALID_ARG],
// Bug 777687: handling of broken %escapes
["attachment; filename*=UTF-8''f%oo; filename=bar",
"attachment", "bar"],
["attachment; filename*=UTF-8''f%oo; filename=bar", "attachment", "bar"],
["attachment; filename*=UTF-8''foo%; filename=bar",
"attachment", "bar"],
["attachment; filename*=UTF-8''foo%; filename=bar", "attachment", "bar"],
// Bug 783502 - xpcshell test netwerk/test/unit/test_MIME_params.js fails on AddressSanitizer
['attachment; filename="\\b\\a\\',
"attachment", "ba\\"],
['attachment; filename="\\b\\a\\', "attachment", "ba\\"],
// Bug 1412213 - do continue to parse, behind an empty parameter
['attachment; ; filename=foo',
"attachment", "foo"],
["attachment; ; filename=foo", "attachment", "foo"],
// Bug 1412213 - do continue to parse, behind a parameter w/o =
['attachment; badparameter; filename=foo',
"attachment", "foo"],
["attachment; badparameter; filename=foo", "attachment", "foo"],
];
var rfc5987paramtests = [
[ // basic test
"UTF-8'language'value", "value", "language", Cr.NS_OK ],
[ // percent decoding
"UTF-8''1%202", "1 2", "", Cr.NS_OK ],
[ // UTF-8
"UTF-8''%c2%a3%20and%20%e2%82%ac%20rates", "\u00a3 and \u20ac rates", "", Cr.NS_OK ],
[ // missing charset
"''abc", "", "", Cr.NS_ERROR_INVALID_ARG ],
[ // ISO-8859-1: unsupported
"ISO-8859-1''%A3%20rates", "", "", Cr.NS_ERROR_INVALID_ARG ],
[ // unknown charset
"foo''abc", "", "", Cr.NS_ERROR_INVALID_ARG ],
[ // missing component
"abc", "", "", Cr.NS_ERROR_INVALID_ARG ],
[ // missing component
"'abc", "", "", Cr.NS_ERROR_INVALID_ARG ],
[ // illegal chars
"UTF-8''a b", "", "", Cr.NS_ERROR_INVALID_ARG ],
[ // broken % escapes
"UTF-8''a%zz", "", "", Cr.NS_ERROR_INVALID_ARG ],
[ // broken % escapes
"UTF-8''a%b", "", "", Cr.NS_ERROR_INVALID_ARG ],
[ // broken % escapes
"UTF-8''a%", "", "", Cr.NS_ERROR_INVALID_ARG ],
[ // broken UTF-8
"UTF-8''%A3%20rates", "", "", 0x8050000E /* NS_ERROR_UDEC_ILLEGALINPUT */ ],
[
// basic test
"UTF-8'language'value",
"value",
"language",
Cr.NS_OK,
],
[
// percent decoding
"UTF-8''1%202",
"1 2",
"",
Cr.NS_OK,
],
[
// UTF-8
"UTF-8''%c2%a3%20and%20%e2%82%ac%20rates",
"\u00a3 and \u20ac rates",
"",
Cr.NS_OK,
],
[
// missing charset
"''abc",
"",
"",
Cr.NS_ERROR_INVALID_ARG,
],
[
// ISO-8859-1: unsupported
"ISO-8859-1''%A3%20rates",
"",
"",
Cr.NS_ERROR_INVALID_ARG,
],
[
// unknown charset
"foo''abc",
"",
"",
Cr.NS_ERROR_INVALID_ARG,
],
[
// missing component
"abc",
"",
"",
Cr.NS_ERROR_INVALID_ARG,
],
[
// missing component
"'abc",
"",
"",
Cr.NS_ERROR_INVALID_ARG,
],
[
// illegal chars
"UTF-8''a b",
"",
"",
Cr.NS_ERROR_INVALID_ARG,
],
[
// broken % escapes
"UTF-8''a%zz",
"",
"",
Cr.NS_ERROR_INVALID_ARG,
],
[
// broken % escapes
"UTF-8''a%b",
"",
"",
Cr.NS_ERROR_INVALID_ARG,
],
[
// broken % escapes
"UTF-8''a%",
"",
"",
Cr.NS_ERROR_INVALID_ARG,
],
[
// broken UTF-8
"UTF-8''%A3%20rates",
"",
"",
0x8050000e /* NS_ERROR_UDEC_ILLEGALINPUT */,
],
];
function do_tests(whichRFC)
{
var mhp = Cc["@mozilla.org/network/mime-hdrparam;1"]
.getService(Ci.nsIMIMEHeaderParam);
function do_tests(whichRFC) {
var mhp = Cc["@mozilla.org/network/mime-hdrparam;1"].getService(
Ci.nsIMIMEHeaderParam
);
var unused = { value: null };
@ -482,19 +659,20 @@ function do_tests(whichRFC)
dump("Testing #" + i + ": " + tests[i] + "\n");
// check disposition type
var expectedDt = tests[i].length == 3 || whichRFC == 0 ? tests[i][1] : tests[i][3];
var expectedDt =
tests[i].length == 3 || whichRFC == 0 ? tests[i][1] : tests[i][3];
try {
var result;
if (whichRFC == 0)
if (whichRFC == 0) {
result = mhp.getParameter(tests[i][0], "", "UTF-8", true, unused);
else
} else {
result = mhp.getParameterHTTP(tests[i][0], "", "UTF-8", true, unused);
}
Assert.equal(result, expectedDt);
}
catch (e) {
} catch (e) {
// Tests can also succeed by expecting to fail with given error code
if (e.result) {
// Allow following tests to run by catching exception from do_check_eq()
@ -506,19 +684,32 @@ function do_tests(whichRFC)
}
// check filename parameter
var expectedFn = tests[i].length == 3 || whichRFC == 0 ? tests[i][2] : tests[i][4];
var expectedFn =
tests[i].length == 3 || whichRFC == 0 ? tests[i][2] : tests[i][4];
try {
var result;
if (whichRFC == 0)
result = mhp.getParameter(tests[i][0], "filename", "UTF-8", true, unused);
else
result = mhp.getParameterHTTP(tests[i][0], "filename", "UTF-8", true, unused);
if (whichRFC == 0) {
result = mhp.getParameter(
tests[i][0],
"filename",
"UTF-8",
true,
unused
);
} else {
result = mhp.getParameterHTTP(
tests[i][0],
"filename",
"UTF-8",
true,
unused
);
}
Assert.equal(result, expectedFn);
}
catch (e) {
} catch (e) {
// Tests can also succeed by expecting to fail with given error code
if (e.result) {
// Allow following tests to run by catching exception from do_check_eq()
@ -532,8 +723,9 @@ function do_tests(whichRFC)
}
function test_decode5987Param() {
var mhp = Cc["@mozilla.org/network/mime-hdrparam;1"]
.getService(Ci.nsIMIMEHeaderParam);
var mhp = Cc["@mozilla.org/network/mime-hdrparam;1"].getService(
Ci.nsIMIMEHeaderParam
);
for (var i = 0; i < rfc5987paramtests.length; ++i) {
dump("Testing #" + i + ": " + rfc5987paramtests[i] + "\n");
@ -544,19 +736,16 @@ function test_decode5987Param() {
if (rfc5987paramtests[i][3] == Cr.NS_OK) {
Assert.equal(rfc5987paramtests[i][1], decoded);
Assert.equal(rfc5987paramtests[i][2], lang.value);
}
else {
} else {
Assert.equal(rfc5987paramtests[i][3], "instead got: " + decoded);
}
}
catch (e) {
} catch (e) {
Assert.equal(rfc5987paramtests[i][3], e.result);
}
}
}
function run_test() {
// Test RFC 2231 (complete header field values)
do_tests(0);

View file

@ -10,13 +10,13 @@
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,16 +28,17 @@ 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 = {};
@ -46,7 +47,6 @@ function getFileContents(aFile)
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,22 +143,24 @@ 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 };
}
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 };
}
@ -159,10 +168,11 @@ function test_async_copy()
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);
@ -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() {});
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({});
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,21 +325,25 @@ 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({
NetUtil.asyncFetch(
{
uri,
loadUsingSystemPrincipal: true,
}, function(aInputStream, aResult) {
},
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);
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);
@ -349,11 +354,11 @@ function test_asyncFetch_with_nsIURI()
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
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,17 +371,20 @@ function test_asyncFetch_with_string()
server.start(-1);
// Open our location asynchronously.
NetUtil.asyncFetch({
NetUtil.asyncFetch(
{
uri: "http://localhost:" + server.identity.primaryPort + "/test",
loadUsingSystemPrincipal: true,
}, function(aInputStream, aResult) {
},
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);
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);
@ -387,23 +395,24 @@ function test_asyncFetch_with_string()
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
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,17 +421,20 @@ 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({
NetUtil.asyncFetch(
{
uri: NetUtil.newURI(file),
loadUsingSystemPrincipal: true,
}, function(aInputStream, aResult) {
},
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);
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);
@ -433,25 +445,30 @@ function test_asyncFetch_with_nsIFile()
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
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) {
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);
Assert.equal(
NetUtil.readInputStreamToString(aInputStream, TEST_DATA.length),
TEST_DATA
);
run_next_test();
},
@ -459,11 +476,11 @@ function test_asyncFetch_with_nsIInputString()
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
Ci.nsIContentPolicy.TYPE_OTHER);
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,
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);
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,
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);
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),
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);
Ci.nsIContentPolicy.TYPE_OTHER
);
function checkEqualToIOSChannel(channel) {
Assert.ok(iosChannel.URI.equals(channel.URI));
}
checkEqualToIOSChannel(NetUtil.newChannel({
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({
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, {
Assert.equal(
NetUtil.readInputStreamToString(istream, TEST_DATA_UTF8.length, {
charset: "UTF-8",
replacement: Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER}),
TEST_DATA);
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

View file

@ -1,8 +1,8 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
var gIoService = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var gIoService = Cc["@mozilla.org/network/io-service;1"].getService(
Ci.nsIIOService
);
// Run by: cd objdir; make -C netwerk/test/ xpcshell-tests
// or: cd objdir; make SOLO_FILE="test_URIs2.js" -C netwerk/test/ check-one
@ -19,81 +19,117 @@ var gIoService = Cc["@mozilla.org/network/io-service;1"]
// TEST DATA
// ---------
var gTests = [
{ spec: "view-source:about:blank",
{
spec: "view-source:about:blank",
scheme: "view-source",
prePath: "view-source:",
pathQueryRef: "about:blank",
ref: "",
nsIURL: false, nsINestedURI: true, immutable: true },
{ spec: "view-source:http://www.mozilla.org/",
nsIURL: false,
nsINestedURI: true,
immutable: true,
},
{
spec: "view-source:http://www.mozilla.org/",
scheme: "view-source",
prePath: "view-source:",
pathQueryRef: "http://www.mozilla.org/",
ref: "",
nsIURL: false, nsINestedURI: true, immutable: true },
{ spec: "x-external:",
nsIURL: false,
nsINestedURI: true,
immutable: true,
},
{
spec: "x-external:",
scheme: "x-external",
prePath: "x-external:",
pathQueryRef: "",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "x-external:abc",
nsIURL: false,
nsINestedURI: false,
},
{
spec: "x-external:abc",
scheme: "x-external",
prePath: "x-external:",
pathQueryRef: "abc",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "http://www2.example.com/",
nsIURL: false,
nsINestedURI: false,
},
{
spec: "http://www2.example.com/",
relativeURI: "a/b/c/d",
scheme: "http",
prePath: "http://www2.example.com",
pathQueryRef: "/a/b/c/d",
ref: "",
nsIURL: true, nsINestedURI: false },
nsIURL: true,
nsINestedURI: false,
},
// relative URL testcases from http://greenbytes.de/tech/webdav/rfc3986.html#rfc.section.5.4
{ spec: "http://a/b/c/d;p?q",
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g:h",
scheme: "g",
prePath: "g:",
pathQueryRef: "h",
ref: "",
nsIURL: false, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: false,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "./g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g/",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "/g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "?y",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/d;p?y",
ref: "", // fix
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g?y",
scheme: "http",
prePath: "http://a",
@ -101,8 +137,11 @@ var gTests = [
ref: "", // fix
specIgnoringRef: "http://a/b/c/g?y",
hasRef: false,
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "#s",
scheme: "http",
prePath: "http://a",
@ -110,21 +149,29 @@ var gTests = [
ref: "s", // fix
specIgnoringRef: "http://a/b/c/d;p?q",
hasRef: true,
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g#s",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g#s",
ref: "s",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g?y#s",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g?y#s",
ref: "s",
nsIURL: true, nsINestedURI: false },
nsIURL: true,
nsINestedURI: false,
},
/*
Bug xxxxxx - we return a path of b/c/;x
{ spec: "http://a/b/c/d;p?q",
@ -135,20 +182,26 @@ var gTests = [
ref: "",
nsIURL: true, nsINestedURI: false },
*/
{ spec: "http://a/b/c/d;p?q",
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g;x",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g;x",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g;x?y#s",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g;x?y#s",
ref: "s",
nsIURL: true, nsINestedURI: false },
nsIURL: true,
nsINestedURI: false,
},
/*
Can't easily specify a relative URI of "" to the test code
{ spec: "http://a/b/c/d;p?q",
@ -159,205 +212,284 @@ var gTests = [
ref: "",
nsIURL: true, nsINestedURI: false },
*/
{ spec: "http://a/b/c/d;p?q",
{
spec: "http://a/b/c/d;p?q",
relativeURI: ".",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "./",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "..",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "../",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "../g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "../..",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "../../",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "../../g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/g",
ref: "",
nsIURL: true, nsINestedURI: false },
nsIURL: true,
nsINestedURI: false,
},
// abnormal examples
{ spec: "http://a/b/c/d;p?q",
{
spec: "http://a/b/c/d;p?q",
relativeURI: "../../../g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "../../../../g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/g",
ref: "",
nsIURL: true, nsINestedURI: false },
nsIURL: true,
nsINestedURI: false,
},
// coalesce
{ spec: "http://a/b/c/d;p?q",
{
spec: "http://a/b/c/d;p?q",
relativeURI: "/./g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "/../g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g.",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g.",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: ".g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/.g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g..",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g..",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "..g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/..g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: ".",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "./../g",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/g",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "./g/.",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g/./h",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g/h",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g/../h",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/h",
ref: "", // fix
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g;x=1/./y",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/g;x=1/y",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://a/b/c/d;p?q",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "http://a/b/c/d;p?q",
relativeURI: "g;x=1/../y",
scheme: "http",
prePath: "http://a",
pathQueryRef: "/b/c/y",
ref: "",
nsIURL: true, nsINestedURI: false },
nsIURL: true,
nsINestedURI: false,
},
// protocol-relative http://tools.ietf.org/html/rfc3986#section-4.2
{ spec: "http://www2.example.com/",
{
spec: "http://www2.example.com/",
relativeURI: "//www3.example2.com/bar",
scheme: "http",
prePath: "http://www3.example2.com",
pathQueryRef: "/bar",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "https://www2.example.com/",
nsIURL: true,
nsINestedURI: false,
},
{
spec: "https://www2.example.com/",
relativeURI: "//www3.example2.com/bar",
scheme: "https",
prePath: "https://www3.example2.com",
pathQueryRef: "/bar",
ref: "",
nsIURL: true, nsINestedURI: false },
nsIURL: true,
nsINestedURI: false,
},
];
var gHashSuffixes = [
"#",
"#myRef",
"#myRef?a=b",
"#myRef#",
"#myRef#x:yz"
];
var gHashSuffixes = ["#", "#myRef", "#myRef?a=b", "#myRef#", "#myRef#x:yz"];
// TEST HELPER FUNCTIONS
// ---------------------
function do_info(text, stack) {
if (!stack)
if (!stack) {
stack = Components.stack.caller;
}
dump( "\n" +
"TEST-INFO | " + stack.filename + " | [" + stack.name + " : " +
stack.lineNumber + "] " + text + "\n");
dump(
"\n" +
"TEST-INFO | " +
stack.filename +
" | [" +
stack.name +
" : " +
stack.lineNumber +
"] " +
text +
"\n"
);
}
// Checks that the URIs satisfy equals(), in both possible orderings.
@ -385,11 +517,13 @@ function do_check_uri_eq(aURI1, aURI2, aCheckTrueFunc = ok) {
// The third argument is optional. If the client passes a third argument
// (e.g. todo_check_true), we'll use that in lieu of ok.
function do_check_uri_eqExceptRef(aURI1, aURI2, aCheckTrueFunc = ok) {
do_info("(uri equalsExceptRef check: '" +
aURI1.spec + "' == '" + aURI2.spec + "')");
do_info(
"(uri equalsExceptRef check: '" + aURI1.spec + "' == '" + aURI2.spec + "')"
);
aCheckTrueFunc(aURI1.equalsExceptRef(aURI2));
do_info("(uri equalsExceptRef check: '" +
aURI2.spec + "' == '" + aURI1.spec + "')");
do_info(
"(uri equalsExceptRef check: '" + aURI2.spec + "' == '" + aURI1.spec + "')"
);
aCheckTrueFunc(aURI2.equalsExceptRef(aURI1));
}
@ -398,13 +532,20 @@ function do_check_uri_eqExceptRef(aURI1, aURI2, aCheckTrueFunc = ok) {
// if aTestFunctor is passed in).
function do_check_property(aTest, aURI, aPropertyName, aTestFunctor) {
if (aTest[aPropertyName]) {
var expectedVal = aTestFunctor ?
aTestFunctor(aTest[aPropertyName]) :
aTest[aPropertyName];
var expectedVal = aTestFunctor
? aTestFunctor(aTest[aPropertyName])
: aTest[aPropertyName];
do_info("testing " + aPropertyName + " of " +
(aTestFunctor ? "modified '" : "'" ) + aTest.spec +
"' is '" + expectedVal + "'");
do_info(
"testing " +
aPropertyName +
" of " +
(aTestFunctor ? "modified '" : "'") +
aTest.spec +
"' is '" +
expectedVal +
"'"
);
Assert.equal(aURI[aPropertyName], expectedVal);
}
}
@ -413,7 +554,9 @@ function do_check_property(aTest, aURI, aPropertyName, aTestFunctor) {
function do_test_uri_basic(aTest) {
var URI;
do_info("Basic tests for " + aTest.spec + " relative URI: " + aTest.relativeURI);
do_info(
"Basic tests for " + aTest.spec + " relative URI: " + aTest.relativeURI
);
try {
URI = NetUtil.newURI(aTest.spec);
@ -432,14 +575,26 @@ function do_test_uri_basic(aTest) {
try {
relURI = gIoService.newURI(aTest.relativeURI, null, URI);
} catch (e) {
do_info("Caught error on Relative parse of " + aTest.spec + " + " + aTest.relativeURI +" Error: " + e.result);
do_info(
"Caught error on Relative parse of " +
aTest.spec +
" + " +
aTest.relativeURI +
" Error: " +
e.result
);
if (aTest.relativeFail) {
Assert.equal(e.result, aTest.relativeFail);
return;
}
do_throw(e.result);
}
do_info("relURI.pathQueryRef = " + relURI.pathQueryRef + ", was " + URI.pathQueryRef);
do_info(
"relURI.pathQueryRef = " +
relURI.pathQueryRef +
", was " +
URI.pathQueryRef
);
URI = relURI;
do_info("URI.pathQueryRef now = " + URI.pathQueryRef);
}
@ -447,15 +602,23 @@ function do_test_uri_basic(aTest) {
// Sanity-check
do_info("testing " + aTest.spec + " equals a clone of itself");
do_check_uri_eq(URI, URI.mutate().finalize());
do_check_uri_eqExceptRef(URI, URI.mutate().setRef("").finalize());
do_check_uri_eqExceptRef(
URI,
URI.mutate()
.setRef("")
.finalize()
);
do_info("testing " + aTest.spec + " instanceof nsIURL");
Assert.equal(URI instanceof Ci.nsIURL, aTest.nsIURL);
do_info("testing " + aTest.spec + " instanceof nsINestedURI");
Assert.equal(URI instanceof Ci.nsINestedURI,
aTest.nsINestedURI);
Assert.equal(URI instanceof Ci.nsINestedURI, aTest.nsINestedURI);
do_info("testing that " + aTest.spec + " throws or returns false " +
"from equals(null)");
do_info(
"testing that " +
aTest.spec +
" throws or returns false " +
"from equals(null)"
);
// XXXdholbert At some point it'd probably be worth making this behavior
// (throwing vs. returning false) consistent across URI implementations.
var threw = false;
@ -467,7 +630,6 @@ function do_test_uri_basic(aTest) {
}
Assert.ok(threw || !isEqualToNull);
// Check the various components
do_check_property(aTest, URI, "scheme");
do_check_property(aTest, URI, "prePath");
@ -497,39 +659,77 @@ function do_test_uri_with_hash_suffix(aTest, aSuffix) {
try {
origURI = gIoService.newURI(aTest.relativeURI, null, origURI);
} catch (e) {
do_info("Caught error on Relative parse of " + aTest.spec + " + " + aTest.relativeURI +" Error: " + e.result);
do_info(
"Caught error on Relative parse of " +
aTest.spec +
" + " +
aTest.relativeURI +
" Error: " +
e.result
);
return;
}
try {
testURI = gIoService.newURI(aSuffix, null, origURI);
} catch (e) {
do_info("Caught error adding suffix to " + aTest.spec + " + " + aTest.relativeURI + ", suffix " + aSuffix + " Error: " + e.result);
do_info(
"Caught error adding suffix to " +
aTest.spec +
" + " +
aTest.relativeURI +
", suffix " +
aSuffix +
" Error: " +
e.result
);
return;
}
} else {
testURI = NetUtil.newURI(aTest.spec + aSuffix);
}
do_info("testing " + aTest.spec + " with '" + aSuffix + "' appended " +
"equals a clone of itself");
do_info(
"testing " +
aTest.spec +
" with '" +
aSuffix +
"' appended " +
"equals a clone of itself"
);
do_check_uri_eq(testURI, testURI.mutate().finalize());
do_info("testing " + aTest.spec +
" doesn't equal self with '" + aSuffix + "' appended");
do_info(
"testing " +
aTest.spec +
" doesn't equal self with '" +
aSuffix +
"' appended"
);
Assert.ok(!origURI.equals(testURI));
do_info("testing " + aTest.spec +
" is equalExceptRef to self with '" + aSuffix + "' appended");
do_info(
"testing " +
aTest.spec +
" is equalExceptRef to self with '" +
aSuffix +
"' appended"
);
do_check_uri_eqExceptRef(origURI, testURI);
Assert.equal(testURI.hasRef, true);
if (!origURI.ref) {
// These tests fail if origURI has a ref
do_info("testing cloneIgnoringRef on " + testURI.spec +
" is equal to no-ref version but not equal to ref version");
var cloneNoRef = testURI.mutate().setRef("").finalize();
do_info(
"testing cloneIgnoringRef on " +
testURI.spec +
" is equal to no-ref version but not equal to ref version"
);
var cloneNoRef = testURI
.mutate()
.setRef("")
.finalize();
do_check_uri_eq(cloneNoRef, origURI);
Assert.ok(!cloneNoRef.equals(testURI));
}
@ -538,10 +738,12 @@ function do_test_uri_with_hash_suffix(aTest, aSuffix) {
do_check_property(aTest, testURI, "prePath");
if (!origURI.ref) {
// These don't work if it's a ref already because '+' doesn't give the right result
do_check_property(aTest, testURI, "pathQueryRef",
function(aStr) { return aStr + aSuffix; });
do_check_property(aTest, testURI, "ref",
function(aStr) { return aSuffix.substr(1); });
do_check_property(aTest, testURI, "pathQueryRef", function(aStr) {
return aStr + aSuffix;
});
do_check_property(aTest, testURI, "ref", function(aStr) {
return aSuffix.substr(1);
});
}
}
@ -556,26 +758,47 @@ function do_test_mutate_ref(aTest, aSuffix) {
var testURI = NetUtil.newURI(aTest.spec);
// First: Try setting .ref to our suffix
do_info("testing that setting .ref on " + aTest.spec +
" to '" + aSuffix + "' does what we expect");
testURI = testURI.mutate().setRef(aSuffix).finalize();
do_info(
"testing that setting .ref on " +
aTest.spec +
" to '" +
aSuffix +
"' does what we expect"
);
testURI = testURI
.mutate()
.setRef(aSuffix)
.finalize();
do_check_uri_eq(testURI, refURIWithSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithoutSuffix);
// Now try setting .ref but leave off the initial hash (expect same result)
var suffixLackingHash = aSuffix.substr(1);
if (suffixLackingHash) { // (skip this our suffix was *just* a #)
do_info("testing that setting .ref on " + aTest.spec +
" to '" + suffixLackingHash + "' does what we expect");
testURI = testURI.mutate().setRef(suffixLackingHash).finalize();
if (suffixLackingHash) {
// (skip this our suffix was *just* a #)
do_info(
"testing that setting .ref on " +
aTest.spec +
" to '" +
suffixLackingHash +
"' does what we expect"
);
testURI = testURI
.mutate()
.setRef(suffixLackingHash)
.finalize();
do_check_uri_eq(testURI, refURIWithSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithoutSuffix);
}
// Now, clear .ref (should get us back the original spec)
do_info("testing that clearing .ref on " + testURI.spec +
" does what we expect");
testURI = testURI.mutate().setRef("").finalize();
do_info(
"testing that clearing .ref on " + testURI.spec + " does what we expect"
);
testURI = testURI
.mutate()
.setRef("")
.finalize();
do_check_uri_eq(testURI, refURIWithoutSuffix);
do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
@ -584,9 +807,13 @@ function do_test_mutate_ref(aTest, aSuffix) {
// Now try setting .spec directly (including suffix) and then clearing .ref
var specWithSuffix = aTest.spec + aSuffix;
do_info("testing that setting spec to " +
specWithSuffix + " and then clearing ref does what we expect");
testURI = testURI.mutate()
do_info(
"testing that setting spec to " +
specWithSuffix +
" and then clearing ref does what we expect"
);
testURI = testURI
.mutate()
.setSpec(specWithSuffix)
.setRef("")
.finalize();
@ -600,9 +827,13 @@ function do_test_mutate_ref(aTest, aSuffix) {
testURI = NetUtil.newURI(aTest.spec);
var pathWithSuffix = aTest.pathQueryRef + aSuffix;
do_info("testing that setting path to " +
pathWithSuffix + " and then clearing ref does what we expect");
testURI = testURI.mutate()
do_info(
"testing that setting path to " +
pathWithSuffix +
" and then clearing ref does what we expect"
);
testURI = testURI
.mutate()
.setPathQueryRef(pathWithSuffix)
.setRef("")
.finalize();
@ -610,10 +841,19 @@ function do_test_mutate_ref(aTest, aSuffix) {
do_check_uri_eqExceptRef(testURI, refURIWithSuffix);
// Also: make sure that clearing .pathQueryRef also clears .ref
testURI = testURI.mutate().setPathQueryRef(pathWithSuffix).finalize();
do_info("testing that clearing path from " +
pathWithSuffix + " also clears .ref");
testURI = testURI.mutate().setPathQueryRef("").finalize();
testURI = testURI
.mutate()
.setPathQueryRef(pathWithSuffix)
.finalize();
do_info(
"testing that clearing path from " +
pathWithSuffix +
" also clears .ref"
);
testURI = testURI
.mutate()
.setPathQueryRef("")
.finalize();
Assert.equal(testURI.ref, "");
}
}
@ -621,14 +861,15 @@ function do_test_mutate_ref(aTest, aSuffix) {
// TEST MAIN FUNCTION
// ------------------
function run_test()
{
function run_test() {
// UTF-8 check - From bug 622981
// ASCII
let base = gIoService.newURI("http://example.org/xenia?");
let resolved = gIoService.newURI("?x", null, base);
let expected = gIoService.newURI("http://example.org/xenia?x");
do_info("Bug 662981: ACSII - comparing " + resolved.spec + " and " + expected.spec);
do_info(
"Bug 662981: ACSII - comparing " + resolved.spec + " and " + expected.spec
);
Assert.ok(resolved.equals(expected));
// UTF-8 character "è"
@ -636,7 +877,9 @@ function run_test()
base = gIoService.newURI("http://example.org/xènia?");
resolved = gIoService.newURI("?x", null, base);
expected = gIoService.newURI("http://example.org/xènia?x");
do_info("Bug 662981: UTF8 - comparing " + resolved.spec + " and " + expected.spec);
do_info(
"Bug 662981: UTF8 - comparing " + resolved.spec + " and " + expected.spec
);
Assert.ok(resolved.equals(expected));
gTests.forEach(function(aTest) {

View file

@ -5,7 +5,9 @@
// 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 { 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);
@ -139,14 +170,22 @@ function run_test() {
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]);
}
@ -161,22 +200,21 @@ function redirect(metadata, response, status, port, bugid) {
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

View file

@ -5,11 +5,13 @@
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,14 +84,20 @@ 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 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,7 +2,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/. */
var unsafeAboutModule = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIAboutModule]),
newChannel(aURI, aLoadInfo) {
@ -13,32 +12,44 @@ var unsafeAboutModule = {
},
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",
const ServerSocket = CC(
"@mozilla.org/network/server-socket;1",
"nsIServerSocket",
"init");
"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

@ -19,10 +19,12 @@ XPCOMUtils.defineLazyGetter(this, "URL", function() {
var httpServer = null;
// needs to be rooted
var cacheFlushObserver = cacheFlushObserver = { observe() {
var cacheFlushObserver = (cacheFlushObserver = {
observe() {
cacheFlushObserver = null;
readServerContentAgain();
}};
},
});
var currentThread = null;
@ -31,9 +33,10 @@ function make_channel(url, callback, ctx) {
}
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,8 +49,7 @@ 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");
@ -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);
@ -93,8 +93,7 @@ function run_test()
}
}
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(_ => {
aos.asyncWait(
_ => {
os.write(altContent, altContent.length);
aos.closeWithStatus(Cr.NS_ERROR_FAILURE);
executeSoon(flushAndReadServerContentAgain);
}, 0, 0, currentThread);
},
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

@ -22,9 +22,10 @@ function make_channel(url, callback, ctx) {
}
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,8 +38,7 @@ 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");
@ -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

@ -37,12 +37,11 @@ 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) {
@ -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,15 +82,15 @@ 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() {
let cacheFlushObserver = {
observe() {
if (!cacheFlushObserver) {
info("ignoring cacheFlushObserver\n");
return;
@ -101,10 +98,10 @@ let cacheFlushObserver = { observe() {
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,15 +129,15 @@ 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() {
let cacheFlushObserver2 = {
observe() {
if (!cacheFlushObserver2) {
info("ignoring cacheFlushObserver2\n");
return;
@ -149,10 +145,10 @@ let cacheFlushObserver2 = { observe() {
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,15 +170,15 @@ 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() {
let cacheFlushObserver3 = {
observe() {
if (!cacheFlushObserver3) {
info("ignoring cacheFlushObserver3\n");
return;
@ -188,11 +187,10 @@ let cacheFlushObserver3 = { observe() {
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

@ -22,9 +22,10 @@ function make_channel(url, callback, ctx) {
}
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,8 +38,7 @@ 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");
@ -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);
@ -84,8 +82,7 @@ function run_test()
}
}
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() {
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

@ -27,7 +27,8 @@ 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) +
const altContent =
"a".repeat(128 * 1024) +
"b".repeat(128 * 1024) +
"c".repeat(128 * 1024) +
"d".repeat(128 * 1024) +
@ -40,16 +41,14 @@ const altContent = "a".repeat(128*1024) +
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);
@ -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);
@ -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);
}
},
});
}

View file

@ -10,10 +10,9 @@
*/
var data = "data ";
var altData = "alt-data"
var altData = "alt-data";
function run_test()
{
function run_test() {
do_get_profile();
// Expand both data to 1MB
@ -30,9 +29,13 @@ function run_test()
do_test_pending();
}
function write_data()
{
asyncOpenCacheEntry("http://data/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null, function (status, entry) {
function write_data() {
asyncOpenCacheEntry(
"http://data/",
"disk",
Ci.nsICacheStorage.OPEN_NORMALLY,
null,
function(status, entry) {
Assert.equal(status, Cr.NS_OK);
var os = entry.openOutputStream(0, -1);
@ -41,11 +44,11 @@ function write_data()
os.close();
open_big_altdata_output(entry);
});
}
);
}
function open_big_altdata_output(entry)
{
function open_big_altdata_output(entry) {
try {
var os = entry.openAlternativeOutputStream("text/binary", altData.length);
} catch (e) {
@ -56,9 +59,13 @@ function open_big_altdata_output(entry)
check_entry(write_big_altdata);
}
function write_big_altdata()
{
asyncOpenCacheEntry("http://data/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null, function (status, entry) {
function write_big_altdata() {
asyncOpenCacheEntry(
"http://data/",
"disk",
Ci.nsICacheStorage.OPEN_NORMALLY,
null,
function(status, entry) {
Assert.equal(status, Cr.NS_OK);
var os = entry.openAlternativeOutputStream("text/binary", -1);
@ -71,12 +78,17 @@ function write_big_altdata()
entry.close();
check_entry(do_test_finished);
});
}
);
}
function check_entry(cb)
{
asyncOpenCacheEntry("http://data/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null, function (status, entry) {
function check_entry(cb) {
asyncOpenCacheEntry(
"http://data/",
"disk",
Ci.nsICacheStorage.OPEN_NORMALLY,
null,
function(status, entry) {
Assert.equal(status, Cr.NS_OK);
var is = null;
@ -94,5 +106,6 @@ function check_entry(cb)
executeSoon(cb);
});
});
}
);
}

View file

@ -23,7 +23,9 @@ var httpBarOrigin; // http://bar.example.com:PORT/
var httpsBarOrigin; // https://bar.example.com:PORT/
function run_test() {
var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
var env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
@ -41,26 +43,38 @@ function run_test() {
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
prefs.setBoolPref("network.http.altsvc.enabled", true);
prefs.setBoolPref("network.http.altsvc.oe", true);
prefs.setCharPref("network.dns.localDomains", "foo.example.com, bar.example.com");
prefs.setCharPref(
"network.dns.localDomains",
"foo.example.com, bar.example.com"
);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. The same cert is used
// for both h2FooRoute and h2BarRoute though it is only valid for
// the foo.example.com domain name.
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
h1Foo = new HttpServer();
h1Foo.registerPathHandler("/altsvc-test", h1Server);
h1Foo.registerPathHandler("/.well-known/http-opportunistic", h1ServerWK);
h1Foo.start(-1);
h1Foo.identity.setPrimary("http", "foo.example.com", h1Foo.identity.primaryPort);
h1Foo.identity.setPrimary(
"http",
"foo.example.com",
h1Foo.identity.primaryPort
);
h1Bar = new HttpServer();
h1Bar.registerPathHandler("/altsvc-test", h1Server);
h1Bar.start(-1);
h1Bar.identity.setPrimary("http", "bar.example.com", h1Bar.identity.primaryPort);
h1Bar.identity.setPrimary(
"http",
"bar.example.com",
h1Bar.identity.primaryPort
);
h2FooRoute = "foo.example.com:" + h2Port;
h2BarRoute = "bar.example.com:" + h2Port;
@ -70,10 +84,20 @@ function run_test() {
httpsFooOrigin = "https://" + h2FooRoute + "/";
httpBarOrigin = "http://bar.example.com:" + h1Bar.identity.primaryPort + "/";
httpsBarOrigin = "https://" + h2BarRoute + "/";
dump ("http foo - " + httpFooOrigin + "\n" +
"https foo - " + httpsFooOrigin + "\n" +
"http bar - " + httpBarOrigin + "\n" +
"https bar - " + httpsBarOrigin + "\n");
dump(
"http foo - " +
httpFooOrigin +
"\n" +
"https foo - " +
httpsFooOrigin +
"\n" +
"http bar - " +
httpBarOrigin +
"\n" +
"https bar - " +
httpsBarOrigin +
"\n"
);
doTest1();
}
@ -121,7 +145,7 @@ function resetPrefs() {
function makeChan(origin) {
return NetUtil.newChannel({
uri: origin + "altsvc-test",
loadUsingSystemPrincipal: true
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
}
@ -141,7 +165,9 @@ Listener.prototype = {
if (expectPass) {
if (!Components.isSuccessCode(request.status)) {
do_throw("Channel should have a success code! (" + request.status + ")");
do_throw(
"Channel should have a success code! (" + request.status + ")"
);
}
Assert.equal(request.responseStatus, 200);
} else {
@ -182,11 +208,10 @@ Listener.prototype = {
}
do_test_finished();
}
},
};
function testsDone()
{
function testsDone() {
dump("testDone\n");
resetPrefs();
do_test_pending();
@ -197,8 +222,7 @@ function testsDone()
h1Bar.stop(do_test_finished);
}
function doTest()
{
function doTest() {
dump("execute doTest " + origin + "\n");
var chan = makeChan(origin);
var listener = new Listener();
@ -208,7 +232,8 @@ function doTest()
if (loadWithoutClearingMappings) {
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
} else {
chan.loadFlags = Ci.nsIRequest.LOAD_FRESH_CONNECTION |
chan.loadFlags =
Ci.nsIRequest.LOAD_FRESH_CONNECTION |
Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
}
loadWithoutClearingMappings = false;
@ -225,8 +250,7 @@ function doTest()
// listener is invoked
// http://foo served from h2=:port
function doTest1()
{
function doTest1() {
dump("doTest1()\n");
origin = httpFooOrigin;
xaltsvc = h2Route;
@ -237,8 +261,7 @@ function doTest1()
}
// http://foo served from h2=foo:port
function doTest2()
{
function doTest2() {
dump("doTest2()\n");
origin = httpFooOrigin;
xaltsvc = h2FooRoute;
@ -249,8 +272,7 @@ function doTest2()
// http://foo served from h2=bar:port
// requires cert for foo
function doTest3()
{
function doTest3() {
dump("doTest3()\n");
origin = httpFooOrigin;
xaltsvc = h2BarRoute;
@ -260,11 +282,10 @@ function doTest3()
}
// https://bar should fail because host bar has cert for foo
function doTest4()
{
function doTest4() {
dump("doTest4()\n");
origin = httpsBarOrigin;
xaltsvc = '';
xaltsvc = "";
expectPass = false;
nextTest = doTest5;
do_test_pending();
@ -272,11 +293,10 @@ function doTest4()
}
// https://foo no alt-svc (just check cert setup)
function doTest5()
{
function doTest5() {
dump("doTest5()\n");
origin = httpsFooOrigin;
xaltsvc = 'NA';
xaltsvc = "NA";
expectPass = true;
nextTest = doTest6;
do_test_pending();
@ -284,8 +304,7 @@ function doTest5()
}
// https://foo via bar (bar has cert for foo)
function doTest6()
{
function doTest6() {
dump("doTest6()\n");
origin = httpsFooOrigin;
xaltsvc = h2BarRoute;
@ -295,11 +314,10 @@ function doTest6()
}
// check again https://bar should fail because host bar has cert for foo
function doTest7()
{
function doTest7() {
dump("doTest7()\n");
origin = httpsBarOrigin;
xaltsvc = '';
xaltsvc = "";
expectPass = false;
nextTest = doTest8;
do_test_pending();
@ -310,8 +328,7 @@ function doTest7()
// should not use TLS/h2 because h2BarRoute is not auth'd for bar
// however the test ought to PASS (i.e. get a 200) because fallback
// to plaintext happens.. thus the timeout
function doTest8()
{
function doTest8() {
dump("doTest8()\n");
origin = httpBarOrigin;
xaltsvc = h2BarRoute;
@ -323,8 +340,7 @@ function doTest8()
}
// http://bar served from h2=:port, which is like the bar route in 8
function doTest9()
{
function doTest9() {
dump("doTest9()\n");
origin = httpBarOrigin;
xaltsvc = h2Route;
@ -337,11 +353,10 @@ function doTest9()
}
// check again https://bar should fail because host bar has cert for foo
function doTest10()
{
function doTest10() {
dump("doTest10()\n");
origin = httpsBarOrigin;
xaltsvc = '';
xaltsvc = "";
expectPass = false;
nextTest = doTest11;
do_test_pending();
@ -351,8 +366,7 @@ function doTest10()
// http://bar served from h2=foo, should fail because host foo only has
// cert for foo. Fail in this case means alt-svc is not used, but content
// is served
function doTest11()
{
function doTest11() {
dump("doTest11()\n");
origin = httpBarOrigin;
xaltsvc = h2FooRoute;
@ -365,8 +379,7 @@ function doTest11()
// Test 12-15:
// Insert a cache of http://foo served from h2=:port with origin attributes.
function doTest12()
{
function doTest12() {
dump("doTest12()\n");
origin = httpFooOrigin;
xaltsvc = h2Route;
@ -381,11 +394,10 @@ function doTest12()
}
// Make sure we get a cache miss with a different userContextId.
function doTest13()
{
function doTest13() {
dump("doTest13()\n");
origin = httpFooOrigin;
xaltsvc = 'NA';
xaltsvc = "NA";
originAttributes = {
userContextId: 2,
firstPartyDomain: "a.com",
@ -397,11 +409,10 @@ function doTest13()
}
// Make sure we get a cache miss with a different firstPartyDomain.
function doTest14()
{
function doTest14() {
dump("doTest14()\n");
origin = httpFooOrigin;
xaltsvc = 'NA';
xaltsvc = "NA";
originAttributes = {
userContextId: 1,
firstPartyDomain: "b.com",
@ -413,11 +424,10 @@ function doTest14()
}
//
// Make sure we get a cache hit with the same origin attributes.
function doTest15()
{
function doTest15() {
dump("doTest15()\n");
origin = httpFooOrigin;
xaltsvc = 'NA';
xaltsvc = "NA";
originAttributes = {
userContextId: 1,
firstPartyDomain: "a.com",
@ -431,15 +441,19 @@ function doTest15()
}
// Check we don't connect to blocked ports
function doTest16()
{
function doTest16() {
dump("doTest16()\n");
origin = httpFooOrigin;
nextTest = testsDone;
otherServer = Cc["@mozilla.org/network/server-socket;1"].createInstance(Ci.nsIServerSocket);
otherServer = Cc["@mozilla.org/network/server-socket;1"].createInstance(
Ci.nsIServerSocket
);
otherServer.init(-1, true, -1);
xaltsvc = "localhost:" + otherServer.port;
Services.prefs.setCharPref("network.security.ports.banned", "" + otherServer.port);
Services.prefs.setCharPref(
"network.security.ports.banned",
"" + otherServer.port
);
dump("Blocked port: " + otherServer.port);
waitFor = 500;
otherServer.asyncListen({

View file

@ -1,4 +1,3 @@
/*
- test to check we use only a single connection for both onymous and anonymous requests over an existing h2 session
- request from a domain w/o LOAD_ANONYMOUS flag
@ -13,7 +12,9 @@ var http2pref;
var extpref;
function run_test() {
var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
var env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
@ -29,12 +30,16 @@ function run_test() {
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
prefs.setBoolPref("network.http.originextension", true);
prefs.setCharPref("network.dns.localDomains", "foo.example.com, alt1.example.com");
prefs.setCharPref(
"network.dns.localDomains",
"foo.example.com, alt1.example.com"
);
// The moz-http2 cert is for {foo, alt1, alt2}.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert.
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
doTest1();
@ -50,7 +55,7 @@ function resetPrefs() {
function makeChan(origin) {
return NetUtil.newChannel({
uri: origin,
loadUsingSystemPrincipal: true
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
}
@ -88,17 +93,15 @@ Listener.prototype = {
currentPort = this.clientPort;
nextTest();
do_test_finished();
}
},
};
function testsDone()
{
function testsDone() {
dump("testsDone\n");
resetPrefs();
}
function doTest()
{
function doTest() {
dump("execute doTest " + origin + "\n");
var loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
@ -118,8 +121,7 @@ function doTest()
chan.asyncOpen(listener);
}
function doTest1()
{
function doTest1() {
dump("doTest1()\n");
origin = "https://foo.example.com:" + h2Port + "/origin-1";
nextTest = doTest2;
@ -128,8 +130,7 @@ function doTest1()
doTest();
}
function doTest2()
{
function doTest2() {
// connection expected to be reused for an anonymous request
dump("doTest2()\n");
origin = "https://foo.example.com:" + h2Port + "/origin-2";
@ -140,8 +141,7 @@ function doTest2()
doTest();
}
function doTest3()
{
function doTest3() {
dump("doTest3()\n");
origin = "https://foo.example.com:" + h2Port + "/origin-3";
nextTest = doTest4;
@ -152,8 +152,7 @@ function doTest3()
doTest();
}
function doTest4()
{
function doTest4() {
dump("doTest4()\n");
origin = "https://foo.example.com:" + h2Port + "/origin-4";
nextTest = testsDone;

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