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 #include "mozilla/dom/TabGroup.h"
9 #include "mozilla/Telemetry.h"
10 #include "nsIDocShell.h"
11 #include "nsDOMMutationObserver.h"
12
13 namespace mozilla {
14 namespace dom {
15
16 AutoTArray<RefPtr<DocGroup>, 2>* DocGroup::sPendingDocGroups = nullptr;
17
GetKey(nsIPrincipal * aPrincipal,nsACString & aKey)18 /* static */ nsresult DocGroup::GetKey(nsIPrincipal* aPrincipal,
19 nsACString& aKey) {
20 // Use GetBaseDomain() to handle things like file URIs, IP address URIs,
21 // etc. correctly.
22 nsresult rv = aPrincipal->GetBaseDomain(aKey);
23 if (NS_FAILED(rv)) {
24 // We don't really know what to do here. But we should be conservative,
25 // otherwise it would be possible to reorder two events incorrectly in the
26 // future if we interrupt at the DocGroup level, so to be safe, use an
27 // empty string to classify all such documents as belonging to the same
28 // DocGroup.
29 aKey.Truncate();
30 }
31
32 return rv;
33 }
34
RemoveDocument(nsIDocument * aDocument)35 void DocGroup::RemoveDocument(nsIDocument* aDocument) {
36 MOZ_ASSERT(NS_IsMainThread());
37 MOZ_ASSERT(mDocuments.Contains(aDocument));
38 mDocuments.RemoveElement(aDocument);
39 }
40
DocGroup(TabGroup * aTabGroup,const nsACString & aKey)41 DocGroup::DocGroup(TabGroup* aTabGroup, const nsACString& aKey)
42 : mKey(aKey), mTabGroup(aTabGroup) {
43 // This method does not add itself to mTabGroup->mDocGroups as the caller does
44 // it for us.
45 }
46
~DocGroup()47 DocGroup::~DocGroup() {
48 MOZ_ASSERT(mDocuments.IsEmpty());
49 if (!NS_IsMainThread()) {
50 nsIEventTarget* target = EventTargetFor(TaskCategory::Other);
51 NS_ProxyRelease("DocGroup::mReactionsStack", target,
52 mReactionsStack.forget());
53 }
54
55 mTabGroup->mDocGroups.RemoveEntry(mKey);
56 }
57
Dispatch(TaskCategory aCategory,already_AddRefed<nsIRunnable> && aRunnable)58 nsresult DocGroup::Dispatch(TaskCategory aCategory,
59 already_AddRefed<nsIRunnable>&& aRunnable) {
60 return mTabGroup->DispatchWithDocGroup(aCategory, Move(aRunnable), this);
61 }
62
EventTargetFor(TaskCategory aCategory) const63 nsISerialEventTarget* DocGroup::EventTargetFor(TaskCategory aCategory) const {
64 return mTabGroup->EventTargetFor(aCategory);
65 }
66
AbstractMainThreadFor(TaskCategory aCategory)67 AbstractThread* DocGroup::AbstractMainThreadFor(TaskCategory aCategory) {
68 MOZ_RELEASE_ASSERT(NS_IsMainThread());
69 return mTabGroup->AbstractMainThreadFor(aCategory);
70 }
71
GetValidAccessPtr()72 bool* DocGroup::GetValidAccessPtr() { return mTabGroup->GetValidAccessPtr(); }
73
SignalSlotChange(const HTMLSlotElement * aSlot)74 void DocGroup::SignalSlotChange(const HTMLSlotElement* aSlot) {
75 if (mSignalSlotList.Contains(aSlot)) {
76 return;
77 }
78
79 mSignalSlotList.AppendElement(const_cast<HTMLSlotElement*>(aSlot));
80
81 if (!sPendingDocGroups) {
82 // Queue a mutation observer compound microtask.
83 nsDOMMutationObserver::QueueMutationObserverMicroTask();
84 sPendingDocGroups = new AutoTArray<RefPtr<DocGroup>, 2>;
85 }
86
87 sPendingDocGroups->AppendElement(this);
88 }
89
90 } // namespace dom
91 } // namespace mozilla
92