Bug 612072 - Crash [@ nsCookieService::EnsureReadDomain(nsCString const&) ]. r=sdwilsh, a=betaN+
authorDan Witte <dwitte@mozilla.com>
Mon, 22 Nov 2010 13:50:25 -0800
changeset 58006 74b4a2f97e232121f2710a3a101fe9488df68f15
parent 58005 f021e21f74aee962917addb8194028a6ba8b9f06
child 58007 7fa56227251a5d77f9eeeafddf0d6b2d2292bda0
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewerssdwilsh, betaN
bugs612072
milestone2.0b8pre
Bug 612072 - Crash [@ nsCookieService::EnsureReadDomain(nsCString const&) ]. r=sdwilsh, a=betaN+
extensions/cookie/test/unit/test_cookies_profile_close.js
netwerk/cookie/nsCookieService.cpp
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/unit/test_cookies_profile_close.js
@@ -0,0 +1,89 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that the cookie APIs behave sanely after 'profile-before-change'.
+
+let test_generator = do_run_test();
+
+function run_test() {
+  do_test_pending();
+  test_generator.next();
+}
+
+function finish_test() {
+  do_execute_soon(function() {
+    test_generator.close();
+    do_test_finished();
+  });
+}
+
+function do_run_test() {
+  // Set up a profile.
+  let profile = do_get_profile();
+
+  // Start the cookieservice.
+  Services.cookies;
+
+  // Set a cookie.
+  let uri = NetUtil.newURI("http://foo.com");
+  Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
+  let enumerator = Services.cookiemgr.enumerator;
+  do_check_true(enumerator.hasMoreElements());
+  let cookie = enumerator.getNext();
+  do_check_false(enumerator.hasMoreElements());
+
+  // Fire 'profile-before-change'.
+  do_close_profile();
+
+  // Check that the APIs behave appropriately.
+  do_check_eq(Services.cookies.getCookieString(uri, null), null);
+  do_check_eq(Services.cookies.getCookieStringFromHttp(uri, null, null), null);
+  Services.cookies.setCookieString(uri, null, "oh2=hai", null);
+  Services.cookies.setCookieStringFromHttp(uri, null, null, "oh3=hai", null, null);
+  do_check_eq(Services.cookies.getCookieString(uri, null), null);
+
+  do_check_throws(function() {
+    Services.cookiemgr.removeAll();
+  }, Cr.NS_ERROR_NOT_AVAILABLE);
+
+  do_check_throws(function() {
+    Services.cookiemgr.enumerator;
+  }, Cr.NS_ERROR_NOT_AVAILABLE);
+
+  do_check_throws(function() {
+    Services.cookiemgr.add("foo.com", "", "oh4", "hai", false, false, false, 0);
+  }, Cr.NS_ERROR_NOT_AVAILABLE);
+
+  do_check_throws(function() {
+    Services.cookiemgr.remove("foo.com", "", "oh4", false);
+  }, Cr.NS_ERROR_NOT_AVAILABLE);
+
+  do_check_throws(function() {
+    let file = profile.clone();
+    file.append("cookies.txt");
+    Services.cookiemgr.importCookies(file);
+  }, Cr.NS_ERROR_NOT_AVAILABLE);
+
+  do_check_throws(function() {
+    Services.cookiemgr.cookieExists(cookie);
+  }, Cr.NS_ERROR_NOT_AVAILABLE);
+
+  do_check_throws(function() {
+    Services.cookies.countCookiesFromHost("foo.com");
+  }, Cr.NS_ERROR_NOT_AVAILABLE);
+
+  do_check_throws(function() {
+    Services.cookies.getCookiesFromHost("foo.com");
+  }, Cr.NS_ERROR_NOT_AVAILABLE);
+
+  // Wait for the database to finish closing.
+  new _observer(test_generator, "cookie-db-closed");
+  yield;
+
+  // Load the profile and check that the API is available.
+  do_load_profile();
+  do_check_true(Services.cookiemgr.cookieExists(cookie));
+
+  finish_test();
+}
+
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -1498,16 +1498,21 @@ void
 nsCookieService::SetCookieStringInternal(nsIURI          *aHostURI,
                                          bool             aIsForeign,
                                          const nsCString &aCookieHeader,
                                          const nsCString &aServerTime,
                                          PRBool           aFromHttp) 
 {
   NS_ASSERTION(aHostURI, "null host!");
 
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return;
+  }
+
   // get the base domain for the host URI.
   // e.g. for "www.bbc.co.uk", this would be "bbc.co.uk".
   // file:// URI's (i.e. with an empty host) are allowed, but any other
   // scheme must have a non-empty host. A trailing dot in the host
   // is acceptable, and will be stripped.
   PRBool requireHostMatch;
   nsCAutoString baseDomain;
   nsresult rv = GetBaseDomain(aHostURI, baseDomain, requireHostMatch);
