Backed out changeset a11078290110 (bug 1182537) a=backout
authorWes Kocher <wkocher@mozilla.com>
Fri, 11 Sep 2015 13:30:24 -0700
changeset 289249 7239a71b423fd9e18ed6b6f2bdfc254b23e20a17
parent 289248 a7bb121ef972f05ab331dab7446410aac25f6165
child 289250 356226c045a9a82a782e42f814e839324fc8c0f0
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1182537
milestone42.0a2
backs outa110782901107a9c9d7c9a38120554df3a71336b
Backed out changeset a11078290110 (bug 1182537) a=backout
dom/base/Navigator.cpp
dom/security/nsContentSecurityManager.cpp
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -63,23 +63,26 @@
 #include "nsIIdleObserver.h"
 #include "nsIPermissionManager.h"
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
 #include "nsStringStream.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIStringStream.h"
 #include "nsIHttpChannel.h"
+#include "nsIHttpChannelInternal.h"
 #include "TimeManager.h"
 #include "DeviceStorage.h"
 #include "nsIDOMNavigatorSystemMessages.h"
 #include "nsStreamUtils.h"
 #include "nsIAppsService.h"
 #include "mozIApplication.h"
 #include "WidgetUtils.h"
+#include "mozIThirdPartyUtil.h"
+#include "nsINetworkInterceptController.h"
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 #include "mozilla/dom/MediaDevices.h"
 #include "MediaManager.h"
 #endif
 #ifdef MOZ_B2G_BT
 #include "BluetoothManager.h"
 #endif
@@ -99,16 +102,17 @@
 
 #include "nsScriptNameSpaceManager.h"
 
 #include "mozilla/dom/NavigatorBinding.h"
 #include "mozilla/dom/Promise.h"
 
 #include "nsIUploadChannel2.h"
 #include "nsFormData.h"
+#include "nsIPrivateBrowsingChannel.h"
 #include "nsIDocShell.h"
 
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 
 #if defined(XP_LINUX)
 #include "mozilla/Hal.h"
 #endif
@@ -1040,42 +1044,32 @@ Navigator::GetGeolocation(ErrorResult& a
   return mGeolocation;
 }
 
 class BeaconStreamListener final : public nsIStreamListener
 {
     ~BeaconStreamListener() {}
 
   public:
-    BeaconStreamListener() : mLoadGroup(nullptr) {}
-
-    void SetLoadGroup(nsILoadGroup* aLoadGroup) {
-      mLoadGroup = aLoadGroup;
-    }
+    BeaconStreamListener() {}
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISTREAMLISTENER
     NS_DECL_NSIREQUESTOBSERVER
-
-  private:
-    nsCOMPtr<nsILoadGroup> mLoadGroup;
-
 };
 
 NS_IMPL_ISUPPORTS(BeaconStreamListener,
                   nsIStreamListener,
                   nsIRequestObserver)
 
+
 NS_IMETHODIMP
 BeaconStreamListener::OnStartRequest(nsIRequest *aRequest,
                                      nsISupports *aContext)
 {
-  // release the loadgroup first
-  mLoadGroup = nullptr;
-
   aRequest->Cancel(NS_ERROR_NET_INTERRUPT);
   return NS_BINDING_ABORTED;
 }
 
 NS_IMETHODIMP
 BeaconStreamListener::OnStopRequest(nsIRequest *aRequest,
                                     nsISupports *aContext,
                                     nsresult aStatus)
@@ -1122,44 +1116,99 @@ Navigator::SendBeacon(const nsAString& a
                   aUrl,
                   doc,
                   doc->GetDocBaseURI());
   if (NS_FAILED(rv)) {
     aRv.Throw(NS_ERROR_DOM_URL_MISMATCH_ERR);
     return false;
   }
 
-  // Explicitly disallow loading data: URIs
-  bool isDataScheme = false;
-  rv = uri->SchemeIs("data", &isDataScheme);
-  if (NS_FAILED(rv) || isDataScheme) {
+  // Check whether this is a sane URI to load
+  // Explicitly disallow things like chrome:, javascript:, and data: URIs
+  nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
+  nsCOMPtr<nsIScriptSecurityManager> secMan = nsContentUtils::GetSecurityManager();
+  uint32_t flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
+                   & nsIScriptSecurityManager::DISALLOW_SCRIPT;
+  rv = secMan->CheckLoadURIWithPrincipal(principal,
+                                         uri,
+                                         flags);
+  if (NS_FAILED(rv)) {
+    // Bad URI
+    aRv.Throw(rv);
+    return false;
+  }
+
+  // Check whether the CSP allows us to load
+  int16_t shouldLoad = nsIContentPolicy::ACCEPT;
+  rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_BEACON,
+                                 uri,
+                                 principal,
+                                 doc,
+                                 EmptyCString(), //mime guess
+                                 nullptr,         //extra
+                                 &shouldLoad,
+                                 nsContentUtils::GetContentPolicy(),
+                                 nsContentUtils::GetSecurityManager());
+  if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
+    // Disallowed by content policy
     aRv.Throw(NS_ERROR_CONTENT_BLOCKED);
     return false;
   }
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannel(getter_AddRefs(channel),
                      uri,
                      doc,
-                     nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
+                     nsILoadInfo::SEC_NORMAL,
                      nsIContentPolicy::TYPE_BEACON);
 
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return false;
   }
 
+  nsIDocShell* docShell = mWindow->GetDocShell();
+  nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(channel);
+  if (pbChannel) {
+    nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
+    if (loadContext) {
+      rv = pbChannel->SetPrivate(loadContext->UsePrivateBrowsing());
+      if (NS_FAILED(rv)) {
+        NS_WARNING("Setting the privacy status on the beacon channel failed");
+      }
+    }
+  }
+
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
   if (!httpChannel) {
     // Beacon spec only supports HTTP requests at this time
     aRv.Throw(NS_ERROR_DOM_BAD_URI);
     return false;
   }
   httpChannel->SetReferrer(documentURI);
 
