Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/workers/SharedWorker.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 file,
5
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "SharedWorker.h"
8
9
#include "nsPIDOMWindow.h"
10
11
#include "mozilla/EventDispatcher.h"
12
#include "mozilla/Preferences.h"
13
#include "mozilla/dom/Event.h"
14
#include "mozilla/dom/EventTarget.h"
15
#include "mozilla/dom/MessagePort.h"
16
#include "mozilla/dom/SharedWorkerBinding.h"
17
#include "mozilla/dom/WorkerBinding.h"
18
#include "mozilla/Telemetry.h"
19
#include "nsContentUtils.h"
20
#include "nsIClassInfoImpl.h"
21
22
#include "RuntimeService.h"
23
#include "WorkerPrivate.h"
24
25
#ifdef XP_WIN
26
#undef PostMessage
27
#endif
28
29
using mozilla::dom::Optional;
30
using mozilla::dom::Sequence;
31
using mozilla::dom::MessagePort;
32
using namespace mozilla;
33
using namespace mozilla::dom;
34
35
SharedWorker::SharedWorker(nsPIDOMWindowInner* aWindow,
36
                           WorkerPrivate* aWorkerPrivate,
37
                           MessagePort* aMessagePort)
38
  : DOMEventTargetHelper(aWindow)
39
  , mWorkerPrivate(aWorkerPrivate)
40
  , mMessagePort(aMessagePort)
41
  , mFrozen(false)
42
0
{
43
0
  AssertIsOnMainThread();
44
0
  MOZ_ASSERT(aWorkerPrivate);
45
0
  MOZ_ASSERT(aMessagePort);
46
0
}
47
48
SharedWorker::~SharedWorker()
49
0
{
50
0
  AssertIsOnMainThread();
51
0
}
52
53
// static
54
already_AddRefed<SharedWorker>
55
SharedWorker::Constructor(const GlobalObject& aGlobal,
56
                          const nsAString& aScriptURL,
57
                          const StringOrWorkerOptions& aOptions,
58
                          ErrorResult& aRv)
59
0
{
60
0
  AssertIsOnMainThread();
61
0
62
0
  workerinternals::RuntimeService* rts =
63
0
    workerinternals::RuntimeService::GetOrCreateService();
64
0
  if (!rts) {
65
0
    aRv = NS_ERROR_NOT_AVAILABLE;
66
0
    return nullptr;
67
0
  }
68
0
69
0
  nsAutoString name;
70
0
  if (aOptions.IsString()) {
71
0
    name = aOptions.GetAsString();
72
0
  } else {
73
0
    MOZ_ASSERT(aOptions.IsWorkerOptions());
74
0
    name = aOptions.GetAsWorkerOptions().mName;
75
0
  }
76
0
77
0
  RefPtr<SharedWorker> sharedWorker;
78
0
  nsresult rv = rts->CreateSharedWorker(aGlobal, aScriptURL, name,
79
0
                                        getter_AddRefs(sharedWorker));
80
0
  if (NS_FAILED(rv)) {
81
0
    aRv = rv;
82
0
    return nullptr;
83
0
  }
84
0
85
0
  return sharedWorker.forget();
86
0
}
87
88
MessagePort*
89
SharedWorker::Port()
90
0
{
91
0
  AssertIsOnMainThread();
92
0
  return mMessagePort;
93
0
}
94
95
void
96
SharedWorker::Freeze()
97
0
{
98
0
  AssertIsOnMainThread();
99
0
  MOZ_ASSERT(!IsFrozen());
100
0
101
0
  mFrozen = true;
102
0
}
103
104
void
105
SharedWorker::Thaw()
106
0
{
107
0
  AssertIsOnMainThread();
108
0
  MOZ_ASSERT(IsFrozen());
109
0
110
0
  mFrozen = false;
111
0
112
0
  if (!mFrozenEvents.IsEmpty()) {
113
0
    nsTArray<RefPtr<Event>> events;
114
0
    mFrozenEvents.SwapElements(events);
115
0
116
0
    for (uint32_t index = 0; index < events.Length(); index++) {
117
0
      RefPtr<Event>& event = events[index];
118
0
      MOZ_ASSERT(event);
119
0
120
0
      RefPtr<EventTarget> target = event->GetTarget();
121
0
      ErrorResult rv;
122
0
      target->DispatchEvent(*event, rv);
123
0
      if (rv.Failed()) {
124
0
        NS_WARNING("Failed to dispatch event!");
125
0
      }
126
0
    }
127
0
  }
128
0
}
129
130
void
131
SharedWorker::QueueEvent(Event* aEvent)
132
0
{
133
0
  AssertIsOnMainThread();
134
0
  MOZ_ASSERT(aEvent);
135
0
  MOZ_ASSERT(IsFrozen());
136
0
137
0
  mFrozenEvents.AppendElement(aEvent);
138
0
}
139
140
void
141
SharedWorker::Close()
142
0
{
143
0
  AssertIsOnMainThread();
144
0
145
0
  if (mMessagePort) {
146
0
    mMessagePort->Close();
147
0
  }
148
0
}
149
150
void
151
SharedWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
152
                          const Sequence<JSObject*>& aTransferable,
153
                          ErrorResult& aRv)
154
0
{
155
0
  AssertIsOnMainThread();
156
0
  MOZ_ASSERT(mWorkerPrivate);
157
0
  MOZ_ASSERT(mMessagePort);
158
0
159
0
  mMessagePort->PostMessage(aCx, aMessage, aTransferable, aRv);
160
0
}
161
162
NS_IMPL_ADDREF_INHERITED(SharedWorker, DOMEventTargetHelper)
163
NS_IMPL_RELEASE_INHERITED(SharedWorker, DOMEventTargetHelper)
164
165
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SharedWorker)
166
0
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
167
168
NS_IMPL_CYCLE_COLLECTION_CLASS(SharedWorker)
169
170
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SharedWorker,
171
0
                                                  DOMEventTargetHelper)
172
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessagePort)
173
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrozenEvents)
174
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
175
176
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SharedWorker,
177
0
                                                DOMEventTargetHelper)
178
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessagePort)
179
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrozenEvents)
180
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
181
182
JSObject*
183
SharedWorker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
184
0
{
185
0
  AssertIsOnMainThread();
186
0
187
0
  return SharedWorker_Binding::Wrap(aCx, this, aGivenProto);
188
0
}
189
190
void
191
SharedWorker::GetEventTargetParent(EventChainPreVisitor& aVisitor)
192
0
{
193
0
  AssertIsOnMainThread();
194
0
195
0
  if (IsFrozen()) {
196
0
    RefPtr<Event> event = aVisitor.mDOMEvent;
197
0
    if (!event) {
198
0
      event = EventDispatcher::CreateEvent(aVisitor.mEvent->mOriginalTarget,
199
0
                                           aVisitor.mPresContext,
200
0
                                           aVisitor.mEvent, EmptyString());
201
0
    }
202
0
203
0
    QueueEvent(event);
204
0
205
0
    aVisitor.mCanHandle = false;
206
0
    aVisitor.SetParentTarget(nullptr, false);
207
0
    return;
208
0
  }
209
0
210
0
  DOMEventTargetHelper::GetEventTargetParent(aVisitor);
211
0
}