Bug 837326 - Informing observers upon accept/reject of a third-party cookie;r=ehsan
authorDavid Rajchenbach-Teller <dteller@mozilla.com>
Sat, 22 Jun 2013 07:11:12 +0200
changeset 147569 649a50fee077769bb798ff492434c09d5628e231
parent 147568 872cb1c92a731fc6cf5f56caf07250140ebbc415
child 147570 6424bcea24607846d5ed5b3e434b8301affdd743
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs837326
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 837326 - Informing observers upon accept/reject of a third-party cookie;r=ehsan
netwerk/cookie/nsCookieService.cpp
netwerk/cookie/nsCookieService.h
netwerk/cookie/nsICookieService.idl
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -1641,23 +1641,33 @@ nsCookieService::SetCookieStringInternal
     return;
   }
 
   nsCookieKey key(baseDomain, aAppId, aInBrowserElement);
 
   // check default prefs
   CookieStatus cookieStatus = CheckPrefs(aHostURI, aIsForeign, requireHostMatch,
                                          aCookieHeader.get());
-  // fire a notification if cookie was rejected (but not if there was an error)
+  // fire a notification if third party or if cookie was rejected
+  // (but not if there was an error)
   switch (cookieStatus) {
   case STATUS_REJECTED:
     NotifyRejected(aHostURI);
-    return;
+    if (aIsForeign) {
+      NotifyThirdParty(aHostURI, false, aChannel);
+    }
+    return; // Stop here
   case STATUS_REJECTED_WITH_ERROR:
     return;
+  case STATUS_ACCEPTED: // Fallthrough
+  case STATUS_ACCEPT_SESSION:
+    if (aIsForeign) {
+      NotifyThirdParty(aHostURI, true, aChannel);
+    }
+    break;
   default:
     break;
   }
 
   // parse server local time. this is not just done here for efficiency
   // reasons - if there's an error parsing it, and we need to default it
   // to the current time, we must do it here since the current time in
   // SetCookieInternal() will change for each cookie processed (e.g. if the
@@ -1680,18 +1690,60 @@ nsCookieService::SetCookieStringInternal
       break;
   }
 }
 
 // notify observers that a cookie was rejected due to the users' prefs.
 void
 nsCookieService::NotifyRejected(nsIURI *aHostURI)
 {
-  if (mObserverService)
+  if (mObserverService) {
     mObserverService->NotifyObservers(aHostURI, "cookie-rejected", nullptr);
+  }
+}
+
+// notify observers that a third-party cookie was accepted/rejected
+// if the cookie issuer is unknown, it defaults to "?"
+void
+nsCookieService::NotifyThirdParty(nsIURI *aHostURI, bool aIsAccepted, nsIChannel *aChannel)
+{
+  if (!mObserverService) {
+    return;
+  }
+  const char* topic = aIsAccepted ? "third-party-cookie-accepted"
+    : "third-party-cookie-rejected";
+
+  do {
+    // Attempt to find the host of aChannel.
+    if (!aChannel) {
+      break;
+    }
+    nsCOMPtr<nsIURI> channelURI;
+    nsresult rv = aChannel->GetURI(getter_AddRefs(channelURI));
+    if (NS_FAILED(rv)) {
+      break;
+    }
+
+    nsAutoCString referringHost;
+    rv = channelURI->GetHost(referringHost);
+    if (NS_FAILED(rv)) {
+      break;
+    }
+
+    nsAutoString referringHostUTF16 = NS_ConvertUTF8toUTF16(referringHost);
+    mObserverService->NotifyObservers(aHostURI,
+                                      topic,
+                                      referringHostUTF16.get());
+    return;
+  } while (0);
+
+  // This can fail for a number of reasons, in which kind we fallback to "?"
+  mObserverService->NotifyObservers(aHostURI,
+                                    topic,
+                                    NS_LITERAL_STRING("?").get());
 }
 
 // notify observers that the cookie list changed. there are five possible
 // values for aData:
 // "deleted" means a cookie was deleted. aSubject is the deleted cookie.
 // "added"   means a cookie was added. aSubject is the added cookie.
 // "changed" means a cookie was altered. aSubject is the new cookie.
 // "cleared" means the entire cookie list was cleared. aSubject is null.
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -282,16 +282,17 @@ class nsCookieService : public nsICookie
     bool                          CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI, const nsCString &aBaseDomain, bool aRequireHostMatch);
     static bool                   CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
     static bool                   GetExpiry(nsCookieAttributes &aCookie, int64_t aServerTime, int64_t aCurrentTime);
     void                          RemoveAllFromMemory();
     already_AddRefed<nsIArray>    PurgeCookies(int64_t aCurrentTimeInUsec);
     bool                          FindCookie(const nsCookieKey& aKey, const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter);
     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 PRUnichar *aData);
     void                          NotifyPurged(nsICookie2* aCookie);
     already_AddRefed<nsIArray>    CreatePurgeList(nsICookie2* aCookie);
 
     /**
      * This method is used to iterate the cookie hash table and select the ones
      * that are part of a specific app.
      */
--- a/netwerk/cookie/nsICookieService.idl
+++ b/netwerk/cookie/nsICookieService.idl
@@ -53,16 +53,28 @@ interface nsIChannel;
  *          the entire cookie list should be reloaded.  the subject is null.
  *
  * topic  : "cookie-rejected"
  *          broadcast whenever a cookie was rejected from being set as a
  *          result of user prefs.
  * subject: an nsIURI interface pointer representing the URI that attempted
  *          to set the cookie.
  * data   : none.
+ *
+ * topic  : "third-party-cookie-accepted"
+ *           broadcast whenever a third party cookie was accepted
+ * subject:  an nsIURI interface pointer representing the URI that attempted
+ *           to set the cookie.
+ * data   :  the referrer, or "?" if unknown
+ *
+ * topic  : "third-party-cookie-rejected"
+ *           broadcast whenever a third party cookie was rejected
+ * subject:  an nsIURI interface pointer representing the URI that attempted
+ *           to set the cookie.
+ * data   :  the referrer, or "?" if unknown
  */
 [scriptable, uuid(2aaa897a-293c-4d2b-a657-8c9b7136996d)]
 interface nsICookieService : nsISupports
 {
   /*
    * Get the complete cookie string associated with the URI.
    *
    * @param aURI