1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/workers/SharedWorker.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,218 @@ 1.4 +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "SharedWorker.h" 1.10 + 1.11 +#include "nsPIDOMWindow.h" 1.12 + 1.13 +#include "mozilla/EventDispatcher.h" 1.14 +#include "mozilla/Preferences.h" 1.15 +#include "mozilla/dom/SharedWorkerBinding.h" 1.16 +#include "nsContentUtils.h" 1.17 +#include "nsIClassInfoImpl.h" 1.18 +#include "nsIDOMEvent.h" 1.19 + 1.20 +#include "MessagePort.h" 1.21 +#include "RuntimeService.h" 1.22 +#include "WorkerPrivate.h" 1.23 + 1.24 +using mozilla::dom::Optional; 1.25 +using mozilla::dom::Sequence; 1.26 +using namespace mozilla; 1.27 + 1.28 +USING_WORKERS_NAMESPACE 1.29 + 1.30 +SharedWorker::SharedWorker(nsPIDOMWindow* aWindow, 1.31 + WorkerPrivate* aWorkerPrivate) 1.32 +: DOMEventTargetHelper(aWindow), mWorkerPrivate(aWorkerPrivate), 1.33 + mSuspended(false) 1.34 +{ 1.35 + AssertIsOnMainThread(); 1.36 + MOZ_ASSERT(aWorkerPrivate); 1.37 + 1.38 + mSerial = aWorkerPrivate->NextMessagePortSerial(); 1.39 + 1.40 + mMessagePort = new MessagePort(aWindow, this, mSerial); 1.41 +} 1.42 + 1.43 +SharedWorker::~SharedWorker() 1.44 +{ 1.45 + AssertIsOnMainThread(); 1.46 + Close(); 1.47 + MOZ_ASSERT(!mWorkerPrivate); 1.48 +} 1.49 + 1.50 +// static 1.51 +already_AddRefed<SharedWorker> 1.52 +SharedWorker::Constructor(const GlobalObject& aGlobal, JSContext* aCx, 1.53 + const nsAString& aScriptURL, 1.54 + const mozilla::dom::Optional<nsAString>& aName, 1.55 + ErrorResult& aRv) 1.56 +{ 1.57 + AssertIsOnMainThread(); 1.58 + 1.59 + RuntimeService* rts = RuntimeService::GetOrCreateService(); 1.60 + if (!rts) { 1.61 + aRv = NS_ERROR_NOT_AVAILABLE; 1.62 + return nullptr; 1.63 + } 1.64 + 1.65 + nsCString name; 1.66 + if (aName.WasPassed()) { 1.67 + name = NS_ConvertUTF16toUTF8(aName.Value()); 1.68 + } 1.69 + 1.70 + nsRefPtr<SharedWorker> sharedWorker; 1.71 + nsresult rv = rts->CreateSharedWorker(aGlobal, aScriptURL, name, 1.72 + getter_AddRefs(sharedWorker)); 1.73 + if (NS_FAILED(rv)) { 1.74 + aRv = rv; 1.75 + return nullptr; 1.76 + } 1.77 + 1.78 + return sharedWorker.forget(); 1.79 +} 1.80 + 1.81 +already_AddRefed<MessagePort> 1.82 +SharedWorker::Port() 1.83 +{ 1.84 + AssertIsOnMainThread(); 1.85 + 1.86 + nsRefPtr<MessagePort> messagePort = mMessagePort; 1.87 + return messagePort.forget(); 1.88 +} 1.89 + 1.90 +void 1.91 +SharedWorker::Suspend() 1.92 +{ 1.93 + AssertIsOnMainThread(); 1.94 + MOZ_ASSERT(!IsSuspended()); 1.95 + 1.96 + mSuspended = true; 1.97 +} 1.98 + 1.99 +void 1.100 +SharedWorker::Resume() 1.101 +{ 1.102 + AssertIsOnMainThread(); 1.103 + MOZ_ASSERT(IsSuspended()); 1.104 + 1.105 + mSuspended = false; 1.106 + 1.107 + if (!mSuspendedEvents.IsEmpty()) { 1.108 + nsTArray<nsCOMPtr<nsIDOMEvent>> events; 1.109 + mSuspendedEvents.SwapElements(events); 1.110 + 1.111 + for (uint32_t index = 0; index < events.Length(); index++) { 1.112 + nsCOMPtr<nsIDOMEvent>& event = events[index]; 1.113 + MOZ_ASSERT(event); 1.114 + 1.115 + nsCOMPtr<nsIDOMEventTarget> target; 1.116 + if (NS_SUCCEEDED(event->GetTarget(getter_AddRefs(target)))) { 1.117 + bool ignored; 1.118 + if (NS_FAILED(target->DispatchEvent(event, &ignored))) { 1.119 + NS_WARNING("Failed to dispatch event!"); 1.120 + } 1.121 + } else { 1.122 + NS_WARNING("Failed to get target!"); 1.123 + } 1.124 + } 1.125 + } 1.126 +} 1.127 + 1.128 +void 1.129 +SharedWorker::QueueEvent(nsIDOMEvent* aEvent) 1.130 +{ 1.131 + AssertIsOnMainThread(); 1.132 + MOZ_ASSERT(aEvent); 1.133 + MOZ_ASSERT(IsSuspended()); 1.134 + 1.135 + mSuspendedEvents.AppendElement(aEvent); 1.136 +} 1.137 + 1.138 +void 1.139 +SharedWorker::Close() 1.140 +{ 1.141 + AssertIsOnMainThread(); 1.142 + 1.143 + if (mMessagePort) { 1.144 + mMessagePort->Close(); 1.145 + } 1.146 + 1.147 + if (mWorkerPrivate) { 1.148 + AutoSafeJSContext cx; 1.149 + NoteDeadWorker(cx); 1.150 + } 1.151 +} 1.152 + 1.153 +void 1.154 +SharedWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage, 1.155 + const Optional<Sequence<JS::Value>>& aTransferable, 1.156 + ErrorResult& aRv) 1.157 +{ 1.158 + AssertIsOnMainThread(); 1.159 + MOZ_ASSERT(mWorkerPrivate); 1.160 + MOZ_ASSERT(mMessagePort); 1.161 + 1.162 + mWorkerPrivate->PostMessageToMessagePort(aCx, mMessagePort->Serial(), 1.163 + aMessage, aTransferable, aRv); 1.164 +} 1.165 + 1.166 +void 1.167 +SharedWorker::NoteDeadWorker(JSContext* aCx) 1.168 +{ 1.169 + AssertIsOnMainThread(); 1.170 + MOZ_ASSERT(mWorkerPrivate); 1.171 + 1.172 + mWorkerPrivate->UnregisterSharedWorker(aCx, this); 1.173 + mWorkerPrivate = nullptr; 1.174 +} 1.175 + 1.176 +NS_IMPL_ADDREF_INHERITED(SharedWorker, DOMEventTargetHelper) 1.177 +NS_IMPL_RELEASE_INHERITED(SharedWorker, DOMEventTargetHelper) 1.178 + 1.179 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SharedWorker) 1.180 +NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) 1.181 + 1.182 +NS_IMPL_CYCLE_COLLECTION_CLASS(SharedWorker) 1.183 + 1.184 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SharedWorker, 1.185 + DOMEventTargetHelper) 1.186 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessagePort) 1.187 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedEvents) 1.188 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.189 + 1.190 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SharedWorker, 1.191 + DOMEventTargetHelper) 1.192 + tmp->Close(); 1.193 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessagePort) 1.194 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedEvents) 1.195 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END 1.196 + 1.197 +JSObject* 1.198 +SharedWorker::WrapObject(JSContext* aCx) 1.199 +{ 1.200 + AssertIsOnMainThread(); 1.201 + 1.202 + return SharedWorkerBinding::Wrap(aCx, this); 1.203 +} 1.204 + 1.205 +nsresult 1.206 +SharedWorker::PreHandleEvent(EventChainPreVisitor& aVisitor) 1.207 +{ 1.208 + AssertIsOnMainThread(); 1.209 + 1.210 + nsIDOMEvent*& event = aVisitor.mDOMEvent; 1.211 + 1.212 + if (IsSuspended() && event) { 1.213 + QueueEvent(event); 1.214 + 1.215 + aVisitor.mCanHandle = false; 1.216 + aVisitor.mParentTarget = nullptr; 1.217 + return NS_OK; 1.218 + } 1.219 + 1.220 + return DOMEventTargetHelper::PreHandleEvent(aVisitor); 1.221 +}