Bug 1320402 - Move url-classifier off of using appIds. r=ehsan, gcp
authordimi <dlee@mozilla.com>
Tue, 03 Jan 2017 14:21:58 +0800
changeset 455486 306a058214a2b8a0b61ddc733adcd2820bfcb3a9
parent 455485 91575284650d1e4fcb9e8bbac27ee379825475b7
child 455487 2bd53e4e662bcdd32c53cb4e09ceff088e8f6369
push id40256
push userbmo:ntim.bugs@gmail.com
push dateTue, 03 Jan 2017 22:40:23 +0000
reviewersehsan, gcp
bugs1320402
milestone53.0a1
Bug 1320402 - Move url-classifier off of using appIds. r=ehsan, gcp MozReview-Commit-ID: IqnAVrv2c9W
caps/BasePrincipal.h
caps/nsIScriptSecurityManager.idl
docshell/base/LoadContext.h
netwerk/base/LoadContextInfo.cpp
netwerk/base/nsNetUtil.h
netwerk/cache2/CacheFileUtils.cpp
netwerk/cookie/nsCookieService.cpp
netwerk/test/unit/test_cookiejars_safebrowsing.js
toolkit/components/downloads/ApplicationReputation.cpp
toolkit/components/url-classifier/content/xml-fetcher.js
toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -132,19 +132,18 @@ public:
   InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs);
 };
 
 // For OriginAttributes stored on Necko.
 class NeckoOriginAttributes : public OriginAttributes
 {
 public:
   NeckoOriginAttributes() {}
-  NeckoOriginAttributes(uint32_t aAppId, bool aInIsolatedMozBrowser)
+  explicit NeckoOriginAttributes(bool aInIsolatedMozBrowser)
   {
-    mAppId = aAppId;
     mInIsolatedMozBrowser = aInIsolatedMozBrowser;
   }
 
   // Inheriting OriginAttributes from document to necko when a network request
   // is made.
   void InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs);
 
   // Inheriting OriginAttributes from a docshell when loading a top-level
--- a/caps/nsIScriptSecurityManager.idl
+++ b/caps/nsIScriptSecurityManager.idl
@@ -251,17 +251,16 @@ interface nsIScriptSecurityManager : nsI
       bool isSystem = false;
       IsSystemPrincipal(aPrincipal, &isSystem);
       return isSystem;
     }
 %}
 
     const unsigned long NO_APP_ID = 0;
     const unsigned long UNKNOWN_APP_ID = 4294967295; // UINT32_MAX
