Bug 1322576 - [1.2] Add tracking protection attribute to nsILoadContext to allow for overriding of the global preference setting for individual DocShells. r=smaug
authorEugen Sawin <esawin@mozilla.com>
Tue, 14 Feb 2017 15:53:21 +0100
changeset 373327 7552fa4a2858a2ca6a51640dcc85133a9537085c
parent 373326 b4f01417998fb54b62ce38942266cda570d47b76
child 373328 dd8000832878e2f2f4f066a295c81b02b94f1c0d
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1322576
milestone54.0a1
Bug 1322576 - [1.2] Add tracking protection attribute to nsILoadContext to allow for overriding of the global preference setting for individual DocShells. r=smaug
docshell/base/LoadContext.cpp
docshell/base/LoadContext.h
docshell/base/SerializedLoadContext.cpp
docshell/base/SerializedLoadContext.h
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
docshell/base/nsILoadContext.idl
dom/ipc/TabParent.cpp
uriloader/prefetch/OfflineCacheUpdateParent.cpp
--- a/docshell/base/LoadContext.cpp
+++ b/docshell/base/LoadContext.cpp
@@ -41,27 +41,29 @@ namespace mozilla {
 NS_IMPL_ISUPPORTS(LoadContext, nsILoadContext, nsIInterfaceRequestor)
 
 LoadContext::LoadContext(nsIPrincipal* aPrincipal,
                          nsILoadContext* aOptionalBase)
   : mTopFrameElement(nullptr)
   , mNestedFrameId(0)
   , mIsContent(true)
   , mUseRemoteTabs(false)
+  , mUseTrackingProtection(false)
 #ifdef DEBUG
   , mIsNotNull(true)
 #endif
 {
   mOriginAttributes.Inherit(aPrincipal->OriginAttributesRef());
   if (!aOptionalBase) {
     return;
   }
 
   MOZ_ALWAYS_SUCCEEDS(aOptionalBase->GetIsContent(&mIsContent));
   MOZ_ALWAYS_SUCCEEDS(aOptionalBase->GetUseRemoteTabs(&mUseRemoteTabs));
+  MOZ_ALWAYS_SUCCEEDS(aOptionalBase->GetUseTrackingProtection(&mUseTrackingProtection));
 }
 
 //-----------------------------------------------------------------------------
 // LoadContext::nsILoadContext
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 LoadContext::GetAssociatedWindow(mozIDOMWindowProxy**)
@@ -175,30 +177,32 @@ LoadContext::GetOriginAttributes(JS::Mut
   MOZ_ASSERT(cx);
 
   bool ok = ToJSValue(cx, mOriginAttributes, aAttrs);
   NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-LoadContext::IsTrackingProtectionOn(bool* aIsTrackingProtectionOn)
+LoadContext::GetUseTrackingProtection(bool* aUseTrackingProtection)
 {
   MOZ_ASSERT(mIsNotNull);
 
-  if (Preferences::GetBool("privacy.trackingprotection.enabled", false)) {
-    *aIsTrackingProtectionOn = true;
-  } else if ((mOriginAttributes.mPrivateBrowsingId > 0) &&
-             Preferences::GetBool("privacy.trackingprotection.pbmode.enabled", false)) {
-    *aIsTrackingProtectionOn = true;
-  } else {
-    *aIsTrackingProtectionOn = false;
-  }
+  NS_ENSURE_ARG_POINTER(aUseTrackingProtection);
+
+  *aUseTrackingProtection = mUseTrackingProtection;
+  return NS_OK;
+}
 
-  return NS_OK;
+NS_IMETHODIMP
+LoadContext::SetUseTrackingProtection(bool aUseTrackingProtection)
+{
+  MOZ_ASSERT_UNREACHABLE("Should only be set through nsDocShell");
+
+  return NS_ERROR_UNEXPECTED;
 }
 
 //-----------------------------------------------------------------------------
 // LoadContext::nsIInterfaceRequestor
 //-----------------------------------------------------------------------------
 NS_IMETHODIMP
 LoadContext::GetInterface(const nsIID& aIID, void** aResult)
 {
--- a/docshell/base/LoadContext.h
+++ b/docshell/base/LoadContext.h
@@ -40,62 +40,67 @@ public:
   // provided by child process.
   LoadContext(const IPC::SerializedLoadContext& aToCopy,
               dom::Element* aTopFrameElement,
               OriginAttributes& aAttrs)
     : mTopFrameElement(do_GetWeakReference(aTopFrameElement))
     , mNestedFrameId(0)
     , mIsContent(aToCopy.mIsContent)
     , mUseRemoteTabs(aToCopy.mUseRemoteTabs)
+    , mUseTrackingProtection(aToCopy.mUseTrackingProtection)
     , mOriginAttributes(aAttrs)
 #ifdef DEBUG
     , mIsNotNull(aToCopy.mIsNotNull)
 #endif
   {
   }
 
   // appId/inIsolatedMozBrowser arguments override those in SerializedLoadContext
   // provided by child process.
   LoadContext(const IPC::SerializedLoadContext& aToCopy,
               uint64_t aNestedFrameId,
               OriginAttributes& aAttrs)
     : mTopFrameElement(nullptr)
     , mNestedFrameId(aNestedFrameId)
     , mIsContent(aToCopy.mIsContent)
     , mUseRemoteTabs(aToCopy.mUseRemoteTabs)
+    , mUseTrackingProtection(aToCopy.mUseTrackingProtection)
     , mOriginAttributes(aAttrs)
 #ifdef DEBUG
     , mIsNotNull(aToCopy.mIsNotNull)
 #endif
   {
   }
 
   LoadContext(dom::Element* aTopFrameElement,
               bool aIsContent,
               bool aUsePrivateBrowsing,
               bool aUseRemoteTabs,
+              bool aUseTrackingProtection,
               const OriginAttributes& aAttrs)
     : mTopFrameElement(do_GetWeakReference(aTopFrameElement))
     , mNestedFrameId(0)
     , mIsContent(aIsContent)
     , mUseRemoteTabs(aUseRemoteTabs)
+    , mUseTrackingProtection(aUseTrackingProtection)
     , mOriginAttributes(aAttrs)
 #ifdef DEBUG
     , mIsNotNull(true)
 #endif
   {
     MOZ_DIAGNOSTIC_ASSERT(aUsePrivateBrowsing == (aAttrs.mPrivateBrowsingId > 0));
   }
 
   // Constructor taking reserved origin attributes.
   explicit LoadContext(OriginAttributes& aAttrs)
     : mTopFrameElement(nullptr)
     , mNestedFrameId(0)
     , mIsContent(false)
     , mUseRemoteTabs(false)
+    , mUseTrackingProtection(false)
     , mOriginAttributes(aAttrs)
 #ifdef DEBUG
     , mIsNotNull(true)
 #endif
   {
   }
 
   // Constructor for creating a LoadContext with a given principal's appId and
@@ -105,16 +110,17 @@ public:
 
 private:
   ~LoadContext() {}
 
   nsWeakPtr mTopFrameElement;
   uint64_t mNestedFrameId;
   bool mIsContent;
   bool mUseRemoteTabs;
+  bool mUseTrackingProtection;
   OriginAttributes mOriginAttributes;
 #ifdef DEBUG
   bool mIsNotNull;
 #endif
 };
 
 } // namespace mozilla
 
--- a/docshell/base/SerializedLoadContext.cpp
+++ b/docshell/base/SerializedLoadContext.cpp
@@ -56,22 +56,24 @@ SerializedLoadContext::SerializedLoadCon
 void
 SerializedLoadContext::Init(nsILoadContext* aLoadContext)
 {
   if (aLoadContext) {
     mIsNotNull = true;
     mIsPrivateBitValid = true;
     aLoadContext->GetIsContent(&mIsContent);
     aLoadContext->GetUseRemoteTabs(&mUseRemoteTabs);
+    aLoadContext->GetUseTrackingProtection(&mUseTrackingProtection);
     if (!aLoadContext->GetOriginAttributes(mOriginAttributes)) {
       NS_WARNING("GetOriginAttributes failed");
     }
   } else {
     mIsNotNull = false;
     mIsPrivateBitValid = false;
     // none of below values really matter when mIsNotNull == false:
     // we won't be GetInterfaced to nsILoadContext
     mIsContent = true;
     mUseRemoteTabs = false;
+    mUseTrackingProtection = false;
   }
 }
 
 } // namespace IPC
