michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: var httpserver; michael@0: michael@0: function inChildProcess() { michael@0: return Cc["@mozilla.org/xre/app-info;1"] michael@0: .getService(Ci.nsIXULRuntime) michael@0: .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; michael@0: } michael@0: function makeChan(path) { michael@0: var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); michael@0: var chan = ios.newChannel("http://localhost:" + httpserver.identity.primaryPort + "/" + path, null, null) michael@0: .QueryInterface(Ci.nsIHttpChannel); michael@0: return chan; michael@0: } michael@0: michael@0: function setup_chan(path, isPrivate, callback) { michael@0: var chan = makeChan(path); michael@0: chan.QueryInterface(Ci.nsIPrivateBrowsingChannel).setPrivate(isPrivate); michael@0: chan.asyncOpen(new ChannelListener(callback), null); michael@0: } michael@0: michael@0: function set_cookie(value, callback) { michael@0: return setup_chan('set?cookie=' + value, false, callback); michael@0: } michael@0: michael@0: function set_private_cookie(value, callback) { michael@0: return setup_chan('set?cookie=' + value, true, callback); michael@0: } michael@0: michael@0: function check_cookie_presence(value, isPrivate, expected, callback) { michael@0: var chan = setup_chan('present?cookie=' + value.replace('=','|'), isPrivate, function(req) { michael@0: req.QueryInterface(Ci.nsIHttpChannel); michael@0: do_check_eq(req.responseStatus, expected ? 200 : 404); michael@0: callback(req); michael@0: }); michael@0: } michael@0: michael@0: function presentHandler(metadata, response) { michael@0: var present = false; michael@0: var match = /cookie=([^&]*)/.exec(metadata.queryString); michael@0: if (match) { michael@0: try { michael@0: present = metadata.getHeader("Cookie").indexOf(match[1].replace("|","=")) != -1; michael@0: } catch (x) { michael@0: } michael@0: } michael@0: response.setStatusLine("1.0", present ? 200 : 404, ""); michael@0: } michael@0: michael@0: function setHandler(metadata, response) { michael@0: response.setStatusLine("1.0", 200, "Cookie set"); michael@0: var match = /cookie=([^&]*)/.exec(metadata.queryString); michael@0: if (match) { michael@0: response.setHeader("Set-Cookie", match[1]); michael@0: } michael@0: } michael@0: michael@0: function run_test() { michael@0: // Allow all cookies if the pref service is available in this process. michael@0: if (!inChildProcess()) michael@0: Services.prefs.setIntPref("network.cookie.cookieBehavior", 0); michael@0: michael@0: httpserver = new HttpServer(); michael@0: httpserver.registerPathHandler("/set", setHandler); michael@0: httpserver.registerPathHandler("/present", presentHandler); michael@0: httpserver.start(-1); michael@0: michael@0: do_test_pending(); michael@0: michael@0: function check_cookie(req) { michael@0: req.QueryInterface(Ci.nsIHttpChannel); michael@0: do_check_eq(req.responseStatus, 200); michael@0: try { michael@0: do_check_true(req.getResponseHeader("Set-Cookie") != "", "expected a Set-Cookie header"); michael@0: } catch (x) { michael@0: do_throw("missing Set-Cookie header"); michael@0: } michael@0: michael@0: runNextTest(); michael@0: } michael@0: michael@0: let tests = []; michael@0: michael@0: function runNextTest() { michael@0: do_execute_soon(tests.shift()); michael@0: } michael@0: michael@0: tests.push(function() { michael@0: set_cookie("C1=V1", check_cookie); michael@0: }); michael@0: tests.push(function() { michael@0: set_private_cookie("C2=V2", check_cookie); michael@0: }); michael@0: tests.push(function() { michael@0: // Check that the first cookie is present in a non-private request michael@0: check_cookie_presence("C1=V1", false, true, runNextTest); michael@0: }); michael@0: tests.push(function() { michael@0: // Check that the second cookie is present in a private request michael@0: check_cookie_presence("C2=V2", true, true, runNextTest); michael@0: }); michael@0: tests.push(function() { michael@0: // Check that the first cookie is not present in a private request michael@0: check_cookie_presence("C1=V1", true, false, runNextTest); michael@0: }); michael@0: tests.push(function() { michael@0: // Check that the second cookie is not present in a non-private request michael@0: check_cookie_presence("C2=V2", false, false, runNextTest); michael@0: }); michael@0: michael@0: // The following test only works in a non-e10s situation at the moment, michael@0: // since the notification needs to run in the parent process but there is michael@0: // no existing mechanism to make that happen. michael@0: if (!inChildProcess()) { michael@0: tests.push(function() { michael@0: // Simulate all private browsing instances being closed michael@0: var obsvc = Cc["@mozilla.org/observer-service;1"]. michael@0: getService(Ci.nsIObserverService); michael@0: obsvc.notifyObservers(null, "last-pb-context-exited", null); michael@0: // Check that all private cookies are now unavailable in new private requests michael@0: check_cookie_presence("C2=V2", true, false, runNextTest); michael@0: }); michael@0: } michael@0: michael@0: tests.push(function() { httpserver.stop(do_test_finished); }); michael@0: michael@0: runNextTest(); michael@0: }