Line data Source code
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/MessagePort.h"
14 : #include "mozilla/dom/SharedWorkerBinding.h"
15 : #include "mozilla/dom/WorkerBinding.h"
16 : #include "mozilla/Telemetry.h"
17 : #include "nsContentUtils.h"
18 : #include "nsIClassInfoImpl.h"
19 : #include "nsIDOMEvent.h"
20 :
21 : #include "RuntimeService.h"
22 : #include "WorkerPrivate.h"
23 :
24 : using mozilla::dom::Optional;
25 : using mozilla::dom::Sequence;
26 : using mozilla::dom::MessagePort;
27 : using namespace mozilla;
28 :
29 : USING_WORKERS_NAMESPACE
30 :
31 0 : SharedWorker::SharedWorker(nsPIDOMWindowInner* aWindow,
32 : WorkerPrivate* aWorkerPrivate,
33 0 : MessagePort* aMessagePort)
34 : : DOMEventTargetHelper(aWindow)
35 : , mWorkerPrivate(aWorkerPrivate)
36 : , mMessagePort(aMessagePort)
37 0 : , mFrozen(false)
38 : {
39 0 : AssertIsOnMainThread();
40 0 : MOZ_ASSERT(aWorkerPrivate);
41 0 : MOZ_ASSERT(aMessagePort);
42 0 : }
43 :
44 0 : SharedWorker::~SharedWorker()
45 : {
46 0 : AssertIsOnMainThread();
47 0 : }
48 :
49 : // static
50 : already_AddRefed<SharedWorker>
51 0 : SharedWorker::Constructor(const GlobalObject& aGlobal,
52 : const nsAString& aScriptURL,
53 : const StringOrWorkerOptions& aOptions,
54 : ErrorResult& aRv)
55 : {
56 0 : AssertIsOnMainThread();
57 :
58 0 : RuntimeService* rts = RuntimeService::GetOrCreateService();
59 0 : if (!rts) {
60 0 : aRv = NS_ERROR_NOT_AVAILABLE;
61 0 : return nullptr;
62 : }
63 :
64 0 : nsAutoString name;
65 0 : if (aOptions.IsString()) {
66 0 : name = aOptions.GetAsString();
67 : } else {
68 0 : MOZ_ASSERT(aOptions.IsWorkerOptions());
69 0 : name = aOptions.GetAsWorkerOptions().mName;
70 : }
71 :
72 0 : RefPtr<SharedWorker> sharedWorker;
73 0 : nsresult rv = rts->CreateSharedWorker(aGlobal, aScriptURL, name,
74 0 : getter_AddRefs(sharedWorker));
75 0 : if (NS_FAILED(rv)) {
76 0 : aRv = rv;
77 0 : return nullptr;
78 : }
79 :
80 0 : Telemetry::Accumulate(Telemetry::SHARED_WORKER_COUNT, 1);
81 :
82 0 : return sharedWorker.forget();
83 : }
84 :
85 : MessagePort*
86 0 : SharedWorker::Port()
87 : {
88 0 : AssertIsOnMainThread();
89 0 : return mMessagePort;
90 : }
91 :
92 : void
93 0 : SharedWorker::Freeze()
94 : {
95 0 : AssertIsOnMainThread();
96 0 : MOZ_ASSERT(!IsFrozen());
97 :
98 0 : mFrozen = true;
99 0 : }
100 :
101 : void
102 0 : SharedWorker::Thaw()
103 : {
104 0 : AssertIsOnMainThread();
105 0 : MOZ_ASSERT(IsFrozen());
106 :
107 0 : mFrozen = false;
108 :
109 0 : if (!mFrozenEvents.IsEmpty()) {
110 0 : nsTArray<nsCOMPtr<nsIDOMEvent>> events;
111 0 : mFrozenEvents.SwapElements(events);
112 :
113 0 : for (uint32_t index = 0; index < events.Length(); index++) {
114 0 : nsCOMPtr<nsIDOMEvent>& event = events[index];
115 0 : MOZ_ASSERT(event);
116 :
117 0 : nsCOMPtr<nsIDOMEventTarget> target;
118 0 : if (NS_SUCCEEDED(event->GetTarget(getter_AddRefs(target)))) {
119 : bool ignored;
120 0 : if (NS_FAILED(target->DispatchEvent(event, &ignored))) {
121 0 : NS_WARNING("Failed to dispatch event!");
122 : }
123 : } else {
124 0 : NS_WARNING("Failed to get target!");
125 : }
126 : }
127 : }
128 0 : }
129 :
130 : void
131 0 : SharedWorker::QueueEvent(nsIDOMEvent* aEvent)
132 : {
133 0 : AssertIsOnMainThread();
134 0 : MOZ_ASSERT(aEvent);
135 0 : MOZ_ASSERT(IsFrozen());
136 :
137 0 : mFrozenEvents.AppendElement(aEvent);
138 0 : }
139 :
140 : void
141 0 : SharedWorker::Close()
142 : {
143 0 : AssertIsOnMainThread();
144 :
145 0 : if (mMessagePort) {
146 0 : mMessagePort->Close();
147 : }
148 0 : }
149 :
150 : void
151 0 : SharedWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
152 : const Sequence<JSObject*>& aTransferable,
153 : ErrorResult& aRv)
154 : {
155 0 : AssertIsOnMainThread();
156 0 : MOZ_ASSERT(mWorkerPrivate);
157 0 : MOZ_ASSERT(mMessagePort);
158 :
159 0 : mMessagePort->PostMessage(aCx, aMessage, aTransferable, aRv);
160 0 : }
161 :
162 0 : NS_IMPL_ADDREF_INHERITED(SharedWorker, DOMEventTargetHelper)
163 0 : NS_IMPL_RELEASE_INHERITED(SharedWorker, DOMEventTargetHelper)
164 :
165 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(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 : 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 : 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 0 : SharedWorker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
184 : {
185 0 : AssertIsOnMainThread();
186 :
187 0 : return SharedWorkerBinding::Wrap(aCx, this, aGivenProto);
188 : }
189 :
190 : nsresult
191 0 : SharedWorker::GetEventTargetParent(EventChainPreVisitor& aVisitor)
192 : {
193 0 : AssertIsOnMainThread();
194 :
195 0 : if (IsFrozen()) {
196 0 : nsCOMPtr<nsIDOMEvent> 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 : }
202 :
203 0 : QueueEvent(event);
204 :
205 0 : aVisitor.mCanHandle = false;
206 0 : aVisitor.mParentTarget = nullptr;
207 0 : return NS_OK;
208 : }
209 :
210 0 : return DOMEventTargetHelper::GetEventTargetParent(aVisitor);
211 : }
|