Bug 421494 - reimplement third party cookie blocking. r=mconnor, sr=bz, blocking1.9+
authordwitte@stanford.edu
Wed, 12 Mar 2008 00:53:50 -0700
changeset 12921 7bef01d821b58c1ab71fe39595dfca249a46ac0b
parent 12920 ea4a5a69e7e6b84163818b64d77f9b22dc0f0e0c
child 12922 c136bded0df29cf26a9665c9caa92e47d04353ac
push idunknown
push userunknown
push dateunknown
reviewersmconnor, bz, blocking1.9
bugs421494
milestone1.9b5pre
Bug 421494 - reimplement third party cookie blocking. r=mconnor, sr=bz, blocking1.9+
extensions/cookie/Makefile.in
extensions/cookie/makefiles.sh
extensions/cookie/nsCookiePermission.cpp
extensions/cookie/test/Makefile.in
extensions/cookie/test/browser_test_favicon.js
extensions/cookie/test/file_domain_inner.html
extensions/cookie/test/file_domain_inner_inner.html
extensions/cookie/test/file_image_inner.html
extensions/cookie/test/file_image_inner_inner.html
extensions/cookie/test/file_loadflags_inner.html
extensions/cookie/test/file_localhost_inner.html
extensions/cookie/test/file_loopback_inner.html
extensions/cookie/test/file_subdomain_inner.html
extensions/cookie/test/file_testcommon.js
extensions/cookie/test/file_testloadflags.js
extensions/cookie/test/image1.png
extensions/cookie/test/image1.png^headers^
extensions/cookie/test/image2.png
extensions/cookie/test/image2.png^headers^
extensions/cookie/test/test1.css
extensions/cookie/test/test1.css^headers^
extensions/cookie/test/test2.css
extensions/cookie/test/test2.css^headers^
extensions/cookie/test/test_differentdomain.html
extensions/cookie/test/test_image.html
extensions/cookie/test/test_loadflags.html
extensions/cookie/test/test_same_base_domain.html
extensions/cookie/test/test_same_base_domain_2.html
extensions/cookie/test/test_same_base_domain_3.html
extensions/cookie/test/test_same_base_domain_4.html
extensions/cookie/test/test_same_base_domain_5.html
extensions/cookie/test/test_same_base_domain_6.html
extensions/cookie/test/test_same_base_domain_7.html
extensions/cookie/test/test_samedomain.html
extensions/cookie/test/unit/test_cookies.js
netwerk/cookie/public/nsICookiePermission.idl
netwerk/cookie/src/nsCookieService.cpp
netwerk/cookie/src/nsCookieService.h
netwerk/test/TestCookie.cpp
--- a/extensions/cookie/Makefile.in
+++ b/extensions/cookie/Makefile.in
@@ -51,20 +51,23 @@ GRE_MODULE	= 1
 LIBXUL_LIBRARY = 1
 
 PACKAGE_FILE = cookie.pkg
 
 REQUIRES	= xpcom \
 		  string \
 		  necko \
 		  dom \
+		  content \
+		  widget \
 		  pref \
 		  windowwatcher \
 		  docshell \
 		  appshell \
+		  caps \
 		  storage \
 		  $(NULL)
 
 CPPSRCS		= \
 		nsCookieModule.cpp \
 		nsPermission.cpp \
 		nsPermissionManager.cpp \
 		nsPopupWindowManager.cpp \
@@ -80,9 +83,13 @@ XPIDLSRCS	= \
 EXTRA_DSO_LDOPTS = \
 		$(MOZ_COMPONENT_LIBS) \
 		$(NULL)
 
 ifdef MOZ_MAIL_NEWS
 DEFINES += -DMOZ_MAIL_NEWS
 endif
 
+ifdef ENABLE_TESTS
+TOOL_DIRS		+= test
+endif
+
 include $(topsrcdir)/config/rules.mk
--- a/extensions/cookie/makefiles.sh
+++ b/extensions/cookie/makefiles.sh
@@ -33,9 +33,10 @@
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 add_makefiles "
   extensions/cookie/Makefile
+  extensions/cookie/test/Makefile
 "
--- a/extensions/cookie/nsCookiePermission.cpp
+++ b/extensions/cookie/nsCookiePermission.cpp
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * Michiel van Leeuwen (mvl@exedo.nl).
  * Portions created by the Initial Developer are Copyright (C) 2003
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Darin Fisher <darin@meer.net>
+ *   Daniel Witte <dwitte@stanford.edu>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -44,21 +45,22 @@
 #include "nsICookieManager2.h"
 #include "nsNetUtil.h"
 #include "nsIURI.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefBranch2.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
-#include "nsIInterfaceRequestor.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsILoadGroup.h"
+#include "nsIWebNavigation.h"
+#include "nsINode.h"
 #include "nsIChannel.h"
 #include "nsIDOMWindow.h"
+#include "nsIDOMDocument.h"
+#include "nsIPrincipal.h"
 #include "nsString.h"
 #include "nsCRT.h"
 
 /****************************************************************
  ************************ nsCookiePermission ********************
  ****************************************************************/
 
 // values for mCookiesLifetimePolicy
@@ -194,17 +196,16 @@ nsCookiePermission::SetAccess(nsIURI    
   //       the permission codes used by nsIPermissionManager.
   //       this is nice because it avoids conversion code.
   //
   return mPermMgr->Add(aURI, kPermissionType, aAccess);
 }
 
 NS_IMETHODIMP
 nsCookiePermission::CanAccess(nsIURI         *aURI,
-                              nsIURI         *aFirstURI,
                               nsIChannel     *aChannel,
                               nsCookieAccess *aResult)
 {
 #ifdef MOZ_MAIL_NEWS
   // disable cookies in mailnews if user's prefs say so
   if (mCookiesDisabledForMailNews) {
     //
     // try to examine the "app type" of the docshell owning this request.  if
@@ -230,17 +231,16 @@ nsCookiePermission::CanAccess(nsIURI    
             if (docshell)
               docshell->GetAppType(&appType);
         } while (appType != nsIDocShell::APP_TYPE_MAIL &&
                  NS_SUCCEEDED(item->GetParent(getter_AddRefs(parent))) &&
                  parent);
       }
     }
     if ((appType == nsIDocShell::APP_TYPE_MAIL) ||
-        (aFirstURI && IsFromMailNews(aFirstURI)) ||
         IsFromMailNews(aURI)) {
       *aResult = ACCESS_DENY;
       return NS_OK;
     }
   }
 #endif // MOZ_MAIL_NEWS
   
   // finally, check with permission manager...
