tor-browser

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

BasePrincipal.cpp (45652B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 sw=2 et 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/BasePrincipal.h"
      8 
      9 #include "nsDocShell.h"
     10 
     11 #include "ExpandedPrincipal.h"
     12 #include "nsNetUtil.h"
     13 #include "nsContentUtils.h"
     14 #include "nsIOService.h"
     15 #include "nsIURIWithSpecialOrigin.h"
     16 #include "nsScriptSecurityManager.h"
     17 #include "nsServiceManagerUtils.h"
     18 #include "nsAboutProtocolUtils.h"
     19 #include "ThirdPartyUtil.h"
     20 #include "mozilla/ContentPrincipal.h"
     21 #include "mozilla/ExtensionPolicyService.h"
     22 #include "mozilla/NullPrincipal.h"
     23 #include "mozilla/dom/BlobURLProtocolHandler.h"
     24 #include "mozilla/dom/ChromeUtils.h"
     25 #include "mozilla/dom/ReferrerInfo.h"
     26 #include "mozilla/dom/ToJSValue.h"
     27 #include "mozilla/dom/nsMixedContentBlocker.h"
     28 #include "mozilla/Components.h"
     29 #include "mozilla/dom/StorageUtils.h"
     30 #include "mozilla/dom/StorageUtils.h"
     31 #include "mozilla/JSONStringWriteFuncs.h"
     32 #include "mozilla/JSONWriter.h"
     33 #include "nsIEffectiveTLDService.h"
     34 #include "nsIURL.h"
     35 #include "nsIURIMutator.h"
     36 #include "mozilla/StaticPrefs_permissions.h"
     37 #include "nsIURIMutator.h"
     38 #include "nsMixedContentBlocker.h"
     39 #include "prnetdb.h"
     40 #include "nsIURIFixup.h"
     41 #include "mozilla/dom/StorageUtils.h"
     42 #include "mozilla/StorageAccess.h"
     43 #include "nsPIDOMWindow.h"
     44 #include "nsIURIMutator.h"
     45 #include "mozilla/PermissionManager.h"
     46 
     47 #include "nsSerializationHelper.h"
     48 
     49 #include "js/JSON.h"
     50 #include "ContentPrincipalJSONHandler.h"
     51 #include "ExpandedPrincipalJSONHandler.h"
     52 #include "NullPrincipalJSONHandler.h"
     53 #include "PrincipalJSONHandler.h"
     54 #include "SubsumedPrincipalJSONHandler.h"
     55 
     56 namespace mozilla {
     57 
     58 BasePrincipal::BasePrincipal(PrincipalKind aKind,
     59                             const nsACString& aOriginNoSuffix,
     60                             const OriginAttributes& aOriginAttributes)
     61    : mOriginNoSuffix(NS_Atomize(aOriginNoSuffix)),
     62      mOriginSuffix(aOriginAttributes.CreateSuffixAtom()),
     63      mOriginAttributes(aOriginAttributes),
     64      mKind(aKind),
     65      mHasExplicitDomain(false) {}
     66 
     67 BasePrincipal::BasePrincipal(BasePrincipal* aOther,
     68                             const OriginAttributes& aOriginAttributes)
     69    : mOriginNoSuffix(aOther->mOriginNoSuffix),
     70      mOriginSuffix(aOriginAttributes.CreateSuffixAtom()),
     71      mOriginAttributes(aOriginAttributes),
     72      mKind(aOther->mKind),
     73      mHasExplicitDomain(aOther->mHasExplicitDomain.load()) {}
     74 
     75 BasePrincipal::~BasePrincipal() = default;
     76 
     77 NS_IMETHODIMP
     78 BasePrincipal::GetOrigin(nsACString& aOrigin) {
     79  nsresult rv = GetOriginNoSuffix(aOrigin);
     80  NS_ENSURE_SUCCESS(rv, rv);
     81 
     82  nsAutoCString suffix;
     83  rv = GetOriginSuffix(suffix);
     84  NS_ENSURE_SUCCESS(rv, rv);
     85  aOrigin.Append(suffix);
     86  return NS_OK;
     87 }
     88 
     89 NS_IMETHODIMP
     90 BasePrincipal::GetWebExposedOriginSerialization(nsACString& aOrigin) {
     91  aOrigin.Truncate();
     92  nsCOMPtr<nsIURI> prinURI;
     93  nsresult rv = GetURI(getter_AddRefs(prinURI));
     94  if (NS_FAILED(rv) || !prinURI) {
     95    return NS_ERROR_NOT_AVAILABLE;
     96  }
     97  return nsContentUtils::GetWebExposedOriginSerialization(prinURI, aOrigin);
     98 }
     99 
    100 NS_IMETHODIMP
    101 BasePrincipal::GetHostPort(nsACString& aRes) {
    102  aRes.Truncate();
    103  nsCOMPtr<nsIURI> prinURI;
    104  nsresult rv = GetURI(getter_AddRefs(prinURI));
    105  if (NS_FAILED(rv) || !prinURI) {
    106    return NS_OK;
    107  }
    108  return prinURI->GetHostPort(aRes);
    109 }
    110 
    111 NS_IMETHODIMP
    112 BasePrincipal::GetHost(nsACString& aRes) {
    113  aRes.Truncate();
    114  nsCOMPtr<nsIURI> prinURI;
    115  nsresult rv = GetURI(getter_AddRefs(prinURI));
    116  if (NS_FAILED(rv) || !prinURI) {
    117    return NS_OK;
    118  }
    119  return prinURI->GetHost(aRes);
    120 }
    121 
    122 NS_IMETHODIMP
    123 BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) {
    124  mOriginNoSuffix->ToUTF8String(aOrigin);
    125  return NS_OK;
    126 }
    127 
    128 NS_IMETHODIMP
    129 BasePrincipal::GetSiteOrigin(nsACString& aSiteOrigin) {
    130  nsresult rv = GetSiteOriginNoSuffix(aSiteOrigin);
    131  NS_ENSURE_SUCCESS(rv, rv);
    132 
    133  nsAutoCString suffix;
    134  rv = GetOriginSuffix(suffix);
    135  NS_ENSURE_SUCCESS(rv, rv);
    136  aSiteOrigin.Append(suffix);
    137  return NS_OK;
    138 }
    139 
    140 NS_IMETHODIMP
    141 BasePrincipal::GetSiteOriginNoSuffix(nsACString& aSiteOrigin) {
    142  return GetOriginNoSuffix(aSiteOrigin);
    143 }
    144 
    145 template <typename HandlerTypesT>
    146 bool ContainerPrincipalJSONHandler<HandlerTypesT>::ProcessInnerResult(
    147    bool aResult) {
    148  if (!aResult) {
    149    NS_WARNING("Failed to parse inner object");
    150    mState = State::Error;
    151    return false;
    152  }
    153  return true;
    154 }
    155 
    156 template <typename HandlerTypesT>
    157 bool ContainerPrincipalJSONHandler<HandlerTypesT>::startObject() {
    158  if (mInnerHandler.isSome()) {
    159    return CallOnInner([&](auto& aInner) { return aInner.startObject(); });
    160  }
    161 
    162  switch (mState) {
    163    case State::Init:
    164      mState = State::StartObject;
    165      break;
    166    case State::SystemPrincipal_Key:
    167      mState = State::SystemPrincipal_StartObject;
    168      break;
    169    default:
    170      NS_WARNING("Unexpected object value");
    171      mState = State::Error;
    172      return false;
    173  }
    174 
    175  return true;
    176 }
    177 
    178 template <typename HandlerTypesT>
    179 bool ContainerPrincipalJSONHandler<HandlerTypesT>::propertyName(
    180    const JS::Latin1Char* name, size_t length) {
    181  if (mInnerHandler.isSome()) {
    182    return CallOnInner(
    183        [&](auto& aInner) { return aInner.propertyName(name, length); });
    184  }
    185 
    186  switch (mState) {
    187    case State::StartObject: {
    188      if (length != 1) {
    189        NS_WARNING(
    190            nsPrintfCString("Unexpected property name length: %zu", length)
    191                .get());
    192        mState = State::Error;
    193        return false;
    194      }
    195 
    196      char key = char(name[0]);
    197      switch (key) {
    198        case BasePrincipal::NullPrincipalKey:
    199          mState = State::NullPrincipal_Inner;
    200          mInnerHandler.emplace(VariantType<NullPrincipalJSONHandler>());
    201          break;
    202        case BasePrincipal::ContentPrincipalKey:
    203          mState = State::ContentPrincipal_Inner;
    204          mInnerHandler.emplace(VariantType<ContentPrincipalJSONHandler>());
    205          break;
    206        case BasePrincipal::SystemPrincipalKey:
    207          mState = State::SystemPrincipal_Key;
    208          break;
    209        default:
    210          if constexpr (CanContainExpandedPrincipal) {
    211            if (key == BasePrincipal::ExpandedPrincipalKey) {
    212              mState = State::ExpandedPrincipal_Inner;
    213              mInnerHandler.emplace(
    214                  VariantType<ExpandedPrincipalJSONHandler>());
    215              break;
    216            }
    217          }
    218          NS_WARNING(
    219              nsPrintfCString("Unexpected property name: '%c'", key).get());
    220          mState = State::Error;
    221          return false;
    222      }
    223      break;
    224    }
    225    default:
    226      NS_WARNING("Unexpected property name");
    227      mState = State::Error;
    228      return false;
    229  }
    230 
    231  return true;
    232 }
    233 
    234 template <typename HandlerTypesT>
    235 bool ContainerPrincipalJSONHandler<HandlerTypesT>::endObject() {
    236  if (mInnerHandler.isSome()) {
    237    return CallOnInner([&](auto& aInner) {
    238      if (!aInner.endObject()) {
    239        return false;
    240      }
    241      if (aInner.HasAccepted()) {
    242        this->mPrincipal = aInner.mPrincipal.forget();
    243        MOZ_ASSERT(this->mPrincipal);
    244        mInnerHandler.reset();
    245      }
    246      return true;
    247    });
    248  }
    249 
    250  switch (mState) {
    251    case State::SystemPrincipal_StartObject:
    252      mState = State::SystemPrincipal_EndObject;
    253      break;
    254    case State::SystemPrincipal_EndObject:
    255      this->mPrincipal =
    256          BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal());
    257      mState = State::EndObject;
    258      break;
    259    case State::NullPrincipal_Inner:
    260      mState = State::EndObject;
    261      break;
    262    case State::ContentPrincipal_Inner:
    263      mState = State::EndObject;
    264      break;
    265    default:
    266      if constexpr (CanContainExpandedPrincipal) {
    267        if (mState == State::ExpandedPrincipal_Inner) {
    268          mState = State::EndObject;
    269          break;
    270        }
    271      }
    272      NS_WARNING("Unexpected end of object");
    273      mState = State::Error;
    274      return false;
    275  }
    276 
    277  return true;
    278 }
    279 
    280 template <typename HandlerTypesT>
    281 bool ContainerPrincipalJSONHandler<HandlerTypesT>::startArray() {
    282  if constexpr (CanContainExpandedPrincipal) {
    283    if (mInnerHandler.isSome()) {
    284      return CallOnInner([&](auto& aInner) { return aInner.startArray(); });
    285    }
    286  }
    287 
    288  NS_WARNING("Unexpected array value");
    289  mState = State::Error;
    290  return false;
    291 }
    292 
    293 template <typename HandlerTypesT>
    294 bool ContainerPrincipalJSONHandler<HandlerTypesT>::endArray() {
    295  if constexpr (CanContainExpandedPrincipal) {
    296    if (mInnerHandler.isSome()) {
    297      return CallOnInner([&](auto& aInner) { return aInner.endArray(); });
    298    }
    299  }
    300 
    301  NS_WARNING("Unexpected array value");
    302  mState = State::Error;
    303  return false;
    304 }
    305 
    306 template <typename HandlerTypesT>
    307 bool ContainerPrincipalJSONHandler<HandlerTypesT>::stringValue(
    308    const JS::Latin1Char* str, size_t length) {
    309  if (mInnerHandler.isSome()) {
    310    return CallOnInner(
    311        [&](auto& aInner) { return aInner.stringValue(str, length); });
    312  }
    313 
    314  NS_WARNING("Unexpected string value");
    315  mState = State::Error;
    316  return false;
    317 }
    318 
    319 template class ContainerPrincipalJSONHandler<PrincipalJSONHandlerTypes>;
    320 template class ContainerPrincipalJSONHandler<SubsumedPrincipalJSONHandlerTypes>;
    321 
    322 // Takes a JSON string and parses it turning it into a principal of the
    323 // corresponding type
    324 //
    325 // Given a content principal:
    326 //
    327 //                               inner JSON object
    328 //                                      |
    329 //       ---------------------------------------------------------
    330 //       |                                                       |
    331 // {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}}
    332 //   |     |             |             |            |
    333 //   |     -----------------------------            |
    334 //   |              |    |                          |
    335 // PrincipalKind    |    |                          |
    336 //                  |    ----------------------------
    337 //           SerializableKeys           |
    338 //                                    Value
    339 //
    340 already_AddRefed<BasePrincipal> BasePrincipal::FromJSON(
    341    const nsACString& aJSON) {
    342  PrincipalJSONHandler handler;
    343 
    344  if (!JS::ParseJSONWithHandler(
    345          reinterpret_cast<const JS::Latin1Char*>(aJSON.BeginReading()),
    346          aJSON.Length(), &handler)) {
    347    NS_WARNING(
    348        nsPrintfCString("Unable to parse: %s", aJSON.BeginReading()).get());
    349    MOZ_ASSERT(false,
    350               "Unable to parse string as JSON to deserialize as a principal");
    351    return nullptr;
    352  }
    353 
    354  return handler.Get();
    355 }
    356 
    357 // Returns a JSON representation of the principal.
    358 // Calling BasePrincipal::FromJSON will deserialize the JSON into
    359 // the corresponding principal type.
    360 nsresult BasePrincipal::ToJSON(nsACString& aJSON) {
    361  MOZ_ASSERT(aJSON.IsEmpty(), "ToJSON only supports an empty result input");
    362  aJSON.Truncate();
    363 
    364  // NOTE: JSONWriter emits raw UTF-8 code units for non-ASCII range.
    365  JSONStringRefWriteFunc func(aJSON);
    366  JSONWriter writer(func, JSONWriter::CollectionStyle::SingleLineStyle);
    367 
    368  nsresult rv = ToJSON(writer);
    369  NS_ENSURE_SUCCESS(rv, rv);
    370 
    371  return NS_OK;
    372 }
    373 
    374 nsresult BasePrincipal::ToJSON(JSONWriter& aWriter) {
    375  static_assert(eKindMax < std::size(JSONEnumKeyStrings));
    376 
    377  aWriter.Start(JSONWriter::CollectionStyle::SingleLineStyle);
    378 
    379  nsresult rv = WriteJSONProperties(aWriter);
    380  NS_ENSURE_SUCCESS(rv, rv);
    381 
    382  aWriter.End();
    383 
    384  return NS_OK;
    385 }
    386 
    387 nsresult BasePrincipal::WriteJSONProperties(JSONWriter& aWriter) {
    388  aWriter.StartObjectProperty(JSONEnumKeyStrings[Kind()],
    389                              JSONWriter::CollectionStyle::SingleLineStyle);
    390 
    391  nsresult rv = WriteJSONInnerProperties(aWriter);
    392  NS_ENSURE_SUCCESS(rv, rv);
    393 
    394  aWriter.EndObject();
    395 
    396  return NS_OK;
    397 }
    398 
    399 nsresult BasePrincipal::WriteJSONInnerProperties(JSONWriter& aWriter) {
    400  return NS_OK;
    401 }
    402 
    403 bool BasePrincipal::FastSubsumesIgnoringFPD(
    404    nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) {
    405  MOZ_ASSERT(aOther);
    406 
    407  if (Kind() == eContentPrincipal &&
    408      !dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
    409          mOriginAttributes, Cast(aOther)->mOriginAttributes)) {
    410    return false;
    411  }
    412 
    413  return SubsumesInternal(aOther, aConsideration);
    414 }
    415 
    416 bool BasePrincipal::Subsumes(nsIPrincipal* aOther,
    417                             DocumentDomainConsideration aConsideration) {
    418  MOZ_ASSERT(aOther);
    419  MOZ_ASSERT_IF(Kind() == eContentPrincipal, mOriginSuffix);
    420 
    421  // Expanded principals handle origin attributes for each of their
    422  // sub-principals individually, null principals do only simple checks for
    423  // pointer equality, and system principals are immune to origin attributes
    424  // checks, so only do this check for content principals.
    425  if (Kind() == eContentPrincipal &&
    426      mOriginSuffix != Cast(aOther)->mOriginSuffix) {
    427    return false;
    428  }
    429 
    430  return SubsumesInternal(aOther, aConsideration);
    431 }
    432 
    433 NS_IMETHODIMP
    434 BasePrincipal::Equals(nsIPrincipal* aOther, bool* aResult) {
    435  NS_ENSURE_ARG_POINTER(aOther);
    436 
    437  *aResult = FastEquals(aOther);
    438 
    439  return NS_OK;
    440 }
    441 
    442 NS_IMETHODIMP
    443 BasePrincipal::EqualsForPermission(nsIPrincipal* aOther, bool aExactHost,
    444                                   bool* aResult) {
    445  *aResult = false;
    446  NS_ENSURE_ARG_POINTER(aOther);
    447  NS_ENSURE_ARG_POINTER(aResult);
    448 
    449  auto* other = Cast(aOther);
    450  if (Kind() != other->Kind()) {
    451    // Principals of different kinds can't be equal.
    452    return NS_OK;
    453  }
    454 
    455  if (Kind() == eSystemPrincipal) {
    456    *aResult = this == other;
    457    return NS_OK;
    458  }
    459 
    460  if (Kind() == eNullPrincipal) {
    461    // We don't store permissions for NullPrincipals.
    462    return NS_OK;
    463  }
    464 
    465  MOZ_ASSERT(Kind() == eExpandedPrincipal || Kind() == eContentPrincipal);
    466 
    467  // Certain origin attributes should not be used to isolate permissions.
    468  // Create a stripped copy of both OA sets to compare.
    469  mozilla::OriginAttributes ourAttrs = mOriginAttributes;
    470  PermissionManager::MaybeStripOriginAttributes(false, ourAttrs);
    471  mozilla::OriginAttributes theirAttrs = aOther->OriginAttributesRef();
    472  PermissionManager::MaybeStripOriginAttributes(false, theirAttrs);
    473 
    474  if (ourAttrs != theirAttrs) {
    475    return NS_OK;
    476  }
    477 
    478  if (mOriginNoSuffix == other->mOriginNoSuffix) {
    479    *aResult = true;
    480    return NS_OK;
    481  }
    482 
    483  // If we are matching with an exact host, we're done now - the permissions
    484  // don't match otherwise, we need to start comparing subdomains!
    485  if (aExactHost) {
    486    return NS_OK;
    487  }
    488 
    489  nsCOMPtr<nsIURI> ourURI;
    490  nsresult rv = GetURI(getter_AddRefs(ourURI));
    491  NS_ENSURE_SUCCESS(rv, rv);
    492  // Some principal types may indicate success, but still return nullptr for
    493  // URI.
    494  NS_ENSURE_TRUE(ourURI, NS_ERROR_FAILURE);
    495 
    496  nsCOMPtr<nsIURI> otherURI;
    497  rv = other->GetURI(getter_AddRefs(otherURI));
    498  NS_ENSURE_SUCCESS(rv, rv);
    499  NS_ENSURE_TRUE(otherURI, NS_ERROR_FAILURE);
    500 
    501  // Compare schemes
    502  nsAutoCString otherScheme;
    503  rv = otherURI->GetScheme(otherScheme);
    504  NS_ENSURE_SUCCESS(rv, rv);
    505 
    506  nsAutoCString ourScheme;
    507  rv = ourURI->GetScheme(ourScheme);
    508  NS_ENSURE_SUCCESS(rv, rv);
    509 
    510  if (otherScheme != ourScheme) {
    511    return NS_OK;
    512  }
    513 
    514  // Compare ports
    515  int32_t otherPort;
    516  rv = otherURI->GetPort(&otherPort);
    517  NS_ENSURE_SUCCESS(rv, rv);
    518 
    519  int32_t ourPort;
    520  rv = ourURI->GetPort(&ourPort);
    521  NS_ENSURE_SUCCESS(rv, rv);
    522 
    523  if (otherPort != ourPort) {
    524    return NS_OK;
    525  }
    526 
    527  // Check if the host or any subdomain of their host matches.
    528  nsAutoCString otherHost;
    529  rv = otherURI->GetHost(otherHost);
    530  if (NS_FAILED(rv) || otherHost.IsEmpty()) {
    531    return NS_OK;
    532  }
    533 
    534  nsAutoCString ourHost;
    535  rv = ourURI->GetHost(ourHost);
    536  if (NS_FAILED(rv) || ourHost.IsEmpty()) {
    537    return NS_OK;
    538  }
    539 
    540  nsCOMPtr<nsIEffectiveTLDService> tldService =
    541      mozilla::components::EffectiveTLD::Service();
    542  if (!tldService) {
    543    NS_ERROR("Should have a tld service!");
    544    return NS_ERROR_FAILURE;
    545  }
    546 
    547  // This loop will not loop forever, as GetNextSubDomain will eventually fail
    548  // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
    549  while (otherHost != ourHost) {
    550    rv = tldService->GetNextSubDomain(otherHost, otherHost);
    551    if (NS_FAILED(rv)) {
    552      if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
    553        return NS_OK;
    554      }
    555      return rv;
    556    }
    557  }
    558 
    559  *aResult = true;
    560  return NS_OK;
    561 }
    562 
    563 NS_IMETHODIMP
    564 BasePrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
    565  NS_ENSURE_ARG_POINTER(aOther);
    566 
    567  *aResult = FastEqualsConsideringDomain(aOther);
    568 
    569  return NS_OK;
    570 }
    571 
    572 NS_IMETHODIMP
    573 BasePrincipal::EqualsURI(nsIURI* aOtherURI, bool* aResult) {
    574  *aResult = false;
    575  nsCOMPtr<nsIURI> prinURI;
    576  nsresult rv = GetURI(getter_AddRefs(prinURI));
    577  if (NS_FAILED(rv) || !prinURI) {
    578    return NS_OK;
    579  }
    580  return prinURI->EqualsExceptRef(aOtherURI, aResult);
    581 }
    582 
    583 NS_IMETHODIMP
    584 BasePrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) {
    585  NS_ENSURE_ARG_POINTER(aOther);
    586 
    587  *aResult = FastSubsumes(aOther);
    588 
    589  return NS_OK;
    590 }
    591 
    592 NS_IMETHODIMP
    593 BasePrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
    594  NS_ENSURE_ARG_POINTER(aOther);
    595 
    596  *aResult = FastSubsumesConsideringDomain(aOther);
    597 
    598  return NS_OK;
    599 }
    600 
    601 NS_IMETHODIMP
    602 BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther,
    603                                                    bool* aResult) {
    604  NS_ENSURE_ARG_POINTER(aOther);
    605 
    606  *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
    607 
    608  return NS_OK;
    609 }
    610 
    611 NS_IMETHODIMP
    612 BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aAllowIfInheritsPrincipal) {
    613  return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, false, 0);
    614 }
    615 
    616 NS_IMETHODIMP
    617 BasePrincipal::CheckMayLoadWithReporting(nsIURI* aURI,
    618                                         bool aAllowIfInheritsPrincipal,
    619                                         uint64_t aInnerWindowID) {
    620  AssertIsOnMainThread();
    621  return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, true,
    622                            aInnerWindowID);
    623 }
    624 
    625 nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
    626                                           bool aAllowIfInheritsPrincipal,
    627                                           bool aReport,
    628                                           uint64_t aInnerWindowID) {
    629  NS_ENSURE_ARG_POINTER(aURI);
    630  MOZ_ASSERT(
    631      aReport || aInnerWindowID == 0,
    632      "Why do we have an inner window id if we're not supposed to report?");
    633  MOZ_ASSERT(!aReport || NS_IsMainThread(), "Must be on main thread to report");
    634 
    635  // Check the internal method first, which allows us to quickly approve loads
    636  // for the System Principal.
    637  if (MayLoadInternal(aURI)) {
    638    return NS_OK;
    639  }
    640 
    641  nsresult rv;
    642  if (aAllowIfInheritsPrincipal) {
    643    // If the caller specified to allow loads of URIs that inherit
    644    // our principal, allow the load if this URI inherits its principal.
    645    bool doesInheritSecurityContext;
    646    rv = NS_URIChainHasFlags(aURI,
    647                             nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
    648                             &doesInheritSecurityContext);
    649    if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
    650      return NS_OK;
    651    }
    652  }
    653 
    654  // Get the principal uri for the WebExtension access check or error.
    655  nsCOMPtr<nsIURI> prinURI;
    656  rv = GetURI(getter_AddRefs(prinURI));
    657  if (!(NS_SUCCEEDED(rv) && prinURI)) {
    658    return NS_ERROR_DOM_BAD_URI;
    659  }
    660 
    661  // If the URL being loaded corresponds to a WebExtension URL, ask the policy
    662  // if the path should be accessible.
    663  bool isWebExtensionResource;
    664  rv = NS_URIChainHasFlags(aURI,
    665                           nsIProtocolHandler::URI_IS_WEBEXTENSION_RESOURCE,
    666                           &isWebExtensionResource);
    667  if (NS_SUCCEEDED(rv) && isWebExtensionResource) {
    668    extensions::URLInfo urlInfo(aURI);
    669    if (RefPtr<extensions::WebExtensionPolicyCore> urlPolicyCore =
    670            ExtensionPolicyService::GetCoreByURL(urlInfo)) {
    671      extensions::URLInfo prinUrlInfo(prinURI);
    672      if (urlPolicyCore->SourceMayAccessPath(prinUrlInfo, urlInfo.FilePath())) {
    673        return NS_OK;
    674      }
    675    }
    676  }
    677 
    678  if (aReport) {
    679    // FIXME: Once bug 1900706 is complete, reporting can be updated to work
    680    // off-main-thread.
    681    nsScriptSecurityManager::ReportError("CheckSameOriginError", prinURI, aURI,
    682                                         mOriginAttributes.IsPrivateBrowsing(),
    683                                         aInnerWindowID);
    684  }
    685 
    686  return NS_ERROR_DOM_BAD_URI;
    687 }
    688 
    689 NS_IMETHODIMP
    690 BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) {
    691  if (IsSystemPrincipal() || (AddonPolicyCore() && AddonAllowsLoad(aURI))) {
    692    *aRes = false;
    693    return NS_OK;
    694  }
    695 
    696  *aRes = true;
    697  // If we do not have a URI its always 3rd party.
    698  nsCOMPtr<nsIURI> prinURI;
    699  nsresult rv = GetURI(getter_AddRefs(prinURI));
    700  if (NS_FAILED(rv) || !prinURI) {
    701    return NS_OK;
    702  }
    703  ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
    704  return thirdPartyUtil->IsThirdPartyURI(prinURI, aURI, aRes);
    705 }
    706 
    707 NS_IMETHODIMP
    708 BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal* aPrin, bool* aRes) {
    709  *aRes = true;
    710  nsCOMPtr<nsIURI> prinURI;
    711  nsresult rv = GetURI(getter_AddRefs(prinURI));
    712  if (NS_FAILED(rv) || !prinURI) {
    713    return NS_OK;
    714  }
    715  return aPrin->IsThirdPartyURI(prinURI, aRes);
    716 }
    717 
    718 NS_IMETHODIMP
    719 BasePrincipal::IsThirdPartyChannel(nsIChannel* aChan, bool* aRes) {
    720  AssertIsOnMainThread();
    721  if (IsSystemPrincipal()) {
    722    // Nothing is 3rd party to the system principal.
    723    *aRes = false;
    724    return NS_OK;
    725  }
    726 
    727  nsCOMPtr<nsIURI> prinURI;
    728  GetURI(getter_AddRefs(prinURI));
    729  ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
    730  return thirdPartyUtil->IsThirdPartyChannel(aChan, prinURI, aRes);
    731 }
    732 
    733 NS_IMETHODIMP
    734 BasePrincipal::IsSameOrigin(nsIURI* aURI, bool* aRes) {
    735  *aRes = false;
    736  nsCOMPtr<nsIURI> prinURI;
    737  nsresult rv = GetURI(getter_AddRefs(prinURI));
    738  if (NS_FAILED(rv) || !prinURI) {
    739    // Note that expanded and system principals return here, because they have
    740    // no URI.
    741    return NS_OK;
    742  }
    743  *aRes = nsScriptSecurityManager::SecurityCompareURIs(prinURI, aURI);
    744  return NS_OK;
    745 }
    746 
    747 NS_IMETHODIMP
    748 BasePrincipal::IsL10nAllowed(nsIURI* aURI, bool* aRes) {
    749  AssertIsOnMainThread();  // URI_DANGEROUS_TO_LOAD is not threadsafe to query.
    750  *aRes = false;
    751 
    752  if (nsContentUtils::IsErrorPage(aURI)) {
    753    *aRes = true;
    754    return NS_OK;
    755  }
    756 
    757  // The system principal is always allowed.
    758  if (IsSystemPrincipal()) {
    759    *aRes = true;
    760    return NS_OK;
    761  }
    762 
    763  nsCOMPtr<nsIURI> uri;
    764  nsresult rv = GetURI(getter_AddRefs(uri));
    765  NS_ENSURE_SUCCESS(rv, NS_OK);
    766 
    767  if (!uri) {
    768    return NS_OK;
    769  }
    770 
    771  bool hasFlags;
    772 
    773  // Allow access to uris that cannot be loaded by web content.
    774  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD,
    775                           &hasFlags);
    776  NS_ENSURE_SUCCESS(rv, NS_OK);
    777  if (hasFlags) {
    778    *aRes = true;
    779    return NS_OK;
    780  }
    781 
    782  // UI resources also get access.
    783  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
    784                           &hasFlags);
    785  NS_ENSURE_SUCCESS(rv, NS_OK);
    786  if (hasFlags) {
    787    *aRes = true;
    788    return NS_OK;
    789  }
    790 
    791  auto policy = AddonPolicyCore();
    792  *aRes = (policy && policy->IsPrivileged());
    793  return NS_OK;
    794 }
    795 
    796 NS_IMETHODIMP
    797 BasePrincipal::GetPrefLightCacheKey(nsIURI* aURI, bool aWithCredentials,
    798                                    const OriginAttributes& aOriginAttributes,
    799                                    nsACString& _retval) {
    800  _retval.Truncate();
    801  constexpr auto space = " "_ns;
    802 
    803  nsCOMPtr<nsIURI> uri;
    804  nsresult rv = GetURI(getter_AddRefs(uri));
    805  NS_ENSURE_SUCCESS(rv, rv);
    806 
    807  nsAutoCString scheme, host, port;
    808  if (uri) {
    809    uri->GetScheme(scheme);
    810    uri->GetHost(host);
    811    port.AppendInt(NS_GetRealPort(uri));
    812  }
    813 
    814  if (aWithCredentials) {
    815    _retval.AssignLiteral("cred");
    816  } else {
    817    _retval.AssignLiteral("nocred");
    818  }
    819 
    820  nsAutoCString spec;
    821  rv = aURI->GetSpec(spec);
    822  NS_ENSURE_SUCCESS(rv, rv);
    823 
    824  nsAutoCString originAttributesSuffix;
    825  aOriginAttributes.CreateSuffix(originAttributesSuffix);
    826 
    827  _retval.Append(space + scheme + space + host + space + port + space + spec +
    828                 space + originAttributesSuffix);
    829 
    830  return NS_OK;
    831 }
    832 
    833 NS_IMETHODIMP
    834 BasePrincipal::HasFirstpartyStorageAccess(mozIDOMWindow* aCheckWindow,
    835                                          uint32_t* aRejectedReason,
    836                                          bool* aOutAllowed) {
    837  AssertIsOnMainThread();
    838  *aRejectedReason = 0;
    839  *aOutAllowed = false;
    840 
    841  if (IsSystemPrincipal()) {
    842    // System principal is always considered to have first-party storage access.
    843    *aOutAllowed = true;
    844    return NS_OK;
    845  }
    846 
    847  nsPIDOMWindowInner* win = nsPIDOMWindowInner::From(aCheckWindow);
    848  nsCOMPtr<nsIURI> uri;
    849  nsresult rv = GetURI(getter_AddRefs(uri));
    850  if (NS_FAILED(rv)) {
    851    return rv;
    852  }
    853 
    854  // The uri could be null if the principal is an expanded principal.
    855  if (!uri) {
    856    return NS_ERROR_UNEXPECTED;
    857  }
    858 
    859  *aOutAllowed = ShouldAllowAccessFor(win, uri, true, aRejectedReason);
    860  return NS_OK;
    861 }
    862 
    863 NS_IMETHODIMP
    864 BasePrincipal::GetIsNullPrincipal(bool* aResult) {
    865  *aResult = Kind() == eNullPrincipal;
    866  return NS_OK;
    867 }
    868 
    869 NS_IMETHODIMP
    870 BasePrincipal::GetIsContentPrincipal(bool* aResult) {
    871  *aResult = Kind() == eContentPrincipal;
    872  return NS_OK;
    873 }
    874 
    875 NS_IMETHODIMP
    876 BasePrincipal::GetIsExpandedPrincipal(bool* aResult) {
    877  *aResult = Kind() == eExpandedPrincipal;
    878  return NS_OK;
    879 }
    880 
    881 NS_IMETHODIMP
    882 BasePrincipal::GetAsciiSpec(nsACString& aSpec) {
    883  aSpec.Truncate();
    884  nsCOMPtr<nsIURI> prinURI;
    885  nsresult rv = GetURI(getter_AddRefs(prinURI));
    886  if (NS_FAILED(rv) || !prinURI) {
    887    return NS_OK;
    888  }
    889  return prinURI->GetAsciiSpec(aSpec);
    890 }
    891 
    892 NS_IMETHODIMP
    893 BasePrincipal::GetSpec(nsACString& aSpec) {
    894  aSpec.Truncate();
    895  nsCOMPtr<nsIURI> prinURI;
    896  nsresult rv = GetURI(getter_AddRefs(prinURI));
    897  if (NS_FAILED(rv) || !prinURI) {
    898    return NS_OK;
    899  }
    900  return prinURI->GetSpec(aSpec);
    901 }
    902 
    903 NS_IMETHODIMP
    904 BasePrincipal::GetAsciiHost(nsACString& aHost) {
    905  aHost.Truncate();
    906  nsCOMPtr<nsIURI> prinURI;
    907  nsresult rv = GetURI(getter_AddRefs(prinURI));
    908  if (NS_FAILED(rv) || !prinURI) {
    909    return NS_OK;
    910  }
    911  return prinURI->GetAsciiHost(aHost);
    912 }
    913 
    914 NS_IMETHODIMP
    915 BasePrincipal::GetExposablePrePath(nsACString& aPrepath) {
    916  aPrepath.Truncate();
    917  nsCOMPtr<nsIURI> prinURI;
    918  nsresult rv = GetURI(getter_AddRefs(prinURI));
    919  if (NS_FAILED(rv) || !prinURI) {
    920    return NS_OK;
    921  }
    922 
    923  nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(prinURI);
    924  return exposableURI->GetDisplayPrePath(aPrepath);
    925 }
    926 
    927 NS_IMETHODIMP
    928 BasePrincipal::GetExposableSpec(nsACString& aSpec) {
    929  aSpec.Truncate();
    930  nsCOMPtr<nsIURI> prinURI;
    931  nsresult rv = GetURI(getter_AddRefs(prinURI));
    932  if (NS_FAILED(rv) || !prinURI) {
    933    return NS_OK;
    934  }
    935  nsCOMPtr<nsIURI> clone;
    936  rv = NS_MutateURI(prinURI)
    937           .SetQuery(""_ns)
    938           .SetRef(""_ns)
    939           .SetUserPass(""_ns)
    940           .Finalize(clone);
    941  NS_ENSURE_SUCCESS(rv, rv);
    942  return clone->GetAsciiSpec(aSpec);
    943 }
    944 
    945 NS_IMETHODIMP
    946 BasePrincipal::GetPrePath(nsACString& aPath) {
    947  aPath.Truncate();
    948  nsCOMPtr<nsIURI> prinURI;
    949  nsresult rv = GetURI(getter_AddRefs(prinURI));
    950  if (NS_FAILED(rv) || !prinURI) {
    951    return NS_OK;
    952  }
    953  return prinURI->GetPrePath(aPath);
    954 }
    955 
    956 NS_IMETHODIMP
    957 BasePrincipal::GetFilePath(nsACString& aPath) {
    958  aPath.Truncate();
    959  nsCOMPtr<nsIURI> prinURI;
    960  nsresult rv = GetURI(getter_AddRefs(prinURI));
    961  if (NS_FAILED(rv) || !prinURI) {
    962    return NS_OK;
    963  }
    964  return prinURI->GetFilePath(aPath);
    965 }
    966 
    967 NS_IMETHODIMP
    968 BasePrincipal::GetIsSystemPrincipal(bool* aResult) {
    969  *aResult = IsSystemPrincipal();
    970  return NS_OK;
    971 }
    972 
    973 NS_IMETHODIMP
    974 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) {
    975  *aResult = AddonPolicyCore() || ContentScriptAddonPolicyCore();
    976  return NS_OK;
    977 }
    978 
    979 NS_IMETHODIMP BasePrincipal::GetIsOnion(bool* aIsOnion) {
    980  *aIsOnion = false;
    981  nsCOMPtr<nsIURI> prinURI;
    982  nsresult rv = GetURI(getter_AddRefs(prinURI));
    983  if (NS_FAILED(rv) || !prinURI) {
    984    return NS_OK;
    985  }
    986 
    987  nsAutoCString host;
    988  rv = prinURI->GetHost(host);
    989  if (NS_FAILED(rv)) {
    990    return NS_OK;
    991  }
    992  *aIsOnion = StringEndsWith(host, ".onion"_ns);
    993  return NS_OK;
    994 }
    995 
    996 NS_IMETHODIMP BasePrincipal::GetIsIpAddress(bool* aIsIpAddress) {
    997  *aIsIpAddress = false;
    998 
    999  nsCOMPtr<nsIURI> prinURI;
   1000  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1001  if (NS_FAILED(rv) || !prinURI) {
   1002    return NS_OK;
   1003  }
   1004 
   1005  nsAutoCString host;
   1006  rv = prinURI->GetHost(host);
   1007  if (NS_FAILED(rv)) {
   1008    return NS_OK;
   1009  }
   1010 
   1011  PRNetAddr prAddr;
   1012  memset(&prAddr, 0, sizeof(prAddr));
   1013 
   1014  if (PR_StringToNetAddr(host.get(), &prAddr) == PR_SUCCESS) {
   1015    *aIsIpAddress = true;
   1016  }
   1017 
   1018  return NS_OK;
   1019 }
   1020 
   1021 NS_IMETHODIMP BasePrincipal::GetIsLocalIpAddress(bool* aIsIpAddress) {
   1022  *aIsIpAddress = false;
   1023 
   1024  nsCOMPtr<nsIURI> prinURI;
   1025  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1026  if (NS_FAILED(rv) || !prinURI) {
   1027    return NS_OK;
   1028  }
   1029 
   1030  nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
   1031  if (NS_FAILED(rv) || !ioService) {
   1032    return NS_OK;
   1033  }
   1034  rv = ioService->HostnameIsLocalIPAddress(prinURI, aIsIpAddress);
   1035  if (NS_FAILED(rv)) {
   1036    *aIsIpAddress = false;
   1037  }
   1038  return NS_OK;
   1039 }
   1040 
   1041 NS_IMETHODIMP
   1042 BasePrincipal::GetScheme(nsACString& aScheme) {
   1043  aScheme.Truncate();
   1044 
   1045  nsCOMPtr<nsIURI> prinURI;
   1046  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1047  if (NS_FAILED(rv) || !prinURI) {
   1048    return NS_OK;
   1049  }
   1050 
   1051  return prinURI->GetScheme(aScheme);
   1052 }
   1053 
   1054 NS_IMETHODIMP
   1055 BasePrincipal::SchemeIs(const char* aScheme, bool* aResult) {
   1056  *aResult = false;
   1057  nsCOMPtr<nsIURI> prinURI;
   1058  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1059  if (NS_WARN_IF(NS_FAILED(rv)) || !prinURI) {
   1060    return NS_OK;
   1061  }
   1062  *aResult = prinURI->SchemeIs(aScheme);
   1063  return NS_OK;
   1064 }
   1065 
   1066 NS_IMETHODIMP
   1067 BasePrincipal::IsURIInPrefList(const char* aPref, bool* aResult) {
   1068  AssertIsOnMainThread();
   1069  *aResult = false;
   1070 
   1071  if (Kind() != eContentPrincipal) {
   1072    // We don't store prefs for non-content principals.
   1073    return NS_OK;
   1074  }
   1075 
   1076  nsCOMPtr<nsIURI> prinURI;
   1077  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1078  if (NS_FAILED(rv) || !prinURI) {
   1079    return NS_OK;
   1080  }
   1081  *aResult = nsContentUtils::IsURIInPrefList(prinURI, aPref);
   1082  return NS_OK;
   1083 }
   1084 
   1085 NS_IMETHODIMP
   1086 BasePrincipal::IsURIInList(const nsACString& aList, bool* aResult) {
   1087  *aResult = false;
   1088  nsCOMPtr<nsIURI> prinURI;
   1089 
   1090  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1091  if (NS_FAILED(rv) || !prinURI) {
   1092    return NS_OK;
   1093  }
   1094 
   1095  *aResult = nsContentUtils::IsURIInList(prinURI, nsCString(aList));
   1096  return NS_OK;
   1097 }
   1098 
   1099 NS_IMETHODIMP
   1100 BasePrincipal::IsContentAccessibleAboutURI(bool* aResult) {
   1101  *aResult = false;
   1102 
   1103  nsCOMPtr<nsIURI> prinURI;
   1104  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1105  if (NS_FAILED(rv) || !prinURI) {
   1106    return NS_OK;
   1107  }
   1108 
   1109  if (!prinURI->SchemeIs("about")) {
   1110    return NS_OK;
   1111  }
   1112 
   1113  *aResult = NS_IsContentAccessibleAboutURI(prinURI);
   1114  return NS_OK;
   1115 }
   1116 
   1117 NS_IMETHODIMP
   1118 BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult) {
   1119  AssertIsOnMainThread();
   1120  *aResult = false;
   1121 
   1122  nsCOMPtr<nsIURI> uri;
   1123  nsresult rv = GetURI(getter_AddRefs(uri));
   1124  if (NS_FAILED(rv) || !uri) {
   1125    return NS_OK;
   1126  }
   1127 
   1128  *aResult = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
   1129  return NS_OK;
   1130 }
   1131 
   1132 NS_IMETHODIMP
   1133 BasePrincipal::GetIsLoopbackHost(bool* aRes) {
   1134  AssertIsOnMainThread();
   1135  *aRes = false;
   1136  nsAutoCString host;
   1137  nsresult rv = GetHost(host);
   1138  // Swallow potential failure as this method is infallible.
   1139  if (NS_FAILED(rv)) {
   1140    return NS_OK;
   1141  }
   1142 
   1143  *aRes = nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(host);
   1144  return NS_OK;
   1145 }
   1146 
   1147 NS_IMETHODIMP
   1148 BasePrincipal::GetAboutModuleFlags(uint32_t* flags) {
   1149  AssertIsOnMainThread();
   1150  *flags = 0;
   1151  nsCOMPtr<nsIURI> prinURI;
   1152  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1153  if (NS_FAILED(rv) || !prinURI) {
   1154    return NS_ERROR_NOT_AVAILABLE;
   1155  }
   1156  if (!prinURI->SchemeIs("about")) {
   1157    return NS_OK;
   1158  }
   1159 
   1160  nsCOMPtr<nsIAboutModule> aboutModule;
   1161  rv = NS_GetAboutModule(prinURI, getter_AddRefs(aboutModule));
   1162  if (NS_FAILED(rv) || !aboutModule) {
   1163    return rv;
   1164  }
   1165  return aboutModule->GetURIFlags(prinURI, flags);
   1166 }
   1167 
   1168 NS_IMETHODIMP
   1169 BasePrincipal::GetOriginAttributes(JSContext* aCx,
   1170                                   JS::MutableHandle<JS::Value> aVal) {
   1171  if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
   1172    return NS_ERROR_FAILURE;
   1173  }
   1174  return NS_OK;
   1175 }
   1176 
   1177 NS_IMETHODIMP
   1178 BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) {
   1179  MOZ_ASSERT(mOriginSuffix);
   1180  mOriginSuffix->ToUTF8String(aOriginAttributes);
   1181  return NS_OK;
   1182 }
   1183 
   1184 NS_IMETHODIMP
   1185 BasePrincipal::GetUserContextId(uint32_t* aUserContextId) {
   1186  *aUserContextId = UserContextId();
   1187  return NS_OK;
   1188 }
   1189 
   1190 NS_IMETHODIMP
   1191 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) {
   1192  *aPrivateBrowsingId = PrivateBrowsingId();
   1193  return NS_OK;
   1194 }
   1195 
   1196 NS_IMETHODIMP
   1197 BasePrincipal::GetIsInPrivateBrowsing(bool* aIsInPrivateBrowsing) {
   1198  *aIsInPrivateBrowsing = mOriginAttributes.IsPrivateBrowsing();
   1199  return NS_OK;
   1200 }
   1201 
   1202 nsresult BasePrincipal::GetAddonPolicy(
   1203    extensions::WebExtensionPolicy** aResult) {
   1204  AssertIsOnMainThread();
   1205  RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy());
   1206  policy.forget(aResult);
   1207  return NS_OK;
   1208 }
   1209 
   1210 nsresult BasePrincipal::GetContentScriptAddonPolicy(
   1211    extensions::WebExtensionPolicy** aResult) {
   1212  RefPtr<extensions::WebExtensionPolicy> policy(ContentScriptAddonPolicy());
   1213  policy.forget(aResult);
   1214  return NS_OK;
   1215 }
   1216 
   1217 extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() {
   1218  AssertIsOnMainThread();
   1219  RefPtr<extensions::WebExtensionPolicyCore> core = AddonPolicyCore();
   1220  return core ? core->GetMainThreadPolicy() : nullptr;
   1221 }
   1222 
   1223 RefPtr<extensions::WebExtensionPolicyCore> BasePrincipal::AddonPolicyCore() {
   1224  if (Is<ContentPrincipal>()) {
   1225    return As<ContentPrincipal>()->AddonPolicyCore();
   1226  }
   1227  return nullptr;
   1228 }
   1229 
   1230 bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) {
   1231  if (auto policy = AddonPolicyCore()) {
   1232    return policy->HasPermission(aPerm);
   1233  }
   1234  return false;
   1235 }
   1236 
   1237 nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
   1238  if (Is<ExpandedPrincipal>()) {
   1239    return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
   1240  }
   1241  return this;
   1242 }
   1243 
   1244 bool BasePrincipal::OverridesCSP(nsIPrincipal* aDocumentPrincipal) {
   1245  MOZ_ASSERT(aDocumentPrincipal);
   1246 
   1247  // Expanded principals override CSP if and only if they subsume the document
   1248  // principal.
   1249  if (mKind == eExpandedPrincipal) {
   1250    return FastSubsumes(aDocumentPrincipal);
   1251  }
   1252  // Extension principals always override the CSP of non-extension principals.
   1253  // This is primarily for the sake of their stylesheets, which are usually
   1254  // loaded from channels and cannot have expanded principals.
   1255  return (AddonPolicyCore() &&
   1256          !BasePrincipal::Cast(aDocumentPrincipal)->AddonPolicyCore());
   1257 }
   1258 
   1259 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
   1260    nsIURI* aURI, const OriginAttributes& aAttrs, nsIURI* aInitialDomain) {
   1261  MOZ_ASSERT(aURI);
   1262 
   1263  nsAutoCString originNoSuffix;
   1264  nsresult rv =
   1265      ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
   1266  if (NS_FAILED(rv)) {
   1267    // If the generation of the origin fails, we still want to have a valid
   1268    // principal. Better to return a null principal here.
   1269    return NullPrincipal::Create(aAttrs);
   1270  }
   1271 
   1272  return CreateContentPrincipal(aURI, aAttrs, originNoSuffix, aInitialDomain);
   1273 }
   1274 
   1275 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
   1276    nsIURI* aURI, const OriginAttributes& aAttrs,
   1277    const nsACString& aOriginNoSuffix, nsIURI* aInitialDomain) {
   1278  MOZ_ASSERT(aURI);
   1279  MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
   1280 
   1281  // If the URI is supposed to inherit the security context of whoever loads it,
   1282  // we shouldn't make a content principal for it.
   1283  bool inheritsPrincipal;
   1284  nsresult rv = NS_URIChainHasFlags(
   1285      aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
   1286      &inheritsPrincipal);
   1287  if (NS_FAILED(rv) || inheritsPrincipal) {
   1288    return NullPrincipal::Create(aAttrs);
   1289  }
   1290 
   1291  // Check whether the URI knows what its principal is supposed to be.
   1292 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
   1293  nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
   1294      do_QueryInterface(aURI);
   1295  if (uriWithSpecialOrigin) {
   1296    nsCOMPtr<nsIURI> origin;
   1297    rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
   1298    if (NS_WARN_IF(NS_FAILED(rv))) {
   1299      return nullptr;
   1300    }
   1301    MOZ_ASSERT(origin);
   1302    OriginAttributes attrs;
   1303    RefPtr<BasePrincipal> principal =
   1304        CreateContentPrincipal(origin, attrs, aInitialDomain);
   1305    return principal.forget();
   1306  }
   1307 #endif
   1308 
   1309  nsCOMPtr<nsIPrincipal> blobPrincipal;
   1310  if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
   1311          aURI, getter_AddRefs(blobPrincipal))) {
   1312    MOZ_ASSERT(blobPrincipal);
   1313    MOZ_ASSERT(!aInitialDomain,
   1314               "an initial domain for a blob URI makes no sense");
   1315    RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
   1316    return principal.forget();
   1317  }
   1318 
   1319  // Mint a content principal.
   1320  RefPtr<ContentPrincipal> principal =
   1321      new ContentPrincipal(aURI, aAttrs, aOriginNoSuffix, aInitialDomain);
   1322  return principal.forget();
   1323 }
   1324 
   1325 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
   1326    const nsACString& aOrigin) {
   1327  MOZ_ASSERT(!StringBeginsWith(aOrigin, "["_ns),
   1328             "CreateContentPrincipal does not support System and Expanded "
   1329             "principals");
   1330 
   1331  MOZ_ASSERT(
   1332      !StringBeginsWith(aOrigin, nsLiteralCString(NS_NULLPRINCIPAL_SCHEME ":")),
   1333      "CreateContentPrincipal does not support NullPrincipal");
   1334 
   1335  nsAutoCString originNoSuffix;
   1336  OriginAttributes attrs;
   1337  if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
   1338    return nullptr;
   1339  }
   1340 
   1341  nsCOMPtr<nsIURI> uri;
   1342  nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
   1343  NS_ENSURE_SUCCESS(rv, nullptr);
   1344 
   1345  return BasePrincipal::CreateContentPrincipal(uri, attrs);
   1346 }
   1347 
   1348 already_AddRefed<BasePrincipal> BasePrincipal::CloneForcingOriginAttributes(
   1349    const OriginAttributes& aOriginAttributes) {
   1350  if (NS_WARN_IF(!IsContentPrincipal())) {
   1351    return nullptr;
   1352  }
   1353 
   1354  nsAutoCString originNoSuffix;
   1355  nsresult rv = GetOriginNoSuffix(originNoSuffix);
   1356  NS_ENSURE_SUCCESS(rv, nullptr);
   1357 
   1358  nsCOMPtr<nsIURI> uri;
   1359  MOZ_ALWAYS_SUCCEEDS(GetURI(getter_AddRefs(uri)));
   1360 
   1361  // XXX: This does not copy over the domain. Should it?
   1362  RefPtr<ContentPrincipal> copy =
   1363      new ContentPrincipal(uri, aOriginAttributes, originNoSuffix, nullptr);
   1364  return copy.forget();
   1365 }
   1366 
   1367 extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() {
   1368  AssertIsOnMainThread();
   1369  RefPtr<extensions::WebExtensionPolicyCore> core =
   1370      ContentScriptAddonPolicyCore();
   1371  return core ? core->GetMainThreadPolicy() : nullptr;
   1372 }
   1373 
   1374 RefPtr<extensions::WebExtensionPolicyCore>
   1375 BasePrincipal::ContentScriptAddonPolicyCore() {
   1376  if (!Is<ExpandedPrincipal>()) {
   1377    return nullptr;
   1378  }
   1379 
   1380  auto* expanded = As<ExpandedPrincipal>();
   1381  for (const auto& prin : expanded->AllowList()) {
   1382    if (RefPtr<extensions::WebExtensionPolicyCore> policy =
   1383            BasePrincipal::Cast(prin)->AddonPolicyCore()) {
   1384      return policy;
   1385    }
   1386  }
   1387 
   1388  return nullptr;
   1389 }
   1390 
   1391 bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI,
   1392                                    bool aExplicit /* = false */) {
   1393  if (Is<ExpandedPrincipal>()) {
   1394    return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
   1395  }
   1396  if (auto policy = AddonPolicyCore()) {
   1397    return policy->CanAccessURI(aURI, aExplicit);
   1398  }
   1399  return false;
   1400 }
   1401 
   1402 NS_IMETHODIMP
   1403 BasePrincipal::GetLocalStorageQuotaKey(nsACString& aKey) {
   1404  aKey.Truncate();
   1405 
   1406  nsCOMPtr<nsIURI> uri;
   1407  nsresult rv = GetURI(getter_AddRefs(uri));
   1408  NS_ENSURE_SUCCESS(rv, rv);
   1409  NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
   1410 
   1411  // The special handling of the file scheme should be consistent with
   1412  // GetStorageOriginKey.
   1413 
   1414  nsAutoCString baseDomain;
   1415  rv = uri->GetAsciiHost(baseDomain);
   1416  NS_ENSURE_SUCCESS(rv, rv);
   1417 
   1418  if (baseDomain.IsEmpty() && uri->SchemeIs("file")) {
   1419    nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
   1420    NS_ENSURE_SUCCESS(rv, rv);
   1421 
   1422    rv = url->GetDirectory(baseDomain);
   1423    NS_ENSURE_SUCCESS(rv, rv);
   1424  } else {
   1425    nsCOMPtr<nsIEffectiveTLDService> eTLDService =
   1426        mozilla::components::EffectiveTLD::Service(&rv);
   1427    NS_ENSURE_SUCCESS(rv, rv);
   1428 
   1429    nsAutoCString eTLDplusOne;
   1430    rv = eTLDService->GetBaseDomain(uri, 0, eTLDplusOne);
   1431    if (NS_SUCCEEDED(rv)) {
   1432      baseDomain = eTLDplusOne;
   1433    } else if (rv == NS_ERROR_HOST_IS_IP_ADDRESS ||
   1434               rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
   1435      rv = NS_OK;
   1436    }
   1437    NS_ENSURE_SUCCESS(rv, rv);
   1438  }
   1439 
   1440  OriginAttributesRef().CreateSuffix(aKey);
   1441 
   1442  nsAutoCString subdomainsDBKey;
   1443  rv = dom::StorageUtils::CreateReversedDomain(baseDomain, subdomainsDBKey);
   1444  NS_ENSURE_SUCCESS(rv, rv);
   1445 
   1446  aKey.Append(':');
   1447  aKey.Append(subdomainsDBKey);
   1448 
   1449  return NS_OK;
   1450 }
   1451 
   1452 NS_IMETHODIMP
   1453 BasePrincipal::GetNextSubDomainPrincipal(
   1454    nsIPrincipal** aNextSubDomainPrincipal) {
   1455  nsCOMPtr<nsIURI> uri;
   1456  nsresult rv = GetURI(getter_AddRefs(uri));
   1457  if (NS_FAILED(rv) || !uri) {
   1458    return NS_OK;
   1459  }
   1460 
   1461  nsAutoCString host;
   1462  rv = uri->GetHost(host);
   1463  if (NS_FAILED(rv) || host.IsEmpty()) {
   1464    return NS_OK;
   1465  }
   1466 
   1467  nsCString subDomain;
   1468  nsCOMPtr<nsIEffectiveTLDService> eTLDService =
   1469      mozilla::components::EffectiveTLD::Service();
   1470  if (!eTLDService) {
   1471    return NS_OK;
   1472  }
   1473  rv = eTLDService->GetNextSubDomain(host, subDomain);
   1474 
   1475  if (NS_FAILED(rv) || subDomain.IsEmpty()) {
   1476    return NS_OK;
   1477  }
   1478 
   1479  nsCOMPtr<nsIURI> subDomainURI;
   1480  rv = NS_MutateURI(uri).SetHost(subDomain).Finalize(subDomainURI);
   1481  if (NS_FAILED(rv) || !subDomainURI) {
   1482    return NS_OK;
   1483  }
   1484  // Copy the attributes over
   1485  mozilla::OriginAttributes attrs = OriginAttributesRef();
   1486 
   1487  if (!StaticPrefs::permissions_isolateBy_userContext()) {
   1488    // Disable userContext for permissions.
   1489    attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
   1490  }
   1491  RefPtr<nsIPrincipal> principal =
   1492      mozilla::BasePrincipal::CreateContentPrincipal(subDomainURI, attrs);
   1493 
   1494  if (!principal) {
   1495    return NS_OK;
   1496  }
   1497  principal.forget(aNextSubDomainPrincipal);
   1498  return NS_OK;
   1499 }
   1500 
   1501 NS_IMETHODIMP
   1502 BasePrincipal::GetStorageOriginKey(nsACString& aOriginKey) {
   1503  aOriginKey.Truncate();
   1504 
   1505  nsCOMPtr<nsIURI> uri;
   1506  nsresult rv = GetURI(getter_AddRefs(uri));
   1507  NS_ENSURE_SUCCESS(rv, rv);
   1508  NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
   1509 
   1510  // The special handling of the file scheme should be consistent with
   1511  // GetLocalStorageQuotaKey.
   1512 
   1513  nsAutoCString domainOrigin;
   1514  rv = uri->GetAsciiHost(domainOrigin);
   1515  NS_ENSURE_SUCCESS(rv, rv);
   1516 
   1517  if (domainOrigin.IsEmpty()) {
   1518    // For the file:/// protocol use the exact directory as domain.
   1519    if (uri->SchemeIs("file")) {
   1520      nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
   1521      NS_ENSURE_SUCCESS(rv, rv);
   1522      rv = url->GetDirectory(domainOrigin);
   1523      NS_ENSURE_SUCCESS(rv, rv);
   1524    }
   1525  }
   1526 
   1527  // Append reversed domain
   1528  nsAutoCString reverseDomain;
   1529  rv = dom::StorageUtils::CreateReversedDomain(domainOrigin, reverseDomain);
   1530  NS_ENSURE_SUCCESS(rv, rv);
   1531 
   1532  aOriginKey.Append(reverseDomain);
   1533 
   1534  // Append scheme
   1535  nsAutoCString scheme;
   1536  rv = uri->GetScheme(scheme);
   1537  NS_ENSURE_SUCCESS(rv, rv);
   1538 
   1539  aOriginKey.Append(':');
   1540  aOriginKey.Append(scheme);
   1541 
   1542  // Append port if any
   1543  int32_t port = NS_GetRealPort(uri);
   1544  if (port != -1) {
   1545    aOriginKey.Append(nsPrintfCString(":%d", port));
   1546  }
   1547 
   1548  return NS_OK;
   1549 }
   1550 
   1551 NS_IMETHODIMP
   1552 BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy) {
   1553  AssertIsOnMainThread();
   1554  *aIsScriptAllowedByPolicy = false;
   1555  nsCOMPtr<nsIURI> prinURI;
   1556  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1557  if (NS_FAILED(rv) || !prinURI) {
   1558    return NS_OK;
   1559  }
   1560  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   1561  if (!ssm) {
   1562    return NS_ERROR_UNEXPECTED;
   1563  }
   1564  return ssm->PolicyAllowsScript(prinURI, aIsScriptAllowedByPolicy);
   1565 }
   1566 
   1567 bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
   1568  MOZ_ASSERT(IsInitialized());
   1569  MOZ_ASSERT(aOther.IsInitialized());
   1570  return mPrincipal->FastEquals(aOther.mPrincipal);
   1571 }
   1572 
   1573 NS_IMETHODIMP
   1574 BasePrincipal::CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy,
   1575                                  nsIReferrerInfo** _retval) {
   1576  nsCOMPtr<nsIURI> prinURI;
   1577  RefPtr<dom::ReferrerInfo> info;
   1578  nsresult rv = GetURI(getter_AddRefs(prinURI));
   1579  if (NS_FAILED(rv) || !prinURI) {
   1580    info = new dom::ReferrerInfo(nullptr);
   1581    info.forget(_retval);
   1582    return NS_OK;
   1583  }
   1584  info = new dom::ReferrerInfo(prinURI, aReferrerPolicy);
   1585  info.forget(_retval);
   1586  return NS_OK;
   1587 }
   1588 
   1589 NS_IMETHODIMP
   1590 BasePrincipal::GetPrecursorPrincipal(nsIPrincipal** aPrecursor) {
   1591  *aPrecursor = nullptr;
   1592  return NS_OK;
   1593 }
   1594 
   1595 NS_IMPL_ADDREF(BasePrincipal::Deserializer)
   1596 NS_IMPL_RELEASE(BasePrincipal::Deserializer)
   1597 
   1598 NS_INTERFACE_MAP_BEGIN(BasePrincipal::Deserializer)
   1599  NS_INTERFACE_MAP_ENTRY(nsISupports)
   1600  NS_INTERFACE_MAP_ENTRY(nsISerializable)
   1601  if (mPrincipal) {
   1602    return mPrincipal->QueryInterface(aIID, aInstancePtr);
   1603  } else
   1604 NS_INTERFACE_MAP_END
   1605 
   1606 NS_IMETHODIMP
   1607 BasePrincipal::Deserializer::Write(nsIObjectOutputStream* aStream) {
   1608  // Read is used still for legacy principals
   1609  MOZ_RELEASE_ASSERT(false, "Old style serialization is removed");
   1610  return NS_OK;
   1611 }
   1612 
   1613 /* static */
   1614 void BasePrincipal::WriteJSONProperty(JSONWriter& aWriter,
   1615                                      const Span<const char>& aKey,
   1616                                      const nsCString& aValue) {
   1617  aWriter.StringProperty(aKey, aValue);
   1618 }
   1619 
   1620 }  // namespace mozilla
   1621 
   1622 uint32_t nsIPrincipal::GetHashValue() const {
   1623  auto* bp = mozilla::BasePrincipal::Cast(this);
   1624  return mozilla::HashGeneric(bp->GetOriginNoSuffixHash(),
   1625                              bp->GetOriginSuffixHash());
   1626 }