--- a/docshell/base/SerializedLoadContext.h
+++ b/docshell/base/SerializedLoadContext.h
@@ -27,16 +27,17 @@ namespace IPC {
 class SerializedLoadContext
 {
 public:
   SerializedLoadContext()
     : mIsNotNull(false)
     , mIsPrivateBitValid(false)
     , mIsContent(false)
     , mUseRemoteTabs(false)
+    , mUseTrackingProtection(false)
   {
     Init(nullptr);
   }
 
   explicit SerializedLoadContext(nsILoadContext* aLoadContext);
   explicit SerializedLoadContext(nsIChannel* aChannel);
   explicit SerializedLoadContext(nsIWebSocketChannel* aChannel);
 
@@ -47,16 +48,17 @@ public:
 
   // used to indicate if child-side LoadContext * was null.
   bool mIsNotNull;
   // used to indicate if child-side mUsePrivateBrowsing flag is valid, even if
   // mIsNotNull is false, i.e., child LoadContext was null.
   bool mIsPrivateBitValid;
   bool mIsContent;
   bool mUseRemoteTabs;
+  bool mUseTrackingProtection;
   mozilla::OriginAttributes mOriginAttributes;
 };
 
 // Function to serialize over IPDL
 template<>
 struct ParamTraits<SerializedLoadContext>
 {
   typedef SerializedLoadContext paramType;
@@ -65,26 +67,28 @@ struct ParamTraits<SerializedLoadContext
   {
     nsAutoCString suffix;
     aParam.mOriginAttributes.CreateSuffix(suffix);
 
     WriteParam(aMsg, aParam.mIsNotNull);
     WriteParam(aMsg, aParam.mIsContent);
     WriteParam(aMsg, aParam.mIsPrivateBitValid);
     WriteParam(aMsg, aParam.mUseRemoteTabs);
+    WriteParam(aMsg, aParam.mUseTrackingProtection);
     WriteParam(aMsg, suffix);
   }
 
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     nsAutoCString suffix;
     if (!ReadParam(aMsg, aIter, &aResult->mIsNotNull) ||
         !ReadParam(aMsg, aIter, &aResult->mIsContent) ||
         !ReadParam(aMsg, aIter, &aResult->mIsPrivateBitValid) ||
         !ReadParam(aMsg, aIter, &aResult->mUseRemoteTabs) ||
+        !ReadParam(aMsg, aIter, &aResult->mUseTrackingProtection) ||
         !ReadParam(aMsg, aIter, &suffix)) {
       return false;
     }
     return aResult->mOriginAttributes.PopulateFromSuffix(suffix);
   }
 };
 
 } // namespace IPC
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -790,16 +790,17 @@ nsDocShell::nsDocShell()
   , mAllowKeywordFixup(false)
   , mIsOffScreenBrowser(false)
   , mIsActive(true)
   , mDisableMetaRefreshWhenInactive(false)
   , mIsPrerendered(false)
   , mIsAppTab(false)
   , mUseGlobalHistory(false)
   , mUseRemoteTabs(false)
