Bug 1214071 - Replace Get/RemoveCookiesForApp() with Get/RemoveCookiesWithOriginAttributes() r=ehsan
authorEthan Tseng <ettseng@mozilla.com>
Fri, 08 Jan 2016 17:58:56 +0800
changeset 366688 29944095078efee2c83925919daf147462cc0201
parent 366687 7b6472147fdf5d6cb3341d6c5c11148dcdab5f09
child 366689 7c9aa29ecd0ef5144a3808a761a18afb500613a2
push id18048
push userbmo:dglastonbury@mozilla.com
push dateFri, 13 May 2016 06:19:42 +0000
reviewersehsan
bugs1214071
milestone49.0a1
Bug 1214071 - Replace Get/RemoveCookiesForApp() with Get/RemoveCookiesWithOriginAttributes() r=ehsan MozReview-Commit-ID: JTi1BwBVvyA
dom/apps/Webapps.jsm
extensions/cookie/test/test_app_uninstall_cookies.html
netwerk/cookie/nsCookieService.cpp
netwerk/cookie/nsCookieService.h
netwerk/cookie/nsICookieManager2.idl
--- a/dom/apps/Webapps.jsm
+++ b/dom/apps/Webapps.jsm
@@ -659,20 +659,19 @@ this.DOMApplicationRegistry = {
         return;
       }
 
       // b : core apps are not removable.
       for (let id in this.webapps) {
         if (id in data || this.webapps[id].removable)
           continue;
         // Remove the permissions, cookies and private data for this app.
+        // Both permission and cookie managers observe the "clear-origin-data"
+        // event.
         let localId = this.webapps[id].localId;
-        let attrs = { appId: localId };
-        permMgr.removePermissionsWithAttributes(JSON.stringify(attrs));
-        Services.cookies.removeCookiesForApp(localId, false);
         this._clearPrivateData(localId, false);
         delete this.webapps[id];
       }
 
       let appDir = FileUtils.getDir("coreAppsDir", ["webapps"], false);
       // c
       for (let id in data) {
         // Core apps have ids matching their domain name (eg: dialer.gaiamobile.org)
--- a/extensions/cookie/test/test_app_uninstall_cookies.html
+++ b/extensions/cookie/test/test_app_uninstall_cookies.html
@@ -48,17 +48,18 @@ var cookies = [
     loadContext: null },
   { cookieName: 'AppUninstall_Witness',
     loadContext: new LoadContextCallback(0, false, false, 1) },
 ];
 var counter = 0;
 
 function getCookiesCountForApp(aAppId) {
   var nbCookies = 0;
-  var enumerator = cookieMng.getCookiesForApp(aAppId, false);
+  var attrs = JSON.stringify({appId: aAppId});
+  var enumerator = cookieMng.getCookiesWithOriginAttributes(attrs);
 
   while (enumerator.hasMoreElements()) {
     enumerator.getNext();
     nbCookies++;
   }
 
   return nbCookies;
 }
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -571,26 +571,22 @@ public:
 
   // nsIObserver implementation.
   NS_IMETHODIMP
   Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) override
   {
     MOZ_ASSERT(!nsCRT::strcmp(aTopic, TOPIC_CLEAR_ORIGIN_DATA));
 
     MOZ_ASSERT(XRE_IsParentProcess());
-    NeckoOriginAttributes attrs;
-    MOZ_ALWAYS_TRUE(attrs.Init(nsDependentString(aData)));
 
     nsCOMPtr<nsICookieManager2> cookieManager
       = do_GetService(NS_COOKIEMANAGER_CONTRACTID);
     MOZ_ASSERT(cookieManager);
 
-    // TODO: We should add a new interface RemoveCookiesForOriginAttributes in
-    // nsICookieManager2 and use it instead of RemoveCookiesForApp.
-    return cookieManager->RemoveCookiesForApp(attrs.mAppId, attrs.mInIsolatedMozBrowser);
+    return cookieManager->RemoveCookiesWithOriginAttributes(nsDependentString(aData));
   }
 };
 
 NS_IMPL_ISUPPORTS(AppClearDataObserver, nsIObserver)
 
 } // namespace
 
 size_t
@@ -4330,89 +4326,107 @@ nsCookieService::GetCookiesFromHost(cons
   for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
     cookieList.AppendObject(cookies[i]);
   }
 
   return NS_NewArrayEnumerator(aEnumerator, cookieList);
 }
 
 NS_IMETHODIMP
