Bug 950399 - Tests for domain cookies. r=yoric, a=sledru
authorTim Taubert <ttaubert@mozilla.com>
Thu, 15 Jan 2015 13:09:02 +0100
changeset 242928 670d3f856665
parent 242927 91f8d6ca5030
child 242929 18ade4ad787e
push id4342
push userryanvm@gmail.com
push date2015-01-20 16:03 +0000
treeherdermozilla-beta@fae52bd681e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyoric, sledru
bugs950399
milestone36.0
Bug 950399 - Tests for domain cookies. r=yoric, a=sledru
browser/components/sessionstore/test/browser.ini
browser/components/sessionstore/test/browser_cookies.js
browser/components/sessionstore/test/browser_cookies.sjs
--- a/browser/components/sessionstore/test/browser.ini
+++ b/browser/components/sessionstore/test/browser.ini
@@ -7,16 +7,17 @@
 # browser_589246.js is disabled for leaking browser windows (bug 752467)
 # browser_580512.js is disabled for leaking browser windows (bug 752467)
 
 [DEFAULT]
 support-files =
   head.js
   content.js
   content-forms.js
+  browser_cookies.sjs
   browser_formdata_sample.html
   browser_formdata_xpath_sample.html
   browser_frametree_sample.html
   browser_frametree_sample_frameset.html
   browser_frame_history_index.html
   browser_frame_history_index2.html
   browser_frame_history_index_blank.html
   browser_frame_history_a.html
@@ -60,16 +61,17 @@ support-files =
 
 [browser_aboutPrivateBrowsing.js]
 [browser_aboutSessionRestore.js]
 [browser_attributes.js]
 [browser_backup_recovery.js]
 [browser_broadcast.js]
 [browser_capabilities.js]
 [browser_cleaner.js]
