Bug 1525036 - Respect CrossOriginPolicy in nsHttpChannel r=nika
☠☠ backed out by 9da6e8f78737 ☠ ☠
authorValentin Gosu <valentin.gosu@gmail.com>
Fri, 08 Mar 2019 15:33:56 +0000
changeset 521162 fa0363d33dbd
parent 521161 6391f42aaa6d
child 521163 502b0bb796cd
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1525036
milestone67.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 1525036 - Respect CrossOriginPolicy in nsHttpChannel r=nika Differential Revision: https://phabricator.services.mozilla.com/D21415
netwerk/protocol/http/nsHttpAtomList.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
--- a/netwerk/protocol/http/nsHttpAtomList.h
+++ b/netwerk/protocol/http/nsHttpAtomList.h
@@ -36,16 +36,17 @@ HTTP_ATOM(Content_Encoding, "Content-Enc
 HTTP_ATOM(Content_Language, "Content-Language")
 HTTP_ATOM(Content_Length, "Content-Length")
 HTTP_ATOM(Content_Location, "Content-Location")
 HTTP_ATOM(Content_MD5, "Content-MD5")
 HTTP_ATOM(Content_Range, "Content-Range")
 HTTP_ATOM(Content_Type, "Content-Type")
 HTTP_ATOM(Cookie, "Cookie")
 HTTP_ATOM(Cross_Origin_Opener_Policy, "Cross-Origin-Opener-Policy")
+HTTP_ATOM(Cross_Origin, "Cross-Origin")
 HTTP_ATOM(Date, "Date")
 HTTP_ATOM(DAV, "DAV")
 HTTP_ATOM(Depth, "Depth")
 HTTP_ATOM(Destination, "Destination")
 HTTP_ATOM(DoNotTrack, "DNT")
 HTTP_ATOM(ETag, "Etag")
 HTTP_ATOM(Expect, "Expect")
 HTTP_ATOM(Expires, "Expires")
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -2446,16 +2446,23 @@ nsresult nsHttpChannel::ContinueProcessR
     rv = mAuthProvider->Disconnect(NS_ERROR_ABORT);
     if (NS_FAILED(rv)) {
       LOG(("  Disconnect failed (%08x)", static_cast<uint32_t>(rv)));
     }
     mAuthProvider = nullptr;
     LOG(("  continuation state has been reset"));
   }
 
+  rv = ProcessCrossOriginHeader();
+  if (NS_FAILED(rv)) {
+    mStatus = NS_ERROR_BLOCKED_BY_POLICY;
+    HandleAsyncAbort();
+    return NS_OK;
+  }
+
   rv = NS_OK;
   if (!mCanceled) {
     // notify "http-on-may-change-process" observers
     gHttpHandler->OnMayChangeProcess(this);
 
     if (mRedirectTabPromise) {
       MOZ_ASSERT(!mOnStartRequestCalled);
 
@@ -7306,16 +7313,83 @@ nsHttpChannel::HasCrossOriginOpenerPolic
       *aMismatch = true;
       return NS_OK;
     }
   }
 
   return NS_OK;
 }
 
