tor-browser

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

Location.cpp (17237B)


      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 "Location.h"
      8 
      9 #include "ReferrerInfo.h"
     10 #include "mozilla/BasePrincipal.h"
     11 #include "mozilla/Components.h"
     12 #include "mozilla/Likely.h"
     13 #include "mozilla/NullPrincipal.h"
     14 #include "mozilla/ServoStyleConsts.h"
     15 #include "mozilla/StaticPrefs_dom.h"
     16 #include "mozilla/dom/Document.h"
     17 #include "mozilla/dom/DocumentInlines.h"
     18 #include "mozilla/dom/FragmentDirective.h"
     19 #include "mozilla/dom/LocationBinding.h"
     20 #include "mozilla/dom/ScriptSettings.h"
     21 #include "nsCOMPtr.h"
     22 #include "nsContentUtils.h"
     23 #include "nsCycleCollectionParticipant.h"
     24 #include "nsDocShell.h"
     25 #include "nsDocShellLoadState.h"
     26 #include "nsError.h"
     27 #include "nsEscape.h"
     28 #include "nsGlobalWindowOuter.h"
     29 #include "nsIJARURI.h"
     30 #include "nsIOService.h"
     31 #include "nsIScriptContext.h"
     32 #include "nsIScriptObjectPrincipal.h"
     33 #include "nsIURIMutator.h"
     34 #include "nsIURL.h"
     35 #include "nsIWebNavigation.h"
     36 #include "nsJSUtils.h"
     37 #include "nsNetUtil.h"
     38 #include "nsPIDOMWindowInlines.h"
     39 #include "nsPresContext.h"
     40 #include "nsReadableUtils.h"
     41 
     42 namespace mozilla::dom {
     43 
     44 nsTArray<nsString> ProduceAncestorOriginsList(
     45    const nsTArray<nsCOMPtr<nsIPrincipal>>& aPrincipals) {
     46  nsTArray<nsString> result;
     47 
     48  for (const auto& principal : aPrincipals) {
     49    nsString origin;
     50    if (principal == nullptr) {
     51      origin.AssignLiteral(u"null");
     52    } else {
     53      nsAutoCString originNoSuffix;
     54      if (NS_WARN_IF(NS_FAILED(principal->GetOriginNoSuffix(originNoSuffix)))) {
     55        origin.AssignLiteral(u"null");
     56      } else {
     57        CopyUTF8toUTF16(originNoSuffix, origin);
     58      }
     59    }
     60    result.AppendElement(std::move(origin));
     61  }
     62 
     63  return result;
     64 }
     65 
     66 Location::Location(nsPIDOMWindowInner* aWindow)
     67    : mCachedHash(VoidCString()), mInnerWindow(aWindow) {
     68  BrowsingContext* bc = GetBrowsingContext();
     69  if (bc) {
     70    bc->LocationCreated(this);
     71  }
     72 }
     73 
     74 Location::~Location() {
     75  if (isInList()) {
     76    remove();
     77  }
     78 }
     79 
     80 // QueryInterface implementation for Location
     81 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Location)
     82  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     83  NS_INTERFACE_MAP_ENTRY(nsISupports)
     84 NS_INTERFACE_MAP_END
     85 
     86 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Location, mInnerWindow)
     87 
     88 NS_IMPL_CYCLE_COLLECTING_ADDREF(Location)
     89 NS_IMPL_CYCLE_COLLECTING_RELEASE(Location)
     90 
     91 BrowsingContext* Location::GetBrowsingContext() {
     92  return mInnerWindow ? mInnerWindow->GetBrowsingContext() : nullptr;
     93 }
     94 
     95 nsIDocShell* Location::GetDocShell() {
     96  if (BrowsingContext* bc = GetBrowsingContext()) {
     97    return bc->GetDocShell();
     98  }
     99  return nullptr;
    100 }
    101 
    102 nsresult Location::GetURI(nsIURI** aURI, bool aGetInnermostURI) {
    103  *aURI = nullptr;
    104 
    105  nsIDocShell* docShell = GetDocShell();
    106  if (!docShell) {
    107    return NS_OK;
    108  }
    109 
    110  nsIWebNavigation* webNav = nsDocShell::Cast(docShell);
    111 
    112  nsCOMPtr<nsIURI> uri;
    113  nsresult rv = webNav->GetCurrentURI(getter_AddRefs(uri));
    114  NS_ENSURE_SUCCESS(rv, rv);
    115 
    116  // It is valid for docshell to return a null URI. Don't try to fixup
    117  // if this happens.
    118  if (!uri) {
    119    return NS_OK;
    120  }
    121 
    122  if (aGetInnermostURI) {
    123    nsCOMPtr<nsIJARURI> jarURI(do_QueryInterface(uri));
    124    while (jarURI) {
    125      jarURI->GetJARFile(getter_AddRefs(uri));
    126      jarURI = do_QueryInterface(uri);
    127    }
    128  }
    129 
    130  NS_ASSERTION(uri, "nsJARURI screwed up?");
    131 
    132  // Remove the fragment directive from the url hash.
    133  FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragment(uri);
    134  nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(uri);
    135  exposableURI.forget(aURI);
    136  return NS_OK;
    137 }
    138 
    139 void Location::GetHash(nsACString& aHash, nsIPrincipal& aSubjectPrincipal,
    140                       ErrorResult& aRv) {
    141  if (!CallerSubsumes(&aSubjectPrincipal)) {
    142    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    143    return;
    144  }
    145 
    146  if (!mCachedHash.IsVoid()) {
    147    aHash = mCachedHash;
    148    return;
    149  }
    150 
    151  aHash.SetLength(0);
    152 
    153  nsCOMPtr<nsIURI> uri;
    154  aRv = GetURI(getter_AddRefs(uri));
    155  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    156    return;
    157  }
    158 
    159  nsAutoCString ref;
    160 
    161  aRv = uri->GetRef(ref);
    162  if (NS_WARN_IF(aRv.Failed())) {
    163    return;
    164  }
    165 
    166  if (!ref.IsEmpty()) {
    167    aHash.SetCapacity(ref.Length() + 1);
    168    aHash.Assign('#');
    169    aHash.Append(ref);
    170  }
    171 
    172  mCachedHash = aHash;
    173 }
    174 
    175 void Location::SetHash(const nsACString& aHash, nsIPrincipal& aSubjectPrincipal,
    176                       ErrorResult& aRv) {
    177  if (!CallerSubsumes(&aSubjectPrincipal)) {
    178    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    179    return;
    180  }
    181 
    182  nsCOMPtr<nsIURI> uri;
    183  aRv = GetURI(getter_AddRefs(uri));
    184  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    185    return;
    186  }
    187 
    188  if (aHash.IsEmpty() || aHash.First() != '#') {
    189    aRv = NS_MutateURI(uri).SetRef("#"_ns + aHash).Finalize(uri);
    190  } else {
    191    aRv = NS_MutateURI(uri).SetRef(aHash).Finalize(uri);
    192  }
    193  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    194    return;
    195  }
    196 
    197  Navigate(uri, aSubjectPrincipal, aRv);
    198 }
    199 
    200 // https://html.spec.whatwg.org/#dom-location-ancestororigins
    201 RefPtr<DOMStringList> Location::GetAncestorOrigins(
    202    nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
    203  Document* doc = mInnerWindow->GetExtantDoc();
    204  // Step 1. If this's relevant Document is null, then return an empty list.
    205  if (!doc || !doc->IsActive()) {
    206    return MakeRefPtr<DOMStringList>();
    207  }
    208 
    209  // Step 2. If this's relevant Document's origin is not same origin-domain with
    210  // the entry settings object's origin, then throw a "SecurityError"
    211  // DOMException.
    212  if (!CallerSubsumes(&aSubjectPrincipal)) {
    213    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    214    return nullptr;
    215  }
    216 
    217  // Step 3. Otherwise, return this's ancestor origins list.
    218  return doc->AncestorOrigins();
    219 }
    220 
    221 void Location::GetHost(nsACString& aHost, nsIPrincipal& aSubjectPrincipal,
    222                       ErrorResult& aRv) {
    223  if (!CallerSubsumes(&aSubjectPrincipal)) {
    224    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    225    return;
    226  }
    227 
    228  aHost.Truncate();
    229 
    230  nsCOMPtr<nsIURI> uri;
    231  (void)GetURI(getter_AddRefs(uri), true);
    232 
    233  if (uri) {
    234    (void)uri->GetHostPort(aHost);
    235  }
    236 }
    237 
    238 void Location::SetHost(const nsACString& aHost, nsIPrincipal& aSubjectPrincipal,
    239                       ErrorResult& aRv) {
    240  if (!CallerSubsumes(&aSubjectPrincipal)) {
    241    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    242    return;
    243  }
    244 
    245  nsCOMPtr<nsIURI> uri;
    246  aRv = GetURI(getter_AddRefs(uri));
    247  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    248    return;
    249  }
    250 
    251  aRv = NS_MutateURI(uri).SetHostPort(aHost).Finalize(uri);
    252  if (NS_WARN_IF(aRv.Failed())) {
    253    return;
    254  }
    255 
    256  Navigate(uri, aSubjectPrincipal, aRv);
    257 }
    258 
    259 void Location::GetHostname(nsACString& aHostname,
    260                           nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
    261  if (!CallerSubsumes(&aSubjectPrincipal)) {
    262    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    263    return;
    264  }
    265 
    266  aHostname.Truncate();
    267 
    268  nsCOMPtr<nsIURI> uri;
    269  GetURI(getter_AddRefs(uri), true);
    270  if (uri) {
    271    nsContentUtils::GetHostOrIPv6WithBrackets(uri, aHostname);
    272  }
    273 }
    274 
    275 void Location::SetHostname(const nsACString& aHostname,
    276                           nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
    277  if (!CallerSubsumes(&aSubjectPrincipal)) {
    278    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    279    return;
    280  }
    281 
    282  nsCOMPtr<nsIURI> uri;
    283  aRv = GetURI(getter_AddRefs(uri));
    284  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    285    return;
    286  }
    287 
    288  aRv = NS_MutateURI(uri).SetHost(aHostname).Finalize(uri);
    289  if (NS_WARN_IF(aRv.Failed())) {
    290    return;
    291  }
    292 
    293  Navigate(uri, aSubjectPrincipal, aRv);
    294 }
    295 
    296 nsresult Location::GetHref(nsACString& aHref) {
    297  aHref.Truncate();
    298 
    299  nsCOMPtr<nsIURI> uri;
    300  nsresult rv = GetURI(getter_AddRefs(uri));
    301  if (NS_WARN_IF(NS_FAILED(rv)) || !uri) {
    302    return rv;
    303  }
    304 
    305  rv = uri->GetSpec(aHref);
    306  if (NS_WARN_IF(NS_FAILED(rv))) {
    307    return rv;
    308  }
    309  return NS_OK;
    310 }
    311 
    312 void Location::GetOrigin(nsACString& aOrigin, nsIPrincipal& aSubjectPrincipal,
    313                         ErrorResult& aRv) {
    314  if (!CallerSubsumes(&aSubjectPrincipal)) {
    315    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    316    return;
    317  }
    318 
    319  aOrigin.Truncate();
    320 
    321  nsCOMPtr<nsIURI> uri;
    322  aRv = GetURI(getter_AddRefs(uri), true);
    323  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    324    return;
    325  }
    326 
    327  aRv = nsContentUtils::GetWebExposedOriginSerialization(uri, aOrigin);
    328  if (NS_WARN_IF(aRv.Failed())) {
    329    aOrigin.Truncate();
    330    return;
    331  }
    332 }
    333 
    334 void Location::GetPathname(nsACString& aPathname,
    335                           nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
    336  if (!CallerSubsumes(&aSubjectPrincipal)) {
    337    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    338    return;
    339  }
    340 
    341  aPathname.Truncate();
    342 
    343  nsCOMPtr<nsIURI> uri;
    344  aRv = GetURI(getter_AddRefs(uri));
    345  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    346    return;
    347  }
    348 
    349  aRv = uri->GetFilePath(aPathname);
    350  if (NS_WARN_IF(aRv.Failed())) {
    351    return;
    352  }
    353 }
    354 
    355 void Location::SetPathname(const nsACString& aPathname,
    356                           nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
    357  if (!CallerSubsumes(&aSubjectPrincipal)) {
    358    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    359    return;
    360  }
    361 
    362  nsCOMPtr<nsIURI> uri;
    363  aRv = GetURI(getter_AddRefs(uri));
    364  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    365    return;
    366  }
    367 
    368  nsresult rv = NS_MutateURI(uri).SetFilePath(aPathname).Finalize(uri);
    369  if (NS_FAILED(rv)) {
    370    return;
    371  }
    372 
    373  Navigate(uri, aSubjectPrincipal, aRv);
    374 }
    375 
    376 void Location::GetPort(nsACString& aPort, nsIPrincipal& aSubjectPrincipal,
    377                       ErrorResult& aRv) {
    378  if (!CallerSubsumes(&aSubjectPrincipal)) {
    379    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    380    return;
    381  }
    382 
    383  aPort.SetLength(0);
    384 
    385  nsCOMPtr<nsIURI> uri;
    386  aRv = GetURI(getter_AddRefs(uri), true);
    387  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    388    return;
    389  }
    390 
    391  int32_t port;
    392  nsresult result = uri->GetPort(&port);
    393 
    394  // Don't propagate this exception to caller
    395  if (NS_SUCCEEDED(result) && -1 != port) {
    396    aPort.AppendInt(port);
    397  }
    398 }
    399 
    400 void Location::SetPort(const nsACString& aPort, nsIPrincipal& aSubjectPrincipal,
    401                       ErrorResult& aRv) {
    402  if (!CallerSubsumes(&aSubjectPrincipal)) {
    403    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    404    return;
    405  }
    406 
    407  nsCOMPtr<nsIURI> uri;
    408  aRv = GetURI(getter_AddRefs(uri));
    409  if (NS_WARN_IF(aRv.Failed() || !uri)) {
    410    return;
    411  }
    412 
    413  // perhaps use nsReadingIterators at some point?
    414  nsAutoCString portStr(aPort);
    415  const char* buf = portStr.get();
    416  int32_t port = -1;
    417 
    418  if (!portStr.IsEmpty() && buf) {
    419    // Sadly, ToInteger() on nsACString does not have the right semantics.
    420    if (*buf == ':') {
    421      port = atol(buf + 1);
    422    } else {
    423      port = atol(buf);
    424    }
    425  }
    426 
    427  aRv = NS_MutateURI(uri).SetPort(port).Finalize(uri);
    428  if (NS_WARN_IF(aRv.Failed())) {
    429    return;
    430  }
    431 
    432  Navigate(uri, aSubjectPrincipal, aRv);
    433 }
    434 
    435 void Location::GetProtocol(nsACString& aProtocol,
    436                           nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
    437  if (!CallerSubsumes(&aSubjectPrincipal)) {
    438    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    439    return;
    440  }
    441 
    442  aProtocol.SetLength(0);
    443 
    444  nsCOMPtr<nsIURI> uri;
    445  aRv = GetURI(getter_AddRefs(uri));
    446  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    447    return;
    448  }
    449 
    450  aRv = uri->GetScheme(aProtocol);
    451  if (NS_WARN_IF(aRv.Failed())) {
    452    return;
    453  }
    454 
    455  aProtocol.Append(':');
    456 }
    457 
    458 void Location::SetProtocol(const nsACString& aProtocol,
    459                           nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
    460  if (!CallerSubsumes(&aSubjectPrincipal)) {
    461    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    462    return;
    463  }
    464 
    465  nsCOMPtr<nsIURI> uri;
    466  aRv = GetURI(getter_AddRefs(uri));
    467  if (NS_WARN_IF(aRv.Failed()) || !uri) {
    468    return;
    469  }
    470 
    471  nsACString::const_iterator start, end;
    472  aProtocol.BeginReading(start);
    473  aProtocol.EndReading(end);
    474  nsACString::const_iterator iter(start);
    475  (void)FindCharInReadable(':', iter, end);
    476 
    477  nsresult rv =
    478      NS_MutateURI(uri).SetScheme(Substring(start, iter)).Finalize(uri);
    479  if (NS_WARN_IF(NS_FAILED(rv))) {
    480    // Oh, I wish nsStandardURL returned NS_ERROR_MALFORMED_URI for _all_ the
    481    // malformed cases, not just some of them!
    482    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
    483    return;
    484  }
    485 
    486  nsAutoCString newSpec;
    487  aRv = uri->GetSpec(newSpec);
    488  if (NS_WARN_IF(aRv.Failed())) {
    489    return;
    490  }
    491  // We may want a new URI class for the new URI, so recreate it:
    492  rv = NS_NewURI(getter_AddRefs(uri), newSpec);
    493  if (NS_FAILED(rv)) {
    494    if (rv == NS_ERROR_MALFORMED_URI) {
    495      rv = NS_ERROR_DOM_SYNTAX_ERR;
    496    }
    497 
    498    aRv.Throw(rv);
    499    return;
    500  }
    501 
    502  if (!net::SchemeIsHttpOrHttps(uri)) {
    503    // No-op, per spec.
    504    return;
    505  }
    506 
    507  Navigate(uri, aSubjectPrincipal, aRv);
    508 }
    509 
    510 void Location::GetSearch(nsACString& aSearch, nsIPrincipal& aSubjectPrincipal,
    511                         ErrorResult& aRv) {
    512  if (!CallerSubsumes(&aSubjectPrincipal)) {
    513    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    514    return;
    515  }
    516 
    517  aSearch.SetLength(0);
    518 
    519  nsCOMPtr<nsIURI> uri;
    520  nsresult result = NS_OK;
    521 
    522  result = GetURI(getter_AddRefs(uri));
    523 
    524  nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
    525 
    526  if (url) {
    527    nsAutoCString search;
    528 
    529    result = url->GetQuery(search);
    530 
    531    if (NS_SUCCEEDED(result) && !search.IsEmpty()) {
    532      aSearch.SetCapacity(search.Length() + 1);
    533      aSearch.Assign('?');
    534      aSearch.Append(search);
    535    }
    536  }
    537 }
    538 
    539 void Location::SetSearch(const nsACString& aSearch,
    540                         nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
    541  if (!CallerSubsumes(&aSubjectPrincipal)) {
    542    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    543    return;
    544  }
    545 
    546  nsCOMPtr<nsIURI> uri;
    547  aRv = GetURI(getter_AddRefs(uri));
    548  nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
    549  if (NS_WARN_IF(aRv.Failed()) || !url) {
    550    return;
    551  }
    552 
    553  aRv = NS_MutateURI(uri).SetQuery(aSearch).Finalize(uri);
    554  if (NS_WARN_IF(aRv.Failed())) {
    555    return;
    556  }
    557 
    558  Navigate(uri, aSubjectPrincipal, aRv);
    559 }
    560 
    561 void Location::Reload(JSContext* aCx, bool aForceget,
    562                      nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) {
    563  if (!CallerSubsumes(&aSubjectPrincipal)) {
    564    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    565    return;
    566  }
    567 
    568  RefPtr<nsDocShell> docShell(nsDocShell::Cast(GetDocShell()));
    569  if (!docShell) {
    570    return aRv.Throw(NS_ERROR_FAILURE);
    571  }
    572 
    573  RefPtr<BrowsingContext> bc = GetBrowsingContext();
    574  if (!bc || bc->IsDiscarded()) {
    575    return;
    576  }
    577 
    578  CallerType callerType = aSubjectPrincipal.IsSystemPrincipal()
    579                              ? CallerType::System
    580                              : CallerType::NonSystem;
    581 
    582  nsresult rv = bc->CheckNavigationRateLimit(callerType);
    583  if (NS_FAILED(rv)) {
    584    aRv.Throw(rv);
    585    return;
    586  }
    587 
    588  uint32_t reloadFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
    589 
    590  if (aForceget) {
    591    reloadFlags = nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE |
    592                  nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
    593  }
    594 
    595  UserNavigationInvolvement userInvolvement =
    596      callerType == CallerType::System ? UserNavigationInvolvement::BrowserUI
    597                                       : UserNavigationInvolvement::None;
    598 
    599  rv = docShell->ReloadNavigable(Some(WrapNotNull(aCx)), reloadFlags, nullptr,
    600                                 userInvolvement);
    601  if (NS_FAILED(rv) && rv != NS_BINDING_ABORTED) {
    602    // NS_BINDING_ABORTED is returned when we attempt to reload a POST result
    603    // and the user says no at the "do you want to reload?" prompt.  Don't
    604    // propagate this one back to callers.
    605    return aRv.Throw(rv);
    606  }
    607 }
    608 
    609 void Location::Assign(const nsACString& aUrl, nsIPrincipal& aSubjectPrincipal,
    610                      ErrorResult& aRv) {
    611  if (!CallerSubsumes(&aSubjectPrincipal)) {
    612    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
    613    return;
    614  }
    615 
    616  DoSetHref(aUrl, aSubjectPrincipal, false, aRv);
    617 }
    618 
    619 bool Location::CallerSubsumes(nsIPrincipal* aSubjectPrincipal) {
    620  MOZ_ASSERT(aSubjectPrincipal);
    621 
    622  BrowsingContext* bc = GetBrowsingContext();
    623  if (MOZ_UNLIKELY(!bc) || MOZ_UNLIKELY(bc->IsDiscarded())) {
    624    // Per spec, operations on a Location object with a discarded BC are no-ops,
    625    // not security errors, so we need to return true from the access check and
    626    // let the caller do its own discarded docShell check.
    627    return true;
    628  }
    629  if (MOZ_UNLIKELY(!bc->IsInProcess())) {
    630    return false;
    631  }
    632 
    633  // Get the principal associated with the location object.  Note that this is
    634  // the principal of the page which will actually be navigated, not the
    635  // principal of the Location object itself.  This is why we need this check
    636  // even though we only allow limited cross-origin access to Location objects
    637  // in general.
    638  nsPIDOMWindowOuter* outer = bc->GetDOMWindow();
    639  MOZ_DIAGNOSTIC_ASSERT(outer);
    640  if (MOZ_UNLIKELY(!outer)) return false;
    641 
    642  nsIScriptObjectPrincipal* sop = nsGlobalWindowOuter::Cast(outer);
    643  bool subsumes = false;
    644  nsresult rv = aSubjectPrincipal->SubsumesConsideringDomain(
    645      sop->GetPrincipal(), &subsumes);
    646  NS_ENSURE_SUCCESS(rv, false);
    647  return subsumes;
    648 }
    649 
    650 JSObject* Location::WrapObject(JSContext* aCx,
    651                               JS::Handle<JSObject*> aGivenProto) {
    652  return Location_Binding::Wrap(aCx, this, aGivenProto);
    653 }
    654 
    655 void Location::ClearCachedValues() { mCachedHash = VoidCString(); }
    656 
    657 }  // namespace mozilla::dom