-    const unsigned long SAFEBROWSING_APP_ID = 4294967294; // UINT32_MAX - 1
 
     const unsigned long DEFAULT_USER_CONTEXT_ID = 0;
 
     /**
      * Per-domain controls to enable and disable script. This system is designed
      * to be used by at most one consumer, and enforces this with its semantics.
      *
      * Initially, domainPolicyActive is false. When activateDomainPolicy() is
--- a/docshell/base/LoadContext.h
+++ b/docshell/base/LoadContext.h
@@ -20,19 +20,16 @@ namespace mozilla {
 /**
  * Class that provides nsILoadContext info in Parent process.  Typically copied
  * from Child via SerializedLoadContext.
  *
  * Note: this is not the "normal" or "original" nsILoadContext.  That is
  * typically provided by nsDocShell.  This is only used when the original
  * docshell is in a different process and we need to copy certain values from
  * it.
- *
- * Note: we also generate a new nsILoadContext using LoadContext(uint32_t aAppId)
- * to separate the safebrowsing cookie.
  */
 
 class LoadContext final
   : public nsILoadContext
   , public nsIInterfaceRequestor
 {
 public:
   NS_DECL_ISUPPORTS
--- a/netwerk/base/LoadContextInfo.cpp
+++ b/netwerk/base/LoadContextInfo.cpp
@@ -132,18 +132,17 @@ GetLoadContextInfo(nsIChannel * aChannel
 
   return new LoadContextInfo(anon, oa);
 }
 
 LoadContextInfo *
 GetLoadContextInfo(nsILoadContext *aLoadContext, bool aIsAnonymous)
 {
   if (!aLoadContext) {
-    return new LoadContextInfo(aIsAnonymous,
-                               NeckoOriginAttributes(nsILoadContextInfo::NO_APP_ID, false));
+    return new LoadContextInfo(aIsAnonymous, NeckoOriginAttributes(false));
   }
 
   DebugOnly<bool> pb = aLoadContext->UsePrivateBrowsing();
   DocShellOriginAttributes doa;
   aLoadContext->GetOriginAttributes(doa);
   MOZ_ASSERT(pb == (doa.mPrivateBrowsingId > 0));
 
   NeckoOriginAttributes noa;
--- a/netwerk/base/nsNetUtil.h
+++ b/netwerk/base/nsNetUtil.h
@@ -667,18 +667,22 @@ bool NS_GetOriginAttributes(nsIChannel *
  * URLs that it was redirected through.
  */
 bool NS_HasBeenCrossOrigin(nsIChannel* aChannel, bool aReport = false);
 
 // Constants duplicated from nsIScriptSecurityManager so we avoid having necko
 // know about script security manager.
 #define NECKO_NO_APP_ID 0
 #define NECKO_UNKNOWN_APP_ID UINT32_MAX
-// special app id reserved for separating the safebrowsing cookie
-#define NECKO_SAFEBROWSING_APP_ID UINT32_MAX - 1
+
+// Unique first-party domain for separating the safebrowsing cookie.
+// Note if this value is changed, code in test_cookiejars_safebrowsing.js
+// should also be changed.
+#define NECKO_SAFEBROWSING_FIRST_PARTY_DOMAIN \
+  "safebrowsing.86868755-6b82-4842-b301-72671a0db32e.mozilla"
 
 /**
  * Determines whether appcache should be checked for a given URI.
  */
 bool NS_ShouldCheckAppCache(nsIURI *aURI, bool usePrivateBrowsing);
 
 bool NS_ShouldCheckAppCache(nsIPrincipal *aPrincipal, bool usePrivateBrowsing);
 
--- a/netwerk/cache2/CacheFileUtils.cpp
+++ b/netwerk/cache2/CacheFileUtils.cpp
@@ -30,17 +30,17 @@ namespace {
  * A simple recursive descent parser for the mapping key.
  */
 class KeyParser : protected Tokenizer
 {
 public:
   explicit KeyParser(nsACString const& aInput)
     : Tokenizer(aInput)
     // Initialize attributes to their default values
-    , originAttribs(0, false)
+    , originAttribs(false)
     , isAnonymous(false)
     // Initialize the cache key to a zero length by default
     , lastTag(0)
   {
   }
 
 private:
   // Results
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -829,26 +829,24 @@ class ConvertAppIdToOriginAttrsSQLFuncti
 
 NS_IMPL_ISUPPORTS(ConvertAppIdToOriginAttrsSQLFunction, mozIStorageFunction);
 
 NS_IMETHODIMP
 ConvertAppIdToOriginAttrsSQLFunction::OnFunctionCall(
   mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult)
 {
   nsresult rv;
-  int32_t appId, inIsolatedMozBrowser;
-
-  rv = aFunctionArguments->GetInt32(0, &appId);
-  NS_ENSURE_SUCCESS(rv, rv);
+  int32_t inIsolatedMozBrowser;
+
   rv = aFunctionArguments->GetInt32(1, &inIsolatedMozBrowser);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Create an originAttributes object by appId and inIsolatedMozBrowser.
+  // Create an originAttributes object by inIsolatedMozBrowser.
   // Then create the originSuffix string from this object.
-  NeckoOriginAttributes attrs(appId, (inIsolatedMozBrowser ? 1 : 0));
+  NeckoOriginAttributes attrs((inIsolatedMozBrowser ? 1 : 0));
   nsAutoCString suffix;
   attrs.CreateSuffix(suffix);
 
   RefPtr<nsVariant> outVar(new nsVariant());
   rv = outVar->SetAsAUTF8String(suffix);
   NS_ENSURE_SUCCESS(rv, rv);
 
   outVar.forget(aResult);
--- a/netwerk/test/unit/test_cookiejars_safebrowsing.js
+++ b/netwerk/test/unit/test_cookiejars_safebrowsing.js
@@ -1,19 +1,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*
  * Description of the test:
  *   We show that we can separate the safebrowsing cookie by creating a custom
- *   OriginAttributes using a reserved AppId (UINT_32_MAX - 1). Setting this
+ *   OriginAttributes using a unique safebrowsing first-party domain. Setting this
  *   custom OriginAttributes on the loadInfo of the channel allows us to query the
- *   AppId and therefore separate the safebrowing cookie in its own cookie-jar.
- *   For testing safebrowsing update we do >> NOT << emulate a response
+ *   first-party domain and therefore separate the safebrowing cookie in its own
+ *   cookie-jar. For testing safebrowsing update we do >> NOT << emulate a response
  *   in the body, rather we only set the cookies in the header of the response
  *   and confirm that cookies are separated in their own cookie-jar.
  *
  * 1) We init safebrowsing and simulate an update (cookies are set for localhost)
  *
  * 2) We open a channel that should send regular cookies, but not the
  *    safebrowsing cookie.
  *
@@ -143,17 +143,19 @@ add_test(function test_non_safebrowsing_
   }
 
   setNonSafeBrowsingCookie();
 });
 
 add_test(function test_safebrowsing_cookie() {
 
   var cookieName = 'sbCookie_id4294967294';
-  var originAttributes = new OriginAttributes(Ci.nsIScriptSecurityManager.SAFEBROWSING_APP_ID, false, 0);
+  var originAttributes = new OriginAttributes(0, false, 0);
+  originAttributes.firstPartyDomain =
+    "safebrowsing.86868755-6b82-4842-b301-72671a0db32e.mozilla";
 
   function setSafeBrowsingCookie() {
     var channel = setupChannel(setCookiePath, originAttributes);
     channel.setRequestHeader("set-cookie", cookieName, false);
     channel.asyncOpen2(new ChannelListener(checkSafeBrowsingCookie, null));
   }
 
   function checkSafeBrowsingCookie() {
--- a/toolkit/components/downloads/ApplicationReputation.cpp
+++ b/toolkit/components/downloads/ApplicationReputation.cpp
@@ -1273,41 +1273,34 @@ PendingLookup::SendRemoteQueryInternal()
                         nullptr, // aTriggeringPrincipal
                         nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                         nsIContentPolicy::TYPE_OTHER,
                         getter_AddRefs(mChannel));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
   if (loadInfo) {
-    loadInfo->SetOriginAttributes(
-      mozilla::NeckoOriginAttributes(NECKO_SAFEBROWSING_APP_ID, false));
+    mozilla::NeckoOriginAttributes neckoAttrs(false);
+    neckoAttrs.mFirstPartyDomain.AssignLiteral(NECKO_SAFEBROWSING_FIRST_PARTY_DOMAIN);
+    loadInfo->SetOriginAttributes(neckoAttrs);
   }
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
   mozilla::Unused << httpChannel;
 
   // Upload the protobuf to the application reputation service.
   nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(mChannel, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = uploadChannel->ExplicitSetUploadStream(sstream,
     NS_LITERAL_CSTRING("application/octet-stream"), serialized.size(),
     NS_LITERAL_CSTRING("POST"), false);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Set the Safebrowsing cookie jar, so that the regular Google cookie is not
-  // sent with this request. See bug 897516.
-  DocShellOriginAttributes attrs;
-  attrs.mAppId = NECKO_SAFEBROWSING_APP_ID;
-  nsCOMPtr<nsIInterfaceRequestor> loadContext = new mozilla::LoadContext(attrs);
-  rv = mChannel->SetNotificationCallbacks(loadContext);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   uint32_t timeoutMs = Preferences::GetUint(PREF_SB_DOWNLOADS_REMOTE_TIMEOUT, 10000);
   mTimeoutTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
   mTimeoutTimer->InitWithCallback(this, timeoutMs, nsITimer::TYPE_ONE_SHOT);
 
   rv = mChannel->AsyncOpen2(this);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
--- a/toolkit/components/url-classifier/content/xml-fetcher.js
+++ b/toolkit/components/url-classifier/content/xml-fetcher.js
@@ -29,24 +29,25 @@ this.PROT_NewXMLHttpRequest = function P
 /**
  * A helper class that does HTTP GETs and calls back a function with
  * the content it receives. Asynchronous, so uses a closure for the
  * callback.
  *
  * Note, that XMLFetcher is only used for SafeBrowsing, therefore
  * we inherit from nsILoadContext, so we can use the callbacks on the
  * channel to separate the safebrowsing cookie based on a reserved
- * appId.
+ * first-party domain.
  * @constructor
  */
 this.PROT_XMLFetcher = function PROT_XMLFetcher() {
   this.debugZone = "xmlfetcher";
   this._request = PROT_NewXMLHttpRequest();
   // implements nsILoadContext
-  this.appId = Ci.nsIScriptSecurityManager.SAFEBROWSING_APP_ID;
+  this.firstPartyDomain =
+    "safebrowsing.86868755-6b82-4842-b301-72671a0db32e.mozilla";
   this.isInIsolatedMozBrowserElement = false;
   this.usePrivateBrowsing = false;
   this.isContent = false;
 }
 
 PROT_XMLFetcher.prototype = {
   /**
    * Function that will be called back upon fetch completion.
@@ -61,17 +62,17 @@ PROT_XMLFetcher.prototype = {
    * @param callback Function to call back when complete.
    */
   get: function(page, callback) {
     this._request.abort();                // abort() is asynchronous, so
     this._request = PROT_NewXMLHttpRequest();
     this._callback = callback;
     var asynchronous = true;
     this._request.loadInfo.originAttributes = {
-      appId: this.appId,
+      firstPartyDomain: this.firstPartyDomain,
       inIsolatedMozBrowser: this.isInIsolatedMozBrowserElement
     };
     this._request.open("GET", page, asynchronous);
     this._request.channel.notificationCallbacks = this;
 
     // Create a closure
     var self = this;
     this._request.addEventListener("readystatechange", function() {
--- a/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
@@ -126,17 +126,19 @@ nsUrlClassifierStreamUpdater::FetchUpdat
                      nsIContentPolicy::TYPE_OTHER,
                      nullptr,  // aLoadGroup
                      this,     // aInterfaceRequestor
                      loadFlags);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
-  loadInfo->SetOriginAttributes(mozilla::NeckoOriginAttributes(NECKO_SAFEBROWSING_APP_ID, false));
+  mozilla::NeckoOriginAttributes neckoAttrs(false);
+  neckoAttrs.mFirstPartyDomain.AssignLiteral(NECKO_SAFEBROWSING_FIRST_PARTY_DOMAIN);
+  loadInfo->SetOriginAttributes(neckoAttrs);
 
   mBeganStream = false;
 
   if (!aIsPostRequest) {
     // We use POST method to send our request in v2. In v4, the request
     // needs to be embedded to the URL and use GET method to send.
     // However, from the Chromium source code, a extended HTTP header has
     // to be sent along with the request to make the request succeed.
@@ -170,25 +172,16 @@ nsUrlClassifierStreamUpdater::FetchUpdat
 
     // Disable keepalive.
     nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Connection"), NS_LITERAL_CSTRING("close"), false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  // Create a custom LoadContext for SafeBrowsing, so we can use callbacks on
-  // the channel to query the appId which allows separation of safebrowsing
-  // cookies in a separate jar.
-  DocShellOriginAttributes attrs;
-  attrs.mAppId = NECKO_SAFEBROWSING_APP_ID;
-  nsCOMPtr<nsIInterfaceRequestor> sbContext = new mozilla::LoadContext(attrs);
-  rv = mChannel->SetNotificationCallbacks(sbContext);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // Make the request.
   rv = mChannel->AsyncOpen2(this);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mStreamTable = aStreamTable;
 
   return NS_OK;
 }