1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "SharedWorker.h"
8 #include "nsPIDOMWindow.h"
10 #include "mozilla/Preferences.h"
11 #include "mozilla/dom/SharedWorkerBinding.h"
12 #include "nsContentUtils.h"
13 #include "nsDOMEvent.h"
14 #include "nsEventDispatcher.h"
15 #include "nsIClassInfoImpl.h"
17 #include "MessagePort.h"
18 #include "RuntimeService.h"
19 #include "WorkerPrivate.h"
21 using mozilla::dom::Optional
;
22 using mozilla::dom::Sequence
;
24 USING_WORKERS_NAMESPACE
28 const char kSharedWorkersEnabledPref
[] = "dom.workers.sharedWorkers.enabled";
30 } // anonymous namespace
32 SharedWorker::SharedWorker(nsPIDOMWindow
* aWindow
,
33 WorkerPrivate
* aWorkerPrivate
)
34 : nsDOMEventTargetHelper(aWindow
), mWorkerPrivate(aWorkerPrivate
),
37 AssertIsOnMainThread();
38 MOZ_ASSERT(aWorkerPrivate
);
40 mSerial
= aWorkerPrivate
->NextMessagePortSerial();
42 mMessagePort
= new MessagePort(aWindow
, this, mSerial
);
45 SharedWorker::~SharedWorker()
47 AssertIsOnMainThread();
48 MOZ_ASSERT(!mWorkerPrivate
);
53 SharedWorker::PrefEnabled()
55 AssertIsOnMainThread();
57 return mozilla::Preferences::GetBool(kSharedWorkersEnabledPref
, false);
61 already_AddRefed
<SharedWorker
>
62 SharedWorker::Constructor(const GlobalObject
& aGlobal
, JSContext
* aCx
,
63 const nsAString
& aScriptURL
,
64 const mozilla::dom::Optional
<nsAString
>& aName
,
67 AssertIsOnMainThread();
69 RuntimeService
* rts
= RuntimeService::GetOrCreateService();
71 aRv
= NS_ERROR_NOT_AVAILABLE
;
76 if (aName
.WasPassed()) {
80 nsRefPtr
<SharedWorker
> sharedWorker
;
81 nsresult rv
= rts
->CreateSharedWorker(aGlobal
, aScriptURL
, name
,
82 getter_AddRefs(sharedWorker
));
88 return sharedWorker
.forget();
91 already_AddRefed
<MessagePort
>
94 AssertIsOnMainThread();
96 nsRefPtr
<MessagePort
> messagePort
= mMessagePort
;
97 return messagePort
.forget();
101 SharedWorker::Suspend()
103 AssertIsOnMainThread();
104 MOZ_ASSERT(!IsSuspended());
110 SharedWorker::Resume()
112 AssertIsOnMainThread();
113 MOZ_ASSERT(IsSuspended());
117 if (!mSuspendedEvents
.IsEmpty()) {
118 nsTArray
<nsCOMPtr
<nsIDOMEvent
>> events
;
119 mSuspendedEvents
.SwapElements(events
);
121 for (uint32_t index
= 0; index
< events
.Length(); index
++) {
122 nsCOMPtr
<nsIDOMEvent
>& event
= events
[index
];
125 nsCOMPtr
<nsIDOMEventTarget
> target
;
126 if (NS_SUCCEEDED(event
->GetTarget(getter_AddRefs(target
)))) {
128 if (NS_FAILED(target
->DispatchEvent(event
, &ignored
))) {
129 NS_WARNING("Failed to dispatch event!");
132 NS_WARNING("Failed to get target!");
139 SharedWorker::QueueEvent(nsIDOMEvent
* aEvent
)
141 AssertIsOnMainThread();
143 MOZ_ASSERT(IsSuspended());
145 mSuspendedEvents
.AppendElement(aEvent
);
149 SharedWorker::Close()
151 AssertIsOnMainThread();
154 mMessagePort
->Close();
157 if (mWorkerPrivate
) {
158 AutoSafeJSContext cx
;
164 SharedWorker::PostMessage(JSContext
* aCx
, JS::Handle
<JS::Value
> aMessage
,
165 const Optional
<Sequence
<JS::Value
>>& aTransferable
,
168 AssertIsOnMainThread();
169 MOZ_ASSERT(mWorkerPrivate
);
170 MOZ_ASSERT(mMessagePort
);
172 mWorkerPrivate
->PostMessageToMessagePort(aCx
, mMessagePort
->Serial(),
173 aMessage
, aTransferable
, aRv
);
177 SharedWorker::NoteDeadWorker(JSContext
* aCx
)
179 AssertIsOnMainThread();
180 MOZ_ASSERT(mWorkerPrivate
);
182 mWorkerPrivate
->UnregisterSharedWorker(aCx
, this);
183 mWorkerPrivate
= nullptr;
186 NS_IMPL_ADDREF_INHERITED(SharedWorker
, nsDOMEventTargetHelper
)
187 NS_IMPL_RELEASE_INHERITED(SharedWorker
, nsDOMEventTargetHelper
)
189 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SharedWorker
)
190 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper
)
192 NS_IMPL_CYCLE_COLLECTION_CLASS(SharedWorker
)
194 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SharedWorker
,
195 nsDOMEventTargetHelper
)
196 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessagePort
)
197 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedEvents
)
198 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
200 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SharedWorker
,
201 nsDOMEventTargetHelper
)
203 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessagePort
)
204 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedEvents
)
205 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
208 SharedWorker::WrapObject(JSContext
* aCx
, JS::Handle
<JSObject
*> aScope
)
210 AssertIsOnMainThread();
212 return SharedWorkerBinding::Wrap(aCx
, aScope
, this);
216 SharedWorker::PreHandleEvent(nsEventChainPreVisitor
& aVisitor
)
218 AssertIsOnMainThread();
220 nsIDOMEvent
*& event
= aVisitor
.mDOMEvent
;
222 if (IsSuspended() && event
) {
225 aVisitor
.mCanHandle
= false;
226 aVisitor
.mParentTarget
= nullptr;
230 return nsDOMEventTargetHelper::PreHandleEvent(aVisitor
);