1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/workers/WorkerScope.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,359 @@ 1.4 +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "WorkerScope.h" 1.11 + 1.12 +#include "jsapi.h" 1.13 +#include "mozilla/EventListenerManager.h" 1.14 +#include "mozilla/dom/FunctionBinding.h" 1.15 +#include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h" 1.16 +#include "mozilla/dom/SharedWorkerGlobalScopeBinding.h" 1.17 +#include "mozilla/dom/Console.h" 1.18 + 1.19 +#ifdef ANDROID 1.20 +#include <android/log.h> 1.21 +#endif 1.22 + 1.23 +#include "Location.h" 1.24 +#include "Navigator.h" 1.25 +#include "Principal.h" 1.26 +#include "RuntimeService.h" 1.27 +#include "ScriptLoader.h" 1.28 +#include "WorkerPrivate.h" 1.29 + 1.30 +#define UNWRAP_WORKER_OBJECT(Interface, obj, value) \ 1.31 + UnwrapObject<prototypes::id::Interface##_workers, \ 1.32 + mozilla::dom::Interface##Binding_workers::NativeType>(obj, value) 1.33 + 1.34 +using namespace mozilla; 1.35 +using namespace mozilla::dom; 1.36 +USING_WORKERS_NAMESPACE 1.37 + 1.38 +BEGIN_WORKERS_NAMESPACE 1.39 + 1.40 +WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate) 1.41 +: mWorkerPrivate(aWorkerPrivate) 1.42 +{ 1.43 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.44 + 1.45 + SetIsDOMBinding(); 1.46 +} 1.47 + 1.48 +WorkerGlobalScope::~WorkerGlobalScope() 1.49 +{ 1.50 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.51 +} 1.52 + 1.53 +NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScope) 1.54 + 1.55 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScope, 1.56 + DOMEventTargetHelper) 1.57 + tmp->mWorkerPrivate->AssertIsOnWorkerThread(); 1.58 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation) 1.59 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator) 1.60 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.61 + 1.62 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScope, 1.63 + DOMEventTargetHelper) 1.64 + tmp->mWorkerPrivate->AssertIsOnWorkerThread(); 1.65 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation) 1.66 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator) 1.67 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END 1.68 + 1.69 +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerGlobalScope, 1.70 + DOMEventTargetHelper) 1.71 + tmp->mWorkerPrivate->AssertIsOnWorkerThread(); 1.72 + 1.73 + tmp->mWorkerPrivate->TraceTimeouts(aCallbacks, aClosure); 1.74 +NS_IMPL_CYCLE_COLLECTION_TRACE_END 1.75 + 1.76 +NS_IMPL_ADDREF_INHERITED(WorkerGlobalScope, DOMEventTargetHelper) 1.77 +NS_IMPL_RELEASE_INHERITED(WorkerGlobalScope, DOMEventTargetHelper) 1.78 + 1.79 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerGlobalScope) 1.80 + NS_INTERFACE_MAP_ENTRY(nsIGlobalObject) 1.81 +NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) 1.82 + 1.83 +JSObject* 1.84 +WorkerGlobalScope::WrapObject(JSContext* aCx) 1.85 +{ 1.86 + MOZ_CRASH("We should never get here!"); 1.87 +} 1.88 + 1.89 +already_AddRefed<Console> 1.90 +WorkerGlobalScope::GetConsole() 1.91 +{ 1.92 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.93 + 1.94 + if (!mConsole) { 1.95 + mConsole = new Console(nullptr); 1.96 + MOZ_ASSERT(mConsole); 1.97 + } 1.98 + 1.99 + return mConsole.forget(); 1.100 +} 1.101 + 1.102 +already_AddRefed<WorkerLocation> 1.103 +WorkerGlobalScope::Location() 1.104 +{ 1.105 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.106 + 1.107 + if (!mLocation) { 1.108 + WorkerPrivate::LocationInfo& info = mWorkerPrivate->GetLocationInfo(); 1.109 + 1.110 + mLocation = WorkerLocation::Create(info); 1.111 + MOZ_ASSERT(mLocation); 1.112 + } 1.113 + 1.114 + nsRefPtr<WorkerLocation> location = mLocation; 1.115 + return location.forget(); 1.116 +} 1.117 + 1.118 +already_AddRefed<WorkerNavigator> 1.119 +WorkerGlobalScope::Navigator() 1.120 +{ 1.121 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.122 + 1.123 + if (!mNavigator) { 1.124 + mNavigator = WorkerNavigator::Create(mWorkerPrivate->OnLine()); 1.125 + MOZ_ASSERT(mNavigator); 1.126 + } 1.127 + 1.128 + nsRefPtr<WorkerNavigator> navigator = mNavigator; 1.129 + return navigator.forget(); 1.130 +} 1.131 + 1.132 +already_AddRefed<WorkerNavigator> 1.133 +WorkerGlobalScope::GetExistingNavigator() const 1.134 +{ 1.135 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.136 + 1.137 + nsRefPtr<WorkerNavigator> navigator = mNavigator; 1.138 + return navigator.forget(); 1.139 +} 1.140 + 1.141 +void 1.142 +WorkerGlobalScope::Close(JSContext* aCx) 1.143 +{ 1.144 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.145 + 1.146 + mWorkerPrivate->CloseInternal(aCx); 1.147 +} 1.148 + 1.149 +OnErrorEventHandlerNonNull* 1.150 +WorkerGlobalScope::GetOnerror() 1.151 +{ 1.152 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.153 + 1.154 + EventListenerManager* elm = GetExistingListenerManager(); 1.155 + return elm ? elm->GetOnErrorEventHandler() : nullptr; 1.156 +} 1.157 + 1.158 +void 1.159 +WorkerGlobalScope::SetOnerror(OnErrorEventHandlerNonNull* aHandler) 1.160 +{ 1.161 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.162 + 1.163 + EventListenerManager* elm = GetOrCreateListenerManager(); 1.164 + if (elm) { 1.165 + elm->SetEventHandler(aHandler); 1.166 + } 1.167 +} 1.168 + 1.169 +void 1.170 +WorkerGlobalScope::ImportScripts(JSContext* aCx, 1.171 + const Sequence<nsString>& aScriptURLs, 1.172 + ErrorResult& aRv) 1.173 +{ 1.174 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.175 + scriptloader::Load(aCx, mWorkerPrivate, aScriptURLs, aRv); 1.176 +} 1.177 + 1.178 +int32_t 1.179 +WorkerGlobalScope::SetTimeout(JSContext* aCx, 1.180 + Function& aHandler, 1.181 + const int32_t aTimeout, 1.182 + const Sequence<JS::Value>& aArguments, 1.183 + ErrorResult& aRv) 1.184 +{ 1.185 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.186 + return mWorkerPrivate->SetTimeout(aCx, &aHandler, EmptyString(), aTimeout, 1.187 + aArguments, false, aRv); 1.188 +} 1.189 + 1.190 +int32_t 1.191 +WorkerGlobalScope::SetTimeout(JSContext* /* unused */, 1.192 + const nsAString& aHandler, 1.193 + const int32_t aTimeout, 1.194 + const Sequence<JS::Value>& /* unused */, 1.195 + ErrorResult& aRv) 1.196 +{ 1.197 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.198 + Sequence<JS::Value> dummy; 1.199 + return mWorkerPrivate->SetTimeout(GetCurrentThreadJSContext(), nullptr, 1.200 + aHandler, aTimeout, dummy, false, aRv); 1.201 +} 1.202 + 1.203 +void 1.204 +WorkerGlobalScope::ClearTimeout(int32_t aHandle, ErrorResult& aRv) 1.205 +{ 1.206 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.207 + mWorkerPrivate->ClearTimeout(aHandle); 1.208 +} 1.209 + 1.210 +int32_t 1.211 +WorkerGlobalScope::SetInterval(JSContext* aCx, 1.212 + Function& aHandler, 1.213 + const Optional<int32_t>& aTimeout, 1.214 + const Sequence<JS::Value>& aArguments, 1.215 + ErrorResult& aRv) 1.216 +{ 1.217 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.218 + 1.219 + int32_t timeout = aTimeout.WasPassed() ? aTimeout.Value() : 0; 1.220 + 1.221 + return mWorkerPrivate->SetTimeout(aCx, &aHandler, EmptyString(), timeout, 1.222 + aArguments, !!timeout, aRv); 1.223 +} 1.224 + 1.225 +int32_t 1.226 +WorkerGlobalScope::SetInterval(JSContext* /* unused */, 1.227 + const nsAString& aHandler, 1.228 + const Optional<int32_t>& aTimeout, 1.229 + const Sequence<JS::Value>& /* unused */, 1.230 + ErrorResult& aRv) 1.231 +{ 1.232 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.233 + 1.234 + Sequence<JS::Value> dummy; 1.235 + 1.236 + int32_t timeout = aTimeout.WasPassed() ? aTimeout.Value() : 0; 1.237 + 1.238 + return mWorkerPrivate->SetTimeout(GetCurrentThreadJSContext(), nullptr, 1.239 + aHandler, timeout, dummy, !!timeout, aRv); 1.240 +} 1.241 + 1.242 +void 1.243 +WorkerGlobalScope::ClearInterval(int32_t aHandle, ErrorResult& aRv) 1.244 +{ 1.245 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.246 + mWorkerPrivate->ClearTimeout(aHandle); 1.247 +} 1.248 + 1.249 +void 1.250 +WorkerGlobalScope::Atob(const nsAString& aAtob, nsAString& aOutput, ErrorResult& aRv) const 1.251 +{ 1.252 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.253 + aRv = nsContentUtils::Atob(aAtob, aOutput); 1.254 +} 1.255 + 1.256 +void 1.257 +WorkerGlobalScope::Btoa(const nsAString& aBtoa, nsAString& aOutput, ErrorResult& aRv) const 1.258 +{ 1.259 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.260 + aRv = nsContentUtils::Btoa(aBtoa, aOutput); 1.261 +} 1.262 + 1.263 +void 1.264 +WorkerGlobalScope::Dump(const Optional<nsAString>& aString) const 1.265 +{ 1.266 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.267 + 1.268 + if (!aString.WasPassed()) { 1.269 + return; 1.270 + } 1.271 + 1.272 + if (!mWorkerPrivate->DumpEnabled()) { 1.273 + return; 1.274 + } 1.275 + 1.276 + NS_ConvertUTF16toUTF8 str(aString.Value()); 1.277 + 1.278 +#ifdef ANDROID 1.279 + __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", str.get()); 1.280 +#endif 1.281 + fputs(str.get(), stdout); 1.282 + fflush(stdout); 1.283 +} 1.284 + 1.285 +DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate) 1.286 +: WorkerGlobalScope(aWorkerPrivate) 1.287 +{ 1.288 +} 1.289 + 1.290 +/* static */ bool 1.291 +DedicatedWorkerGlobalScope::Visible(JSContext* aCx, JSObject* aObj) 1.292 +{ 1.293 + DedicatedWorkerGlobalScope* self = nullptr; 1.294 + nsresult rv = UNWRAP_WORKER_OBJECT(DedicatedWorkerGlobalScope, aObj, self); 1.295 + return NS_SUCCEEDED(rv) && self; 1.296 +} 1.297 + 1.298 +JSObject* 1.299 +DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx) 1.300 +{ 1.301 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.302 + MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker()); 1.303 + 1.304 + JS::CompartmentOptions options; 1.305 + mWorkerPrivate->CopyJSCompartmentOptions(options); 1.306 + 1.307 + // We're wrapping the global, so the scope is undefined. 1.308 + JS::Rooted<JSObject*> scope(aCx); 1.309 + 1.310 + return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this, 1.311 + options, 1.312 + GetWorkerPrincipal()); 1.313 +} 1.314 + 1.315 +void 1.316 +DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx, 1.317 + JS::Handle<JS::Value> aMessage, 1.318 + const Optional<Sequence<JS::Value>>& aTransferable, 1.319 + ErrorResult& aRv) 1.320 +{ 1.321 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.322 + mWorkerPrivate->PostMessageToParent(aCx, aMessage, aTransferable, aRv); 1.323 +} 1.324 + 1.325 +SharedWorkerGlobalScope::SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate, 1.326 + const nsCString& aName) 1.327 +: WorkerGlobalScope(aWorkerPrivate), mName(aName) 1.328 +{ 1.329 +} 1.330 + 1.331 +/* static */ bool 1.332 +SharedWorkerGlobalScope::Visible(JSContext* aCx, JSObject* aObj) 1.333 +{ 1.334 + SharedWorkerGlobalScope* self = nullptr; 1.335 + nsresult rv = UNWRAP_WORKER_OBJECT(SharedWorkerGlobalScope, aObj, self); 1.336 + return NS_SUCCEEDED(rv) && self; 1.337 +} 1.338 + 1.339 +JSObject* 1.340 +SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx) 1.341 +{ 1.342 + mWorkerPrivate->AssertIsOnWorkerThread(); 1.343 + MOZ_ASSERT(mWorkerPrivate->IsSharedWorker()); 1.344 + 1.345 + JS::CompartmentOptions options; 1.346 + mWorkerPrivate->CopyJSCompartmentOptions(options); 1.347 + 1.348 + // We're wrapping the global, so the scope is undefined. 1.349 + JS::Rooted<JSObject*> scope(aCx); 1.350 + 1.351 + return SharedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this, options, 1.352 + GetWorkerPrincipal()); 1.353 +} 1.354 + 1.355 +bool 1.356 +GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp) 1.357 +{ 1.358 + JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr, JSMSG_GETTER_ONLY); 1.359 + return false; 1.360 +} 1.361 + 1.362 +END_WORKERS_NAMESPACE