@@ -1621,16 +1626,21 @@ nsCookieService::PrefChanged(nsIPrefBran
 /******************************************************************************
  * nsICookieManager impl:
  * nsICookieManager
  ******************************************************************************/
 
 NS_IMETHODIMP
 nsCookieService::RemoveAll()
 {
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   RemoveAllFromMemory();
 
   // clear the cookie file
   if (mDBState->dbConn) {
     NS_ASSERTION(mDBState == mDefaultDBState, "not in default DB state");
 
     // Cancel any pending read. No further results will be received by our
     // read listener.
@@ -1670,16 +1680,21 @@ COMArrayCallback(nsCookieEntry *aEntry,
   }
 
   return PL_DHASH_NEXT;
 }
 
 NS_IMETHODIMP
 nsCookieService::GetEnumerator(nsISimpleEnumerator **aEnumerator)
 {
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   EnsureReadComplete();
 
   nsCOMArray<nsICookie> cookieList(mDBState->cookieCount);
   mDBState->hostTable.EnumerateEntries(COMArrayCallback, &cookieList);
 
   return NS_NewArrayEnumerator(aEnumerator, cookieList);
 }
 
@@ -1688,16 +1703,21 @@ nsCookieService::Add(const nsACString &a
                      const nsACString &aPath,
                      const nsACString &aName,
                      const nsACString &aValue,
                      PRBool            aIsSecure,
                      PRBool            aIsHttpOnly,
                      PRBool            aIsSession,
                      PRInt64           aExpiry)
 {
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // first, normalize the hostname, and fail if it contains illegal characters.
   nsCAutoString host(aHost);
   nsresult rv = NormalizeHost(host);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // get the base domain for the host URI.
   // e.g. for "www.bbc.co.uk", this would be "bbc.co.uk".
   nsCAutoString baseDomain;
@@ -1723,16 +1743,21 @@ nsCookieService::Add(const nsACString &a
 }
 
 NS_IMETHODIMP
 nsCookieService::Remove(const nsACString &aHost,
                         const nsACString &aName,
                         const nsACString &aPath,
                         PRBool           aBlocked)
 {
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // first, normalize the hostname, and fail if it contains illegal characters.
   nsCAutoString host(aHost);
   nsresult rv = NormalizeHost(host);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString baseDomain;
   rv = GetBaseDomainFromHost(host, baseDomain);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -2097,16 +2122,21 @@ nsCookieService::EnsureReadComplete()
 
   COOKIE_LOGSTRING(PR_LOG_DEBUG,
     ("EnsureReadComplete(): %ld cookies read", array.Length()));
 }
 
 NS_IMETHODIMP
 nsCookieService::ImportCookies(nsIFile *aCookieFile)
 {
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // Make sure we're in the default DB state. We don't want people importing
   // cookies into a private browsing session!
   if (mDBState != mDefaultDBState) {
     NS_WARNING("Trying to import cookies in a private browsing session!");
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsresult rv;
@@ -2300,16 +2330,21 @@ public:
 void
 nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
                                          bool aIsForeign,
                                          PRBool aHttpBound,
                                          nsCString &aCookieString)
 {
   NS_ASSERTION(aHostURI, "null host!");
 
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return;
+  }
+
   // get the base domain, host, and path from the URI.
   // e.g. for "www.bbc.co.uk", the base domain would be "bbc.co.uk".
   // file:// URI's (i.e. with an empty host) are allowed, but any other
   // scheme must have a non-empty host. A trailing dot in the host
   // is acceptable, and will be stripped.
   PRBool requireHostMatch;
   nsCAutoString baseDomain, hostFromURI, pathFromURI;
   nsresult rv = GetBaseDomain(aHostURI, baseDomain, requireHostMatch);
@@ -3482,16 +3517,21 @@ nsCookieService::PurgeCookies(PRInt64 aC
 // find whether a given cookie has been previously set. this is provided by the
 // nsICookieManager2 interface.
 NS_IMETHODIMP
 nsCookieService::CookieExists(nsICookie2 *aCookie,
                               PRBool     *aFoundCookie)
 {
   NS_ENSURE_ARG_POINTER(aCookie);
 
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   nsCAutoString host, name, path;
   nsresult rv = aCookie->GetHost(host);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = aCookie->GetName(name);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = aCookie->GetPath(path);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -3535,16 +3575,21 @@ nsCookieService::FindStaleCookie(nsCooki
 }
 
 // count the number of cookies stored by a particular host. this is provided by the
 // nsICookieManager2 interface.
 NS_IMETHODIMP
 nsCookieService::CountCookiesFromHost(const nsACString &aHost,
                                       PRUint32         *aCountFromHost)
 {
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // first, normalize the hostname, and fail if it contains illegal characters.
   nsCAutoString host(aHost);
   nsresult rv = NormalizeHost(host);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString baseDomain;
   rv = GetBaseDomainFromHost(host, baseDomain);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -3558,16 +3603,21 @@ nsCookieService::CountCookiesFromHost(co
 }
 
 // get an enumerator of cookies stored by a particular host. this is provided by the
 // nsICookieManager2 interface.
 NS_IMETHODIMP
 nsCookieService::GetCookiesFromHost(const nsACString     &aHost,
                                     nsISimpleEnumerator **aEnumerator)
 {
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already closed?");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   // first, normalize the hostname, and fail if it contains illegal characters.
   nsCAutoString host(aHost);
   nsresult rv = NormalizeHost(host);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString baseDomain;
   rv = GetBaseDomainFromHost(host, baseDomain);
   NS_ENSURE_SUCCESS(rv, rv);