+  , mUseTrackingProtection(false)
   , mDeviceSizeIsPageSize(false)
   , mWindowDraggingAllowed(false)
   , mInFrameSwap(false)
   , mInheritPrivateBrowsingId(true)
   , mCanExecuteScripts(false)
   , mFiredUnloadEvent(false)
   , mEODForCurrentDocument(false)
   , mURIResultedInDocument(false)
@@ -13674,27 +13675,50 @@ nsDocShell::GetTopFrameElement(nsIDOMEle
 NS_IMETHODIMP
 nsDocShell::GetNestedFrameId(uint64_t* aId)
 {
   *aId = 0;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocShell::IsTrackingProtectionOn(bool* aIsTrackingProtectionOn)
-{
-  if (Preferences::GetBool("privacy.trackingprotection.enabled", false)) {
-    *aIsTrackingProtectionOn = true;
-  } else if (UsePrivateBrowsing() &&
-             Preferences::GetBool("privacy.trackingprotection.pbmode.enabled", false)) {
-    *aIsTrackingProtectionOn = true;
-  } else {
-    *aIsTrackingProtectionOn = false;
-  }
-
+nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection)
+{
+  *aUseTrackingProtection  = false;
+
+  static bool sTPEnabled = false;
+  static bool sTPInPBEnabled = false;
+  static bool sPrefsInit = false;
+
+  if (!sPrefsInit) {
+    sPrefsInit = true;
+    Preferences::AddBoolVarCache(&sTPEnabled,
+      "privacy.trackingprotection.enabled", false);
+    Preferences::AddBoolVarCache(&sTPInPBEnabled,
+      "privacy.trackingprotection.pbmode.enabled", false);
+  }
+
+  if (mUseTrackingProtection || sTPEnabled ||
+      (UsePrivateBrowsing() && sTPInPBEnabled)) {
+    *aUseTrackingProtection = true;
+    return NS_OK;
+  }
+
+  RefPtr<nsDocShell> parent = GetParentDocshell();
+  if (parent) {
+    return parent->GetUseTrackingProtection(aUseTrackingProtection);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection)
+{
+  mUseTrackingProtection = aUseTrackingProtection;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetIsContent(bool* aIsContent)
 {
   *aIsContent = (mItemType == typeContent);
   return NS_OK;
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -229,17 +229,16 @@ public:
   NS_IMETHOD GetNestedFrameId(uint64_t*) override;
   NS_IMETHOD GetIsContent(bool*) override;
   NS_IMETHOD GetUsePrivateBrowsing(bool*) override;
   NS_IMETHOD SetUsePrivateBrowsing(bool) override;
   NS_IMETHOD SetPrivateBrowsing(bool) override;
   NS_IMETHOD GetUseRemoteTabs(bool*) override;
   NS_IMETHOD SetRemoteTabs(bool) override;
   NS_IMETHOD GetOriginAttributes(JS::MutableHandle<JS::Value>) override;
-  NS_IMETHOD IsTrackingProtectionOn(bool*) override;
 
   // Restores a cached presentation from history (mLSHE).
   // This method swaps out the content viewer and simulates loads for
   // subframes. It then simulates the completion of the toplevel load.
   nsresult RestoreFromHistory();
 
   // Perform a URI load from a refresh timer. This is just like the
   // ForceRefreshURI method on nsIRefreshURI, but makes sure to take
@@ -956,16 +955,17 @@ protected:
   bool mAllowKeywordFixup : 1;
   bool mIsOffScreenBrowser : 1;
   bool mIsActive : 1;
   bool mDisableMetaRefreshWhenInactive : 1;
   bool mIsPrerendered : 1;
   bool mIsAppTab : 1;
   bool mUseGlobalHistory : 1;
   bool mUseRemoteTabs : 1;
+  bool mUseTrackingProtection : 1;
   bool mDeviceSizeIsPageSize : 1;
   bool mWindowDraggingAllowed : 1;
   bool mInFrameSwap : 1;
   bool mInheritPrivateBrowsingId : 1;
 
   // Because scriptability depends on the mAllowJavascript values of our
   // ancestors, we cache the effective scriptability and recompute it when
   // it might have changed;
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -1126,9 +1126,14 @@ interface nsIDocShell : nsIDocShellTreeI
    */
   [infallible] readonly attribute boolean isOnlyToplevelInTabGroup;
 
   /**
    * Returns `true` if this docshell was created due to a Large-Allocation
    * header, and has not seen the initiating load yet.
    */
   [infallible] readonly attribute boolean awaitingLargeAlloc;
+
+  /**
+   * Attribute that determines whether tracking protection is enabled.
+   */
+  attribute boolean useTrackingProtection;
 };
--- a/docshell/base/nsILoadContext.idl
+++ b/docshell/base/nsILoadContext.idl
@@ -73,31 +73,43 @@ interface nsILoadContext : nsISupports
    */
   attribute boolean usePrivateBrowsing;
 
   /**
    * Attribute that determines if remote (out-of-process) tabs should be used.
    */
   readonly attribute boolean useRemoteTabs;
 
+  /*
+   * Attribute that determines if tracking protection should be used. May not be
+   * changed after a document has been loaded in this context.
+   */
+  attribute boolean useTrackingProtection;
+
 %{C++
   /**
    * De-XPCOMed getter to make call-sites cleaner.
    */
   bool UsePrivateBrowsing() {
     bool usingPB;
     GetUsePrivateBrowsing(&usingPB);
     return usingPB;
   }
 
   bool UseRemoteTabs() {
     bool usingRT;
     GetUseRemoteTabs(&usingRT);
     return usingRT;
   }
+
+  bool UseTrackingProtection() {
+    bool usingTP;
+    GetUseTrackingProtection(&usingTP);
+    return usingTP;
+  }
 %}
 
   /**
    * Set the private browsing state of the load context, meant to be used internally.
    */
   [noscript] void SetPrivateBrowsing(in boolean aInPrivateBrowsing);
 
   /**
@@ -125,25 +137,9 @@ interface nsILoadContext : nsISupports
   /**
    * The C++ getter for origin attributes.
    *
    * Defined in LoadContext.cpp
    */
   bool GetOriginAttributes(mozilla::OriginAttributes& aAttrs);
 #endif
 %}
-
-  /**
-   * Returns true if tracking protection is enabled for the load context.
-   */
-  boolean IsTrackingProtectionOn();
-
-%{C++
-  /**
-   * De-XPCOMed getter to make call-sites cleaner.
-   */
-  bool UseTrackingProtection() {
-    bool usingTP;
-    IsTrackingProtectionOn(&usingTP);
-    return usingTP;
-  }
-%}
 };
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2676,20 +2676,26 @@ already_AddRefed<nsILoadContext>
 TabParent::GetLoadContext()
 {
   nsCOMPtr<nsILoadContext> loadContext;
   if (mLoadContext) {
     loadContext = mLoadContext;
   } else {
     bool isPrivate = mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
     SetPrivateBrowsingAttributes(isPrivate);
+    bool useTrackingProtection = false;
+    nsCOMPtr<nsIDocShell> docShell = mFrameElement->OwnerDoc()->GetDocShell();
+    if (docShell) {
+      docShell->GetUseTrackingProtection(&useTrackingProtection);
+    }
     loadContext = new LoadContext(GetOwnerElement(),
                                   true /* aIsContent */,
                                   isPrivate,
                                   mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW,
+                                  useTrackingProtection,
                                   OriginAttributesRef());
     mLoadContext = loadContext;
   }
   return loadContext.forget();
 }
 
 NS_IMETHODIMP
 TabParent::GetUseAsyncPanZoom(bool* useAsyncPanZoom)
@@ -2989,17 +2995,18 @@ public:
   NS_IMETHOD GetIsContent(bool*) NO_IMPL
   NS_IMETHOD GetUsePrivateBrowsing(bool*) NO_IMPL
   NS_IMETHOD SetUsePrivateBrowsing(bool) NO_IMPL
   NS_IMETHOD SetPrivateBrowsing(bool) NO_IMPL
   NS_IMETHOD GetIsInIsolatedMozBrowserElement(bool*) NO_IMPL
   NS_IMETHOD GetOriginAttributes(JS::MutableHandleValue) NO_IMPL
   NS_IMETHOD GetUseRemoteTabs(bool*) NO_IMPL
   NS_IMETHOD SetRemoteTabs(bool) NO_IMPL
-  NS_IMETHOD IsTrackingProtectionOn(bool*) NO_IMPL
+  NS_IMETHOD GetUseTrackingProtection(bool*) NO_IMPL
+  NS_IMETHOD SetUseTrackingProtection(bool) NO_IMPL
 #undef NO_IMPL
 
 protected:
   ~FakeChannel() {}
 
   nsCOMPtr<nsIURI> mUri;
   uint64_t mCallbackId;
   nsCOMPtr<Element> mElement;
--- a/uriloader/prefetch/OfflineCacheUpdateParent.cpp
+++ b/uriloader/prefetch/OfflineCacheUpdateParent.cpp
@@ -272,15 +272,21 @@ OfflineCacheUpdateParent::GetOriginAttri
 
     nsresult rv = mLoadingPrincipal->GetOriginAttributes(cx, aAttrs);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-OfflineCacheUpdateParent::IsTrackingProtectionOn(bool* aIsTrackingProtectionOn)
+OfflineCacheUpdateParent::GetUseTrackingProtection(bool *aUseTrackingProtection)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+OfflineCacheUpdateParent::SetUseTrackingProtection(bool aUseTrackingProtection)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 } // namespace docshell
 } // namespace mozilla