summaryrefslogtreecommitdiffstats
path: root/netwerk/cookie/test
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/cookie/test')
-rw-r--r--netwerk/cookie/test/browser/browser.ini5
-rw-r--r--netwerk/cookie/test/browser/browser_originattributes.js113
-rw-r--r--netwerk/cookie/test/browser/file_empty.html3
-rw-r--r--netwerk/cookie/test/unit/test_bug1155169.js73
-rw-r--r--netwerk/cookie/test/unit/test_bug1267910.js196
-rw-r--r--netwerk/cookie/test/unit/test_bug643051.js29
-rw-r--r--netwerk/cookie/test/unit/test_eviction.js296
-rw-r--r--netwerk/cookie/test/unit/test_parser_0001.js29
-rw-r--r--netwerk/cookie/test/unit/test_parser_0019.js29
-rw-r--r--netwerk/cookie/test/unit/xpcshell.ini10
-rw-r--r--netwerk/cookie/test/unit_ipc/test_ipc_parser_0001.js9
-rw-r--r--netwerk/cookie/test/unit_ipc/test_ipc_parser_0019.js9
-rw-r--r--netwerk/cookie/test/unit_ipc/xpcshell.ini10
13 files changed, 811 insertions, 0 deletions
diff --git a/netwerk/cookie/test/browser/browser.ini b/netwerk/cookie/test/browser/browser.ini
new file mode 100644
index 000000000..342e14578
--- /dev/null
+++ b/netwerk/cookie/test/browser/browser.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+support-files =
+ file_empty.html
+
+[browser_originattributes.js]
diff --git a/netwerk/cookie/test/browser/browser_originattributes.js b/netwerk/cookie/test/browser/browser_originattributes.js
new file mode 100644
index 000000000..617d52e35
--- /dev/null
+++ b/netwerk/cookie/test/browser/browser_originattributes.js
@@ -0,0 +1,113 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let { classes: Cc, interfaces: Ci } = Components;
+
+const USER_CONTEXTS = ["default", "personal", "work"];
+
+const COOKIE_NAMES = ["cookie0", "cookie1", "cookie2"];
+
+const TEST_URL =
+ "http://example.com/browser/netwerk/cookie/test/browser/file_empty.html";
+
+let cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
+
+// opens `uri' in a new tab with the provided userContextId and focuses it.
+// returns the newly opened tab
+function* openTabInUserContext(uri, userContextId) {
+ // open the tab in the correct userContextId
+ let tab = gBrowser.addTab(uri, {userContextId});
+
+ // select tab and make sure its browser is focused
+ gBrowser.selectedTab = tab;
+ tab.ownerDocument.defaultView.focus();
+
+ let browser = gBrowser.getBrowserForTab(tab);
+ // wait for tab load
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ return {tab, browser};
+}
+
+add_task(function* setup() {
+ // make sure userContext is enabled.
+ yield new Promise(resolve => {
+ SpecialPowers.pushPrefEnv({"set": [
+ ["privacy.userContext.enabled", true]
+ ]}, resolve);
+ });
+});
+
+add_task(function* test() {
+ // load the page in 3 different contexts and set a cookie
+ // which should only be visible in that context
+ for (let userContextId of Object.keys(USER_CONTEXTS)) {
+ // open our tab in the given user context
+ let {tab, browser} = yield* openTabInUserContext(TEST_URL, userContextId);
+
+ yield 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);
+ }
+
+ let expectedValues = USER_CONTEXTS.slice(0);
+ yield checkCookies(expectedValues, "before removal");
+
+ // remove cookies that belongs to user context id #1
+ cm.removeCookiesWithOriginAttributes(JSON.stringify({userContextId: 1}));
+
+ expectedValues[1] = undefined;
+ yield checkCookies(expectedValues, "after removal");
+});
+
+function *checkCookies(expectedValues, time) {
+ for (let userContextId of Object.keys(expectedValues)) {
+ let cookiesFromTitle = yield* getCookiesFromJS(userContextId);
+ let cookiesFromManager = getCookiesFromManager(userContextId);
+
+ 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}`);
+ }
+
+ }
+}
+
+function getCookiesFromManager(userContextId) {
+ let cookies = {};
+ let enumerator = cm.getCookiesWithOriginAttributes(JSON.stringify({userContextId}));
+ while (enumerator.hasMoreElements()) {
+ let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
+ cookies[cookie.name] = cookie.value;
+ }
+ return cookies;
+}
+
+function* getCookiesFromJS(userContextId) {
+ let {tab, browser} = yield* openTabInUserContext(TEST_URL, userContextId);
+
+ // get the cookies
+ let cookieString = yield ContentTask.spawn(browser, null, function() {
+ return content.document.cookie;
+ });
+
+ // check each item in the title and validate it meets expectatations
+ let cookies = {};
+ for (let cookie of cookieString.split(";")) {
+ let [name, value] = cookie.trim().split("=");
+ cookies[name] = value;
+ }
+
+ gBrowser.removeTab(tab);
+ return cookies;
+}
diff --git a/netwerk/cookie/test/browser/file_empty.html b/netwerk/cookie/test/browser/file_empty.html
new file mode 100644
index 000000000..5a08c4205
--- /dev/null
+++ b/netwerk/cookie/test/browser/file_empty.html
@@ -0,0 +1,3 @@
+<html><body>
+</body></html>
+
diff --git a/netwerk/cookie/test/unit/test_bug1155169.js b/netwerk/cookie/test/unit/test_bug1155169.js
new file mode 100644
index 000000000..6806ffe6d
--- /dev/null
+++ b/netwerk/cookie/test/unit/test_bug1155169.js
@@ -0,0 +1,73 @@
+var {utils: Cu, interfaces: Ci, classes: Cc} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+const URI = Services.io.newURI("http://example.org/", null, null);
+
+const cs = Cc["@mozilla.org/cookieService;1"]
+ .getService(Ci.nsICookieService);
+
+function run_test() {
+ // Allow all cookies.
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
+ // Clear cookies.
+ Services.cookies.removeAll();
+
+ // Add a new cookie.
+ setCookie("foo=bar", {
+ 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
+ });
+
+ // Update cookie with isSecure=true.
+ setCookie("foo=bar; Secure", {
+ 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
+ });
+
+ // Reset cookie.
+ setCookie("foo=bar", {
+ type: "changed", isSession: true, isSecure: false, isHttpOnly: false
+ });
+}
+
+function setCookie(value, expected) {
+ function setCookieInternal(value, expected = null) {
+ function observer(subject, topic, data) {
+ if (!expected) {
+ do_throw("no notification expected");
+ return;
+ }
+
+ // Check we saw the right notification.
+ do_check_eq(data, expected.type);
+
+ // Check cookie details.
+ let cookie = subject.QueryInterface(Ci.nsICookie2);
+ do_check_eq(cookie.isSession, expected.isSession);
+ do_check_eq(cookie.isSecure, expected.isSecure);
+ do_check_eq(cookie.isHttpOnly, expected.isHttpOnly);
+ }
+
+ Services.obs.addObserver(observer, "cookie-changed", false);
+ cs.setCookieStringFromHttp(URI, null, null, value, null, null);
+ Services.obs.removeObserver(observer, "cookie-changed");
+ }
+
+ // Check that updating/inserting the cookie works.
+ setCookieInternal(value, expected);
+
+ // Check that we ignore identical cookies.
+ setCookieInternal(value);
+}
diff --git a/netwerk/cookie/test/unit/test_bug1267910.js b/netwerk/cookie/test/unit/test_bug1267910.js
new file mode 100644
index 000000000..93ea5e132
--- /dev/null
+++ b/netwerk/cookie/test/unit/test_bug1267910.js
@@ -0,0 +1,196 @@
+/*
+ * Bug 1267910 - Add test cases for the backward compatiability and originAttributes
+ * of nsICookieManager2.
+ */
+
+var {utils: Cu, interfaces: Ci, classes: Cc} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+const BASE_URL = "http://example.org/";
+
+const COOKIE = {
+ host: BASE_URL,
+ path: "/",
+ name: "test1",
+ value: "yes",
+ isSecure: false,
+ isHttpOnly: false,
+ isSession: true,
+ expiry: 2145934800,
+};
+
+const COOKIE_OA_DEFAULT = {
+ host: BASE_URL,
+ path: "/",
+ name: "test0",
+ value: "yes0",
+ isSecure: false,
+ isHttpOnly: false,
+ isSession: true,
+ expiry: 2145934800,
+ originAttributes: {},
+};
+
+const COOKIE_OA_1 = {
+ host: BASE_URL,
+ path: "/",
+ name: "test1",
+ value: "yes1",
+ isSecure: false,
+ isHttpOnly: false,
+ isSession: true,
+ expiry: 2145934800,
+ originAttributes: {userContextId: 1},
+};
+
+function checkCookie(cookie, cookieObj) {
+ for (let prop of Object.keys(cookieObj)) {
+ if (prop === "originAttributes") {
+ ok(ChromeUtils.isOriginAttributesEqual(cookie[prop], cookieObj[prop]),
+ "Check cookie: " + prop);
+ } else {
+ equal(cookie[prop], cookieObj[prop], "Check cookie: " + prop);
+ }
+ }
+}
+
+function countCookies(enumerator) {
+ let cnt = 0;
+
+ while (enumerator.hasMoreElements()) {
+ cnt++;
+ enumerator.getNext();
+ }
+
+ return cnt;
+}
+
+function run_test() {
+ // Allow all cookies.
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
+ // Enable user context id
+ Services.prefs.setBoolPref("privacy.userContext.enabled", true);
+
+ add_test(test_backward_compatiability);
+ add_test(test_originAttributes);
+
+
+ run_next_test();
+}
+
+/*
+ * Test for backward compatiablility that APIs works correctly without
+ * originAttributes.
+ */
+function test_backward_compatiability() {
+ // Clear cookies.
+ Services.cookies.removeAll();
+
+ // Call Add() to add a cookie without originAttributes
+ Services.cookies.add(COOKIE.host,
+ COOKIE.path,
+ COOKIE.name,
+ COOKIE.value,
+ COOKIE.isSecure,
+ COOKIE.isHttpOnly,
+ COOKIE.isSession,
+ COOKIE.expiry);
+
+ // Call getCookiesFromHost() to get cookies without originAttributes
+ let enumerator = Services.cookies.getCookiesFromHost(BASE_URL);
+
+ ok(enumerator.hasMoreElements(), "Cookies available");
+ let foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+
+ checkCookie(foundCookie, COOKIE);
+
+ ok(!enumerator.hasMoreElements(), "We should get only one cookie");
+
+ run_next_test();
+}
+
+/*
+ * Test for originAttributes.
+ */
+function test_originAttributes() {
+ // Clear cookies.
+ Services.cookies.removeAll();
+
+ // Add a cookie for default originAttributes.
+ Services.cookies.add(COOKIE_OA_DEFAULT.host,
+ COOKIE_OA_DEFAULT.path,
+ COOKIE_OA_DEFAULT.name,
+ COOKIE_OA_DEFAULT.value,
+ COOKIE_OA_DEFAULT.isSecure,
+ COOKIE_OA_DEFAULT.isHttpOnly,
+ COOKIE_OA_DEFAULT.isSession,
+ COOKIE_OA_DEFAULT.expiry,
+ COOKIE_OA_DEFAULT.originAttributes);
+
+ // Get cookies for default originAttributes.
+ let enumerator = Services.cookies.getCookiesFromHost(BASE_URL, COOKIE_OA_DEFAULT.originAttributes);
+
+ // Check that do we get cookie correctly.
+ ok(enumerator.hasMoreElements(), "Cookies available");
+ let foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+ checkCookie(foundCookie, COOKIE_OA_DEFAULT);
+
+ // We should only get one cookie.
+ ok(!enumerator.hasMoreElements(), "We should get only one cookie");
+
+ // Get cookies for originAttributes with user context id 1.
+ enumerator = Services.cookies.getCookiesFromHost(BASE_URL, COOKIE_OA_1.originAttributes);
+
+ // Check that we will not get cookies if the originAttributes is different.
+ ok(!enumerator.hasMoreElements(), "No cookie should be here");
+
+ // Add a cookie for originAttributes with user context id 1.
+ Services.cookies.add(COOKIE_OA_1.host,
+ COOKIE_OA_1.path,
+ COOKIE_OA_1.name,
+ COOKIE_OA_1.value,
+ COOKIE_OA_1.isSecure,
+ COOKIE_OA_1.isHttpOnly,
+ COOKIE_OA_1.isSession,
+ COOKIE_OA_1.expiry,
+ COOKIE_OA_1.originAttributes);
+
+ // Get cookies for originAttributes with user context id 1.
+ enumerator = Services.cookies.getCookiesFromHost(BASE_URL, COOKIE_OA_1.originAttributes);
+
+ // Check that do we get cookie correctly.
+ ok(enumerator.hasMoreElements(), "Cookies available");
+ foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+ checkCookie(foundCookie, COOKIE_OA_1);
+
+ // We should only get one cookie.
+ ok(!enumerator.hasMoreElements(), "We should get only one cookie");
+
+ // Check that add a cookie will not affect cookies in different originAttributes.
+ enumerator = Services.cookies.getCookiesFromHost(BASE_URL, COOKIE_OA_DEFAULT.originAttributes);
+ equal(countCookies(enumerator), 1, "We should get only one cookie for default originAttributes");
+
+ // Remove a cookie for originAttributes with user context id 1.
+ Services.cookies.remove(COOKIE_OA_1.host, COOKIE_OA_1.name, COOKIE_OA_1.path,
+ false, COOKIE_OA_1.originAttributes);
+
+ // Check that remove will not affect cookies in default originAttributes.
+ enumerator = Services.cookies.getCookiesFromHost(BASE_URL, COOKIE_OA_DEFAULT.originAttributes);
+ equal(countCookies(enumerator), 1, "Get one cookie for default originAttributes.");
+
+ // Check that should be no cookie for originAttributes with user context id 1.
+ enumerator = Services.cookies.getCookiesFromHost(BASE_URL, COOKIE_OA_1.originAttributes);
+ equal(countCookies(enumerator), 0, "No cookie shold be here");
+
+ // Remove a cookie for default originAttributes.
+ Services.cookies.remove(COOKIE_OA_DEFAULT.host, COOKIE_OA_DEFAULT.name, COOKIE_OA_DEFAULT.path,
+ false, COOKIE_OA_DEFAULT.originAttributes);
+
+ // Check remove() works correctly for default originAttributes.
+ enumerator = Services.cookies.getCookiesFromHost(BASE_URL, COOKIE_OA_DEFAULT.originAttributes);
+ equal(countCookies(enumerator), 0, "No cookie shold be here");
+
+ run_next_test();
+}
diff --git a/netwerk/cookie/test/unit/test_bug643051.js b/netwerk/cookie/test/unit/test_bug643051.js
new file mode 100644
index 000000000..d6695054e
--- /dev/null
+++ b/netwerk/cookie/test/unit/test_bug643051.js
@@ -0,0 +1,29 @@
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+function run_test() {
+ // Allow all cookies.
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
+ let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
+
+ let uri = NetUtil.newURI("http://example.org/");
+
+ let set = "foo=bar\nbaz=foo";
+ let expected = "foo=bar; baz=foo";
+ cs.setCookieStringFromHttp(uri, null, null, set, null, null);
+
+ let actual = cs.getCookieStringFromHttp(uri, null, null);
+ do_check_eq(actual, expected);
+
+ uri = NetUtil.newURI("http://example.com/");
+ cs.setCookieString(uri, null, set, null);
+
+ expected = "foo=bar";
+ actual = cs.getCookieString(uri, null, null);
+ do_check_eq(actual, expected);
+}
+
diff --git a/netwerk/cookie/test/unit/test_eviction.js b/netwerk/cookie/test/unit/test_eviction.js
new file mode 100644
index 000000000..7f693ee94
--- /dev/null
+++ b/netwerk/cookie/test/unit/test_eviction.js
@@ -0,0 +1,296 @@
+var {utils: Cu, interfaces: Ci, classes: Cc} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+const BASE_HOSTNAMES = ["example.org", "example.co.uk"];
+const SUBDOMAINS = ["", "pub.", "www.", "other."];
+
+const cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
+const cm = cs.QueryInterface(Ci.nsICookieManager2);
+
+function run_test() {
+ var tests = [];
+ Services.prefs.setIntPref("network.cookie.staleThreshold", 0);
+ for (var host of BASE_HOSTNAMES) {
+ var base = SUBDOMAINS[0] + host;
+ var sub = SUBDOMAINS[1] + host;
+ var other = SUBDOMAINS[2] + host;
+ var another = SUBDOMAINS[3] + host;
+ tests.push([host, test_basic_eviction.bind(this, base, sub, other, another)]);
+ add_task(function* a() {
+ var t = tests.splice(0, 1)[0];
+ do_print('testing with host ' + t[0]);
+ yield t[1]();
+ cm.removeAll();
+ });
+ tests.push([host, test_domain_or_path_matches_not_both.bind(this, base, sub, other, another)]);
+ add_task(function*() {
+ var t = tests.splice(0, 1)[0];
+ do_print('testing with host ' + t[0]);
+ yield t[1]();
+ cm.removeAll();
+ });
+ }
+ add_task(function*() {
+ yield test_localdomain();
+ cm.removeAll();
+ });
+
+ add_task(function*() {
+ yield test_path_prefix();
+ });
+
+ run_next_test();
+}
+
+// Verify that cookies that share a path prefix with the URI path are still considered
+// candidates for eviction, since the paths do not actually match.
+function* test_path_prefix() {
+ Services.prefs.setIntPref("network.cookie.maxPerHost", 2);
+
+ const BASE_URI = Services.io.newURI("http://example.org/", null, null);
+ const BASE_BAR = Services.io.newURI("http://example.org/bar/", null, null);
+ const BASE_BARBAR = Services.io.newURI("http://example.org/barbar/", null, null);
+
+ yield setCookie("session_first", null, null, null, BASE_URI);
+ yield setCookie("session_second", null, "/bar", null, BASE_BAR);
+ verifyCookies(['session_first', 'session_second'], BASE_URI);
+
+ yield setCookie("session_third", null, "/barbar", null, BASE_BARBAR);
+ verifyCookies(['session_first', 'session_third'], BASE_URI);
+}
+
+// Verify that subdomains of localhost are treated as separate hosts and aren't considered
+// candidates for eviction.
+function* test_localdomain() {
+ Services.prefs.setIntPref("network.cookie.maxPerHost", 2);
+
+ const BASE_URI = Services.io.newURI("http://localhost", null, null);
+ const BASE_BAR = Services.io.newURI("http://localhost/bar", null, null);
+ const OTHER_URI = Services.io.newURI("http://other.localhost", null, null);
+ const OTHER_BAR = Services.io.newURI("http://other.localhost/bar", null, null);
+
+ yield setCookie("session_no_path", null, null, null, BASE_URI);
+ yield setCookie("session_bar_path", null, "/bar", null, BASE_BAR);
+
+ yield setCookie("session_no_path", null, null, null, OTHER_URI);
+ yield setCookie("session_bar_path", null, "/bar", null, OTHER_BAR);
+
+ verifyCookies(['session_no_path',
+ 'session_bar_path'], BASE_URI);
+ verifyCookies(['session_no_path',
+ 'session_bar_path'], OTHER_URI);
+
+ yield setCookie("session_another_no_path", null, null, null, BASE_URI);
+ verifyCookies(['session_no_path',
+ 'session_another_no_path'], BASE_URI);
+
+ yield setCookie("session_another_no_path", null, null, null, OTHER_URI);
+ verifyCookies(['session_no_path',
+ 'session_another_no_path'], OTHER_URI);
+}
+
+// Ensure that cookies are still considered candidates for eviction if either the domain
+// or path matches, but not both.
+function* test_domain_or_path_matches_not_both(base_host,
+ subdomain_host,
+ other_subdomain_host,
+ another_subdomain_host) {
+ Services.prefs.setIntPref("network.cookie.maxPerHost", 2);
+
+ const BASE_URI = Services.io.newURI("http://" + base_host, null, null);
+ const PUB_FOO_PATH = Services.io.newURI("http://" + subdomain_host + "/foo/", null, null);
+ const WWW_BAR_PATH = Services.io.newURI("http://" + other_subdomain_host + "/bar/", null, null);
+ const OTHER_BAR_PATH = Services.io.newURI("http://" + another_subdomain_host + "/bar/", null, null);
+ const PUB_BAR_PATH = Services.io.newURI("http://" + subdomain_host + "/bar/", null, null);
+ const WWW_FOO_PATH = Services.io.newURI("http://" + other_subdomain_host + "/foo/", null, null);
+
+ yield setCookie("session_pub_with_foo_path", subdomain_host, "/foo", null, PUB_FOO_PATH);
+ yield setCookie("session_www_with_bar_path", other_subdomain_host, "/bar", null, WWW_BAR_PATH);
+ verifyCookies(['session_pub_with_foo_path',
+ 'session_www_with_bar_path'], BASE_URI);
+
+ yield setCookie("session_pub_with_bar_path", subdomain_host, "/bar", null, PUB_BAR_PATH);
+ verifyCookies(['session_www_with_bar_path',
+ 'session_pub_with_bar_path'], BASE_URI);
+
+ yield setCookie("session_other_with_bar_path", another_subdomain_host, "/bar", null, OTHER_BAR_PATH);
+ verifyCookies(['session_pub_with_bar_path',
+ 'session_other_with_bar_path'], BASE_URI);
+}
+
+function* test_basic_eviction(base_host, subdomain_host, other_subdomain_host) {
+ Services.prefs.setIntPref("network.cookie.maxPerHost", 5);
+
+ const BASE_URI = Services.io.newURI("http://" + base_host, null, null);
+ const SUBDOMAIN_URI = Services.io.newURI("http://" + subdomain_host, null, null);
+ const OTHER_SUBDOMAIN_URI = Services.io.newURI("http://" + other_subdomain_host, null, null);
+ const FOO_PATH = Services.io.newURI("http://" + base_host + "/foo/", null, null);
+ const BAR_PATH = Services.io.newURI("http://" + base_host + "/bar/", null, null);
+ const ALL_SUBDOMAINS = '.' + base_host;
+ const OTHER_SUBDOMAIN = other_subdomain_host;
+
+ // Initialize the set of cookies with a mix of non-session cookies with no path,
+ // and session cookies with explicit paths. Any subsequent cookies added will cause
+ // existing cookies to be evicted.
+ yield setCookie("non_session_non_path_non_domain", null, null, 100000, BASE_URI);
+ yield setCookie("non_session_non_path_subdomain", ALL_SUBDOMAINS, null, 100000, SUBDOMAIN_URI);
+ yield setCookie("session_non_path_pub_domain", OTHER_SUBDOMAIN, null, null, OTHER_SUBDOMAIN_URI);
+ yield setCookie("session_foo_path", null, "/foo", null, FOO_PATH);
+ yield setCookie("session_bar_path", null, "/bar", null, BAR_PATH);
+ verifyCookies(['non_session_non_path_non_domain',
+ 'non_session_non_path_subdomain',
+ 'session_non_path_pub_domain',
+ 'session_foo_path',
+ 'session_bar_path'], BASE_URI);
+
+ // Ensure that cookies set for the / path appear more recent.
+ cs.getCookieString(OTHER_SUBDOMAIN_URI, null)
+ verifyCookies(['non_session_non_path_non_domain',
+ 'session_foo_path',
+ 'session_bar_path',
+ 'non_session_non_path_subdomain',
+ 'session_non_path_pub_domain'], BASE_URI);
+
+ // Evict oldest session cookie that does not match example.org/foo (session_bar_path)
+ yield setCookie("session_foo_path_2", null, "/foo", null, FOO_PATH);
+ verifyCookies(['non_session_non_path_non_domain',
+ 'session_foo_path',
+ 'non_session_non_path_subdomain',
+ 'session_non_path_pub_domain',
+ 'session_foo_path_2'], BASE_URI);
+
+ // Evict oldest session cookie that does not match example.org/bar (session_foo_path)
+ yield setCookie("session_bar_path_2", null, "/bar", null, BAR_PATH);
+ verifyCookies(['non_session_non_path_non_domain',
+ 'non_session_non_path_subdomain',
+ 'session_non_path_pub_domain',
+ 'session_foo_path_2',
+ 'session_bar_path_2'], BASE_URI);
+
+ // Evict oldest session cookie that does not match example.org/ (session_non_path_pub_domain)
+ yield setCookie("non_session_non_path_non_domain_2", null, null, 100000, BASE_URI);
+ verifyCookies(['non_session_non_path_non_domain',
+ 'non_session_non_path_subdomain',
+ 'session_foo_path_2',
+ 'session_bar_path_2',
+ 'non_session_non_path_non_domain_2'], BASE_URI);
+
+ // Evict oldest session cookie that does not match example.org/ (session_foo_path_2)
+ yield setCookie("session_non_path_non_domain_3", null, null, null, BASE_URI);
+ verifyCookies(['non_session_non_path_non_domain',
+ 'non_session_non_path_subdomain',
+ 'session_bar_path_2',
+ 'non_session_non_path_non_domain_2',
+ 'session_non_path_non_domain_3'], BASE_URI);
+
+ // Evict oldest session cookie; all such cookies match example.org/bar (session_bar_path_2)
+ // note: this new cookie doesn't have an explicit path, but empty paths inherit the
+ // request's path
+ yield setCookie("non_session_bar_path_non_domain", null, null, 100000, BAR_PATH);
+ verifyCookies(['non_session_non_path_non_domain',
+ 'non_session_non_path_subdomain',
+ 'non_session_non_path_non_domain_2',
+ 'session_non_path_non_domain_3',
+ 'non_session_bar_path_non_domain'], BASE_URI);
+
+ // Evict oldest session cookie, even though it matches pub.example.org (session_non_path_non_domain_3)
+ yield setCookie("non_session_non_path_pub_domain", null, null, 100000, OTHER_SUBDOMAIN_URI);
+ verifyCookies(['non_session_non_path_non_domain',
+ 'non_session_non_path_subdomain',
+ 'non_session_non_path_non_domain_2',
+ 'non_session_bar_path_non_domain',
+ 'non_session_non_path_pub_domain'], BASE_URI);
+
+ // All session cookies have been evicted.
+ // Evict oldest non-session non-domain-matching cookie (non_session_non_path_pub_domain)
+ yield setCookie("non_session_bar_path_non_domain_2", null, '/bar', 100000, BAR_PATH);
+ verifyCookies(['non_session_non_path_non_domain',
+ 'non_session_non_path_subdomain',
+ 'non_session_non_path_non_domain_2',
+ 'non_session_bar_path_non_domain',
+ 'non_session_bar_path_non_domain_2'], BASE_URI);
+
+ // Evict oldest non-session non-path-matching cookie (non_session_bar_path_non_domain)
+ yield setCookie("non_session_non_path_non_domain_4", null, null, 100000, BASE_URI);
+ verifyCookies(['non_session_non_path_non_domain',
+ 'non_session_non_path_subdomain',
+ 'non_session_non_path_non_domain_2',
+ 'non_session_bar_path_non_domain_2',
+ 'non_session_non_path_non_domain_4'], BASE_URI);
+
+ // At this point all remaining cookies are non-session cookies, have a path of /,
+ // and either don't have a domain or have one that matches subdomains.
+ // They will therefore be evicted from oldest to newest if all new cookies added share
+ // similar characteristics.
+}
+
+// Verify that the given cookie names exist, and are ordered from least to most recently accessed
+function verifyCookies(names, uri) {
+ do_check_eq(cm.countCookiesFromHost(uri.host), names.length);
+ let cookies = cm.getCookiesFromHost(uri.host, {});
+ let actual_cookies = [];
+ while (cookies.hasMoreElements()) {
+ let cookie = cookies.getNext().QueryInterface(Ci.nsICookie2);
+ actual_cookies.push(cookie);
+ }
+ if (names.length != actual_cookies.length) {
+ let left = names.filter(function(n) {
+ return actual_cookies.findIndex(function(c) {
+ return c.name == n;
+ }) == -1;
+ });
+ let right = actual_cookies.filter(function(c) {
+ return names.findIndex(function(n) {
+ return c.name == n;
+ }) == -1;
+ }).map(function(c) { return c.name });
+ if (left.length) {
+ do_print("unexpected cookies: " + left);
+ }
+ if (right.length) {
+ do_print("expected cookies: " + right);
+ }
+ }
+ do_check_eq(names.length, actual_cookies.length);
+ actual_cookies.sort(function(a, b) {
+ if (a.lastAccessed < b.lastAccessed)
+ return -1;
+ if (a.lastAccessed > b.lastAccessed)
+ return 1;
+ return 0;
+ });
+ for (var i = 0; i < names.length; i++) {
+ do_check_eq(names[i], actual_cookies[i].name);
+ do_check_eq(names[i].startsWith('session'), actual_cookies[i].isSession);
+ }
+}
+
+var lastValue = 0
+function* setCookie(name, domain, path, maxAge, url) {
+ let value = name + "=" + ++lastValue;
+ var s = 'setting cookie ' + value;
+ if (domain) {
+ value += "; Domain=" + domain;
+ s += ' (d=' + domain + ')';
+ }
+ if (path) {
+ value += "; Path=" + path;
+ s += ' (p=' + path + ')';
+ }
+ if (maxAge) {
+ value += "; Max-Age=" + maxAge;
+ s += ' (non-session)';
+ } else {
+ s += ' (session)';
+ }
+ s += ' for ' + url.spec;
+ do_print(s);
+ cs.setCookieStringFromHttp(url, null, null, value, null, null);
+ return new Promise(function(resolve) {
+ // Windows XP has low precision timestamps that cause our cookie eviction
+ // algorithm to produce different results from other platforms. We work around
+ // this by ensuring that there's a clear gap between each cookie update.
+ do_timeout(10, resolve);
+ })
+}
diff --git a/netwerk/cookie/test/unit/test_parser_0001.js b/netwerk/cookie/test/unit/test_parser_0001.js
new file mode 100644
index 000000000..f885972a0
--- /dev/null
+++ b/netwerk/cookie/test/unit/test_parser_0001.js
@@ -0,0 +1,29 @@
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+function inChildProcess() {
+ return Cc["@mozilla.org/xre/app-info;1"]
+ .getService(Ci.nsIXULRuntime)
+ .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+}
+
+function run_test() {
+ // Allow all cookies if the pref service is available in this process.
+ if (!inChildProcess())
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
+ let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
+
+ let uri = NetUtil.newURI("http://example.org/");
+
+ let set = "foo=bar";
+ cs.setCookieStringFromHttp(uri, null, null, set, null, null);
+
+ let expected = "foo=bar";
+ let actual = cs.getCookieStringFromHttp(uri, null, null);
+ do_check_eq(actual, expected);
+}
+
diff --git a/netwerk/cookie/test/unit/test_parser_0019.js b/netwerk/cookie/test/unit/test_parser_0019.js
new file mode 100644
index 000000000..7811b01fe
--- /dev/null
+++ b/netwerk/cookie/test/unit/test_parser_0019.js
@@ -0,0 +1,29 @@
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+function inChildProcess() {
+ return Cc["@mozilla.org/xre/app-info;1"]
+ .getService(Ci.nsIXULRuntime)
+ .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+}
+
+function run_test() {
+ // Allow all cookies if the pref service is available in this process.
+ if (!inChildProcess())
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
+ let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
+
+ let uri = NetUtil.newURI("http://example.org/");
+
+ let set = "foo=b;max-age=3600, c=d;path=/";
+ cs.setCookieStringFromHttp(uri, null, null, set, null, null);
+
+ let expected = "foo=b";
+ let actual = cs.getCookieStringFromHttp(uri, null, null);
+ do_check_eq(actual, expected);
+}
+
diff --git a/netwerk/cookie/test/unit/xpcshell.ini b/netwerk/cookie/test/unit/xpcshell.ini
new file mode 100644
index 000000000..f9c4093cf
--- /dev/null
+++ b/netwerk/cookie/test/unit/xpcshell.ini
@@ -0,0 +1,10 @@
+[DEFAULT]
+head =
+tail =
+
+[test_bug643051.js]
+[test_bug1155169.js]
+[test_bug1267910.js]
+[test_parser_0001.js]
+[test_parser_0019.js]
+[test_eviction.js] \ No newline at end of file
diff --git a/netwerk/cookie/test/unit_ipc/test_ipc_parser_0001.js b/netwerk/cookie/test/unit_ipc/test_ipc_parser_0001.js
new file mode 100644
index 000000000..988c8d196
--- /dev/null
+++ b/netwerk/cookie/test/unit_ipc/test_ipc_parser_0001.js
@@ -0,0 +1,9 @@
+var Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+function run_test() {
+ // Allow all cookies.
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+ run_test_in_child("../unit/test_parser_0001.js");
+}
diff --git a/netwerk/cookie/test/unit_ipc/test_ipc_parser_0019.js b/netwerk/cookie/test/unit_ipc/test_ipc_parser_0019.js
new file mode 100644
index 000000000..535ac6e34
--- /dev/null
+++ b/netwerk/cookie/test/unit_ipc/test_ipc_parser_0019.js
@@ -0,0 +1,9 @@
+var Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+function run_test() {
+ // Allow all cookies.
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+ run_test_in_child("../unit/test_parser_0019.js");
+}
diff --git a/netwerk/cookie/test/unit_ipc/xpcshell.ini b/netwerk/cookie/test/unit_ipc/xpcshell.ini
new file mode 100644
index 000000000..922443490
--- /dev/null
+++ b/netwerk/cookie/test/unit_ipc/xpcshell.ini
@@ -0,0 +1,10 @@
+[DEFAULT]
+head =
+tail =
+skip-if = toolkit == 'android'
+support-files =
+ !/netwerk/cookie/test/unit/test_parser_0001.js
+ !/netwerk/cookie/test/unit/test_parser_0019.js
+
+[test_ipc_parser_0001.js]
+[test_ipc_parser_0019.js]