-nsCookieService::GetCookiesForApp(uint32_t aAppId, bool aOnlyIsolatedMozBrowser,
-                                  nsISimpleEnumerator** aEnumerator)
+nsCookieService::GetCookiesWithOriginAttributes(const nsAString& aPattern,
+                                                nsISimpleEnumerator **aEnumerator)
+{
+  mozilla::OriginAttributesPattern pattern;
+  if (!pattern.Init(aPattern)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  return GetCookiesWithOriginAttributes(pattern, aEnumerator);
+}
+
+nsresult
+nsCookieService::GetCookiesWithOriginAttributes(
+    const mozilla::OriginAttributesPattern& aPattern,
+    nsISimpleEnumerator **aEnumerator)
 {
   if (!mDBState) {
     NS_WARNING("No DBState! Profile already closed?");
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  NS_ENSURE_TRUE(aAppId != NECKO_UNKNOWN_APP_ID, NS_ERROR_INVALID_ARG);
+  if (aPattern.mAppId.WasPassed() && aPattern.mAppId.Value() == NECKO_UNKNOWN_APP_ID) {
+    return NS_ERROR_INVALID_ARG;
+  }
 
   nsCOMArray<nsICookie> cookies;
   for (auto iter = mDBState->hostTable.Iter(); !iter.Done(); iter.Next()) {
     nsCookieEntry* entry = iter.Get();
 
-    if (entry->mOriginAttributes.mAppId != aAppId ||
-        (aOnlyIsolatedMozBrowser && !entry->mOriginAttributes.mInIsolatedMozBrowser)) {
+    if (!aPattern.Matches(entry->mOriginAttributes)) {
       continue;
     }
 
     const nsCookieEntry::ArrayType& entryCookies = entry->GetCookies();
 
     for (nsCookieEntry::IndexType i = 0; i < entryCookies.Length(); ++i) {
       cookies.AppendObject(entryCookies[i]);
     }
   }
 
   return NS_NewArrayEnumerator(aEnumerator, cookies);
 }
 
 NS_IMETHODIMP
-nsCookieService::RemoveCookiesForApp(uint32_t aAppId,
-                                     bool aOnlyIsolatedMozBrowser)
+nsCookieService::RemoveCookiesWithOriginAttributes(const nsAString& aPattern)
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  mozilla::OriginAttributesPattern pattern;
+  if (!pattern.Init(aPattern)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  return RemoveCookiesWithOriginAttributes(pattern);
+}
+
+nsresult
+nsCookieService::RemoveCookiesWithOriginAttributes(
+    const mozilla::OriginAttributesPattern& aPattern)
 {
-  nsCOMPtr<nsISimpleEnumerator> enumerator;
-  nsresult rv = GetCookiesForApp(aAppId, aOnlyIsolatedMozBrowser,
-                                 getter_AddRefs(enumerator));
-
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  bool hasMore;
-  while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
-    nsCOMPtr<nsISupports> supports;
-    nsCOMPtr<nsICookie> cookie;
-    rv = enumerator->GetNext(getter_AddRefs(supports));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    cookie = do_QueryInterface(supports);
-
-    nsAutoCString host;
-    cookie->GetHost(host);
-
-    nsAutoCString name;
-    cookie->GetName(name);
-
-    nsAutoCString path;
-    cookie->GetPath(path);
-
-    // nsICookie do not carry the appId/isIsolatedBrowser information.
-    // That means we have to guess. This is easy for appId but not for
-    // isIsolatedBrowser flag.
-    // A simple solution is to always ask to remove the cookie with
-    // isIsolatedBrowser = true and only ask for the other one to be removed if
-    // we happen to be in the case of !aOnlyBrowserElement.
-    // Anyway, with this solution, we will likely be looking for non-existent
-    // cookies.
-    //
-    // NOTE: we could make this better by getting nsCookieEntry objects instead
-    // of plain nsICookie.
-    NeckoOriginAttributes attrs(aAppId, true);
-    Remove(host, attrs, name, path, false);
-    if (!aOnlyIsolatedMozBrowser) {
-      attrs.mInIsolatedMozBrowser = false;
-      Remove(host, attrs, name, path, false);
+  if (!mDBState) {
+    NS_WARNING("No DBState! Profile already close?");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  // Iterate the hash table of nsCookieEntry.
+  for (auto iter = mDBState->hostTable.Iter(); !iter.Done(); iter.Next()) {
+    nsCookieEntry* entry = iter.Get();
+
+    if (!aPattern.Matches(entry->mOriginAttributes)) {
+      continue;
+    }
+
+    // Pattern matches. Delete all cookies within this nsCookieEntry.
+    const nsCookieEntry::ArrayType& cookies = entry->GetCookies();
+
+    while (!cookies.IsEmpty()) {
+      nsCookie *cookie = cookies.LastElement();
+
+      nsAutoCString host;
+      cookie->GetHost(host);
+
+      nsAutoCString name;
+      cookie->GetName(name);
+
+      nsAutoCString path;
+      cookie->GetPath(path);
+
+      // Remove the cookie.
+      nsresult rv = Remove(host, entry->mOriginAttributes, name, path, false);
+      NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   return NS_OK;
 }
 
 // find an exact cookie specified by host, name, and path that hasn't expired.
 bool
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -314,16 +314,19 @@ class nsCookieService final : public nsI
     static void                   FindStaleCookie(nsCookieEntry *aEntry, int64_t aCurrentTime, nsListIter &aIter);
     void                          NotifyRejected(nsIURI *aHostURI);
     void                          NotifyThirdParty(nsIURI *aHostURI, bool aAccepted, nsIChannel *aChannel);
     void                          NotifyChanged(nsISupports *aSubject, const char16_t *aData);
     void                          NotifyPurged(nsICookie2* aCookie);
     already_AddRefed<nsIArray>    CreatePurgeList(nsICookie2* aCookie);
     void                          UpdateCookieOldestTime(DBState* aDBState, nsCookie* aCookie);
 
+    nsresult                      GetCookiesWithOriginAttributes(const mozilla::OriginAttributesPattern& aPattern, nsISimpleEnumerator **aEnumerator);
+    nsresult                      RemoveCookiesWithOriginAttributes(const mozilla::OriginAttributesPattern& aPattern);
+
     /**
      * This method is a helper that allows calling nsICookieManager::Remove()
      * with NeckoOriginAttributes parameter.
      * NOTE: this could be added to a public interface if we happen to need it.
      */
     nsresult Remove(const nsACString& aHost, const NeckoOriginAttributes& aAttrs,
                     const nsACString& aName, const nsACString& aPath,
                     bool aBlocked);
--- a/netwerk/cookie/nsICookieManager2.idl
+++ b/netwerk/cookie/nsICookieManager2.idl
@@ -104,32 +104,21 @@ interface nsICookieManager2 : nsICookieM
    * existing database. If the database contains any cookies the same as those
    * being imported (i.e. domain, name, and path match), they will be replaced.
    *
    * @param aCookieFile the file to import, usually cookies.txt
    */
   void importCookies(in nsIFile aCookieFile);
 
   /**
-   * Returns an enumerator of all cookies that are related to a specific app.
+   * Returns an enumerator of all cookies whose origin attributes matches aPattern
    *
-   * If the onlyIsolatedMozBrowser parameter is set to true, only cookies part
-   * of an isolated mozbrowser element inside the app will be returned. If set
-   * to false, all cookies will be returned, regardless of their
-   * inIsolatedMozBrowser flag.
-   *
-   * This method assumes that appId is a valid app id. It should not be a
-   * special value like UNKNOWN_APP_ID or NO_APP_ID.
+   * @param aPattern origin attribute pattern in JSON format
    */
-  nsISimpleEnumerator getCookiesForApp(in unsigned long appId,
-                                       in boolean onlyIsolatedMozBrowser);
+  nsISimpleEnumerator getCookiesWithOriginAttributes(in DOMString aPattern);
 
   /**
-   * Remove all the cookies associated with the app with the id aAppId.
-   *
-   * If onlyIsolatedMozBrowser is set to true, the method will only remove the
-   * cookies marked as part of an isolated mozbrowser element inside the app.
+   * Remove all the cookies whose origin attributes matches aPattern
    *
-   * Special app id values are not allowed (NO_APP_ID or UNKNOWN_APP_ID for example).
+   * @param aPattern origin attribute pattern in JSON format
    */
-  void removeCookiesForApp(in unsigned long appId,
-                           in boolean onlyIsolatedMozBrowser);
+  void removeCookiesWithOriginAttributes(in DOMString aPattern);
 };