tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TrustedTypeUtils.cpp (41326B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/dom/TrustedTypeUtils.h"
      8 
      9 #include "js/RootingAPI.h"
     10 #include "mozilla/ErrorResult.h"
     11 #include "mozilla/Maybe.h"
     12 #include "mozilla/StaticPrefs_dom.h"
     13 #include "mozilla/dom/CSPViolationData.h"
     14 #include "mozilla/dom/Document.h"
     15 #include "mozilla/dom/ElementBinding.h"
     16 #include "mozilla/dom/HTMLScriptElementBinding.h"
     17 #include "mozilla/dom/PolicyContainer.h"
     18 #include "mozilla/dom/TrustedHTML.h"
     19 #include "mozilla/dom/TrustedScript.h"
     20 #include "mozilla/dom/TrustedScriptURL.h"
     21 #include "mozilla/dom/TrustedTypePolicy.h"
     22 #include "mozilla/dom/TrustedTypePolicyFactory.h"
     23 #include "mozilla/dom/TrustedTypesConstants.h"
     24 #include "mozilla/dom/UnionTypes.h"
     25 #include "mozilla/dom/WindowOrWorkerGlobalScopeBinding.h"
     26 #include "mozilla/dom/WorkerCommon.h"
     27 #include "mozilla/dom/WorkerPrivate.h"
     28 #include "mozilla/dom/WorkerRunnable.h"
     29 #include "mozilla/dom/WorkerScope.h"
     30 #include "mozilla/dom/nsCSPUtils.h"
     31 #include "mozilla/extensions/WebExtensionPolicy.h"
     32 #include "nsContentUtils.h"
     33 #include "nsGlobalWindowInner.h"
     34 #include "nsIContentSecurityPolicy.h"
     35 #include "nsLiteralString.h"
     36 #include "nsTArray.h"
     37 #include "xpcpublic.h"
     38 
     39 namespace mozilla::dom::TrustedTypeUtils {
     40 
     41 nsString GetTrustedTypeName(TrustedType aTrustedType) {
     42  switch (aTrustedType) {
     43    case TrustedType::TrustedHTML:
     44      return GetTrustedTypeName<TrustedHTML>();
     45      break;
     46    case TrustedType::TrustedScript:
     47      return GetTrustedTypeName<TrustedScript>();
     48      break;
     49    case TrustedType::TrustedScriptURL:
     50      return GetTrustedTypeName<TrustedScriptURL>();
     51      break;
     52  }
     53  MOZ_ASSERT_UNREACHABLE();
     54  return EmptyString();
     55 }
     56 
     57 namespace SinkTypeMismatch {
     58 
     59 static constexpr nsLiteralString kSampleSeparator = u"|"_ns;
     60 static constexpr nsLiteralString kFunctionAnonymousPrefix =
     61    u"function anonymous"_ns;
     62 static constexpr nsLiteralString kAsyncFunctionAnonymousPrefix =
     63    u"async function anonymous"_ns;
     64 static constexpr nsLiteralString kFunctionStarAnonymousPrefix =
     65    u"function* anonymous"_ns;
     66 static constexpr nsLiteralString kAsyncFunctionStarAnonymousPrefix =
     67    u"async function* anonymous"_ns;
     68 }  // namespace SinkTypeMismatch
     69 
     70 // Implement reporting of sink type mismatch violations.
     71 // https://w3c.github.io/trusted-types/dist/spec/#abstract-opdef-should-sink-type-mismatch-violation-be-blocked-by-content-security-policy
     72 void ReportSinkTypeMismatchViolations(nsIContentSecurityPolicy* aCSP,
     73                                      nsICSPEventListener* aCSPEventListener,
     74                                      const nsCString& aFileName,
     75                                      uint32_t aLine, uint32_t aColumn,
     76                                      const nsAString& aSink,
     77                                      const nsAString& aSinkGroup,
     78                                      const nsAString& aSource) {
     79  MOZ_ASSERT(aSinkGroup == kTrustedTypesOnlySinkGroup);
     80  MOZ_ASSERT(aCSP);
     81  MOZ_ASSERT(aCSP->GetRequireTrustedTypesForDirectiveState() !=
     82             RequireTrustedTypesForDirectiveState::NONE);
     83 
     84  uint32_t numPolicies = 0;
     85  aCSP->GetPolicyCount(&numPolicies);
     86 
     87  // First determine the trimmed sample to be used for violation reports.
     88  size_t startPos = 0;
     89  if (aSink.Equals(u"Function"_ns)) {
     90    auto sourceStartsWith = [&aSource, &startPos](const nsAString& aPrefix) {
     91      MOZ_ASSERT(startPos == 0);
     92      if (aSource.Length() >= aPrefix.Length() &&
     93          Substring(aSource, 0, aPrefix.Length()).Equals(aPrefix)) {
     94        startPos = aPrefix.Length();
     95        return true;
     96      }
     97      return false;
     98    };
     99    for (auto& prefix : {SinkTypeMismatch::kFunctionAnonymousPrefix,
    100                         SinkTypeMismatch::kAsyncFunctionAnonymousPrefix,
    101                         SinkTypeMismatch::kFunctionStarAnonymousPrefix,
    102                         SinkTypeMismatch::kAsyncFunctionStarAnonymousPrefix}) {
    103      if (sourceStartsWith(prefix)) {
    104        break;
    105      }
    106    }
    107  }
    108 
    109  const nsDependentSubstring trimmedSample =
    110      CSPViolationData::MaybeTruncateSample(Substring(aSource, startPos));
    111  const nsString sample =
    112      aSink + SinkTypeMismatch::kSampleSeparator + trimmedSample;
    113 
    114  for (uint32_t i = 0; i < numPolicies; ++i) {
    115    const auto* policy = aCSP->GetPolicy(i);
    116 
    117    if (!policy->AreTrustedTypesForSinkGroupRequired(aSinkGroup)) {
    118      continue;
    119    }
    120 
    121    CSPViolationData cspViolationData{
    122        i,
    123        CSPViolationData::Resource{
    124            CSPViolationData::BlockedContentSource::TrustedTypesSink},
    125        nsIContentSecurityPolicy::REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE,
    126        aFileName,
    127        aLine,
    128        aColumn,
    129        /* aElement */ nullptr,
    130        sample};
    131 
    132    aCSP->LogTrustedTypesViolationDetailsUnchecked(
    133        std::move(cspViolationData),
    134        NS_LITERAL_STRING_FROM_CSTRING(
    135            REQUIRE_TRUSTED_TYPES_FOR_SCRIPT_OBSERVER_TOPIC),
    136        aCSPEventListener);
    137  }
    138 }
    139 
    140 class LogSinkTypeMismatchViolationsRunnable final
    141    : public WorkerMainThreadRunnable {
    142 public:
    143  LogSinkTypeMismatchViolationsRunnable(WorkerPrivate* aWorker,
    144                                        const nsCString& aFileName,
    145                                        uint32_t aLine, uint32_t aColumn,
    146                                        const nsAString& aSink,
    147                                        const nsAString& aSinkGroup,
    148                                        const nsAString& aSource)
    149      : WorkerMainThreadRunnable(
    150            aWorker,
    151            "RuntimeService :: LogSinkTypeMismatchViolationsRunnable"_ns),
    152        mFileName(aFileName),
    153        mLine(aLine),
    154        mColumn(aColumn),
    155        mSink(aSink),
    156        mSinkGroup(aSinkGroup),
    157        mSource(aSource) {
    158    MOZ_ASSERT(aWorker);
    159  }
    160 
    161  virtual bool MainThreadRun() override {
    162    AssertIsOnMainThread();
    163    MOZ_ASSERT(mWorkerRef);
    164    if (nsIContentSecurityPolicy* csp = mWorkerRef->Private()->GetCsp()) {
    165      ReportSinkTypeMismatchViolations(
    166          csp, mWorkerRef->Private()->CSPEventListener(), mFileName, mLine,
    167          mColumn, mSink, mSinkGroup, mSource);
    168    }
    169    return true;
    170  }
    171 
    172 private:
    173  ~LogSinkTypeMismatchViolationsRunnable() = default;
    174  const nsCString& mFileName;
    175  uint32_t mLine;
    176  uint32_t mColumn;
    177  const nsString mSink;
    178  const nsString mSinkGroup;
    179  const nsString mSource;
    180 };
    181 
    182 constexpr size_t kNumArgumentsForDetermineTrustedTypePolicyValue = 2;
    183 
    184 template <typename ExpectedType>
    185 void ProcessValueWithADefaultPolicy(nsIGlobalObject& aGlobalObject,
    186                                    const nsAString& aInput,
    187                                    const nsAString& aSink,
    188                                    ExpectedType** aResult,
    189                                    ErrorResult& aError) {
    190  *aResult = nullptr;
    191 
    192  TrustedTypePolicyFactory* trustedTypePolicyFactory;
    193  if (nsPIDOMWindowInner* piDOMWindowInner = aGlobalObject.GetAsInnerWindow()) {
    194    nsGlobalWindowInner* globalWindowInner =
    195        nsGlobalWindowInner::Cast(piDOMWindowInner);
    196    trustedTypePolicyFactory = globalWindowInner->TrustedTypes();
    197  } else {
    198    MOZ_ASSERT(IsWorkerGlobal(aGlobalObject.GetGlobalJSObject()));
    199    MOZ_ASSERT(!NS_IsMainThread());
    200    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    201    WorkerGlobalScope* scope = workerPrivate->GlobalScope();
    202    trustedTypePolicyFactory = scope->TrustedTypes();
    203  }
    204 
    205  const RefPtr<TrustedTypePolicy> defaultPolicy =
    206      trustedTypePolicyFactory->GetDefaultPolicy();
    207  if (!defaultPolicy) {
    208    return;
    209  }
    210 
    211  JSContext* cx = nsContentUtils::GetCurrentJSContext();
    212  if (!cx) {
    213    return;
    214  }
    215 
    216  JS::Rooted<JS::Value> trustedTypeName{cx};
    217  using ExpectedTypeArg =
    218      std::remove_const_t<std::remove_reference_t<decltype(**aResult)>>;
    219  if (!xpc::NonVoidStringToJsval(cx, GetTrustedTypeName<ExpectedTypeArg>(),
    220                                 &trustedTypeName)) {
    221    aError.StealExceptionFromJSContext(cx);
    222    return;
    223  }
    224 
    225  JS::Rooted<JS::Value> sink{cx};
    226  if (!xpc::NonVoidStringToJsval(cx, aSink, &sink)) {
    227    aError.StealExceptionFromJSContext(cx);
    228    return;
    229  }
    230 
    231  AutoTArray<JS::Value, kNumArgumentsForDetermineTrustedTypePolicyValue>
    232      arguments = {trustedTypeName, sink};
    233 
    234  nsString policyValue;
    235  if constexpr (std::is_same_v<ExpectedTypeArg, TrustedHTML>) {
    236    RefPtr<CreateHTMLCallback> callbackObject =
    237        defaultPolicy->GetOptions().mCreateHTMLCallback;
    238    defaultPolicy->DetermineTrustedPolicyValue(
    239        callbackObject, aInput, arguments,
    240        /* aThrowIfMissing */ false, aError, policyValue);
    241  } else if constexpr (std::is_same_v<ExpectedTypeArg, TrustedScript>) {
    242    RefPtr<CreateScriptCallback> callbackObject =
    243        defaultPolicy->GetOptions().mCreateScriptCallback;
    244    defaultPolicy->DetermineTrustedPolicyValue(
    245        callbackObject, aInput, arguments,
    246        /* aThrowIfMissing */ false, aError, policyValue);
    247  } else {
    248    MOZ_ASSERT((std::is_same_v<ExpectedTypeArg, TrustedScriptURL>));
    249    RefPtr<CreateScriptURLCallback> callbackObject =
    250        defaultPolicy->GetOptions().mCreateScriptURLCallback;
    251    defaultPolicy->DetermineTrustedPolicyValue(
    252        callbackObject, aInput, arguments,
    253        /* aThrowIfMissing */ false, aError, policyValue);
    254  }
    255 
    256  if (aError.Failed()) {
    257    return;
    258  }
    259 
    260  if (policyValue.IsVoid()) {
    261    return;
    262  }
    263 
    264  MakeRefPtr<ExpectedType>(policyValue).forget(aResult);
    265 }
    266 
    267 // GetTrustedTypesCompliantString() and GetTrustedTypesCompliantAttributeValue()
    268 // deal with "trusted type or string" union types. These union types provide
    269 // inline methods Is*() and GetAs*() to test and access the actual value. The
    270 // following inline functions provide similar logic to conveniently deal with
    271 // the different union types.
    272 template <typename TrustedTypeOrStringArg>
    273 static inline bool IsString(const TrustedTypeOrStringArg& aInput) {
    274  if constexpr (
    275      std::is_same_v<TrustedTypeOrStringArg, TrustedHTMLOrString> ||
    276      std::is_same_v<TrustedTypeOrStringArg, TrustedScriptOrString> ||
    277      std::is_same_v<TrustedTypeOrStringArg, FunctionOrTrustedScriptOrString> ||
    278      std::is_same_v<TrustedTypeOrStringArg, TrustedScriptURLOrString> ||
    279      std::is_same_v<TrustedTypeOrStringArg, OwningTrustedScriptURLOrString> ||
    280      std::is_same_v<TrustedTypeOrStringArg,
    281                     TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString>) {
    282    return aInput.IsString();
    283  }
    284  if constexpr (std::is_same_v<TrustedTypeOrStringArg,
    285                               TrustedHTMLOrNullIsEmptyString> ||
    286                std::is_same_v<TrustedTypeOrStringArg,
    287                               TrustedScriptOrNullIsEmptyString>) {
    288    return aInput.IsNullIsEmptyString();
    289  }
    290  if constexpr (std::is_same_v<TrustedTypeOrStringArg,
    291                               TrustedScriptURLOrUSVString>) {
    292    return aInput.IsUSVString();
    293  }
    294  if constexpr (std::is_same_v<TrustedTypeOrStringArg, const nsAString*>) {
    295    (void)aInput;
    296    return true;
    297  }
    298  MOZ_ASSERT_UNREACHABLE();
    299  return false;
    300 }
    301 
    302 template <typename TrustedTypeOrStringArg>
    303 static inline const nsAString* GetAsString(
    304    const TrustedTypeOrStringArg& aInput) {
    305  if constexpr (
    306      std::is_same_v<TrustedTypeOrStringArg, TrustedHTMLOrString> ||
    307      std::is_same_v<TrustedTypeOrStringArg, TrustedScriptOrString> ||
    308      std::is_same_v<TrustedTypeOrStringArg, FunctionOrTrustedScriptOrString> ||
    309      std::is_same_v<TrustedTypeOrStringArg, TrustedScriptURLOrString> ||
    310      std::is_same_v<TrustedTypeOrStringArg, OwningTrustedScriptURLOrString> ||
    311      std::is_same_v<TrustedTypeOrStringArg,
    312                     TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString>) {
    313    return &aInput.GetAsString();
    314  }
    315  if constexpr (std::is_same_v<TrustedTypeOrStringArg,
    316                               TrustedHTMLOrNullIsEmptyString> ||
    317                std::is_same_v<TrustedTypeOrStringArg,
    318                               TrustedScriptOrNullIsEmptyString>) {
    319    return &aInput.GetAsNullIsEmptyString();
    320  }
    321  if constexpr (std::is_same_v<TrustedTypeOrStringArg,
    322                               TrustedScriptURLOrUSVString>) {
    323    return &aInput.GetAsUSVString();
    324  }
    325  if constexpr (std::is_same_v<TrustedTypeOrStringArg, const nsAString*>) {
    326    return aInput;
    327  }
    328  MOZ_ASSERT_UNREACHABLE();
    329  return &EmptyString();
    330 }
    331 
    332 template <typename TrustedTypeOrStringArg>
    333 static inline bool IsTrustedType(const TrustedTypeOrStringArg& aInput) {
    334  if constexpr (std::is_same_v<TrustedTypeOrStringArg, TrustedHTMLOrString> ||
    335                std::is_same_v<TrustedTypeOrStringArg,
    336                               TrustedHTMLOrNullIsEmptyString>) {
    337    return aInput.IsTrustedHTML();
    338  }
    339  if constexpr (std::is_same_v<TrustedTypeOrStringArg, TrustedScriptOrString> ||
    340                std::is_same_v<TrustedTypeOrStringArg,
    341                               FunctionOrTrustedScriptOrString> ||
    342                std::is_same_v<TrustedTypeOrStringArg,
    343                               TrustedScriptOrNullIsEmptyString>) {
    344    return aInput.IsTrustedScript();
    345  }
    346  if constexpr (std::is_same_v<TrustedTypeOrStringArg,
    347                               TrustedScriptURLOrString> ||
    348                std::is_same_v<TrustedTypeOrStringArg,
    349                               TrustedScriptURLOrUSVString> ||
    350                std::is_same_v<TrustedTypeOrStringArg,
    351                               OwningTrustedScriptURLOrString>) {
    352    return aInput.IsTrustedScriptURL();
    353  }
    354  if constexpr (std::is_same_v<TrustedTypeOrStringArg, const nsAString*>) {
    355    (void)aInput;
    356    return false;
    357  }
    358  MOZ_ASSERT_UNREACHABLE();
    359  return false;
    360 };
    361 
    362 template <typename TrustedTypeOrStringArg>
    363 static inline const nsAString* GetAsTrustedType(
    364    const TrustedTypeOrStringArg& aInput) {
    365  if constexpr (std::is_same_v<TrustedTypeOrStringArg, TrustedHTMLOrString> ||
    366                std::is_same_v<TrustedTypeOrStringArg,
    367                               TrustedHTMLOrNullIsEmptyString>) {
    368    return &aInput.GetAsTrustedHTML().mData;
    369  }
    370  if constexpr (std::is_same_v<TrustedTypeOrStringArg, TrustedScriptOrString> ||
    371                std::is_same_v<TrustedTypeOrStringArg,
    372                               FunctionOrTrustedScriptOrString> ||
    373                std::is_same_v<TrustedTypeOrStringArg,
    374                               TrustedScriptOrNullIsEmptyString>) {
    375    return &aInput.GetAsTrustedScript().mData;
    376  }
    377  if constexpr (std::is_same_v<TrustedTypeOrStringArg,
    378                               TrustedScriptURLOrString> ||
    379                std::is_same_v<TrustedTypeOrStringArg,
    380                               TrustedScriptURLOrUSVString>) {
    381    return &aInput.GetAsTrustedScriptURL().mData;
    382  }
    383  if constexpr (std::is_same_v<TrustedTypeOrStringArg,
    384                               OwningTrustedScriptURLOrString>) {
    385    return &aInput.GetAsTrustedScriptURL()->mData;
    386  }
    387  if constexpr (std::is_same_v<
    388                    TrustedTypeOrStringArg,
    389                    TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString>) {
    390    if (aInput.IsTrustedHTML()) {
    391      return &aInput.GetAsTrustedHTML().mData;
    392    }
    393    if (aInput.IsTrustedScript()) {
    394      return &aInput.GetAsTrustedScript().mData;
    395    }
    396    MOZ_ASSERT(aInput.IsTrustedScriptURL());
    397    return &aInput.GetAsTrustedScriptURL().mData;
    398  }
    399  (void)aInput;
    400  MOZ_ASSERT_UNREACHABLE();
    401  return &EmptyString();
    402 };
    403 
    404 template <typename TrustedTypeOrStringArg>
    405 static inline const nsAString* GetContent(
    406    const TrustedTypeOrStringArg& aInput) {
    407  return IsString(aInput) ? GetAsString(aInput) : GetAsTrustedType(aInput);
    408 }
    409 
    410 template <typename NodeOrGlobalObject>
    411 inline bool PrepareExecutionOfTrustedTypesDefaultPolicy(
    412    NodeOrGlobalObject& aNodeOrGlobalObject, nsIPrincipal* aPrincipalOrNull,
    413    nsIGlobalObject*& aGlobalObject, nsPIDOMWindowInner*& aPIDOMWindowInner,
    414    RequireTrustedTypesForDirectiveState* aRequireTrustedTypesForDirectiveState,
    415    ErrorResult& aError) {
    416  if (!StaticPrefs::dom_security_trusted_types_enabled()) {
    417    // A trusted type might've been created before the pref was set to `false`,
    418    // so we cannot assume aInput.IsString().
    419    return false;
    420  }
    421 
    422  // Exempt web extension content scripts from trusted types policies defined by
    423  // the page in which they are running.
    424  if (auto* principal = BasePrincipal::Cast(aPrincipalOrNull)) {
    425    if (principal->ContentScriptAddonPolicyCore()) {
    426      return false;
    427    }
    428  }
    429 
    430  // Below, we use fast paths when there are no require-trusted-types-for
    431  // directives. Note that the global object's CSP may differ from the
    432  // owner-document's one. E.g. when aDocument was created by
    433  // `document.implementation.createHTMLDocument` and it's not connected to a
    434  // browsing context.
    435  using NodeOrGlobalObjectArg = std::remove_const_t<
    436      std::remove_reference_t<decltype(aNodeOrGlobalObject)>>;
    437  nsIGlobalObject* globalObject = nullptr;
    438  nsPIDOMWindowInner* piDOMWindowInner = nullptr;
    439  if constexpr (std::is_same_v<NodeOrGlobalObjectArg, nsINode>) {
    440    if (aNodeOrGlobalObject.HasBeenInUAWidget()) {
    441      return false;
    442    }
    443    Document* ownerDoc = aNodeOrGlobalObject.OwnerDoc();
    444    const bool ownerDocLoadedAsData = ownerDoc->IsLoadedAsData();
    445    if (!ownerDoc->HasPolicyWithRequireTrustedTypesForDirective() &&
    446        !ownerDocLoadedAsData) {
    447      return false;
    448    }
    449    globalObject = ownerDoc->GetScopeObject();
    450    if (!globalObject) {
    451      aError.ThrowTypeError("No global object");
    452      return false;
    453    }
    454    piDOMWindowInner = globalObject->GetAsInnerWindow();
    455    if (!piDOMWindowInner) {
    456      // Global object is not a Window. This can happen when DOM APIs are used
    457      // in some contexts where Trusted Types don't apply (e.g. bug 1942517),
    458      // so just return the input string.
    459      return false;
    460    }
    461    if (ownerDocLoadedAsData && piDOMWindowInner->GetExtantDoc() &&
    462        !piDOMWindowInner->GetExtantDoc()
    463             ->HasPolicyWithRequireTrustedTypesForDirective()) {
    464      return false;
    465    }
    466  } else if constexpr (std::is_same_v<NodeOrGlobalObjectArg, nsIGlobalObject>) {
    467    piDOMWindowInner = aNodeOrGlobalObject.GetAsInnerWindow();
    468    if (piDOMWindowInner) {
    469      const Document* extantDoc = piDOMWindowInner->GetExtantDoc();
    470      if (extantDoc &&
    471          !extantDoc->HasPolicyWithRequireTrustedTypesForDirective()) {
    472        return false;
    473      }
    474    }
    475    globalObject = &aNodeOrGlobalObject;
    476  }
    477  MOZ_ASSERT(globalObject);
    478 
    479  // Now retrieve the CSP from the global object.
    480  // Because there is only one sink group, its associated
    481  // RequireTrustedTypesForDirectiveState actually provides the results of
    482  // "Does sink type require trusted types?"
    483  // (https://w3c.github.io/trusted-types/dist/spec/#abstract-opdef-does-sink-type-require-trusted-types)
    484  // and "Should sink type mismatch violation be blocked by CSP?"
    485  // (https://w3c.github.io/trusted-types/dist/spec/#should-block-sink-type-mismatch).
    486  RequireTrustedTypesForDirectiveState requireTrustedTypesForDirectiveState =
    487      RequireTrustedTypesForDirectiveState::NONE;
    488  if (piDOMWindowInner) {
    489    RefPtr<nsIContentSecurityPolicy> csp =
    490        PolicyContainer::GetCSP(piDOMWindowInner->GetPolicyContainer());
    491    if (!csp) {
    492      return false;
    493    }
    494    requireTrustedTypesForDirectiveState =
    495        csp->GetRequireTrustedTypesForDirectiveState();
    496    // The following assert is guaranteed by above calls to
    497    // HasPolicyWithRequireTrustedTypesForDirective.
    498    MOZ_ASSERT(requireTrustedTypesForDirectiveState !=
    499               RequireTrustedTypesForDirectiveState::NONE);
    500  } else if (IsWorkerGlobal(globalObject->GetGlobalJSObject())) {
    501    MOZ_ASSERT(!NS_IsMainThread());
    502    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    503    const mozilla::ipc::CSPInfo& cspInfo = workerPrivate->GetCSPInfo();
    504    requireTrustedTypesForDirectiveState =
    505        cspInfo.requireTrustedTypesForDirectiveState();
    506    if (requireTrustedTypesForDirectiveState ==
    507        RequireTrustedTypesForDirectiveState::NONE) {
    508      return false;
    509    }
    510  } else {
    511    // Global object is neither Window nor WorkerGlobalScope. This can happen
    512    // when DOM APIs are used in some contexts where Trusted Types don't apply
    513    // (e.g. bugs 1942517 and 1936219), so just return the input string.
    514    return false;
    515  }
    516 
    517  aGlobalObject = globalObject;
    518  aPIDOMWindowInner = piDOMWindowInner;
    519  *aRequireTrustedTypesForDirectiveState = requireTrustedTypesForDirectiveState;
    520  return true;
    521 }
    522 
    523 bool CanSkipTrustedTypesEnforcement(const nsINode& aNode) {
    524  nsIGlobalObject* dummyGlobal = nullptr;
    525  nsPIDOMWindowInner* dummyWindow = nullptr;
    526  RequireTrustedTypesForDirectiveState dummyState;
    527  // Specify a null principal, as ScriptElement::UpdateTrustWorthiness() has
    528  // already checked whether this is running in an isolated web extension
    529  // context.
    530  return !PrepareExecutionOfTrustedTypesDefaultPolicy(
    531      aNode, nullptr /* aPrincipalOrNull */, dummyGlobal, dummyWindow,
    532      &dummyState, IgnoreErrors());
    533 }
    534 
    535 template <typename ExpectedType, typename TrustedTypeOrString,
    536          typename NodeOrGlobalObject>
    537 MOZ_CAN_RUN_SCRIPT inline const nsAString* GetTrustedTypesCompliantString(
    538    const TrustedTypeOrString& aInput, const nsAString& aSink,
    539    const nsAString& aSinkGroup, NodeOrGlobalObject& aNodeOrGlobalObject,
    540    nsIPrincipal* aPrincipalOrNull, Maybe<nsAutoString>& aResultHolder,
    541    ErrorResult& aError) {
    542  MOZ_ASSERT(aSinkGroup == kTrustedTypesOnlySinkGroup);
    543 
    544  if (IsTrustedType(aInput)) {
    545    return GetAsTrustedType(aInput);
    546  }
    547 
    548  nsIGlobalObject* globalObject = nullptr;
    549  nsPIDOMWindowInner* piDOMWindowInner = nullptr;
    550  RequireTrustedTypesForDirectiveState requireTrustedTypesForDirectiveState;
    551  if (!PrepareExecutionOfTrustedTypesDefaultPolicy(
    552          aNodeOrGlobalObject, aPrincipalOrNull, globalObject, piDOMWindowInner,
    553          &requireTrustedTypesForDirectiveState, aError)) {
    554    return aError.Failed() ? nullptr : GetAsString(aInput);
    555  }
    556 
    557  RefPtr<ExpectedType> convertedInput;
    558  nsCOMPtr<nsIGlobalObject> pinnedGlobalObject = globalObject;
    559  ProcessValueWithADefaultPolicy<ExpectedType>(
    560      *pinnedGlobalObject, *GetAsString(aInput), aSink,
    561      getter_AddRefs(convertedInput), aError);
    562 
    563  if (aError.Failed()) {
    564    return nullptr;
    565  }
    566 
    567  if (!convertedInput) {
    568    auto location = JSCallingLocation::Get();
    569    if (piDOMWindowInner) {
    570      RefPtr<nsIContentSecurityPolicy> csp =
    571          PolicyContainer::GetCSP(piDOMWindowInner->GetPolicyContainer());
    572      ReportSinkTypeMismatchViolations(csp, nullptr /* aCSPEventListener */,
    573                                       location.FileName(), location.mLine,
    574                                       location.mColumn, aSink, aSinkGroup,
    575                                       *GetAsString(aInput));
    576    } else {
    577      MOZ_ASSERT(IsWorkerGlobal(globalObject->GetGlobalJSObject()));
    578      MOZ_ASSERT(!NS_IsMainThread());
    579      WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    580      RefPtr<LogSinkTypeMismatchViolationsRunnable> runnable =
    581          new LogSinkTypeMismatchViolationsRunnable(
    582              workerPrivate, location.FileName(), location.mLine,
    583              location.mColumn, aSink, aSinkGroup, *GetAsString(aInput));
    584      ErrorResult rv;
    585      runnable->Dispatch(workerPrivate, Killing, rv);
    586      if (NS_WARN_IF(rv.Failed())) {
    587        rv.SuppressException();
    588      }
    589    }
    590    if (requireTrustedTypesForDirectiveState ==
    591        RequireTrustedTypesForDirectiveState::REPORT_ONLY) {
    592      return GetAsString(aInput);
    593    }
    594 
    595    aError.ThrowTypeError("Sink type mismatch violation blocked by CSP"_ns);
    596    return nullptr;
    597  }
    598 
    599  aResultHolder = Some(convertedInput->mData);
    600  return aResultHolder.ptr();
    601 }
    602 
    603 #define IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(                          \
    604    _trustedTypeOrString, _expectedType, _nodeOrGlobalObject)             \
    605  const nsAString* GetTrustedTypesCompliantString(                        \
    606      const _trustedTypeOrString& aInput, const nsAString& aSink,         \
    607      const nsAString& aSinkGroup, _nodeOrGlobalObject& aNodeOrGlobal,    \
    608      nsIPrincipal* aPrincipalOrNull, Maybe<nsAutoString>& aResultHolder, \
    609      ErrorResult& aError) {                                              \
    610    return GetTrustedTypesCompliantString<_expectedType>(                 \
    611        aInput, aSink, aSinkGroup, aNodeOrGlobal, aPrincipalOrNull,       \
    612        aResultHolder, aError);                                           \
    613  }
    614 
    615 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedHTMLOrString, TrustedHTML,
    616                                        const nsINode);
    617 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedHTMLOrNullIsEmptyString,
    618                                        TrustedHTML, const nsINode);
    619 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedHTMLOrString, TrustedHTML,
    620                                        nsIGlobalObject);
    621 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedScriptOrString, TrustedScript,
    622                                        const nsINode);
    623 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedScriptOrNullIsEmptyString,
    624                                        TrustedScript, const nsINode);
    625 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(FunctionOrTrustedScriptOrString,
    626                                        TrustedScript, nsIGlobalObject);
    627 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedScriptURLOrString,
    628                                        TrustedScriptURL, const nsINode);
    629 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedScriptURLOrUSVString,
    630                                        TrustedScriptURL, nsIGlobalObject);
    631 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(TrustedScriptURLOrUSVString,
    632                                        TrustedScriptURL, const nsINode);
    633 IMPL_GET_TRUSTED_TYPES_COMPLIANT_STRING(OwningTrustedScriptURLOrString,
    634                                        TrustedScriptURL, nsIGlobalObject);
    635 
    636 MOZ_CAN_RUN_SCRIPT const nsAString*
    637 GetTrustedTypesCompliantStringForTrustedHTML(const nsAString& aInput,
    638                                             const nsAString& aSink,
    639                                             const nsAString& aSinkGroup,
    640                                             const nsINode& aNode,
    641                                             nsIPrincipal* aPrincipalOrNull,
    642                                             Maybe<nsAutoString>& aResultHolder,
    643                                             ErrorResult& aError) {
    644  return GetTrustedTypesCompliantString<TrustedHTML>(&aInput, aSink, aSinkGroup,
    645                                                     aNode, aPrincipalOrNull,
    646                                                     aResultHolder, aError);
    647 }
    648 
    649 MOZ_CAN_RUN_SCRIPT const nsAString*
    650 GetTrustedTypesCompliantStringForTrustedScript(
    651    const nsAString& aInput, const nsAString& aSink,
    652    const nsAString& aSinkGroup, nsIGlobalObject& aGlobalObject,
    653    nsIPrincipal* aPrincipalOrNull, Maybe<nsAutoString>& aResultHolder,
    654    ErrorResult& aError) {
    655  return GetTrustedTypesCompliantString<TrustedScript>(
    656      &aInput, aSink, aSinkGroup, aGlobalObject, aPrincipalOrNull,
    657      aResultHolder, aError);
    658 }
    659 
    660 MOZ_CAN_RUN_SCRIPT const nsAString*
    661 GetTrustedTypesCompliantStringForTrustedScript(
    662    const nsAString& aInput, const nsAString& aSink,
    663    const nsAString& aSinkGroup, const nsINode& aNode,
    664    Maybe<nsAutoString>& aResultHolder, ErrorResult& aError) {
    665  // Specify a null principal, as ScriptElement::UpdateTrustWorthiness() has
    666  // already checked whether this is running in an isolated web extension
    667  // context.
    668  return GetTrustedTypesCompliantString<TrustedScript>(
    669      &aInput, aSink, aSinkGroup, aNode, nullptr /* aPrincipalOrNull */,
    670      aResultHolder, aError);
    671 }
    672 
    673 bool GetTrustedTypeDataForAttribute(const nsAtom* aElementName,
    674                                    int32_t aElementNamespaceID,
    675                                    nsAtom* aAttributeName,
    676                                    int32_t aAttributeNamespaceID,
    677                                    TrustedType& aTrustedType,
    678                                    nsAString& aSink) {
    679  if (aElementNamespaceID != kNameSpaceID_XHTML &&
    680      aElementNamespaceID != kNameSpaceID_SVG &&
    681      aElementNamespaceID != kNameSpaceID_MathML) {
    682    return false;
    683  }
    684 
    685  // The spec is not really clear about which "event handler content attributes"
    686  // we should consider, so we just include everything but XUL's specific ones.
    687  // See https://github.com/w3c/trusted-types/issues/520.
    688  if (aAttributeNamespaceID == kNameSpaceID_None &&
    689      nsContentUtils::IsEventAttributeName(
    690          aAttributeName, EventNameType_All & ~EventNameType_XUL)) {
    691    aTrustedType = TrustedType::TrustedScript;
    692    aSink.AssignLiteral(u"Element ");
    693    aSink.Append(*aAttributeName);
    694    return true;
    695  }
    696  if (aElementNamespaceID == kNameSpaceID_XHTML) {
    697    if (aElementName == nsGkAtoms::iframe) {
    698      // HTMLIFrameElement
    699      if (aAttributeNamespaceID == kNameSpaceID_None &&
    700          aAttributeName == nsGkAtoms::srcdoc) {
    701        aTrustedType = TrustedType::TrustedHTML;
    702        aSink.AssignLiteral(u"HTMLIFrameElement srcdoc");
    703        return true;
    704      }
    705    } else if (aElementName == nsGkAtoms::script) {
    706      // HTMLScriptElement
    707      if (aAttributeNamespaceID == kNameSpaceID_None &&
    708          aAttributeName == nsGkAtoms::src) {
    709        aTrustedType = TrustedType::TrustedScriptURL;
    710        aSink.AssignLiteral(u"HTMLScriptElement src");
    711        return true;
    712      }
    713    }
    714  } else if (aElementNamespaceID == kNameSpaceID_SVG) {
    715    if (aElementName == nsGkAtoms::script) {
    716      // SVGScriptElement
    717      if ((aAttributeNamespaceID == kNameSpaceID_None ||
    718           aAttributeNamespaceID == kNameSpaceID_XLink) &&
    719          aAttributeName == nsGkAtoms::href) {
    720        aTrustedType = TrustedType::TrustedScriptURL;
    721        aSink.AssignLiteral(u"SVGScriptElement href");
    722        return true;
    723      }
    724    }
    725  }
    726 
    727  return false;
    728 }
    729 
    730 template <typename TrustedTypeOrStringArg>
    731 MOZ_CAN_RUN_SCRIPT const nsAString* GetTrustedTypesCompliantAttributeValue(
    732    const nsINode& aElement, nsAtom* aAttributeName,
    733    int32_t aAttributeNamespaceID, const TrustedTypeOrStringArg& aNewValue,
    734    nsIPrincipal* aPrincipalOrNull, Maybe<nsAutoString>& aResultHolder,
    735    ErrorResult& aError) {
    736  if (!StaticPrefs::dom_security_trusted_types_enabled()) {
    737    // A trusted type might've been created before the pref was set to `false`,
    738    // so we cannot assume aNewValue.IsString().
    739    return GetContent(aNewValue);
    740  }
    741 
    742  // In the common situation of non-data document without any
    743  // require-trusted-types-for directive, we just return immediately.
    744  const NodeInfo* nodeInfo = aElement.NodeInfo();
    745  Document* ownerDoc = nodeInfo->GetDocument();
    746  const bool ownerDocLoadedAsData = ownerDoc->IsLoadedAsData();
    747  if (!ownerDoc->HasPolicyWithRequireTrustedTypesForDirective() &&
    748      !ownerDocLoadedAsData) {
    749    return GetContent(aNewValue);
    750  }
    751 
    752  TrustedType expectedType;
    753  nsAutoString sink;
    754  if (!GetTrustedTypeDataForAttribute(
    755          nodeInfo->NameAtom(), nodeInfo->NamespaceID(), aAttributeName,
    756          aAttributeNamespaceID, expectedType, sink)) {
    757    return GetContent(aNewValue);
    758  }
    759 
    760  if constexpr (std::is_same_v<
    761                    TrustedTypeOrStringArg,
    762                    TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString>) {
    763    if ((expectedType == TrustedType::TrustedHTML &&
    764         aNewValue.IsTrustedHTML()) ||
    765        (expectedType == TrustedType::TrustedScript &&
    766         aNewValue.IsTrustedScript()) ||
    767        (expectedType == TrustedType::TrustedScriptURL &&
    768         aNewValue.IsTrustedScriptURL())) {
    769      return GetAsTrustedType(aNewValue);
    770    }
    771  } else {
    772    MOZ_ASSERT((std::is_same_v<TrustedTypeOrStringArg, const nsAString*>));
    773  }
    774 
    775  const nsAString* input = GetContent(aNewValue);
    776  switch (expectedType) {
    777    case TrustedType::TrustedHTML:
    778      return GetTrustedTypesCompliantString<TrustedHTML>(
    779          input, sink, kTrustedTypesOnlySinkGroup, aElement, aPrincipalOrNull,
    780          aResultHolder, aError);
    781    case TrustedType::TrustedScript:
    782      return GetTrustedTypesCompliantString<TrustedScript>(
    783          input, sink, kTrustedTypesOnlySinkGroup, aElement, aPrincipalOrNull,
    784          aResultHolder, aError);
    785    case TrustedType::TrustedScriptURL:
    786      return GetTrustedTypesCompliantString<TrustedScriptURL>(
    787          input, sink, kTrustedTypesOnlySinkGroup, aElement, aPrincipalOrNull,
    788          aResultHolder, aError);
    789  }
    790  MOZ_ASSERT_UNREACHABLE();
    791  return nullptr;
    792 }
    793 
    794 MOZ_CAN_RUN_SCRIPT const nsAString* GetTrustedTypesCompliantAttributeValue(
    795    const nsINode& aElement, nsAtom* aAttributeName,
    796    int32_t aAttributeNamespaceID,
    797    const TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString& aNewValue,
    798    nsIPrincipal* aPrincipalOrNull, Maybe<nsAutoString>& aResultHolder,
    799    ErrorResult& aError) {
    800  return GetTrustedTypesCompliantAttributeValue<
    801      TrustedHTMLOrTrustedScriptOrTrustedScriptURLOrString>(
    802      aElement, aAttributeName, aAttributeNamespaceID, aNewValue,
    803      aPrincipalOrNull, aResultHolder, aError);
    804 }
    805 
    806 MOZ_CAN_RUN_SCRIPT const nsAString* GetTrustedTypesCompliantAttributeValue(
    807    const nsINode& aElement, nsAtom* aAttributeName,
    808    int32_t aAttributeNamespaceID, const nsAString& aNewValue,
    809    nsIPrincipal* aPrincipalOrNull, Maybe<nsAutoString>& aResultHolder,
    810    ErrorResult& aError) {
    811  return GetTrustedTypesCompliantAttributeValue<const nsAString*>(
    812      aElement, aAttributeName, aAttributeNamespaceID, &aNewValue,
    813      aPrincipalOrNull, aResultHolder, aError);
    814 }
    815 
    816 bool HostGetCodeForEval(JSContext* aCx, JS::Handle<JSObject*> aCode,
    817                        JS::MutableHandle<JSString*> aOutCode) {
    818  JS::Rooted<JSObject*> obj(aCx, aCode);
    819  TrustedScript* trustedScript;
    820  if (StaticPrefs::dom_security_trusted_types_enabled() &&
    821      NS_SUCCEEDED(UNWRAP_OBJECT(TrustedScript, &obj, trustedScript))) {
    822    if (JSString* copy = JS_NewUCStringCopyZ(aCx, trustedScript->mData.get())) {
    823      aOutCode.set(copy);
    824      return true;
    825    }
    826    return false;
    827  }
    828  aOutCode.set(nullptr);
    829  return true;
    830 }
    831 
    832 bool AreArgumentsTrustedForEnsureCSPDoesNotBlockStringCompilation(
    833    JSContext* aCx, JS::Handle<JSString*> aCodeString,
    834    JS::CompilationType aCompilationType,
    835    JS::Handle<JS::StackGCVector<JSString*>> aParameterStrings,
    836    JS::Handle<JSString*> aBodyString,
    837    JS::Handle<JS::StackGCVector<JS::Value>> aParameterArgs,
    838    JS::Handle<JS::Value> aBodyArg, nsIPrincipal* aPrincipalOrNull,
    839    ErrorResult& aError) {
    840  // EnsureCSPDoesNotBlockStringCompilation is essentially HTML's implementation
    841  // of HostEnsureCanCompileStrings, so we only consider the cases described in
    842  // the Dynamic Code Brand Checks spec. The algorithm is also supposed to be
    843  // called for "TIMER" too but in that case it does not execute the specific
    844  // part implemented in the present method (step 2).
    845  // https://html.spec.whatwg.org/multipage/webappapis.html#hostensurecancompilestrings(realm,-parameterstrings,-bodystring,-codestring,-compilationtype,-parameterargs,-bodyarg)
    846  // https://tc39.es/proposal-dynamic-code-brand-checks/#sec-hostensurecancompilestrings
    847  // https://html.spec.whatwg.org/#timer-initialisation-steps
    848  if (!StaticPrefs::dom_security_trusted_types_enabled() ||
    849      aCompilationType == JS::CompilationType::Undefined) {
    850    return true;
    851  }
    852 
    853  // https://html.spec.whatwg.org/multipage/webappapis.html#hostensurecancompilestrings(realm,-parameterstrings,-bodystring,-codestring,-compilationtype,-parameterargs,-bodyarg)
    854  // https://w3c.github.io/webappsec-csp/#can-compile-strings
    855  nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
    856  if (!global) {
    857    aError.Throw(NS_ERROR_NULL_POINTER);
    858    return false;
    859  }
    860 
    861  // Exit early for some cases where GetTrustedTypesCompliantString
    862  // would have no effect on aCodeString.
    863  if (nsPIDOMWindowInner* piDOMWindowInner = global->GetAsInnerWindow()) {
    864    const Document* extantDoc = piDOMWindowInner->GetExtantDoc();
    865    if (extantDoc &&
    866        !extantDoc->HasPolicyWithRequireTrustedTypesForDirective()) {
    867      return true;
    868    }
    869  } else {
    870    JSObject* globalJSObject = global->GetGlobalJSObject();
    871    if (!globalJSObject || !IsWorkerGlobal(globalJSObject)) {
    872      // Global object is neither a Window not a WorkerGlobalScope, this can
    873      // happen in some contexts where Trusted Types don't apply (chrome JS
    874      // globals) so just treat arguments as trusted.
    875      return true;
    876    }
    877    MOZ_ASSERT(!NS_IsMainThread());
    878    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    879    const mozilla::ipc::CSPInfo& cspInfo = workerPrivate->GetCSPInfo();
    880    if (cspInfo.requireTrustedTypesForDirectiveState() ==
    881        RequireTrustedTypesForDirectiveState::NONE) {
    882      return true;
    883    }
    884  }
    885 
    886  // Steps 2.2 - 2.4.
    887  bool isTrusted = true;
    888  auto isArgumentTrusted = [&aCx](JS::Handle<JS::Value> aValue,
    889                                  JS::Handle<JSString*> aString,
    890                                  ErrorResult& aError) {
    891    if (!aValue.isObject()) {
    892      return false;
    893    }
    894    JS::Rooted<JSObject*> object(aCx, &aValue.toObject());
    895    TrustedScript* trustedScript;
    896    if (NS_FAILED(UNWRAP_OBJECT(TrustedScript, &object, trustedScript))) {
    897      return false;
    898    }
    899    nsAutoJSString jsString;
    900    if (NS_WARN_IF(!jsString.init(aCx, aString))) {
    901      aError.StealExceptionFromJSContext(aCx);
    902      return false;
    903    }
    904    return jsString.Equals(trustedScript->mData);
    905  };
    906  if (aCompilationType == JS::CompilationType::DirectEval ||
    907      aCompilationType == JS::CompilationType::IndirectEval) {
    908    // The following assertions are guanranteed by the steps of PerformEval.
    909    MOZ_ASSERT(aParameterArgs.empty());
    910    MOZ_ASSERT(aParameterStrings.empty());
    911    MOZ_ASSERT(aBodyString);
    912    MOZ_ASSERT(aBodyArg.isString() || aBodyArg.isObject());
    913    isTrusted = aBodyArg.isObject();
    914 #ifdef DEBUG
    915    bool trusted = isArgumentTrusted(aBodyArg, aBodyString, aError);
    916    if (aError.Failed()) {
    917      return false;
    918    }
    919    // The following assertion is guaranteed by the HTML implementation of
    920    // HostGetCodeForEval.
    921    MOZ_ASSERT(isTrusted == trusted);
    922 #endif
    923  } else {
    924    MOZ_ASSERT(aCompilationType == JS::CompilationType::Function);
    925    if (aBodyString) {
    926      isTrusted = isArgumentTrusted(aBodyArg, aBodyString, aError);
    927      if (aError.Failed()) {
    928        return false;
    929      }
    930    }
    931    if (isTrusted) {
    932      MOZ_ASSERT(aParameterArgs.length() == aParameterStrings.length());
    933      for (size_t index = 0; index < aParameterArgs.length(); index++) {
    934        isTrusted = isArgumentTrusted(aParameterArgs[index],
    935                                      aParameterStrings[index], aError);
    936        if (aError.Failed()) {
    937          return false;
    938        }
    939        if (!isTrusted) {
    940          break;
    941        }
    942      }
    943    }
    944  }
    945 
    946  // If successful, the steps below always ends up with sourceString ==
    947  // codeString. Moreover if isTrusted == true, passing a new TrustedScript to
    948  // GetTrustedTypesCompliantStringForTrustedScript would just return codeString
    949  // immediately, so we can skip all these steps.
    950  if (isTrusted) {
    951    return true;
    952  }
    953 
    954  // Steps 2.5 - 2.6.
    955  nsAutoJSString codeString;
    956  if (NS_WARN_IF(!codeString.init(aCx, aCodeString))) {
    957    aError.StealExceptionFromJSContext(aCx);
    958    return false;
    959  }
    960 
    961  Maybe<nsAutoString> compliantStringHolder;
    962  constexpr nsLiteralString evalSink = u"eval"_ns;
    963  constexpr nsLiteralString functionSink = u"Function"_ns;
    964  nsCOMPtr<nsIGlobalObject> pinnedGlobal = global;
    965  const nsAString* compliantString =
    966      dom::TrustedTypeUtils::GetTrustedTypesCompliantStringForTrustedScript(
    967          codeString,
    968          aCompilationType == JS::CompilationType::Function ? functionSink
    969                                                            : evalSink,
    970          kTrustedTypesOnlySinkGroup, *pinnedGlobal, aPrincipalOrNull,
    971          compliantStringHolder, aError);
    972 
    973  // Step 2.7-2.8.
    974  // Callers will take care of throwing an EvalError when we return false.
    975  if (aError.Failed()) {
    976    aError.SuppressException();
    977    return false;
    978  }
    979  return compliantString->Equals(codeString);
    980 }
    981 
    982 MOZ_CAN_RUN_SCRIPT const nsAString*
    983 GetConvertedScriptSourceForPreNavigationCheck(
    984    nsIGlobalObject& aGlobalObject, const nsAString& aEncodedScriptSource,
    985    const nsAString& aSink, Maybe<nsAutoString>& aResultHolder,
    986    ErrorResult& aError) {
    987  RefPtr<TrustedScript> convertedScriptSource;
    988  nsCOMPtr<nsIGlobalObject> pinnedGlobalObject = &aGlobalObject;
    989  ProcessValueWithADefaultPolicy<TrustedScript>(
    990      *pinnedGlobalObject, aEncodedScriptSource, aSink,
    991      getter_AddRefs(convertedScriptSource), aError);
    992 
    993  // If that algorithm threw an error or convertedScriptSource is not a
    994  // TrustedScript object, return "Blocked" and abort further steps.
    995  if (aError.Failed()) {
    996    return nullptr;
    997  }
    998  if (!convertedScriptSource) {
    999    aError.ThrowTypeError("Pre-Navigation check Blocked"_ns);
   1000    return nullptr;
   1001  }
   1002 
   1003  aResultHolder = Some(convertedScriptSource->mData);
   1004  return aResultHolder.ptr();
   1005 }
   1006 
   1007 }  // namespace mozilla::dom::TrustedTypeUtils