summaryrefslogtreecommitdiffstats
path: root/dom/base/DocGroup.h
blob: fb8c552fbfd8bb1070f64c59294bbe14de91c509 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef DocGroup_h
#define DocGroup_h

#include "nsISupportsImpl.h"
#include "nsIPrincipal.h"
#include "nsThreadUtils.h"
#include "nsTHashSet.h"
#include "nsString.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/PerformanceCounter.h"
#include "mozilla/PerformanceTypes.h"

namespace mozilla {
class AbstractThread;
namespace dom {

class CustomElementReactionsStack;
class JSExecutionManager;

// Two browsing contexts are considered "related" if they are reachable from one
// another through window.opener, window.parent, or window.frames. This is the
// spec concept of a browsing context group.
//
// Two browsing contexts are considered "similar-origin" if they can be made to
// have the same origin by setting document.domain. This is the spec concept of
// a "unit of similar-origin related browsing contexts"
//
// A BrowsingContextGroup is a set of browsing contexts which are all
// "related".  Within a BrowsingContextGroup, browsing contexts are
// broken into "similar-origin" DocGroups.  A DocGroup is a member
// of exactly one BrowsingContextGroup.
class DocGroup final {
 public:
  typedef nsTArray<Document*>::iterator Iterator;

  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DocGroup)
  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(DocGroup)

  static already_AddRefed<DocGroup> Create(
      BrowsingContextGroup* aBrowsingContextGroup, const nsACString& aKey);

  // Returns NS_ERROR_FAILURE and sets |aString| to an empty string if the TLD
  // service isn't available. Returns NS_OK on success, but may still set
  // |aString| may still be set to an empty string.
  [[nodiscard]] static nsresult GetKey(nsIPrincipal* aPrincipal,
                                       bool aCrossOriginIsolated,
                                       nsACString& aKey);

  bool MatchesKey(const nsACString& aKey) { return aKey == mKey; }

  const nsACString& GetKey() const { return mKey; }

  PerformanceCounter* GetPerformanceCounter() { return mPerformanceCounter; }

  JSExecutionManager* GetExecutionManager() const { return mExecutionManager; }
  void SetExecutionManager(JSExecutionManager*);

  RefPtr<PerformanceInfoPromise> ReportPerformanceInfo();

  BrowsingContextGroup* GetBrowsingContextGroup() const {
    return mBrowsingContextGroup;
  }

  mozilla::dom::DOMArena* ArenaAllocator() { return mArena; }

  mozilla::dom::CustomElementReactionsStack* CustomElementReactionsStack();

  // Adding documents to a DocGroup should be done through
  // BrowsingContextGroup::AddDocument (which in turn calls
  // DocGroup::AddDocument).
  void AddDocument(Document* aDocument);

  // Removing documents from a DocGroup should be done through
  // BrowsingContextGroup::RemoveDocument(which in turn calls
  // DocGroup::RemoveDocument).
  void RemoveDocument(Document* aDocument);

  // Iterators for iterating over every document within the DocGroup
  Iterator begin() {
    MOZ_ASSERT(NS_IsMainThread());
    return mDocuments.begin();
  }
  Iterator end() {
    MOZ_ASSERT(NS_IsMainThread());
    return mDocuments.end();
  }

  nsresult Dispatch(TaskCategory aCategory,
                    already_AddRefed<nsIRunnable>&& aRunnable);

  nsISerialEventTarget* EventTargetFor(TaskCategory aCategory) const;

  AbstractThread* AbstractMainThreadFor(TaskCategory aCategory);

  // Return a pointer that can be continually checked to see if access to this
  // DocGroup is valid. This pointer should live at least as long as the
  // DocGroup.
  bool* GetValidAccessPtr();

  // Append aSlot to the list of signal slot list, and queue a mutation observer
  // microtask.
  void SignalSlotChange(HTMLSlotElement& aSlot);

  nsTArray<RefPtr<HTMLSlotElement>> MoveSignalSlotList();

  // List of DocGroups that has non-empty signal slot list.
  static AutoTArray<RefPtr<DocGroup>, 2>* sPendingDocGroups;

  // Returns true if any of its documents are active but not in the bfcache.
  bool IsActive() const;

  nsresult QueueIframePostMessages(already_AddRefed<nsIRunnable>&& aRunnable,
                                   uint64_t aWindowId);

  void TryFlushIframePostMessages(uint64_t aWindowId);

  static bool TryToLoadIframesInBackground();

  const nsID& AgentClusterId() const { return mAgentClusterId; }

  bool IsEmpty() const { return mDocuments.IsEmpty(); }

 private:
  DocGroup(BrowsingContextGroup* aBrowsingContextGroup, const nsACString& aKey);

  ~DocGroup();

  void FlushIframePostMessageQueue();
  nsCString mKey;
  nsTArray<Document*> mDocuments;
  RefPtr<mozilla::dom::CustomElementReactionsStack> mReactionsStack;
  nsTArray<RefPtr<HTMLSlotElement>> mSignalSlotList;
  RefPtr<mozilla::PerformanceCounter> mPerformanceCounter;
  RefPtr<BrowsingContextGroup> mBrowsingContextGroup;
  RefPtr<mozilla::ThrottledEventQueue> mIframePostMessageQueue;
  nsTHashSet<uint64_t> mIframesUsedPostMessageQueue;
  nsCOMPtr<nsISerialEventTarget> mEventTarget;

  // non-null if the JS execution for this docgroup is regulated with regards
  // to worker threads. This should only be used when we are forcing serialized
  // SAB access.
  RefPtr<JSExecutionManager> mExecutionManager;

  // Each DocGroup has a persisted agent cluster ID.
  const nsID mAgentClusterId;

  RefPtr<mozilla::dom::DOMArena> mArena;
};

}  // namespace dom
}  // namespace mozilla

#endif  // defined(DocGroup_h)