Bug 1551379: Allow non linkable about: pages to skip CORS when loading local module scripts. r=smaug
authorChristoph Kerschbaumer <ckerschb@christophkerschbaumer.com>
Mon, 20 May 2019 15:59:28 +0000
changeset 474547 768599bb59656539a33ade81980a49601adb5c0f
parent 474546 4a73759aafa6f3168453b2765f9b13e5fdc640d3
child 474548 158eb97dfd5e6b18f6a13cbf4e648b361deb1a41
push id36042
push userdvarga@mozilla.com
push dateTue, 21 May 2019 04:19:40 +0000
treeherdermozilla-central@ca560ff55451 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1551379
milestone69.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 1551379: Allow non linkable about: pages to skip CORS when loading local module scripts. r=smaug Differential Revision: https://phabricator.services.mozilla.com/D31514
dom/script/ScriptLoader.cpp
dom/script/ScriptLoader.h
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -25,16 +25,17 @@
 #include "nsIContent.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/SRILogHelper.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/StaticPrefs.h"
+#include "nsAboutProtocolUtils.h"
 #include "nsGkAtoms.h"
 #include "nsNetUtil.h"
 #include "nsGlobalWindowInner.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
@@ -333,16 +334,60 @@ nsresult ScriptLoader::CheckContentPolic
       return NS_ERROR_CONTENT_BLOCKED;
     }
     return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
   }
 
   return NS_OK;
 }
 
+/* static */
+bool ScriptLoader::IsAboutPageLoadingChromeURI(ScriptLoadRequest* aRequest) {
+  // if we are not dealing with a codebasePrincipal it can not be a
+  // Principal with a scheme of about: and there is nothing left to do
+  if (!aRequest->TriggeringPrincipal()->GetIsCodebasePrincipal()) {
+    return false;
+  }
+
+  // if the triggering uri is not of scheme about:, there is nothing to do
+  nsCOMPtr<nsIURI> triggeringURI;
+  nsresult rv =
+      aRequest->TriggeringPrincipal()->GetURI(getter_AddRefs(triggeringURI));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  bool isAbout =
+      (NS_SUCCEEDED(triggeringURI->SchemeIs("about", &isAbout)) && isAbout);
+  if (!isAbout) {
+    return false;
+  }
+
+  // if the about: page is linkable from content, there is nothing to do
+  nsCOMPtr<nsIAboutModule> aboutMod;
+  rv = NS_GetAboutModule(triggeringURI, getter_AddRefs(aboutMod));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  uint32_t aboutModuleFlags = 0;
+  rv = aboutMod->GetURIFlags(triggeringURI, &aboutModuleFlags);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  if (aboutModuleFlags & nsIAboutModule::MAKE_LINKABLE) {
+    return false;
+  }
+
+  // if the uri to be loaded is not of scheme chrome:, there is nothing to do.
+  bool isChrome =
+      (NS_SUCCEEDED(aRequest->mURI->SchemeIs("chrome", &isChrome)) && isChrome);
+  if (!isChrome) {
+    return false;
+  }
+
+  // seems like an about page wants to load a chrome URI.
+  return true;
+}
+
 bool ScriptLoader::ModuleMapContainsURL(nsIURI* aURL) const {
   // Returns whether we have fetched, or are currently fetching, a module script
   // for a URL.
   return mFetchingModules.Contains(aURL) || mFetchedModules.Contains(aURL);
 }
 
 bool ScriptLoader::IsFetchingModule(ModuleLoadRequest* aRequest) const {
   bool fetching = mFetchingModules.Contains(aRequest->mURI);
@@ -1235,24 +1280,29 @@ nsresult ScriptLoader::StartLoad(ScriptL
   nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow();
   NS_ENSURE_TRUE(window, NS_ERROR_NULL_POINTER);
   nsIDocShell* docshell = window->GetDocShell();
   nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
 
   nsSecurityFlags securityFlags;
   if (aRequest->IsModuleRequest()) {
     // According to the spec, module scripts have different behaviour to classic
-    // scripts and always use CORS.
-    securityFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
-    if (aRequest->CORSMode() == CORS_NONE ||
-        aRequest->CORSMode() == CORS_ANONYMOUS) {
-      securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
+    // scripts and always use CORS. Only exception: Non linkable about: pages
+    // which load local module scripts.
+    if (IsAboutPageLoadingChromeURI(aRequest)) {
+      securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
     } else {
-      MOZ_ASSERT(aRequest->CORSMode() == CORS_USE_CREDENTIALS);
-      securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
+      securityFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
+      if (aRequest->CORSMode() == CORS_NONE ||
+          aRequest->CORSMode() == CORS_ANONYMOUS) {
+        securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
+      } else {
+        MOZ_ASSERT(aRequest->CORSMode() == CORS_USE_CREDENTIALS);
+        securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
+      }
     }
   } else {
     securityFlags = aRequest->CORSMode() == CORS_NONE
                         ? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL
                         : nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
     if (aRequest->CORSMode() == CORS_ANONYMOUS) {
       securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
     } else if (aRequest->CORSMode() == CORS_USE_CREDENTIALS) {
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -383,16 +383,25 @@ class ScriptLoader final : public nsISup
   /**
    * Helper function to check the content policy for a given request.
    */
   static nsresult CheckContentPolicy(Document* aDocument, nsISupports* aContext,
                                      const nsAString& aType,
                                      ScriptLoadRequest* aRequest);
 
   /**
+   * Helper function to determine whether an about: page loads a chrome: URI.
+   * Please note that this function only returns true if:
+   *   * the about: page uses a CodeBasePrincipal with scheme about:
+   *   * the about: page is not linkable from content
+   *     (e.g. the function will return false for about:blank or about:srcdoc)
+   */
+  static bool IsAboutPageLoadingChromeURI(ScriptLoadRequest* aRequest);
+
+  /**
    * Start a load for aRequest's URI.
    */
   nsresult StartLoad(ScriptLoadRequest* aRequest);
 
   /**
    * Abort the current stream, and re-start with a new load request from scratch
    * without requesting any alternate data. Returns NS_BINDING_RETARGETED on
    * success, as this error code is used to abort the input stream.