+  // Anything that will need to refer to the window during the request
+  // will need to be done now.  For example, detection of whether any
+  // cookies set by this request are foreign.  Note that ThirdPartyUtil
+  // (nsIThirdPartyUtil.isThirdPartyChannel) does a secondary check between
+  // the channel URI and the cookie URI even when forceAllowThirdPartyCookie
+  // is set, so this is safe with regard to redirects.
+  nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(do_QueryInterface(channel));
+  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID);
+  if (!httpChannelInternal) {
+    aRv.Throw(NS_ERROR_DOM_BAD_URI);
+    return false;
+  }
+  bool isForeign = true;
+  thirdPartyUtil->IsThirdPartyWindow(mWindow, uri, &isForeign);
+  uint32_t thirdPartyFlags = isForeign ?
+    0 :
+    nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW;
+  httpChannelInternal->SetThirdPartyFlags(thirdPartyFlags);
+
   nsCString mimeType;
   if (!aData.IsNull()) {
     nsCOMPtr<nsIInputStream> in;
 
     if (aData.Value().IsString()) {
       nsCString stringData = NS_ConvertUTF16toUTF8(aData.Value().GetAsString());
       nsCOMPtr<nsIStringInputStream> strStream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
       if (NS_FAILED(rv)) {
@@ -1236,28 +1285,27 @@ Navigator::SendBeacon(const nsAString& a
     p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
   }
 
   nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
   if (cos) {
     cos->AddClassFlags(nsIClassOfService::Background);
   }
 
-  // The channel needs to have a loadgroup associated with it, so that we can
-  // cancel the channel and any redirected channels it may create.
-  nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
-  nsCOMPtr<nsIInterfaceRequestor> callbacks =
-    do_QueryInterface(mWindow->GetDocShell());
-  loadGroup->SetNotificationCallbacks(callbacks);
-  channel->SetLoadGroup(loadGroup);
-
-  nsRefPtr<BeaconStreamListener> beaconListener = new BeaconStreamListener();
+  nsRefPtr<nsCORSListenerProxy> cors = new nsCORSListenerProxy(new BeaconStreamListener(),
+                                                               principal,
+                                                               true);
+
+  rv = cors->Init(channel, DataURIHandling::Allow);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  nsCOMPtr<nsINetworkInterceptController> interceptController = do_QueryInterface(docShell);
+  cors->SetInterceptController(interceptController);
 
   // Start a preflight if cross-origin and content type is not whitelisted
-  nsCOMPtr<nsIScriptSecurityManager> secMan = nsContentUtils::GetSecurityManager();
   rv = secMan->CheckSameOriginURI(documentURI, uri, false);
   bool crossOrigin = NS_FAILED(rv);
   nsAutoCString contentType, parsedCharset;
   rv = NS_ParseContentType(mimeType, contentType, parsedCharset);
   if (crossOrigin &&
       contentType.Length() > 0 &&
       !contentType.Equals(APPLICATION_WWW_FORM_URLENCODED) &&
       !contentType.Equals(MULTIPART_FORM_DATA) &&
@@ -1267,32 +1315,28 @@ Navigator::SendBeacon(const nsAString& a
     // so we can tell the channel not to follow redirects
     nsCOMPtr<nsIInterfaceRequestor> soc = nsContentUtils::SameOriginChecker();
     channel->SetNotificationCallbacks(soc);
 
     nsCOMPtr<nsIChannel> preflightChannel;
     nsTArray<nsCString> unsafeHeaders;
     unsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type"));
     rv = NS_StartCORSPreflight(channel,
-                               beaconListener,
-                               doc->NodePrincipal(),
+                               cors,
+                               principal,
                                true,
                                unsafeHeaders,
                                getter_AddRefs(preflightChannel));
   } else {
-    rv = channel->AsyncOpen2(beaconListener);
+    rv = channel->AsyncOpen(cors, nullptr);
   }
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return false;
   }
-  // make the beaconListener hold a strong reference to the loadgroup
-  // which is released in ::OnStartRequest
-  beaconListener->SetLoadGroup(loadGroup);
-
   return true;
 }
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 MediaDevices*
 Navigator::GetMediaDevices(ErrorResult& aRv)
 {
   if (!mMediaDevices) {
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -174,30 +174,18 @@ DoContentSecurityChecks(nsIURI* aURI, ns
       MOZ_ASSERT(!requestingContext ||
                  requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE,
                  "type_media requires requestingContext of type Element");
       break;
     }
 
     case nsIContentPolicy::TYPE_WEBSOCKET:
     case nsIContentPolicy::TYPE_CSP_REPORT:
-    case nsIContentPolicy::TYPE_XSLT: {
-      MOZ_ASSERT(false, "contentPolicyType not supported yet");
-      break;
-    }
-
-    case nsIContentPolicy::TYPE_BEACON: {
-      mimeTypeGuess = EmptyCString();
-      requestingContext = aLoadInfo->LoadingNode();
-      MOZ_ASSERT(!requestingContext ||
-                 requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
-                 "type_beacon requires requestingContext of type Document");
-      break;
-    }
-
+    case nsIContentPolicy::TYPE_XSLT:
+    case nsIContentPolicy::TYPE_BEACON:
     case nsIContentPolicy::TYPE_FETCH:
     case nsIContentPolicy::TYPE_IMAGESET: {
       MOZ_ASSERT(false, "contentPolicyType not supported yet");
       break;
     }
 
     default:
       // nsIContentPolicy::TYPE_INVALID