/src/mozilla-central/dom/base/nsIGlobalObject.cpp
Line | Count | Source (jump to first uncovered line) |
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 |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "nsIGlobalObject.h" |
8 | | |
9 | | #include "mozilla/dom/BlobURLProtocolHandler.h" |
10 | | #include "mozilla/dom/ServiceWorker.h" |
11 | | #include "mozilla/dom/ServiceWorkerRegistration.h" |
12 | | #include "nsContentUtils.h" |
13 | | #include "nsThreadUtils.h" |
14 | | #include "nsGlobalWindowInner.h" |
15 | | |
16 | | using mozilla::MallocSizeOf; |
17 | | using mozilla::Maybe; |
18 | | using mozilla::DOMEventTargetHelper; |
19 | | using mozilla::dom::BlobURLProtocolHandler; |
20 | | using mozilla::dom::ClientInfo; |
21 | | using mozilla::dom::ServiceWorker; |
22 | | using mozilla::dom::ServiceWorkerDescriptor; |
23 | | using mozilla::dom::ServiceWorkerRegistration; |
24 | | using mozilla::dom::ServiceWorkerRegistrationDescriptor; |
25 | | |
26 | | nsIGlobalObject::~nsIGlobalObject() |
27 | 0 | { |
28 | 0 | UnlinkHostObjectURIs(); |
29 | 0 | DisconnectEventTargetObjects(); |
30 | 0 | MOZ_DIAGNOSTIC_ASSERT(mEventTargetObjects.isEmpty()); |
31 | 0 | } |
32 | | |
33 | | nsIPrincipal* |
34 | | nsIGlobalObject::PrincipalOrNull() |
35 | 0 | { |
36 | 0 | JSObject *global = GetGlobalJSObject(); |
37 | 0 | if (NS_WARN_IF(!global)) |
38 | 0 | return nullptr; |
39 | 0 | |
40 | 0 | return nsContentUtils::ObjectPrincipal(global); |
41 | 0 | } |
42 | | |
43 | | void |
44 | | nsIGlobalObject::RegisterHostObjectURI(const nsACString& aURI) |
45 | 0 | { |
46 | 0 | MOZ_ASSERT(!mHostObjectURIs.Contains(aURI)); |
47 | 0 | mHostObjectURIs.AppendElement(aURI); |
48 | 0 | } |
49 | | |
50 | | void |
51 | | nsIGlobalObject::UnregisterHostObjectURI(const nsACString& aURI) |
52 | 0 | { |
53 | 0 | mHostObjectURIs.RemoveElement(aURI); |
54 | 0 | } |
55 | | |
56 | | namespace { |
57 | | |
58 | | class UnlinkHostObjectURIsRunnable final : public mozilla::Runnable |
59 | | { |
60 | | public: |
61 | | explicit UnlinkHostObjectURIsRunnable(nsTArray<nsCString>& aURIs) |
62 | | : mozilla::Runnable("UnlinkHostObjectURIsRunnable") |
63 | 0 | { |
64 | 0 | mURIs.SwapElements(aURIs); |
65 | 0 | } |
66 | | |
67 | | NS_IMETHOD Run() override |
68 | 0 | { |
69 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
70 | 0 |
|
71 | 0 | for (uint32_t index = 0; index < mURIs.Length(); ++index) { |
72 | 0 | BlobURLProtocolHandler::RemoveDataEntry(mURIs[index]); |
73 | 0 | } |
74 | 0 |
|
75 | 0 | return NS_OK; |
76 | 0 | } |
77 | | |
78 | | private: |
79 | 0 | ~UnlinkHostObjectURIsRunnable() {} |
80 | | |
81 | | nsTArray<nsCString> mURIs; |
82 | | }; |
83 | | |
84 | | } // namespace |
85 | | |
86 | | void |
87 | | nsIGlobalObject::UnlinkHostObjectURIs() |
88 | 0 | { |
89 | 0 | if (mHostObjectURIs.IsEmpty()) { |
90 | 0 | return; |
91 | 0 | } |
92 | 0 | |
93 | 0 | if (NS_IsMainThread()) { |
94 | 0 | for (uint32_t index = 0; index < mHostObjectURIs.Length(); ++index) { |
95 | 0 | BlobURLProtocolHandler::RemoveDataEntry(mHostObjectURIs[index]); |
96 | 0 | } |
97 | 0 |
|
98 | 0 | mHostObjectURIs.Clear(); |
99 | 0 | return; |
100 | 0 | } |
101 | 0 |
|
102 | 0 | // BlobURLProtocolHandler is main-thread only. |
103 | 0 |
|
104 | 0 | RefPtr<UnlinkHostObjectURIsRunnable> runnable = |
105 | 0 | new UnlinkHostObjectURIsRunnable(mHostObjectURIs); |
106 | 0 | MOZ_ASSERT(mHostObjectURIs.IsEmpty()); |
107 | 0 |
|
108 | 0 | nsresult rv = NS_DispatchToMainThread(runnable); |
109 | 0 | if (NS_FAILED(rv)) { |
110 | 0 | NS_WARNING("Failed to dispatch a runnable to the main-thread."); |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | | void |
115 | | nsIGlobalObject::TraverseHostObjectURIs(nsCycleCollectionTraversalCallback &aCb) |
116 | 0 | { |
117 | 0 | if (mHostObjectURIs.IsEmpty()) { |
118 | 0 | return; |
119 | 0 | } |
120 | 0 | |
121 | 0 | // Currently we only store BlobImpl objects off the the main-thread and they |
122 | 0 | // are not CCed. |
123 | 0 | if (!NS_IsMainThread()) { |
124 | 0 | return; |
125 | 0 | } |
126 | 0 | |
127 | 0 | for (uint32_t index = 0; index < mHostObjectURIs.Length(); ++index) { |
128 | 0 | BlobURLProtocolHandler::Traverse(mHostObjectURIs[index], aCb); |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | | void |
133 | | nsIGlobalObject::AddEventTargetObject(DOMEventTargetHelper* aObject) |
134 | 0 | { |
135 | 0 | MOZ_DIAGNOSTIC_ASSERT(aObject); |
136 | 0 | MOZ_ASSERT(!aObject->isInList()); |
137 | 0 | mEventTargetObjects.insertBack(aObject); |
138 | 0 | } |
139 | | |
140 | | void |
141 | | nsIGlobalObject::RemoveEventTargetObject(DOMEventTargetHelper* aObject) |
142 | 0 | { |
143 | 0 | MOZ_DIAGNOSTIC_ASSERT(aObject); |
144 | 0 | MOZ_ASSERT(aObject->isInList()); |
145 | 0 | MOZ_ASSERT(aObject->GetOwnerGlobal() == this); |
146 | 0 | aObject->remove(); |
147 | 0 | } |
148 | | |
149 | | void |
150 | | nsIGlobalObject::ForEachEventTargetObject(const std::function<void(DOMEventTargetHelper*, bool* aDoneOut)>& aFunc) const |
151 | 0 | { |
152 | 0 | // Protect against the function call triggering a mutation of the list |
153 | 0 | // while we are iterating by copying the DETH references to a temporary |
154 | 0 | // list. |
155 | 0 | AutoTArray<RefPtr<DOMEventTargetHelper>, 64> targetList; |
156 | 0 | for (const DOMEventTargetHelper* deth = mEventTargetObjects.getFirst(); |
157 | 0 | deth; deth = deth->getNext()) { |
158 | 0 | targetList.AppendElement(const_cast<DOMEventTargetHelper*>(deth)); |
159 | 0 | } |
160 | 0 |
|
161 | 0 | // Iterate the target list and call the function on each one. |
162 | 0 | bool done = false; |
163 | 0 | for (auto target : targetList) { |
164 | 0 | // Check to see if a previous iteration's callback triggered the removal |
165 | 0 | // of this target as a side-effect. If it did, then just ignore it. |
166 | 0 | if (target->GetOwnerGlobal() != this) { |
167 | 0 | continue; |
168 | 0 | } |
169 | 0 | aFunc(target, &done); |
170 | 0 | if (done) { |
171 | 0 | break; |
172 | 0 | } |
173 | 0 | } |
174 | 0 | } |
175 | | |
176 | | void |
177 | | nsIGlobalObject::DisconnectEventTargetObjects() |
178 | 0 | { |
179 | 0 | ForEachEventTargetObject([&] (DOMEventTargetHelper* aTarget, bool* aDoneOut) { |
180 | 0 | aTarget->DisconnectFromOwner(); |
181 | 0 |
|
182 | 0 | // Calling DisconnectFromOwner() should result in |
183 | 0 | // RemoveEventTargetObject() being called. |
184 | 0 | MOZ_DIAGNOSTIC_ASSERT(aTarget->GetOwnerGlobal() != this); |
185 | 0 | }); |
186 | 0 | } |
187 | | |
188 | | Maybe<ClientInfo> |
189 | | nsIGlobalObject::GetClientInfo() const |
190 | 0 | { |
191 | 0 | // By default globals do not expose themselves as a client. Only real |
192 | 0 | // window and worker globals are currently considered clients. |
193 | 0 | return Maybe<ClientInfo>(); |
194 | 0 | } |
195 | | |
196 | | Maybe<ServiceWorkerDescriptor> |
197 | | nsIGlobalObject::GetController() const |
198 | 0 | { |
199 | 0 | // By default globals do not have a service worker controller. Only real |
200 | 0 | // window and worker globals can currently be controlled as a client. |
201 | 0 | return Maybe<ServiceWorkerDescriptor>(); |
202 | 0 | } |
203 | | |
204 | | RefPtr<ServiceWorker> |
205 | | nsIGlobalObject::GetOrCreateServiceWorker(const ServiceWorkerDescriptor& aDescriptor) |
206 | 0 | { |
207 | 0 | MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers"); |
208 | 0 | return nullptr; |
209 | 0 | } |
210 | | |
211 | | RefPtr<ServiceWorkerRegistration> |
212 | | nsIGlobalObject::GetServiceWorkerRegistration(const mozilla::dom::ServiceWorkerRegistrationDescriptor& aDescriptor) const |
213 | 0 | { |
214 | 0 | MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers"); |
215 | 0 | return nullptr; |
216 | 0 | } |
217 | | |
218 | | RefPtr<ServiceWorkerRegistration> |
219 | | nsIGlobalObject::GetOrCreateServiceWorkerRegistration(const ServiceWorkerRegistrationDescriptor& aDescriptor) |
220 | 0 | { |
221 | 0 | MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service worker registrations"); |
222 | 0 | return nullptr; |
223 | 0 | } |
224 | | |
225 | | nsPIDOMWindowInner* |
226 | | nsIGlobalObject::AsInnerWindow() |
227 | 0 | { |
228 | 0 | if (MOZ_LIKELY(mIsInnerWindow)) { |
229 | 0 | return static_cast<nsPIDOMWindowInner*>(static_cast<nsGlobalWindowInner*>(this)); |
230 | 0 | } |
231 | 0 | return nullptr; |
232 | 0 | } |
233 | | |
234 | | size_t |
235 | | nsIGlobalObject::ShallowSizeOfExcludingThis(MallocSizeOf aSizeOf) const |
236 | 0 | { |
237 | 0 | size_t rtn = mHostObjectURIs.ShallowSizeOfExcludingThis(aSizeOf); |
238 | 0 | return rtn; |
239 | 0 | } |