+nsresult nsHttpChannel::GetResponseCrossOriginPolicy(
+    nsILoadInfo::CrossOriginPolicy *aResponseCrossOriginPolicy) {
+  if (!mResponseHead) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  nsILoadInfo::CrossOriginPolicy policy = nsILoadInfo::CROSS_ORIGIN_POLICY_NULL;
+
+  nsAutoCString content;
+  Unused << mResponseHead->GetHeader(nsHttp::Cross_Origin, content);
+
+  // Cross-Origin = %s"anonymous" / %s"use-credentials" ; case-sensitive
+
+  if (content.EqualsLiteral("anonymous")) {
+    policy = nsILoadInfo::CROSS_ORIGIN_POLICY_ANONYMOUS;
+  } else if (content.EqualsLiteral("use-credentials")) {
+    policy = nsILoadInfo::CROSS_ORIGIN_POLICY_USE_CREDENTIALS;
+  }
+
+  *aResponseCrossOriginPolicy = policy;
+  return NS_OK;
+}
+
+nsresult nsHttpChannel::ProcessCrossOriginHeader() {
+  nsresult rv;
+  if (!StaticPrefs::browser_tabs_remote_useCrossOriginPolicy()) {
+    return NS_OK;
+  }
+
+  // Only consider Cross-Origin for document loads.
+  if (mLoadInfo->GetExternalContentPolicyType() !=
+          nsIContentPolicy::TYPE_DOCUMENT &&
+      mLoadInfo->GetExternalContentPolicyType() !=
+          nsIContentPolicy::TYPE_SUBDOCUMENT) {
+    return NS_OK;
+  }
+
+  RefPtr<mozilla::dom::BrowsingContext> ctx;
+  if (mLoadInfo->GetExternalContentPolicyType() ==
+      nsIContentPolicy::TYPE_DOCUMENT) {
+    mLoadInfo->GetBrowsingContext(getter_AddRefs(ctx));
+  } else {
+    mLoadInfo->GetFrameBrowsingContext(getter_AddRefs(ctx));
+  }
+
+  if (!ctx) {
+    return NS_OK;
+  }
+
+  nsILoadInfo::CrossOriginPolicy documentPolicy = ctx->CrossOriginPolicy();
+  nsILoadInfo::CrossOriginPolicy resultPolicy =
+      nsILoadInfo::CROSS_ORIGIN_POLICY_NULL;
+  rv = GetResponseCrossOriginPolicy(&resultPolicy);
+  if (NS_FAILED(rv)) {
+    return NS_OK;
+  }
+
+  ctx->SetCrossOriginPolicy(resultPolicy);
+
+  if (documentPolicy != nsILoadInfo::CROSS_ORIGIN_POLICY_NULL &&
+      resultPolicy == nsILoadInfo::CROSS_ORIGIN_POLICY_NULL) {
+    return NS_ERROR_BLOCKED_BY_POLICY;
+  }
+
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsHttpChannel::OnStartRequest(nsIRequest *request) {
   nsresult rv;
 
   MOZ_ASSERT(mRequestObserversCalled);
 
   AUTO_PROFILER_LABEL("nsHttpChannel::OnStartRequest", NETWORK);
 
@@ -7421,16 +7495,23 @@ nsHttpChannel::OnStartRequest(nsIRequest
   }
 
   // avoid crashing if mListener happens to be null...
   if (!mListener) {
     MOZ_ASSERT_UNREACHABLE("mListener is null");
     return NS_OK;
   }
 
+  rv = ProcessCrossOriginHeader();
+  if (NS_FAILED(rv)) {
+    mStatus = NS_ERROR_BLOCKED_BY_POLICY;
+    HandleAsyncAbort();
+    return NS_OK;
+  }
+
   // before we check for redirects, check if the load should be shifted into a
   // new process.
   rv = NS_OK;
   if (!mCanceled) {
     // notify "http-on-may-change-process" observers
     gHttpHandler->OnMayChangeProcess(this);
 
     if (mRedirectTabPromise) {
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -470,16 +470,20 @@ class nsHttpChannel final : public HttpB
   MOZ_MUST_USE nsresult
   ProcessContentSignatureHeader(nsHttpResponseHead *aResponseHead);
 
   /**
    * A function that will, if the feature is enabled, send security reports.
    */
   void ProcessSecurityReport(nsresult status);
 
+  nsresult GetResponseCrossOriginPolicy(
+      nsILoadInfo::CrossOriginPolicy *aResponseCrossOriginPolicy);
+  nsresult ProcessCrossOriginHeader();
+
   /**
    * A function to process a single security header (STS or PKP), assumes
    * some basic sanity checks have been applied to the channel. Called
    * from ProcessSecurityHeaders.
    */
   MOZ_MUST_USE nsresult ProcessSingleSecurityHeader(
       uint32_t aType, nsITransportSecurityInfo *aSecInfo, uint32_t aFlags);