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/. */
7 #include "mozilla/dom/DocGroup.h"
9 #include "mozilla/AbstractThread.h"
10 #include "mozilla/SchedulerGroup.h"
11 #include "mozilla/StaticPrefs_dom.h"
12 #include "mozilla/Telemetry.h"
13 #include "mozilla/ThrottledEventQueue.h"
14 #include "mozilla/dom/BrowsingContext.h"
15 #include "mozilla/dom/CustomElementRegistry.h"
16 #include "mozilla/dom/DOMTypes.h"
17 #include "mozilla/dom/JSExecutionManager.h"
18 #include "mozilla/dom/WindowContext.h"
19 #include "nsDOMMutationObserver.h"
20 #include "nsIDirectTaskDispatcher.h"
21 #include "nsIXULRuntime.h"
22 #include "nsProxyRelease.h"
25 # include <processthreadsapi.h> // for GetCurrentProcessId()
27 # include <unistd.h> // for getpid()
28 #endif // defined(XP_WIN)
30 namespace mozilla::dom
{
32 AutoTArray
<RefPtr
<DocGroup
>, 2>* DocGroup::sPendingDocGroups
= nullptr;
34 NS_IMPL_CYCLE_COLLECTION_CLASS(DocGroup
)
36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DocGroup
)
37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSignalSlotList
)
38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContextGroup
)
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
41 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DocGroup
)
42 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSignalSlotList
)
43 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContextGroup
)
45 // If we still have any documents in this array, they were just unlinked, so
46 // clear out our weak pointers to them.
47 tmp
->mDocuments
.Clear();
48 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
51 already_AddRefed
<DocGroup
> DocGroup::Create(
52 BrowsingContextGroup
* aBrowsingContextGroup
, const nsACString
& aKey
) {
53 return do_AddRef(new DocGroup(aBrowsingContextGroup
, aKey
));
57 nsresult
DocGroup::GetKey(nsIPrincipal
* aPrincipal
, bool aCrossOriginIsolated
,
59 // Use GetBaseDomain() to handle things like file URIs, IP address URIs,
61 nsresult rv
= aCrossOriginIsolated
? aPrincipal
->GetOrigin(aKey
)
62 : aPrincipal
->GetSiteOrigin(aKey
);
70 void DocGroup::SetExecutionManager(JSExecutionManager
* aManager
) {
71 mExecutionManager
= aManager
;
74 mozilla::dom::CustomElementReactionsStack
*
75 DocGroup::CustomElementReactionsStack() {
76 MOZ_ASSERT(NS_IsMainThread());
77 if (!mReactionsStack
) {
78 mReactionsStack
= new mozilla::dom::CustomElementReactionsStack();
81 return mReactionsStack
;
84 void DocGroup::AddDocument(Document
* aDocument
) {
85 MOZ_ASSERT(NS_IsMainThread());
86 MOZ_ASSERT(!mDocuments
.Contains(aDocument
));
87 MOZ_ASSERT(mBrowsingContextGroup
);
88 // If the document is loaded as data it may not have a container, in which
89 // case it can be difficult to determine the BrowsingContextGroup it's
90 // associated with. XSLT can also add the document to the DocGroup before it
91 // gets a container in some cases, in which case this will be asserted
94 aDocument
->GetBrowsingContext(),
95 aDocument
->GetBrowsingContext()->Group() == mBrowsingContextGroup
);
96 mDocuments
.AppendElement(aDocument
);
99 void DocGroup::RemoveDocument(Document
* aDocument
) {
100 MOZ_ASSERT(NS_IsMainThread());
101 MOZ_ASSERT(mDocuments
.Contains(aDocument
));
102 mDocuments
.RemoveElement(aDocument
);
104 if (mDocuments
.IsEmpty()) {
105 mBrowsingContextGroup
= nullptr;
109 DocGroup::DocGroup(BrowsingContextGroup
* aBrowsingContextGroup
,
110 const nsACString
& aKey
)
112 mBrowsingContextGroup(aBrowsingContextGroup
),
113 mAgentClusterId(nsID::GenerateUUID()) {
114 // This method does not add itself to
115 // mBrowsingContextGroup->mDocGroups as the caller does it for us.
116 MOZ_ASSERT(NS_IsMainThread());
117 if (StaticPrefs::dom_arena_allocator_enabled_AtStartup()) {
118 mArena
= new mozilla::dom::DOMArena();
122 DocGroup::~DocGroup() {
123 MOZ_RELEASE_ASSERT(NS_IsMainThread());
124 MOZ_RELEASE_ASSERT(mDocuments
.IsEmpty());
127 void DocGroup::SignalSlotChange(HTMLSlotElement
& aSlot
) {
128 MOZ_ASSERT(!mSignalSlotList
.Contains(&aSlot
));
129 mSignalSlotList
.AppendElement(&aSlot
);
131 if (!sPendingDocGroups
) {
132 // Queue a mutation observer compound microtask.
133 nsDOMMutationObserver::QueueMutationObserverMicroTask();
134 sPendingDocGroups
= new AutoTArray
<RefPtr
<DocGroup
>, 2>;
137 sPendingDocGroups
->AppendElement(this);
140 nsTArray
<RefPtr
<HTMLSlotElement
>> DocGroup::MoveSignalSlotList() {
141 for (const RefPtr
<HTMLSlotElement
>& slot
: mSignalSlotList
) {
142 slot
->RemovedFromSignalSlotList();
144 return std::move(mSignalSlotList
);
147 bool DocGroup::IsActive() const {
148 for (Document
* doc
: mDocuments
) {
149 if (doc
->IsCurrentActiveDocument()) {
157 } // namespace mozilla::dom