Bug 1854550 - pt 10. Allow LOG() with zero extra arguments r=glandium
[gecko.git] / dom / base / DocGroup.cpp
blob7c7f44de396bf45dc12495794e68a620bc1330ac
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"
23 #include "nsThread.h"
24 #if defined(XP_WIN)
25 # include <processthreadsapi.h> // for GetCurrentProcessId()
26 #else
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
50 /* static */
51 already_AddRefed<DocGroup> DocGroup::Create(
52 BrowsingContextGroup* aBrowsingContextGroup, const nsACString& aKey) {
53 return do_AddRef(new DocGroup(aBrowsingContextGroup, aKey));
56 /* static */
57 nsresult DocGroup::GetKey(nsIPrincipal* aPrincipal, bool aCrossOriginIsolated,
58 nsACString& aKey) {
59 // Use GetBaseDomain() to handle things like file URIs, IP address URIs,
60 // etc. correctly.
61 nsresult rv = aCrossOriginIsolated ? aPrincipal->GetOrigin(aKey)
62 : aPrincipal->GetSiteOrigin(aKey);
63 if (NS_FAILED(rv)) {
64 aKey.Truncate();
67 return rv;
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
92 // elsewhere.
93 MOZ_ASSERT_IF(
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)
111 : mKey(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());
126 if (mIframePostMessageQueue) {
127 FlushIframePostMessageQueue();
130 void DocGroup::SignalSlotChange(HTMLSlotElement& aSlot) {
131 MOZ_ASSERT(!mSignalSlotList.Contains(&aSlot));
132 mSignalSlotList.AppendElement(&aSlot);
134 if (!sPendingDocGroups) {
135 // Queue a mutation observer compound microtask.
136 nsDOMMutationObserver::QueueMutationObserverMicroTask();
137 sPendingDocGroups = new AutoTArray<RefPtr<DocGroup>, 2>;
140 sPendingDocGroups->AppendElement(this);
143 bool DocGroup::TryToLoadIframesInBackground() {
144 return !FissionAutostart() &&
145 StaticPrefs::dom_separate_event_queue_for_post_message_enabled() &&
146 StaticPrefs::dom_cross_origin_iframes_loaded_in_background();
149 nsresult DocGroup::QueueIframePostMessages(
150 already_AddRefed<nsIRunnable>&& aRunnable, uint64_t aWindowId) {
151 if (DocGroup::TryToLoadIframesInBackground()) {
152 if (!mIframePostMessageQueue) {
153 nsCOMPtr<nsISerialEventTarget> target = GetMainThreadSerialEventTarget();
154 mIframePostMessageQueue = ThrottledEventQueue::Create(
155 target, "Background Loading Iframe PostMessage Queue",
156 nsIRunnablePriority::PRIORITY_DEFERRED_TIMERS);
157 nsresult rv = mIframePostMessageQueue->SetIsPaused(true);
158 MOZ_ALWAYS_SUCCEEDS(rv);
161 // Ensure the queue is disabled. Unlike the postMessageEvent queue
162 // in BrowsingContextGroup, this postMessage queue should always
163 // be paused, because if we leave it open, the postMessage may get
164 // dispatched to an unloaded iframe
165 MOZ_ASSERT(mIframePostMessageQueue);
166 MOZ_ASSERT(mIframePostMessageQueue->IsPaused());
168 mIframesUsedPostMessageQueue.Insert(aWindowId);
170 mIframePostMessageQueue->Dispatch(std::move(aRunnable), NS_DISPATCH_NORMAL);
171 return NS_OK;
173 return NS_ERROR_FAILURE;
176 void DocGroup::TryFlushIframePostMessages(uint64_t aWindowId) {
177 if (DocGroup::TryToLoadIframesInBackground()) {
178 mIframesUsedPostMessageQueue.Remove(aWindowId);
179 if (mIframePostMessageQueue && mIframesUsedPostMessageQueue.IsEmpty()) {
180 MOZ_ASSERT(mIframePostMessageQueue->IsPaused());
181 nsresult rv = mIframePostMessageQueue->SetIsPaused(true);
182 MOZ_ALWAYS_SUCCEEDS(rv);
183 FlushIframePostMessageQueue();
188 void DocGroup::FlushIframePostMessageQueue() {
189 nsCOMPtr<nsIRunnable> event;
190 while ((event = mIframePostMessageQueue->GetEvent())) {
191 SchedulerGroup::Dispatch(event.forget());
195 nsTArray<RefPtr<HTMLSlotElement>> DocGroup::MoveSignalSlotList() {
196 for (const RefPtr<HTMLSlotElement>& slot : mSignalSlotList) {
197 slot->RemovedFromSignalSlotList();
199 return std::move(mSignalSlotList);
202 bool DocGroup::IsActive() const {
203 for (Document* doc : mDocuments) {
204 if (doc->IsCurrentActiveDocument()) {
205 return true;
209 return false;
212 } // namespace mozilla::dom