Coverage Report

Created: 2018-09-25 14:53

/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
}