@@ -416,16 +416,104 @@ nsCookiePermission::CanSetCookie(nsIURI 
         }
       }
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP 
+nsCookiePermission::GetOriginatingURI(nsIChannel  *aChannel,
+                                      nsIURI     **aURI)
+{
+  /* to find the originating URI, we use the loadgroup of the channel to obtain
+   * the docshell owning the load, and from there, we find the root content
+   * docshell and its URI. there are several possible cases:
+   *
+   * 1) no channel. this will occur for plugins using the nsICookieStorage
+   *    interface, since they have none to provide. other consumers should
+   *    have a channel.
+   *
+   * 2) a channel, but no docshell. this can occur when the consumer kicking
+   *    off the load doesn't provide one to the channel, and should be limited
+   *    to loads of certain types of resources (e.g. favicons).
+   *
+   * 3) a non-content docshell. this occurs for loads kicked off from chrome,
+   *    where no content docshell exists (favicons can also fall into this
+   *    category).
+   *
+   * 4) a content docshell equal to the root content docshell, with channel
+   *    loadflags LOAD_DOCUMENT_URI. this covers the case of a freshly kicked-
+   *    off load (e.g. the user typing something in the location bar, or
+   *    clicking on a bookmark), where the currentURI hasn't yet been set,
+   *    and will be bogus. we return the channel URI in this case. note that
+   *    we could also allow non-content docshells here, but that goes against
+   *    the philosophy of having an audit trail back to a URI the user typed
+   *    or clicked on.
+   *
+   * 5) a root content docshell. this covers most cases for an ordinary page
+   *    load from the location bar, and will catch nested frames within
+   *    a page, image loads, etc. we return the URI of the docshell's principal
+   *    in this case.
+   *
+   */
+
+  *aURI = nsnull;
+
+  // case 1)
+  if (!aChannel)
+    return NS_ERROR_NULL_POINTER;
+
+  // find the docshell and its root
+  nsCOMPtr<nsIDocShellTreeItem> docshell, root;
+  NS_QueryNotificationCallbacks(aChannel, docshell);
+  if (docshell)
+    docshell->GetSameTypeRootTreeItem(getter_AddRefs(root));
+
+  PRInt32 type;
+  if (root)
+    root->GetItemType(&type);
+
+  // cases 2) and 3)
+  if (!root || type != nsIDocShellTreeItem::typeContent)
+    return NS_ERROR_INVALID_ARG;
+
+  // case 4)
+  if (docshell == root) {
+    nsLoadFlags flags;
+    aChannel->GetLoadFlags(&flags);
+
+    if (flags & nsIChannel::LOAD_DOCUMENT_URI) {
+      // get the channel URI - the docshell's will be bogus
+      aChannel->GetURI(aURI);
+      if (!*aURI)
+        return NS_ERROR_NULL_POINTER;
+
+      return NS_OK;
+    }
+  }
+
+  // case 5) - get the originating URI from the docshell's principal
+  nsCOMPtr<nsIWebNavigation> webnav = do_QueryInterface(root);
+  if (webnav) {
+    nsCOMPtr<nsIDOMDocument> doc;
+    webnav->GetDocument(getter_AddRefs(doc));
+    nsCOMPtr<nsINode> node = do_QueryInterface(doc);
+    if (node)
+      node->NodePrincipal()->GetURI(aURI);
+  }
+
+  if (!*aURI)
+    return NS_ERROR_NULL_POINTER;
+
+  // all done!
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsCookiePermission::Observe(nsISupports     *aSubject,
                             const char      *aTopic,
                             const PRUnichar *aData)
 {
   nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(aSubject);
   NS_ASSERTION(!nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic),
                "unexpected topic - we only deal with pref changes!");
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/Makefile.in
@@ -0,0 +1,93 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = extensions/cookie/test
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE          = test_cookies
+
+_TEST_FILES = \
+  test_samedomain.html \
+  file_testcommon.js \
+  file_domain_inner.html \
+  file_domain_inner_inner.html \
+  test_differentdomain.html \
+  test_image.html \
+  file_image_inner.html \
+  file_image_inner_inner.html \
+  image1.png \
+  image1.png^headers^ \
+  image2.png \
+  image2.png^headers^ \
+  test1.css \
+  test1.css^headers^ \
+  test2.css \
+  test2.css^headers^ \
+  test_loadflags.html \
+  file_testloadflags.js \
+  file_loadflags_inner.html \
+  test_same_base_domain.html \
+  file_subdomain_inner.html \
+  test_same_base_domain_2.html \
+  test_same_base_domain_3.html \
+  test_same_base_domain_4.html \
+  file_localhost_inner.html \
+  test_same_base_domain_5.html \
+  test_same_base_domain_6.html \
+  file_loopback_inner.html \
+  test_same_base_domain_7.html \
+	$(NULL)
+
+_BROWSER_TEST_FILES = \
+  browser_test_favicon.js \
+  $(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+
+libs:: $(_BROWSER_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
+
+XPCSHELL_TESTS = unit
+
+include $(topsrcdir)/config/rules.mk
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/browser_test_favicon.js
@@ -0,0 +1,44 @@
+// tests third party cookie blocking using a favicon load directly from chrome.
+// in this case, the docshell of the channel is chrome, not content; thus
+// the cookie should be considered third party.
+
+function test() {
+  waitForExplicitFinish();
+
+  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                        .getService(Components.interfaces.nsIPrefBranch);
+  prefs.setIntPref("network.cookie.cookieBehavior", 1);
+
+  var o = new obs();
+
+  // kick off a favicon load
+  PageProxySetIcon("http://example.org/tests/extensions/cookie/test/image1.png");
+}
+
+function obs () {
+  this.os = Components.classes["@mozilla.org/observer-service;1"]
+                      .getService(Components.interfaces.nsIObserverService);
+  this.os.addObserver(this, "cookie-rejected", false);
+}
+
+obs.prototype = {
+  observe: function obs_observe (theSubject, theTopic, theData)
+  {
+    var uri = theSubject.QueryInterface(Components.interfaces.nsIURI);
+    var domain = uri.host;
+
+    if (domain == "example.org") {
+      ok(true, "foreign favicon cookie was blocked");
+
+      var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                            .getService(Components.interfaces.nsIPrefBranch);
+      prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
+      this.os.removeObserver(this, "cookie-rejected");
+      this.os = null;
+
+      finish();
+    }
+  }
+}
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_domain_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+<body>
+<iframe name="frame1" src="http://example.org/tests/extensions/cookie/test/file_domain_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_domain_inner_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta2=tag2">
+  <script type="text/javascript">
+    document.cookie = "can2=has2";
+
+    // send a message to our test document, to say we're done loading
+    window.parent.opener.postMessage("message");
+  </script>
+</head>
+<body>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_image_inner.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+</head>
+<body>
+<iframe name="frame1" src="http://example.org/tests/extensions/cookie/test/file_image_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_image_inner_inner.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <link rel="stylesheet" type="text/css" media="all" href="http://example.org/tests/extensions/cookie/test/test1.css" />
+  <link rel="stylesheet" type="text/css" media="all" href="http://example.com/tests/extensions/cookie/test/test2.css" />
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta2=tag2">
+  <script type="text/javascript">
+    function runTest() {
+      document.cookie = "can2=has2";
+
+      // send a message to our test document, to say we're done loading
+      window.parent.opener.postMessage("message");
+    }
+  </script>
+</head>
+<body>
+<img src="http://example.org/tests/extensions/cookie/test/image1.png" onload="runTest()" />
+<img src="http://example.com/tests/extensions/cookie/test/image2.png" onload="runTest()" />
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_loadflags_inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    function runTest() {
+      document.cookie = "can=has";
+
+      // send a message to our test document, to say we're done loading
+      window.opener.postMessage("message");
+    }
+  </script>
+</head>
+<body>
+<img src="http://example.org/tests/extensions/cookie/test/image1.png" onload="runTest()" />
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_localhost_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+<body>
+<iframe name="frame1" src="http://localhost:8888/tests/extensions/cookie/test/file_domain_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_loopback_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+<body>
+<iframe name="frame1" src="http://127.0.0.1:8888/tests/extensions/cookie/test/file_domain_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_subdomain_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+<body>
+<iframe name="frame1" src="http://test2.example.org/tests/extensions/cookie/test/file_domain_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_testcommon.js
@@ -0,0 +1,67 @@
+SimpleTest.waitForExplicitFinish();
+
+var gPopup = null;
+
+var gExpectedCookies = 0;
+var gExpectedLoads = 0;
+var gLoads = 0;
+
+function setupTest(uri, cookies, loads) {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
+  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                        .getService(Components.interfaces.nsIPrefBranch);
+  prefs.setIntPref("network.cookie.cookieBehavior", 1);
+
+  var cs = Components.classes["@mozilla.org/cookiemanager;1"]
+                      .getService(Components.interfaces.nsICookieManager2);
+  cs.removeAll();
+
+  gExpectedCookies = cookies;
+  gExpectedLoads = loads;
+
+  // 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');
+}
+
+/** Receives MessageEvents to this window. */
+function messageReceiver(evt)
+{
+  ok(evt instanceof MessageEvent, "wrong event type");
+
+  if (evt.data == "message")
+    gLoads++;
+  else {
+    ok(false, "wrong message");
+    gPopup.close();
+    SimpleTest.finish();
+  }
+
+  // only run the test when all our children are done loading & setting cookies
+  if (gLoads == gExpectedLoads)
+    runTest();
+}
+
+function runTest() {
+  // set a cookie from a domain of "localhost"
+  document.cookie = "oh=hai";
+
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  var cs = Components.classes["@mozilla.org/cookiemanager;1"]
+                     .getService(Components.interfaces.nsICookieManager);
+  var list = cs.enumerator;
+  var count = 0;
+  while (list.hasMoreElements()) {
+    count++;
+    list.getNext();
+  }
+  is(count, gExpectedCookies, "incorrect number of cookies");
+
+  gPopup.close();
+  cs.removeAll();
+  SimpleTest.finish();
+}
+
+document.addEventListener("message", messageReceiver, false);
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_testloadflags.js
@@ -0,0 +1,111 @@
+SimpleTest.waitForExplicitFinish();
+
+var gPopup = null;
+
+var gExpectedCookies = 0;
+var gExpectedLoads = 0;
+var gExpectedHeaders = 0;
+var gLoads = 0;
+var gHeaders = 0;
+
+var o = null;
+
+function setupTest(uri, domain, cookies, loads, headers) {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
+  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                        .getService(Components.interfaces.nsIPrefBranch);
+  prefs.setIntPref("network.cookie.cookieBehavior", 1);
+
+  var cs = Components.classes["@mozilla.org/cookiemanager;1"]
+                      .getService(Components.interfaces.nsICookieManager2);
+  cs.removeAll();
+  cs.add(domain, "", "oh", "hai", false, false, true, Math.pow(2, 62));
+  is(cs.countCookiesFromHost(domain), 1, "cookie wasn't inited");
+
+  o = new obs();
+
+  gExpectedCookies = cookies;
+  gExpectedLoads = loads;
+  gExpectedHeaders = headers;
+
+  // 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');
+}
+
+function obs () {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  this.os = Components.classes["@mozilla.org/observer-service;1"]
+                      .getService(Components.interfaces.nsIObserverService);
+  this.os.addObserver(this, "http-on-modify-request", false);
+  this.window = window;
+}
+
+obs.prototype = {
+  observe: function obs_observe (theSubject, theTopic, theData)
+  {
+    this.window.netscape.security
+        .PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    var httpchannel = theSubject.QueryInterface(this.window.Components.interfaces
+                                                    .nsIHttpChannel);
+
+    var cookie = httpchannel.getRequestHeader("Cookie");
+
+    var got = cookie.indexOf("oh=hai");
+    this.window.isnot(got, -1, "cookie wasn't sent");
+    gHeaders++;
+  },
+
+  remove: function obs_remove()
+  {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    this.os.removeObserver(this, "http-on-modify-request");
+    this.os = null;
+    this.window = null;
+  }
+}
+
+/** Receives MessageEvents to this window. */
+function messageReceiver(evt)
+{
+  ok(evt instanceof MessageEvent, "wrong event type");
+
+  if (evt.data == "message")
+    gLoads++;
+  else {
+    ok(false, "wrong message");
+    o.remove();
+    gPopup.close();
+    SimpleTest.finish();
+  }
+
+  // only run the test when all our children are done loading & setting cookies
+  if (gLoads == gExpectedLoads)
+    runTest();
+}
+
+function runTest() {
+  // set a cookie from a domain of "localhost"
+  document.cookie = "o=noes";
+
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  var cs = Components.classes["@mozilla.org/cookiemanager;1"]
+                     .getService(Components.interfaces.nsICookieManager);
+  var list = cs.enumerator;
+  var count = 0;
+  while (list.hasMoreElements()) {
+    count++;
+    list.getNext();
+  }
+  is(count, gExpectedCookies, "incorrect number of cookies");
+  is(gHeaders, gExpectedHeaders, "incorrect number of request headers");
+
+  o.remove();
+  gPopup.close();
+  cs.removeAll();
+  SimpleTest.finish();
+}
+
+document.addEventListener("message", messageReceiver, false);
+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4b7c102840cab57d589b4380cb1d0675498fcda9
GIT binary patch
literal 1242
zc$@*+1SR{4P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960004lX+uL$Nkc;*P;zf(X>4Tx0C=30k<TjxVHn3h??_7Q#rTm@a}ax2+PJKe
zvU@-r)~4+4ZFXj?tugyH^IH4??#fLLew35sB**;&+>{)ols`Zz7ik<`+6&3Ip87oB
zo_c<P(X^%X4PYZsVPP(76-#BS;~s-<0I;1%&gSz={HnJ*1i<Z>Ev5f^-H+-Di={FM
z6ELfqlYm*#JPnvzN-7X}z;xDa7laF>!j(b}#2%2SYCZxI70s7GqTy5(h$fH@+*$zQ
z1<1Hw<baU`lp{k0#vw3VER`)inp%XJA!xg4dF2Ss&!B&#<s}E8cNMNDTi)w30uX&S
z(c0t$0HP}k?T>N%IszU0@Ua)i?<aBmaSCk@&<vc-u<>;lVNAhax!z6Z`Ujx<{>*xR
z0Mc+g538N9xC;kQFnR$!SCH?9l_`wO^LOZ50Wg@e{aPiomFHT8xvZ6|`}HuAw&VTl
z?SD&o+X^68mpfstx~{BQDSa<xEd<VZ%9=>0GkgN=i*4c{6kO5(000SaNLh0L01FcU
z01FcV0GgZ_0008*Nkl<ZIE{T$Ye<t}7(L&&O{Z?Nd7+D};jFBPF5AR8uUV00Q5Gd)
zKT4ttQFOBm>R(axBghhpis%YaSwDm*SW%g1$|O^3ZZj?II&IEfzwiCtw_nPP?EE`C
z&pGg%=K%jf;S(z>Y{*>-00s4y4S5f;!hi4Z(WKaB&4}hqq@WS;;O=v!1|mwyG(yGy
z8c+eQqK2HqV_XubKnZe*S2&sKR$M>`s`3N5XD2m~1nMJ%o&tdU`xYM~EQS)Q?acUH
zu_(_HduHWvq^HfQUbEd;J*MF%-25<msYKaxPU3wUxmr^-w*m>W7<7C3alP#pjB_(l
zsx86kH+5iyff5F;;E}~gz%OYkYjOjC^^Tb-pup~V<#7G#KqwM~2ql^aKjOD<1X*bd
z(f^>`ZF}4^3jpMlvN%p6F6-T_+j5C7nWmhMb^3gK{AR~!cmzL#qad+~*ki7O$M47G
z#w$=MY3FzbjT>7OQiQfpk!}%0lCs&b9FFhp@P)ki>Gwg9sZco8jJIwZ<SYy(a`2{e
zE9O_v-a8?K?5n1TL9LH5C8uFvxDTE{0AX1?ignrO`PzY@HZPL>@#sq>7^Gj|3kLuK
z$j1{5GbvF!1qwbML%|S2h(k`&0(A9u!+EV6`SxB|l>(mdTDWKG`c>_&+1_1-qvLOs
z5x(~Ar&f%FfDnyCPRc^`4t3#Wy%TD?6FW!*J)kg)VOsO)vwn{{;niBxv4(Mjru}U-
zoWQ@n@!}p<8CD`lMj=VS6qyE9ni#kwiZU<2jrw^zBV-$87TuAWMp<+ZzS(|U*A>lJ
z*5Yc_PgU!nlxfjwcOc<|2TLTvK64x=0&pZ~_-4~$49EpCp-5wxe`wB4Ng$OHVZ5R*
z8OB~O>KrcVI|pv3J}t0*alys+&Uf7K{)(sn(ocYSUzWXcQz>%->~>Nd%PU!SK6);n
zOgM(N+E(N6)=crl>P!-NHh3v^T6#SIY%MBM22xYSKMhDxmS%e%O#lD@07*qoM6N<$
Eg369MXaE2J
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/image1.png^headers^
@@ -0,0 +1,3 @@
+Cache-Control: no-cache
+Set-Cookie: foo=bar
+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4b7c102840cab57d589b4380cb1d0675498fcda9
GIT binary patch
literal 1242
zc$@*+1SR{4P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960004lX+uL$Nkc;*P;zf(X>4Tx0C=30k<TjxVHn3h??_7Q#rTm@a}ax2+PJKe
zvU@-r)~4+4ZFXj?tugyH^IH4??#fLLew35sB**;&+>{)ols`Zz7ik<`+6&3Ip87oB
zo_c<P(X^%X4PYZsVPP(76-#BS;~s-<0I;1%&gSz={HnJ*1i<Z>Ev5f^-H+-Di={FM
z6ELfqlYm*#JPnvzN-7X}z;xDa7laF>!j(b}#2%2SYCZxI70s7GqTy5(h$fH@+*$zQ
z1<1Hw<baU`lp{k0#vw3VER`)inp%XJA!xg4dF2Ss&!B&#<s}E8cNMNDTi)w30uX&S
z(c0t$0HP}k?T>N%IszU0@Ua)i?<aBmaSCk@&<vc-u<>;lVNAhax!z6Z`Ujx<{>*xR
z0Mc+g538N9xC;kQFnR$!SCH?9l_`wO^LOZ50Wg@e{aPiomFHT8xvZ6|`}HuAw&VTl
z?SD&o+X^68mpfstx~{BQDSa<xEd<VZ%9=>0GkgN=i*4c{6kO5(000SaNLh0L01FcU
z01FcV0GgZ_0008*Nkl<ZIE{T$Ye<t}7(L&&O{Z?Nd7+D};jFBPF5AR8uUV00Q5Gd)
zKT4ttQFOBm>R(axBghhpis%YaSwDm*SW%g1$|O^3ZZj?II&IEfzwiCtw_nPP?EE`C
z&pGg%=K%jf;S(z>Y{*>-00s4y4S5f;!hi4Z(WKaB&4}hqq@WS;;O=v!1|mwyG(yGy
z8c+eQqK2HqV_XubKnZe*S2&sKR$M>`s`3N5XD2m~1nMJ%o&tdU`xYM~EQS)Q?acUH
zu_(_HduHWvq^HfQUbEd;J*MF%-25<msYKaxPU3wUxmr^-w*m>W7<7C3alP#pjB_(l
zsx86kH+5iyff5F;;E}~gz%OYkYjOjC^^Tb-pup~V<#7G#KqwM~2ql^aKjOD<1X*bd
z(f^>`ZF}4^3jpMlvN%p6F6-T_+j5C7nWmhMb^3gK{AR~!cmzL#qad+~*ki7O$M47G
z#w$=MY3FzbjT>7OQiQfpk!}%0lCs&b9FFhp@P)ki>Gwg9sZco8jJIwZ<SYy(a`2{e
zE9O_v-a8?K?5n1TL9LH5C8uFvxDTE{0AX1?ignrO`PzY@HZPL>@#sq>7^Gj|3kLuK
z$j1{5GbvF!1qwbML%|S2h(k`&0(A9u!+EV6`SxB|l>(mdTDWKG`c>_&+1_1-qvLOs
z5x(~Ar&f%FfDnyCPRc^`4t3#Wy%TD?6FW!*J)kg)VOsO)vwn{{;niBxv4(Mjru}U-
zoWQ@n@!}p<8CD`lMj=VS6qyE9ni#kwiZU<2jrw^zBV-$87TuAWMp<+ZzS(|U*A>lJ
z*5Yc_PgU!nlxfjwcOc<|2TLTvK64x=0&pZ~_-4~$49EpCp-5wxe`wB4Ng$OHVZ5R*
z8OB~O>KrcVI|pv3J}t0*alys+&Uf7K{)(sn(ocYSUzWXcQz>%->~>Nd%PU!SK6);n
zOgM(N+E(N6)=crl>P!-NHh3v^T6#SIY%MBM22xYSKMhDxmS%e%O#lD@07*qoM6N<$
Eg369MXaE2J
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/image2.png^headers^
@@ -0,0 +1,3 @@
+Cache-Control: no-cache
+Set-Cookie: foo2=bar2
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test1.css
@@ -0,0 +1,2 @@
+
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test1.css^headers^
@@ -0,0 +1,3 @@
+Cache-Control: no-cache
+Set-Cookie: css=bar
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test2.css
@@ -0,0 +1,2 @@
+
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test2.css^headers^
@@ -0,0 +1,3 @@
+Cache-Control: no-cache
+Set-Cookie: css2=bar2
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_differentdomain.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.com/tests/extensions/cookie/test/file_domain_inner.html', 3, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_image.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_image_inner.html', 7, 3)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js"></script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_loadflags.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_loadflags_inner.html', 'example.org', 5, 1, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testloadflags.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://test1.example.org/tests/extensions/cookie/test/file_domain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_2.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://test1.example.org/tests/extensions/cookie/test/file_subdomain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_3.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_subdomain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_4.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://localhost:8888/tests/extensions/cookie/test/file_localhost_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_5.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://sub1.test1.example.org/tests/extensions/cookie/test/file_subdomain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_6.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://127.0.0.1:8888/tests/extensions/cookie/test/file_loopback_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_7.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://127.1:8888/tests/extensions/cookie/test/file_loopback_inner.html', 3, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_samedomain.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_domain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/unit/test_cookies.js
@@ -0,0 +1,49 @@
+// test third party cookie blocking, for the cases:
+// 1) with null channel
+// 2) with channel, but with no docshell parent
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+function run_test() {
+  var cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
+  var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
+  var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
+  var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+
+  var spec = "http://foo.com/dribble.html";
+  var uri = ios.newURI(spec, null, null);
+  var channel = ios.newChannelFromURI(uri);
+
+  // test with cookies enabled
+  prefs.setIntPref("network.cookie.cookieBehavior", 0);
+  // without channel
+  cs.setCookieString(uri, null, "oh=hai", null);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 1);
+  // with channel
+  cs.setCookieString(uri, null, "can=has", channel);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 2);
+  // without channel, from http
+  cs.setCookieStringFromHttp(uri, null, null, "cheez=burger", null, null);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 3);
+  // with channel, from http
+  cs.setCookieStringFromHttp(uri, null, null, "hot=dog", null, channel);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 4);
+  cs.removeAll();
+
+  // test with third party cookies blocked
+  prefs.setIntPref("network.cookie.cookieBehavior", 1);
+  // without channel
+  cs.setCookieString(uri, null, "oh=hai", null);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 0);
+  // with channel
+  cs.setCookieString(uri, null, "can=has", channel);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 0);
+  // without channel, from http
+  cs.setCookieStringFromHttp(uri, null, null, "cheez=burger", null, null);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 0);
+  // with channel, from http
+  cs.setCookieStringFromHttp(uri, null, null, "hot=dog", null, channel);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 0);
+}
+
--- a/netwerk/cookie/public/nsICookiePermission.idl
+++ b/netwerk/cookie/public/nsICookiePermission.idl
@@ -14,16 +14,17 @@
  * The Original Code is cookie manager code.
  *
  * The Initial Developer of the Original Code is
  * Michiel van Leeuwen (mvl@exedo.nl).
  * Portions created by the Initial Developer are Copyright (C) 2003
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ * Daniel Witte <dwitte@stanford.edu>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -40,17 +41,17 @@ interface nsICookie2;
 interface nsIURI;
 interface nsIChannel;
 
 typedef long nsCookieAccess;
 
 /**
  * An interface to test for cookie permissions
  */
-[scriptable, uuid(91f1c3ec-73a0-4bf0-bdc5-348a1f181b0e)]
+[scriptable, uuid(4b1a775d-f6d3-4389-be2e-9dfbaf2ab47b)]
 interface nsICookiePermission : nsISupports
 {
   /**
    * nsCookieAccess values
    */
   const nsCookieAccess ACCESS_DEFAULT = 0;
   const nsCookieAccess ACCESS_ALLOW   = 1;
   const nsCookieAccess ACCESS_DENY    = 2;
@@ -81,42 +82,39 @@ interface nsICookiePermission : nsISuppo
   /**
    * canAccess
    *
    * this method is called to test whether or not the given URI/channel may
    * access the cookie database, either to set or get cookies.
    *
    * @param aURI
    *        the URI trying to access cookies
-   * @param aFirstURI
-   *        the URI initiated by the user that resulted in aURI being loaded
    * @param aChannel
    *        the channel corresponding to aURI
    *
    * @return one of the following nsCookieAccess values:
    *         ACCESS_DEFAULT, ACCESS_ALLOW, or ACCESS_DENY
    */
   nsCookieAccess canAccess(in nsIURI     aURI,
-                           in nsIURI     aFirstURI,
                            in nsIChannel aChannel);
 
   /**
    * canSetCookie
    *
    * this method is called to test whether or not the given URI/channel may
    * set a specific cookie.  this method is always preceded by a call to
    * canAccess. it may modify the isSession and expiry attributes of the
    * cookie via the aIsSession and aExpiry parameters, in order to limit
    * or extend the lifetime of the cookie. this is useful, for instance, to
    * downgrade a cookie to session-only if it fails to meet certain criteria.
    *
    * @param aURI
    *        the URI trying to set the cookie
    * @param aChannel
-   *        the corresponding to aURI
+   *        the channel corresponding to aURI
    * @param aCookie
    *        the cookie being added to the cookie database
    * @param aIsSession
    *        when canSetCookie is invoked, this is the current isSession attribute
    *        of the cookie. canSetCookie may leave this value unchanged to
    *        preserve this attribute of the cookie.
    * @param aExpiry
    *        when canSetCookie is invoked, this is the current expiry time of
@@ -125,16 +123,32 @@ interface nsICookiePermission : nsISuppo
    *
    * @return true if the cookie can be set.
    */
   boolean canSetCookie(in nsIURI     aURI,
                        in nsIChannel aChannel,
                        in nsICookie2 aCookie,
                        inout boolean aIsSession,
                        inout PRInt64 aExpiry);
+
+  /**
+   * getOriginatingURI
+   *
+   * determines the originating URI for a load given a channel, for third-party
+   * cookie blocking. this is done by leveraging the loadgroup of the channel to
+   * find the root content docshell, and the URI associated with its principal.
+   * if the root content docshell or its principal's URI cannot be obtained,
+   * this method will throw.
+   *
+   * @param aChannel
+   *        the channel for the load trying to get or set cookies
+   *
+   * @return the originating URI.
+   */
+  nsIURI getOriginatingURI(in nsIChannel aChannel);
 };
 
 %{ C++
 /**
  * The nsICookiePermission implementation is an XPCOM service registered
  * under the ContractID:
  */
 #define NS_COOKIEPERMISSION_CONTRACTID "@mozilla.org/cookie/permission;1"
--- a/netwerk/cookie/src/nsCookieService.cpp
+++ b/netwerk/cookie/src/nsCookieService.cpp
@@ -43,19 +43,16 @@
 #include "nsIIOService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefBranch2.h"
 #include "nsIPrefService.h"
 #include "nsICookiePermission.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsIChannel.h"
-#include "nsIHttpChannel.h"
-#include "nsIHttpChannelInternal.h" // evil hack!
-#include "nsIPrompt.h"
 #include "nsIFile.h"
 #include "nsIObserverService.h"
 #include "nsILineInputStream.h"
 #include "nsIEffectiveTLDService.h"
 
 #include "nsCOMArray.h"
 #include "nsArrayEnumerator.h"
 #include "nsAutoPtr.h"
@@ -443,16 +440,18 @@ nsCookieService::Init()
 
   mObserverService = do_GetService("@mozilla.org/observer-service;1");
   if (mObserverService) {
     mObserverService->AddObserver(this, "profile-before-change", PR_TRUE);
     mObserverService->AddObserver(this, "profile-do-change", PR_TRUE);
   }
 
   mPermissionService = do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
+  if (!mPermissionService)
+    NS_WARNING("nsICookiePermission implementation not available - some features won't work!");
 
   return NS_OK;
 }
 
 nsresult
 nsCookieService::InitDB()
 {
   nsCOMPtr<nsIFile> cookieFile;
@@ -642,85 +641,67 @@ nsCookieService::Observe(nsISupports    
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCookieService::GetCookieString(nsIURI     *aHostURI,
                                  nsIChannel *aChannel,
                                  char       **aCookie)
 {
-  // try to determine first party URI
-  nsCOMPtr<nsIURI> firstURI;
-  if (aChannel) {
-    nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(aChannel);
-    if (httpInternal)
-      httpInternal->GetDocumentURI(getter_AddRefs(firstURI));
-  }
-
-  GetCookieInternal(aHostURI, firstURI, aChannel, PR_FALSE, aCookie);
+  GetCookieInternal(aHostURI, aChannel, PR_FALSE, aCookie);
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCookieService::GetCookieStringFromHttp(nsIURI     *aHostURI,
                                          nsIURI     *aFirstURI,
                                          nsIChannel *aChannel,
                                          char       **aCookie)
 {
-  GetCookieInternal(aHostURI, aFirstURI, aChannel, PR_TRUE, aCookie);
+  GetCookieInternal(aHostURI, aChannel, PR_TRUE, aCookie);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCookieService::SetCookieString(nsIURI     *aHostURI,
                                  nsIPrompt  *aPrompt,
                                  const char *aCookieHeader,
                                  nsIChannel *aChannel)
 {
-  // try to determine first party URI
-  nsCOMPtr<nsIURI> firstURI;
-
-  if (aChannel) {
-    nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(aChannel);
-    if (httpInternal)
-      httpInternal->GetDocumentURI(getter_AddRefs(firstURI));
-  }
-
-  return SetCookieStringInternal(aHostURI, firstURI, aPrompt, aCookieHeader, nsnull, aChannel, PR_FALSE);
+  return SetCookieStringInternal(aHostURI, aPrompt, aCookieHeader, nsnull, aChannel, PR_FALSE);
 }
 
 NS_IMETHODIMP
 nsCookieService::SetCookieStringFromHttp(nsIURI     *aHostURI,
                                          nsIURI     *aFirstURI,
                                          nsIPrompt  *aPrompt,
                                          const char *aCookieHeader,
                                          const char *aServerTime,
                                          nsIChannel *aChannel) 
 {
-  return SetCookieStringInternal(aHostURI, aFirstURI, aPrompt, aCookieHeader, aServerTime, aChannel, PR_TRUE);
+  return SetCookieStringInternal(aHostURI, aPrompt, aCookieHeader, aServerTime, aChannel, PR_TRUE);
 }
 
 nsresult
 nsCookieService::SetCookieStringInternal(nsIURI     *aHostURI,
-                                         nsIURI     *aFirstURI,
                                          nsIPrompt  *aPrompt,
                                          const char *aCookieHeader,
                                          const char *aServerTime,
                                          nsIChannel *aChannel,
                                          PRBool      aFromHttp) 
 {
   if (!aHostURI) {
     COOKIE_LOGFAILURE(SET_COOKIE, nsnull, aCookieHeader, "host URI is null");
     return NS_OK;
   }
 
   // check default prefs
-  PRUint32 cookieStatus = CheckPrefs(aHostURI, aFirstURI, aChannel, aCookieHeader);
+  PRUint32 cookieStatus = CheckPrefs(aHostURI, aChannel, aCookieHeader);
   // fire a notification if cookie was rejected (but not if there was an error)
   switch (cookieStatus) {
   case STATUS_REJECTED:
     NotifyRejected(aHostURI);
   case STATUS_REJECTED_WITH_ERROR:
     return NS_OK;
   }
 
@@ -1114,30 +1095,29 @@ nsCookieService::ImportCookies(nsIFile *
  * private GetCookie/SetCookie helpers
  ******************************************************************************/
 
 // helper function for GetCookieList
 static inline PRBool ispathdelimiter(char c) { return c == '/' || c == '?' || c == '#' || c == ';'; }
 
 void
 nsCookieService::GetCookieInternal(nsIURI      *aHostURI,
-                                   nsIURI      *aFirstURI,
                                    nsIChannel  *aChannel,
                                    PRBool       aHttpBound,
                                    char       **aCookie)
 {
   *aCookie = nsnull;
 
   if (!aHostURI) {
     COOKIE_LOGFAILURE(GET_COOKIE, nsnull, nsnull, "host URI is null");
     return;
   }
 
   // check default prefs
-  PRUint32 cookieStatus = CheckPrefs(aHostURI, aFirstURI, aChannel, nsnull);
+  PRUint32 cookieStatus = CheckPrefs(aHostURI, aChannel, nsnull);
   // for GetCookie(), we don't fire rejection notifications.
   switch (cookieStatus) {
   case STATUS_REJECTED:
   case STATUS_REJECTED_WITH_ERROR:
     return;
   }
 
   // get host and path from the nsIURI
@@ -1724,25 +1704,21 @@ nsCookieService::ParseAttributes(nsDepen
  * nsCookieService impl:
  * private domain & permission compliance enforcement functions
  ******************************************************************************/
 
 PRBool
 nsCookieService::IsForeign(nsIURI *aHostURI,
                            nsIURI *aFirstURI)
 {
-  // if aFirstURI is null, default to not foreign
-  if (!aFirstURI) {
-    return PR_FALSE;
-  }
-
   // Get hosts
   nsCAutoString currentHost, firstHost;
   if (NS_FAILED(aHostURI->GetAsciiHost(currentHost)) ||
       NS_FAILED(aFirstURI->GetAsciiHost(firstHost))) {
+    // assume foreign
     return PR_TRUE;
   }
   // trim trailing dots
   currentHost.Trim(".");
   firstHost.Trim(".");
 
   // fast path: check if the two hosts are identical.
   // this also covers two special cases:
@@ -1753,110 +1729,81 @@ nsCookieService::IsForeign(nsIURI *aHost
   // error if the URI is an IP address.
   // 2) we also need this for the (rare) case where the site is actually an eTLD,
   // e.g. http://co.tv; GetBaseDomain() will throw an error and we might
   // erroneously think currentHost is foreign. so we consider this case non-
   // foreign only if the hosts exactly match.
   if (firstHost.Equals(currentHost))
     return PR_FALSE;
 
-  // chrome URLs are never foreign (otherwise sidebar cookies won't work).
-  // eventually we want to have a protocol whitelist here,
-  // _or_ do something smart with nsIProtocolHandler::protocolFlags.
-  PRBool isChrome = PR_FALSE;
-  nsresult rv = aFirstURI->SchemeIs("chrome", &isChrome);
-  if (NS_SUCCEEDED(rv) && isChrome) {
-    return PR_FALSE;
-  }
-
   // get the base domain for the originating URI.
   // e.g. for "images.bbc.co.uk", this would be "bbc.co.uk".
   nsCAutoString baseDomain;
-  rv = mTLDService->GetBaseDomain(aFirstURI, 0, baseDomain);
+  nsresult rv = mTLDService->GetBaseDomain(aFirstURI, 0, baseDomain);
   if (NS_FAILED(rv)) {
     // URI is an IP, eTLD, or something else went wrong - assume foreign
     return PR_TRUE;
   }  
   baseDomain.Trim(".");
 
   // ensure the host domain is derived from the base domain.
   // we prepend dots before the comparison to ensure e.g.
   // "mybbc.co.uk" isn't matched as a superset of "bbc.co.uk".
   currentHost.Insert(NS_LITERAL_CSTRING("."), 0);
   baseDomain.Insert(NS_LITERAL_CSTRING("."), 0);
   return !StringEndsWith(currentHost, baseDomain);
 }
 
 PRUint32
 nsCookieService::CheckPrefs(nsIURI     *aHostURI,
-                            nsIURI     *aFirstURI,
                             nsIChannel *aChannel,
                             const char *aCookieHeader)
 {
-  // pref tree:
-  // 0) get the scheme strings from the two URI's
-  // 1) disallow ftp
-  // 2) disallow mailnews, if pref set
-  // 3) perform a permissionlist lookup to see if an entry exists for this host
-  //    (a match here will override defaults in 4)
-  // 4) go through enumerated permissions to see which one we have:
-  // -> cookies disabled: return
-  // -> dontacceptforeign: check if cookie is foreign
-
-  // first, get the URI scheme for further use
-  // if GetScheme fails on aHostURI, reject; aFirstURI is optional, so failing is ok
-  nsCAutoString currentURIScheme, firstURIScheme;
-  nsresult rv, rv2 = NS_OK;
-  rv = aHostURI->GetScheme(currentURIScheme);
-  if (aFirstURI) {
-    rv2 = aFirstURI->GetScheme(firstURIScheme);
-  }
-  if (NS_FAILED(rv) || NS_FAILED(rv2)) {
-    COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "couldn't get scheme of host URI");
-    return STATUS_REJECTED_WITH_ERROR;
-  }
+  nsresult rv;
 
   // don't let ftp sites get/set cookies (could be a security issue)
-  if (currentURIScheme.EqualsLiteral("ftp")) {
+  PRBool ftp;
+  if (NS_SUCCEEDED(aHostURI->SchemeIs("ftp", &ftp)) && ftp) {
     COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "ftp sites cannot read cookies");
     return STATUS_REJECTED_WITH_ERROR;
   }
 
   // check the permission list first; if we find an entry, it overrides
   // default prefs. see bug 184059.
   if (mPermissionService) {
     nsCookieAccess access;
-    rv = mPermissionService->CanAccess(aHostURI, aFirstURI, aChannel, &access);
+    rv = mPermissionService->CanAccess(aHostURI, aChannel, &access);
 
     // if we found an entry, use it
     if (NS_SUCCEEDED(rv)) {
       switch (access) {
       case nsICookiePermission::ACCESS_DENY:
         COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "cookies are blocked for this site");
         return STATUS_REJECTED;
 
       case nsICookiePermission::ACCESS_ALLOW:
         return STATUS_ACCEPTED;
       }
     }
   }
 
-  // check default prefs - go thru enumerated permissions
+  // check default prefs
   if (mCookiesPermissions == BEHAVIOR_REJECT) {
     COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "cookies are disabled");
     return STATUS_REJECTED;
 
   } else if (mCookiesPermissions == BEHAVIOR_REJECTFOREIGN) {
-    // check if cookie is foreign.
-    // if aFirstURI is null, allow by default
+    // check if cookie is foreign
+    if (!mPermissionService)
+      return STATUS_REJECTED;
 
-    // note: this can be circumvented if we have http redirects within html,
-    // since the documentURI attribute isn't always correctly
-    // passed to the redirected channels. (or isn't correctly set in the first place)
-    if (IsForeign(aHostURI, aFirstURI)) {
+    nsCOMPtr<nsIURI> firstURI;
+    rv = mPermissionService->GetOriginatingURI(aChannel, getter_AddRefs(firstURI));
+
+    if (NS_FAILED(rv) || IsForeign(aHostURI, firstURI)) {
       COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "originating server test failed");
       return STATUS_REJECTED;
     }
   }
 
   // if nothing has complained, accept cookie
   return STATUS_ACCEPTED;
 }
--- a/netwerk/cookie/src/nsCookieService.h
+++ b/netwerk/cookie/src/nsCookieService.h
@@ -49,19 +49,16 @@
 #include "nsCookie.h"
 #include "nsString.h"
 #include "nsTHashtable.h"
 
 struct nsCookieAttributes;
 struct nsListIter;
 struct nsEnumerationData;
 
-class nsAutoVoidArray;
-
-class nsIPrefBranch;
 class nsICookiePermission;
 class nsIEffectiveTLDService;
 class nsIPrefBranch;
 class nsIObserverService;
 class nsIURI;
 class nsIChannel;
 class mozIStorageConnection;
 class mozIStorageStatement;
@@ -163,27 +160,27 @@ class nsCookieService : public nsICookie
     static nsCookieService*       GetSingleton();
     nsresult                      Init();
 
   protected:
     void                          PrefChanged(nsIPrefBranch *aPrefBranch);
     nsresult                      InitDB();
     nsresult                      CreateTable();
     nsresult                      Read();
-    void                          GetCookieInternal(nsIURI *aHostURI, nsIURI *aFirstURI, nsIChannel *aChannel, PRBool aHttpBound, char **aCookie);
-    nsresult                      SetCookieStringInternal(nsIURI *aHostURI, nsIURI *aFirstURI, nsIPrompt *aPrompt, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, PRBool aFromHttp);
+    void                          GetCookieInternal(nsIURI *aHostURI, nsIChannel *aChannel, PRBool aHttpBound, char **aCookie);
+    nsresult                      SetCookieStringInternal(nsIURI *aHostURI, nsIPrompt *aPrompt, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, PRBool aFromHttp);
     PRBool                        SetCookieInternal(nsIURI *aHostURI, nsIChannel *aChannel, nsDependentCString &aCookieHeader, PRInt64 aServerTime, PRBool aFromHttp);
     void                          AddInternal(nsCookie *aCookie, PRInt64 aCurrentTime, nsIURI *aHostURI, const char *aCookieHeader, PRBool aFromHttp);
     void                          RemoveCookieFromList(nsListIter &aIter);
     PRBool                        AddCookieToList(nsCookie *aCookie, PRBool aWriteToDB = PR_TRUE);
     void                          UpdateCookieInList(nsCookie *aCookie, PRInt64 aLastAccessed);
     static PRBool                 GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, PRBool &aEqualsFound);
     static PRBool                 ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
     PRBool                        IsForeign(nsIURI *aHostURI, nsIURI *aFirstURI);
-    PRUint32                      CheckPrefs(nsIURI *aHostURI, nsIURI *aFirstURI, nsIChannel *aChannel, const char *aCookieHeader);
+    PRUint32                      CheckPrefs(nsIURI *aHostURI, nsIChannel *aChannel, const char *aCookieHeader);
     PRBool                        CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI);
     static PRBool                 CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
     static PRBool                 GetExpiry(nsCookieAttributes &aCookie, PRInt64 aServerTime, PRInt64 aCurrentTime);
     void                          RemoveAllFromMemory();
     void                          RemoveExpiredCookies(PRInt64 aCurrentTime);
     PRBool                        FindCookie(const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter);
     void                          FindOldestCookie(nsEnumerationData &aData);
     PRUint32                      CountCookiesFromHostInternal(const nsACString &aHost, nsEnumerationData &aData);
--- a/netwerk/test/TestCookie.cpp
+++ b/netwerk/test/TestCookie.cpp
@@ -198,18 +198,19 @@ PrintResult(const PRBool aResult[], PRUi
     }
     return !failed;
 }
 
 void
 InitPrefs(nsIPrefBranch *aPrefBranch)
 {
     // init some relevant prefs, so the tests don't go awry.
-    // we use the most restrictive set of prefs we can.
-    aPrefBranch->SetIntPref(kCookiesPermissions, 1); // 'reject foreign'
+    // we use the most restrictive set of prefs we can;
+    // however, we don't test third party blocking here.
+    aPrefBranch->SetIntPref(kCookiesPermissions, 0); // accept all
     aPrefBranch->SetBoolPref(kCookiesDisabledForMailNews, PR_TRUE);
     aPrefBranch->SetBoolPref(kCookiesLifetimeEnabled, PR_TRUE);
     aPrefBranch->SetIntPref(kCookiesLifetimeCurrentSession, 0);
     aPrefBranch->SetIntPref(kCookiesLifetimeDays, 1);
     aPrefBranch->SetBoolPref(kCookiesAskPermission, PR_FALSE);
 }
 
 class ScopedXPCOM
@@ -507,86 +508,16 @@ main(PRInt32 argc, char *argv[])
       rv[7] = CheckResult(cookie.get(), MUST_NOT_CONTAIN, "test=different");
       SetACookie(cookieService, "http://multiple.cookies/", nsnull,  "newtest=dead; max-age=0", nsnull);
       GetACookie(cookieService, "http://multiple.cookies/", nsnull, getter_Copies(cookie));
       rv[8] = CheckResult(cookie.get(), MUST_BE_NULL);
 
       allTestsPassed = PrintResult(rv, 9) && allTestsPassed;
 
 
-      // *** foreign cookie tests
-      printf("*** Beginning foreign cookie tests...\n");
-
-      // test the blocking of foreign cookies, under various circumstances.
-      // order of URI arguments is hostURI, firstURI
-      SetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[0] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://weather.yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://notweather.yahoo.com/", "http://sport.yahoo.com/", getter_Copies(cookie));
-      rv[1] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://moose.yahoo.com/", "http://canada.yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://sport.yahoo.com/", getter_Copies(cookie));
-      rv[2] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://sport.yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[3] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://jack.yahoo.com/", "http://jill.yahoo.com/", "test=foreign; domain=.yahoo.com; max-age=0", nsnull);
-      GetACookie(cookieService, "http://jane.yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[4] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      SetACookie(cookieService, "http://moose.yahoo.com/", "http://foo.moose.yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[5] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://foo.bar.yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[6] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://foo.bar.yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com; max-age=0", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[7] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      // test handling of IP addresses by the foreign blocking algo
-      SetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", "test=foreign; domain=192.168.54.33", nsnull);
-      GetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", getter_Copies(cookie));
-      rv[8] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://192.168.54.33./", "http://.192.168.54.33../", getter_Copies(cookie));
-      rv[9] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://192.168.54.33/", nsnull, getter_Copies(cookie));
-      rv[10] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://192.168.54.33/", "http://148.168.54.33", getter_Copies(cookie));
-      rv[11] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", "test=foreign; domain=192.168.54.33; max-age=0", nsnull);
-      GetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", getter_Copies(cookie));
-      rv[12] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://192.168.54.33/", "http://148.168.54.33/", "test=foreign; domain=192.168.54.33", nsnull);
-      GetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", getter_Copies(cookie));
-      rv[13] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      // test the case where the host is an eTLD, e.g. http://co.tv/ (a legitimate site)
-      SetACookie(cookieService, "http://co.uk/", "http://co.uk/", "test=foreign; domain=.co.uk", nsnull);
-      GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie));
-      // should be rejected, can't set a domain cookie for .co.uk
-      rv[14] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://co.uk/", "http://co.uk/", "test=foreign", nsnull);
-      GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie));
-      // should be allowed, hostURI == firstURI and it's not a domain cookie
-      rv[15] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://oblivious.co.uk/", nsnull, getter_Copies(cookie));
-      rv[16] = CheckResult(cookie.get(), MUST_BE_NULL);
-      // remove cookie
-      SetACookie(cookieService, "http://co.uk/", "http://co.uk/", "test=foreign; max-age=0", nsnull);
-      GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie));
-      rv[17] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://co.uk/", "http://evil.co.uk/", "test=foreign", nsnull);
-      GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie));
-      // should be rejected, hostURI != firstURI and hostURI is an eTLD
-      rv[18] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      allTestsPassed = PrintResult(rv, 19) && allTestsPassed;
-
-
       // *** parser tests
       printf("*** Beginning parser tests...\n");
 
       // test the cookie header parser, under various circumstances.
       SetACookie(cookieService, "http://parser.test/", nsnull, "test=parser; domain=.parser.test; ;; ;=; ,,, ===,abc,=; abracadabra! max-age=20;=;;", nsnull);
       GetACookie(cookieService, "http://parser.test/", nsnull, getter_Copies(cookie));
       rv[0] = CheckResult(cookie.get(), MUST_EQUAL, "test=parser");
       SetACookie(cookieService, "http://parser.test/", nsnull, "test=parser; domain=.parser.test; max-age=0", nsnull);
@@ -634,25 +565,17 @@ main(PRInt32 argc, char *argv[])
       GetACookie(cookieService, "mailbox://mail.co.uk/", nsnull, getter_Copies(cookie));
       rv[2] = CheckResult(cookie.get(), MUST_BE_NULL);
       GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie));
       rv[3] = CheckResult(cookie.get(), MUST_EQUAL, "test=mailnews");
       SetACookie(cookieService, "http://mail.co.uk/", nsnull, "test=mailnews; max-age=0", nsnull);
       GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie));
       rv[4] = CheckResult(cookie.get(), MUST_BE_NULL);
 
-      // test non-null firstURI's, i) from mailnews ii) not from mailnews
-      SetACookie(cookieService, "mailbox://mail.co.uk/", "http://mail.co.uk/", "test=mailnews", nsnull);
-      GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie));
-      rv[5] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://mail.co.uk/", "mailbox://mail.co.uk/", "test=mailnews", nsnull);
-      GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie));
-      rv[6] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      allTestsPassed = PrintResult(rv, 7) && allTestsPassed;
+      allTestsPassed = PrintResult(rv, 5) && allTestsPassed;
 
 
       // *** path ordering tests
       printf("*** Beginning path ordering tests...\n");
 
       // test that cookies are returned in path order - longest to shortest.
       // if the header doesn't specify a path, it's taken from the host URI.
       SetACookie(cookieService, "http://multi.path.tests/", nsnull, "test1=path; path=/one/two/three", nsnull);