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 344300 7552fa4a2858a2ca6a51640dcc85133a9537085c
parent 344299 b4f01417998fb54b62ce38942266cda570d47b76
child 344301 dd8000832878e2f2f4f066a295c81b02b94f1c0d
push id31406
push userkwierso@gmail.com
push dateWed, 22 Feb 2017 23:01:18 +0000
treeherdermozilla-central@32dcdde1fc64 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1322576
milestone54.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 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