tor-browser

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

DocGroup.cpp (5642B)


      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/dom/DocGroup.h"
      8 
      9 #include "mozilla/AbstractThread.h"
     10 #include "mozilla/SchedulerGroup.h"
     11 #include "mozilla/StaticPrefs_dom.h"
     12 #include "mozilla/ThrottledEventQueue.h"
     13 #include "mozilla/dom/BrowsingContext.h"
     14 #include "mozilla/dom/CustomElementRegistry.h"
     15 #include "mozilla/dom/DOMTypes.h"
     16 #include "mozilla/dom/JSExecutionManager.h"
     17 #include "mozilla/dom/WindowContext.h"
     18 #include "nsDOMMutationObserver.h"
     19 #include "nsIDirectTaskDispatcher.h"
     20 #include "nsIXULRuntime.h"
     21 #include "nsProxyRelease.h"
     22 #include "nsThread.h"
     23 #if defined(XP_WIN)
     24 #  include <processthreadsapi.h>  // for GetCurrentProcessId()
     25 #else
     26 #  include <unistd.h>  // for getpid()
     27 #endif                 // defined(XP_WIN)
     28 
     29 namespace mozilla::dom {
     30 
     31 AutoTArray<RefPtr<DocGroup>, 2>* DocGroup::sPendingDocGroups = nullptr;
     32 
     33 NS_IMPL_CYCLE_COLLECTION_CLASS(DocGroup)
     34 
     35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DocGroup)
     36  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSignalSlotList)
     37  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContextGroup)
     38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     39 
     40 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DocGroup)
     41  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSignalSlotList)
     42  NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContextGroup)
     43 
     44  // If we still have any documents in this array, they were just unlinked, so
     45  // clear out our weak pointers to them.
     46  tmp->mDocuments.Clear();
     47 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     48 
     49 /* static */
     50 already_AddRefed<DocGroup> DocGroup::Create(
     51    BrowsingContextGroup* aBrowsingContextGroup, const DocGroupKey& aKey) {
     52  return do_AddRef(new DocGroup(aBrowsingContextGroup, aKey));
     53 }
     54 
     55 void DocGroup::AssertMatches(const Document* aDocument) const {
     56  nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
     57 
     58  // Ensure that this DocGroup is correctly origin keyed / non-origin-keyed.
     59  Maybe<bool> usesOriginAgentCluster =
     60      mBrowsingContextGroup->UsesOriginAgentCluster(principal);
     61  MOZ_RELEASE_ASSERT(
     62      usesOriginAgentCluster.isSome(),
     63      "Document principal with unknown OriginAgentCluster behaviour");
     64  MOZ_RELEASE_ASSERT(*usesOriginAgentCluster == mKey.mOriginKeyed,
     65                     "DocGroup origin keying does not match Principal");
     66 
     67  // Ensure that the origin is as expected. Note that `GetSiteOrigin` can fail
     68  // after the TLD service is shut down, and we don't want to assert in that
     69  // case.
     70  nsresult rv = NS_ERROR_FAILURE;
     71  nsAutoCString key;
     72  if (mKey.mOriginKeyed) {
     73    rv = principal->GetOrigin(key);
     74  } else {
     75    rv = principal->GetSiteOrigin(key);
     76  }
     77  if (NS_SUCCEEDED(rv)) {
     78    MOZ_RELEASE_ASSERT(key == mKey.mKey,
     79                       "DocGroup Key does not match Document");
     80  }
     81 }
     82 
     83 void DocGroup::SetExecutionManager(JSExecutionManager* aManager) {
     84  mExecutionManager = aManager;
     85 }
     86 
     87 mozilla::dom::CustomElementReactionsStack*
     88 DocGroup::CustomElementReactionsStack() {
     89  MOZ_ASSERT(NS_IsMainThread());
     90  if (!mReactionsStack) {
     91    mReactionsStack = new mozilla::dom::CustomElementReactionsStack();
     92  }
     93 
     94  return mReactionsStack;
     95 }
     96 
     97 void DocGroup::AddDocument(Document* aDocument) {
     98  MOZ_ASSERT(NS_IsMainThread());
     99  MOZ_ASSERT(!mDocuments.Contains(aDocument));
    100  MOZ_ASSERT(mBrowsingContextGroup);
    101  // If the document is loaded as data it may not have a container, in which
    102  // case it can be difficult to determine the BrowsingContextGroup it's
    103  // associated with. XSLT can also add the document to the DocGroup before it
    104  // gets a container in some cases, in which case this will be asserted
    105  // elsewhere.
    106  MOZ_ASSERT_IF(
    107      aDocument->GetBrowsingContext(),
    108      aDocument->GetBrowsingContext()->Group() == mBrowsingContextGroup);
    109  mDocuments.AppendElement(aDocument);
    110 }
    111 
    112 void DocGroup::RemoveDocument(Document* aDocument) {
    113  MOZ_ASSERT(NS_IsMainThread());
    114  MOZ_ASSERT(mDocuments.Contains(aDocument));
    115  mDocuments.RemoveElement(aDocument);
    116 
    117  if (mDocuments.IsEmpty()) {
    118    mBrowsingContextGroup = nullptr;
    119  }
    120 }
    121 
    122 DocGroup::DocGroup(BrowsingContextGroup* aBrowsingContextGroup,
    123                   const DocGroupKey& aKey)
    124    : mKey(aKey),
    125      mBrowsingContextGroup(aBrowsingContextGroup),
    126      mAgentClusterId(nsID::GenerateUUID()) {
    127  // This method does not add itself to
    128  // mBrowsingContextGroup->mDocGroups as the caller does it for us.
    129  MOZ_ASSERT(NS_IsMainThread());
    130  if (StaticPrefs::dom_arena_allocator_enabled_AtStartup()) {
    131    mArena = new mozilla::dom::DOMArena(aKey.mKey);
    132  }
    133 }
    134 
    135 DocGroup::~DocGroup() {
    136  MOZ_RELEASE_ASSERT(NS_IsMainThread());
    137  MOZ_RELEASE_ASSERT(mDocuments.IsEmpty());
    138 }
    139 
    140 void DocGroup::SignalSlotChange(HTMLSlotElement& aSlot) {
    141  MOZ_ASSERT(!mSignalSlotList.Contains(&aSlot));
    142  mSignalSlotList.AppendElement(&aSlot);
    143 
    144  if (!sPendingDocGroups) {
    145    // Queue a mutation observer compound microtask.
    146    nsDOMMutationObserver::QueueMutationObserverMicroTask();
    147    sPendingDocGroups = new AutoTArray<RefPtr<DocGroup>, 2>;
    148  }
    149 
    150  sPendingDocGroups->AppendElement(this);
    151 }
    152 
    153 nsTArray<RefPtr<HTMLSlotElement>> DocGroup::MoveSignalSlotList() {
    154  for (const RefPtr<HTMLSlotElement>& slot : mSignalSlotList) {
    155    slot->RemovedFromSignalSlotList();
    156  }
    157  return std::move(mSignalSlotList);
    158 }
    159 
    160 bool DocGroup::IsActive() const {
    161  for (Document* doc : mDocuments) {
    162    if (doc->IsCurrentActiveDocument()) {
    163      return true;
    164    }
    165  }
    166 
    167  return false;
    168 }
    169 
    170 }  // namespace mozilla::dom