Bug 1426977 P3 Use StorageAllowedForNewWindow() in nsDocShell::ServiceWorkerAllowedToControlWindow(). r=mystor
authorBen Kelly <ben@wanderview.com>
Mon, 08 Jan 2018 20:25:53 -0500
changeset 450092 5b5c58cb8123d6888f6bb11ebdb6a5d37bb10a48
parent 450091 47a65c7932c7c40b38407427e8af02698a2bffbb
child 450093 ab49425989fe8c324bdfc9eea751edb7aa51d80b
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmystor
bugs1426977
milestone59.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 1426977 P3 Use StorageAllowedForNewWindow() in nsDocShell::ServiceWorkerAllowedToControlWindow(). r=mystor
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2830,20 +2830,24 @@ nsDocShell::MaybeCreateInitialClientSour
   nsCOMPtr<nsIDocShell> parent = GetParentDocshell();
   nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
   nsPIDOMWindowInner* parentInner =
     parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
   if (!parentInner) {
     return;
   }
 
+  nsCOMPtr<nsIURI> uri;
+  MOZ_ALWAYS_SUCCEEDS(
+    NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank")));
+
   // We're done if there is no parent controller or if this docshell
   // is not permitted to control for some reason.
   Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
-  if (controller.isNothing() || !ServiceWorkerAllowedToControlWindow(nullptr)) {
+  if (controller.isNothing() || !ServiceWorkerAllowedToControlWindow(principal, uri)) {
     return;
   }
 
   nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
   if (!swm) {
     return;
   }
 
@@ -14094,61 +14098,36 @@ nsDocShell::CanSetOriginAttributes()
       }
     }
   }
 
   return true;
 }
 
 bool
-nsDocShell::ServiceWorkerAllowedToControlWindow(nsIURI* aURI)
-{
-  // NOTE: Ideally this method would call one of the
-  //       nsContentUtils::StorageAllowed*() methods to determine if the
-  //       interception is allowed.  Unfortunately we cannot safely do this
-  //       before the first window loads in the child process because the
-  //       permission manager might not have all its data yet.  Therefore,
-  //       we use this somewhat lame alternate implementation here.  Once
-  //       interception is moved to the parent process we should switch
-  //       to calling nsContentUtils::StorageAllowed*().  See bug 1428130.
+nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
+                                                nsIURI* aURI)
+{
+  MOZ_ASSERT(aPrincipal);
+  MOZ_ASSERT(aURI);
 
   if (UsePrivateBrowsing() || mSandboxFlags) {
     return false;
   }
 
-  uint32_t cookieBehavior = nsContentUtils::CookiesBehavior();
-  uint32_t lifetimePolicy = nsContentUtils::CookiesLifetimePolicy();
-  if (cookieBehavior == nsICookieService::BEHAVIOR_REJECT ||
-      lifetimePolicy == nsICookieService::ACCEPT_SESSION) {
-    return false;
-  }
-
-  if (!aURI || cookieBehavior == nsICookieService::BEHAVIOR_ACCEPT) {
-    return true;
-  }
-
   nsCOMPtr<nsIDocShellTreeItem> parent;
   GetSameTypeParent(getter_AddRefs(parent));
-  nsCOMPtr<nsPIDOMWindowOuter> parentWindow = parent ? parent->GetWindow()
-                                                     : nullptr;
-  if (parentWindow) {
-    nsresult rv = NS_OK;
-    nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
-      do_GetService(THIRDPARTYUTIL_CONTRACTID, &rv);
-    if (thirdPartyUtil) {
-      bool isThirdPartyURI = true;
-      rv = thirdPartyUtil->IsThirdPartyWindow(parentWindow, aURI,
-                                              &isThirdPartyURI);
-      if (NS_SUCCEEDED(rv) && isThirdPartyURI) {
-        return false;
-      }
-    }
-  }
-
-  return true;
+  nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
+  nsPIDOMWindowInner* parentInner =
+    parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
+
+  nsContentUtils::StorageAccess storage =
+    nsContentUtils::StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
+
+  return storage == nsContentUtils::StorageAccess::eAllow;
 }
 
 nsresult
 nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs)
 {
   if (!CanSetOriginAttributes()) {
     return NS_ERROR_FAILURE;
   }
@@ -14365,31 +14344,32 @@ nsDocShell::ShouldPrepareForIntercept(ns
     *aShouldIntercept = doc->GetController().isSome();
     if (NS_WARN_IF(rv.Failed())) {
       return rv.StealNSResult();
     }
 
     return NS_OK;
   }
 
+  nsCOMPtr<nsIPrincipal> principal =
+    BasePrincipal::CreateCodebasePrincipal(aURI, mOriginAttributes);
+
   // For navigations, first check to see if we are allowed to control a
   // window with the given URL.
-  if (!ServiceWorkerAllowedToControlWindow(aURI)) {
+  if (!ServiceWorkerAllowedToControlWindow(principal, aURI)) {
     return NS_OK;
   }
 
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   if (!swm) {
     return NS_OK;
   }
 
   // We're allowed to control a window, so check with the ServiceWorkerManager
   // for a matching service worker.
-  nsCOMPtr<nsIPrincipal> principal =
-    BasePrincipal::CreateCodebasePrincipal(aURI, mOriginAttributes);
   *aShouldIntercept = swm->IsAvailable(principal, aURI);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
 {
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -787,20 +787,18 @@ private: // member functions
   void MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal = nullptr);
 
   // Determine if a service worker is allowed to control a window in this
   // docshell with the given URL.  If there are any reasons it should not,
   // this will return false.  If true is returned then the window *may* be
   // controlled.  The caller must still consult either the parent controller
   // or the ServiceWorkerManager to determine if a service worker should
   // actually control the window.
-  //
-  // A nullptr URL is considered to be an about:blank window and will not
-  // trigger 3rd party iframe checks.
-  bool ServiceWorkerAllowedToControlWindow(nsIURI* aURI);
+  bool ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
+                                           nsIURI* aURI);
 
   // Return the ClientInfo for the initial about:blank window, if it exists
   // or we have speculatively created a ClientSource in
   // MaybeCreateInitialClientSource().  This can return a ClientInfo object
   // even if GetExtantDoc() returns nullptr.
   mozilla::Maybe<mozilla::dom::ClientInfo> GetInitialClientInfo() const;
 
   /**