+[browser_cookies.js]
 [browser_crashedTabs.js]
 skip-if = !e10s || os == "linux" # Waiting on OMTC enabled by default on Linux (Bug 994541)
 [browser_dying_cache.js]
 [browser_dynamic_frames.js]
 [browser_form_restore_events.js]
 [browser_formdata.js]
 skip-if = buildapp == 'mulet'
 [browser_formdata_format.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_cookies.js
@@ -0,0 +1,175 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const PATH = "/browser/browser/components/sessionstore/test/";
+
+/**
+ * Remove all cookies to start off a clean slate.
+ */
+add_task(function* test_setup() {
+  Services.cookies.removeAll();
+});
+
+/**
+ * Test multiple scenarios with different Set-Cookie header domain= params.
+ */
+add_task(function* test_run() {
+  // Set-Cookie: foobar=random()
+  // The domain of the cookie should be the request domain (www.example.com).
+  // We should collect data only for the request domain, no parent or subdomains.
+  yield testCookieCollection({
+    host: "http://www.example.com",
+    cookieHost: "www.example.com",
+    cookieURIs: ["http://www.example.com" + PATH],
+    noCookieURIs: ["http://example.com/" + PATH]
+  });
+
+  // Set-Cookie: foobar=random()
+  // The domain of the cookie should be the request domain (example.com).
+  // We should collect data only for the request domain, no parent or subdomains.
+  yield testCookieCollection({
+    host: "http://example.com",
+    cookieHost: "example.com",
+    cookieURIs: ["http://example.com" + PATH],
+    noCookieURIs: ["http://www.example.com/" + PATH]
+  });
+
+  // Set-Cookie: foobar=random(); Domain=example.com
+  // The domain of the cookie should be the given one (.example.com).
+  // We should collect data for the given domain and its subdomains.
+  yield testCookieCollection({
+    host: "http://example.com",
+    domain: "example.com",
+    cookieHost: ".example.com",
+    cookieURIs: ["http://example.com" + PATH, "http://www.example.com/" + PATH],
+    noCookieURIs: ["about:robots"]
+  });
+
+  // Set-Cookie: foobar=random(); Domain=.example.com
+  // The domain of the cookie should be the given one (.example.com).
+  // We should collect data for the given domain and its subdomains.
+  yield testCookieCollection({
+    host: "http://example.com",
+    domain: ".example.com",
+    cookieHost: ".example.com",
+    cookieURIs: ["http://example.com" + PATH, "http://www.example.com/" + PATH],
+    noCookieURIs: ["about:robots"]
+  });
+
+  // Set-Cookie: foobar=random(); Domain=www.example.com
+  // The domain of the cookie should be the given one (.www.example.com).
+  // We should collect data for the given domain and its subdomains.
+  yield testCookieCollection({
+    host: "http://www.example.com",
+    domain: "www.example.com",
+    cookieHost: ".www.example.com",
+    cookieURIs: ["http://www.example.com/" + PATH],
+    noCookieURIs: ["http://example.com"]
+  });
+
+  // Set-Cookie: foobar=random(); Domain=.www.example.com
+  // The domain of the cookie should be the given one (.www.example.com).
+  // We should collect data for the given domain and its subdomains.
+  yield testCookieCollection({
+    host: "http://www.example.com",
+    domain: ".www.example.com",
+    cookieHost: ".www.example.com",
+    cookieURIs: ["http://www.example.com/" + PATH],
+    noCookieURIs: ["http://example.com"]
+  });
+});
+
+/**
+ * Generic test function to check sessionstore's cookie collection module with
+ * different cookie domains given in the Set-Cookie header. See above for some
+ * usage examples.
+ */
+let testCookieCollection = Task.async(function (params) {
+  let tab = gBrowser.addTab("about:blank");
+  let browser = tab.linkedBrowser;
+
+  let urlParams = new URLSearchParams();
+  let value = Math.random();
+  urlParams.append("value", value);
+
+  if (params.domain) {
+    urlParams.append("domain", params.domain);
+  }
+
+  // Construct request URI.
+  let uri = `${params.host}${PATH}browser_cookies.sjs?${urlParams}`;
+
+  // Wait for the browser to load and the cookie to be set.
+  // These two events can probably happen in no particular order,
+  // so let's wait for them in parallel.
+  yield Promise.all([
+    waitForNewCookie(),
+    replaceCurrentURI(browser, uri)
+  ]);
+
+  // Check all URIs for which the cookie should be collected.
+  for (let uri of params.cookieURIs || []) {
+    yield replaceCurrentURI(browser, uri);
+
+    // Check the cookie.
+    let cookie = getCookie();
+    is(cookie.host, params.cookieHost, "cookie host is correct");
+    is(cookie.path, PATH, "cookie path is correct");
+    is(cookie.name, "foobar", "cookie name is correct");
+    is(cookie.value, value, "cookie value is correct");
+  }
+
+  // Check all URIs for which the cookie should NOT be collected.
+  for (let uri of params.noCookieURIs || []) {
+    yield replaceCurrentURI(browser, uri);
+
+    // Cookie should be ignored.
+    ok(!getCookie(), "no cookie collected");
+  }
+
+  // Clean up.
+  gBrowser.removeTab(tab);
+  Services.cookies.removeAll();
+});
+
+/**
+ * Replace the current URI of the given browser by loading a new URI. The
+ * browser's session history will be completely replaced. This function ensures
+ * that the parent process has the lastest shistory data before resolving.
+ */
+let replaceCurrentURI = Task.async(function* (browser, uri) {
+  // Replace the tab's current URI with the parent domain.
+  let flags = Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
+  browser.loadURIWithFlags(uri, flags);
+  yield promiseBrowserLoaded(browser);
+
+  // Ensure the tab's session history is up-to-date.
+  TabState.flush(browser);
+});
+
+/**
+ * Waits for a new "*example.com" cookie to be added.
+ */
+function waitForNewCookie() {
+  return new Promise(resolve => {
+    Services.obs.addObserver(function observer(subj, topic, data) {
+      let cookie = subj.QueryInterface(Ci.nsICookie2);
+      if (data == "added" && cookie.host.endsWith("example.com")) {
+        Services.obs.removeObserver(observer, topic);
+        resolve();
+      }
+    }, "cookie-changed", false);
+  });
+}
+
+/**
+ * Retrieves the first cookie in the first window from the current sessionstore
+ * state.
+ */
+function getCookie() {
+  let state = JSON.parse(ss.getWindowState(window));
+  let cookies = state.windows[0].cookies || [];
+  return cookies[0] || null;
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_cookies.sjs
@@ -0,0 +1,21 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+Components.utils.importGlobalProperties(["URLSearchParams"]);
+
+function handleRequest(req, resp) {
+  resp.setStatusLine(req.httpVersion, 200);
+
+  let params = new URLSearchParams(req.queryString);
+  let value = params.get("value");
+
+  let domain = "";
+  if  (params.has("domain")) {
+    domain = `; Domain=${params.get("domain")}`;
+  }
+
+  resp.setHeader("Set-Cookie", `foobar=${value}${domain}`);
+  resp.write("<meta charset=utf-8>hi");
+}