Bug 1622042 - Refactor NsContentUtils:Allowsl10n r=ckerschb
authorSebastian Streich <sstreich@mozilla.com>
Thu, 26 Mar 2020 13:18:40 +0000
changeset 520553 a266e7a5a2e1b5141b42f635d93eb6604849e345
parent 520552 ac0d06c0ca9330d5356717094910e977cf8f6c29
child 520554 9fb3f7cd8f275e9b82c01d292aab5ca34237f05d
push id37253
push usernerli@mozilla.com
push dateThu, 26 Mar 2020 21:36:52 +0000
treeherdermozilla-central@c644dd16e2cc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs1622042
milestone76.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 1622042 - Refactor NsContentUtils:Allowsl10n r=ckerschb Differential Revision: https://phabricator.services.mozilla.com/D66633
caps/BasePrincipal.cpp
caps/BasePrincipal.h
caps/nsIPrincipal.idl
dom/base/Document.cpp
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/security/nsContentSecurityManager.cpp
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -483,16 +483,61 @@ BasePrincipal::IsSameOrigin(nsIURI* aURI
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   if (!ssm) {
     return NS_ERROR_UNEXPECTED;
   }
   *aRes = NS_SUCCEEDED(
       ssm->CheckSameOriginURI(prinURI, aURI, false, aIsPrivateWin));
   return NS_OK;
 }
+
+NS_IMETHODIMP
+BasePrincipal::IsL10nAllowed(nsIURI* aURI, bool* aRes) {
+  *aRes = false;
+
+  if (nsContentUtils::IsErrorPage(aURI)) {
+    *aRes = true;
+    return NS_OK;
+  }
+
+  // The system principal is always allowed.
+  if (IsSystemPrincipal()) {
+    *aRes = true;
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = GetURI(getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, NS_OK);
+
+  bool hasFlags;
+
+  // Allow access to uris that cannot be loaded by web content.
+  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD,
+                           &hasFlags);
+  NS_ENSURE_SUCCESS(rv, NS_OK);
+  if (hasFlags) {
+    *aRes = true;
+    return NS_OK;
+  }
+
+  // UI resources also get access.
+  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
+                           &hasFlags);
+  NS_ENSURE_SUCCESS(rv, NS_OK);
+  if (hasFlags) {
+    *aRes = true;
+    return NS_OK;
+  }
+
+  auto policy = AddonPolicy();
+  *aRes = (policy && policy->IsPrivileged());
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 BasePrincipal::AllowsRelaxStrictFileOriginPolicy(nsIURI* aURI, bool* aRes) {
   *aRes = false;
   nsCOMPtr<nsIURI> prinURI;
   nsresult rv = GetURI(getter_AddRefs(prinURI));
   if (NS_FAILED(rv) || !prinURI) {
     return NS_OK;
   }
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -117,16 +117,17 @@ class BasePrincipal : public nsJSPrincip
                                        uint64_t innerWindowID) final;
   NS_IMETHOD GetAddonPolicy(nsISupports** aResult) final;
   NS_IMETHOD GetIsNullPrincipal(bool* aResult) override;
   NS_IMETHOD GetIsContentPrincipal(bool* aResult) override;
   NS_IMETHOD GetIsExpandedPrincipal(bool* aResult) override;
   NS_IMETHOD GetIsSystemPrincipal(bool* aResult) override;
   NS_IMETHOD SchemeIs(const char* aScheme, bool* aResult) override;
   NS_IMETHOD IsURIInPrefList(const char* aPref, bool* aResult) override;
+  NS_IMETHOD IsL10nAllowed(nsIURI* aURI, bool* aResult) override;
   NS_IMETHOD GetAboutModuleFlags(uint32_t* flags) override;
   NS_IMETHOD GetIsAddonOrExpandedAddonPrincipal(bool* aResult) override;
   NS_IMETHOD GetOriginAttributes(JSContext* aCx,
                                  JS::MutableHandle<JS::Value> aVal) final;
   NS_IMETHOD GetAsciiSpec(nsACString& aSpec) override;
   NS_IMETHOD GetExposablePrePath(nsACString& aResult) override;
   NS_IMETHOD GetExposableSpec(nsACString& aSpec) override;
   NS_IMETHOD GetHostPort(nsACString& aRes) override;
--- a/caps/nsIPrincipal.idl
+++ b/caps/nsIPrincipal.idl
@@ -457,16 +457,23 @@ interface nsIPrincipal : nsISerializable
     [infallible] readonly attribute boolean isOnion;
 
     /*
      * Returns true if the Domain Policy allows js execution
      * for the Principals URI
      */
     readonly attribute boolean isScriptAllowedByPolicy;
 
