Bug 1182537 - Use channel->ascynOpen2 in dom/base/Navigator.cpp (r=sicking,bz)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Mon, 27 Jul 2015 20:39:17 -0700
changeset 287172 a110782901107a9c9d7c9a38120554df3a71336b
parent 287171 9a5f4793b17fb8df0f1b3b2d5bee606968b270b4
child 287173 dc7fa51079ad659350332e63cb44e4d6d8d402b8
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)
reviewerssicking, bz
bugs1182537
milestone42.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 1182537 - Use channel->ascynOpen2 in dom/base/Navigator.cpp (r=sicking,bz)
dom/base/Navigator.cpp
dom/security/nsContentSecurityManager.cpp
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -62,26 +62,23 @@
 #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
@@ -101,17 +98,16 @@
 
 #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
@@ -1038,32 +1034,42 @@ Navigator::GetGeolocation(ErrorResult& a
   return mGeolocation;
 }
 
 class BeaconStreamListener final : public nsIStreamListener
 {
     ~BeaconStreamListener() {}
 
   public:
-    BeaconStreamListener() {}
+    BeaconStreamListener() : mLoadGroup(nullptr) {}
+
+    void SetLoadGroup(nsILoadGroup* aLoadGroup) {
+      mLoadGroup = aLoadGroup;
+    }
 
     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)
@@ -1110,99 +1116,44 @@ Navigator::SendBeacon(const nsAString& a
                   aUrl,
                   doc,
                   doc->GetDocBaseURI());
   if (NS_FAILED(rv)) {
     aRv.Throw(NS_ERROR_DOM_URL_MISMATCH_ERR);
     return false;
   }
 
-  // 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
+  // Explicitly disallow loading data: URIs
+  bool isDataScheme = false;
+  rv = uri->SchemeIs("data", &isDataScheme);
+  if (NS_FAILED(rv) || isDataScheme) {
     aRv.Throw(NS_ERROR_CONTENT_BLOCKED);
     return false;
   }
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannel(getter_AddRefs(channel),
                      uri,
                      doc,
-                     nsILoadInfo::SEC_NORMAL,
+                     nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
                      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)) {
@@ -1279,27 +1230,28 @@ Navigator::SendBeacon(const nsAString& a
     p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
   }
 
   nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
   if (cos) {
     cos->AddClassFlags(nsIClassOfService::Background);
   }
 
-  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);
+  // 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();
 
   // 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) &&
@@ -1309,28 +1261,32 @@ 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,
-                               cors,
-                               principal,
+                               beaconListener,
+                               doc->NodePrincipal(),
                                true,
                                unsafeHeaders,
                                getter_AddRefs(preflightChannel));
   } else {
-    rv = channel->AsyncOpen(cors, nullptr);
+    rv = channel->AsyncOpen2(beaconListener);
   }
   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
@@ -151,18 +151,30 @@ 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:
-    case nsIContentPolicy::TYPE_BEACON:
+    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_FETCH:
     case nsIContentPolicy::TYPE_IMAGESET: {
       MOZ_ASSERT(false, "contentPolicyType not supported yet");
       break;
     }
 
     default:
       // nsIContentPolicy::TYPE_INVALID