+
+     /*
+     * Returns true if the Principal can acess l10n 
+     * features for the Provided DocumentURI
+     */
+    boolean isL10nAllowed(in nsIURI aDocumentURI);
+     
     /**
      * Returns if the principal is for an IP address.
      */
     [infallible] readonly attribute boolean isIpAddress;
 };
 
 /**
  * If SystemPrincipal is too risky to use, but we want a principal to access
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -3869,18 +3869,20 @@ void Document::InitializeLocalization(ns
 }
 
 DocumentL10n* Document::GetL10n() { return mDocumentL10n; }
 
 bool Document::DocumentSupportsL10n(JSContext* aCx, JSObject* aObject) {
   nsCOMPtr<nsIPrincipal> callerPrincipal =
       nsContentUtils::SubjectPrincipal(aCx);
   nsGlobalWindowInner* win = xpc::WindowOrNull(aObject);
-  return nsContentUtils::PrincipalAllowsL10n(
-      *callerPrincipal, win ? win->GetDocumentURI() : nullptr);
+  bool allowed = false;
+  callerPrincipal->IsL10nAllowed(win ? win->GetDocumentURI() : nullptr,
+                                 &allowed);
+  return allowed;
 }
 
 void Document::LocalizationLinkAdded(Element* aLinkElement) {
   if (!AllowsL10n()) {
     return;
   }
 
   nsAutoString href;
@@ -3979,18 +3981,19 @@ void Document::InitialDocumentTranslatio
 
   nsXULPrototypeDocument* proto = GetPrototype();
   if (proto) {
     proto->SetIsL10nCached();
   }
 }
 
 bool Document::AllowsL10n() const {
-  return nsContentUtils::PrincipalAllowsL10n(*NodePrincipal(),
-                                             GetDocumentURI());
+  bool allowed = false;
+  NodePrincipal()->IsL10nAllowed(GetDocumentURI(), &allowed);
+  return allowed;
 }
 
 bool Document::IsWebAnimationsEnabled(JSContext* aCx, JSObject* /*unused*/) {
   MOZ_ASSERT(NS_IsMainThread());
 
   return nsContentUtils::IsSystemCaller(aCx) ||
          StaticPrefs::dom_animations_api_core_enabled();
 }
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -1714,73 +1714,34 @@ bool nsContentUtils::OfflineAppAllowed(n
   if (!updateService) {
     return false;
   }
 
   bool allowed;
   nsresult rv = updateService->OfflineAppAllowed(aPrincipal, &allowed);
   return NS_SUCCEEDED(rv) && allowed;
 }
-
-static bool IsErrorPage(nsIURI* aURI) {
+// Static
+bool nsContentUtils::IsErrorPage(nsIURI* aURI) {
   if (!aURI) {
     return false;
   }
 
   if (!aURI->SchemeIs("about")) {
     return false;
   }
 
   nsAutoCString name;
   nsresult rv = NS_GetAboutModuleName(aURI, name);
   NS_ENSURE_SUCCESS(rv, false);
 
   return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") ||
          name.EqualsLiteral("blocked");
 }
 
-/* static */
-bool nsContentUtils::PrincipalAllowsL10n(nsIPrincipal& aPrincipal,
-                                         nsIURI* aDocumentURI) {
-  if (IsErrorPage(aDocumentURI)) {
-    return true;
-  }
-
-  // The system principal is always allowed.
-  if (aPrincipal.IsSystemPrincipal()) {
-    return true;
-  }
-
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = aPrincipal.GetURI(getter_AddRefs(uri));
-  NS_ENSURE_SUCCESS(rv, false);
-
-  bool hasFlags;
-
-  // Allow access to uris that cannot be loaded by web content.
-  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD,
-                           &hasFlags);
-  NS_ENSURE_SUCCESS(rv, false);
-  if (hasFlags) {
-    return true;
-  }
-
-  // UI resources also get access.
-  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
-                           &hasFlags);
-  NS_ENSURE_SUCCESS(rv, false);
-  if (hasFlags) {
-    return true;
-  }
-
-  auto& principal = BasePrincipal::Cast(aPrincipal);
-  auto policy = principal.AddonPolicy();
-  return (policy && policy->IsPrivileged());
-}
-
 // static
 void nsContentUtils::Shutdown() {
   sInitialized = false;
 
   nsHTMLTags::ReleaseTable();
 
   NS_IF_RELEASE(sContentPolicyService);
   sTriedToGetContentPolicy = false;
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -232,16 +232,17 @@ class nsContentUtils {
   static bool IsFuzzingEnabled()
 #ifndef FUZZING
   {
     return false;
   }
 #else
       ;
 #endif
+  static bool IsErrorPage(nsIURI* aURI);
 
   static bool IsCallerChromeOrFuzzingEnabled(JSContext* aCx, JSObject*) {
     return ThreadsafeIsSystemCaller(aCx) || IsFuzzingEnabled();
   }
 
   static bool IsCallerChromeOrElementTransformGettersEnabled(JSContext* aCx,
                                                              JSObject*);
 
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -282,21 +282,21 @@ static bool IsImageLoadInEditorAppType(n
 
 static nsresult DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) {
   // In practice, these DTDs are just used for localization, so applying the
   // same principal check as Fluent.
   if (aLoadInfo->InternalContentPolicyType() ==
       nsIContentPolicy::TYPE_INTERNAL_DTD) {
     RefPtr<Document> doc;
     aLoadInfo->GetLoadingDocument(getter_AddRefs(doc));
-    return nsContentUtils::PrincipalAllowsL10n(
-               *aLoadInfo->TriggeringPrincipal(),
-               doc ? doc->GetDocumentURI() : nullptr)
-               ? NS_OK
-               : NS_ERROR_DOM_BAD_URI;
+    bool allowed = false;
+    aLoadInfo->TriggeringPrincipal()->IsL10nAllowed(
+        doc ? doc->GetDocumentURI() : nullptr, &allowed);
+
+    return allowed ? NS_OK : NS_ERROR_DOM_BAD_URI;
   }
 
   // This is used in order to allow a privileged DOMParser to parse documents
   // that need to access localization DTDs. We just allow through
   // TYPE_INTERNAL_FORCE_ALLOWED_DTD no matter what the triggering principal is.
   if (aLoadInfo->InternalContentPolicyType() ==
       nsIContentPolicy::TYPE_INTERNAL_FORCE_ALLOWED_DTD) {
     return NS_OK;