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
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "ChromeWorker.h"
8 
9 #include "mozilla/dom/WorkerBinding.h"
10 #include "nsContentUtils.h"
11 #include "WorkerPrivate.h"
12 
13 namespace mozilla {
14 namespace dom {
15 
16 /* static */
Constructor(const GlobalObject & aGlobal,const nsAString & aScriptURL,ErrorResult & aRv)17 already_AddRefed<ChromeWorker> ChromeWorker::Constructor(
18     const GlobalObject& aGlobal, const nsAString& aScriptURL,
19     ErrorResult& aRv) {
20   JSContext* cx = aGlobal.Context();
21 
22   RefPtr<WorkerPrivate> workerPrivate = WorkerPrivate::Constructor(
23       cx, aScriptURL, true /* aIsChromeWorker */, WorkerKindDedicated, u""_ns,
24       VoidCString(), nullptr /*aLoadInfo */, aRv);
25   if (NS_WARN_IF(aRv.Failed())) {
26     return nullptr;
27   }
28 
29   nsCOMPtr<nsIGlobalObject> globalObject =
30       do_QueryInterface(aGlobal.GetAsSupports());
31 
32   RefPtr<ChromeWorker> worker =
33       new ChromeWorker(globalObject, workerPrivate.forget());
34   return worker.forget();
35 }
36 
37 /* static */
WorkerAvailable(JSContext * aCx,JSObject *)38 bool ChromeWorker::WorkerAvailable(JSContext* aCx, JSObject* /* unused */) {
39   // Chrome is always allowed to use workers, and content is never
40   // allowed to use ChromeWorker, so all we have to check is the
41   // caller.  However, chrome workers apparently might not have a
42   // system principal, so we have to check for them manually.
43   if (NS_IsMainThread()) {
44     return nsContentUtils::IsSystemCaller(aCx);
45   }
46 
47   return GetWorkerPrivateFromContext(aCx)->IsChromeWorker();
48 }
49 
ChromeWorker(nsIGlobalObject * aGlobalObject,already_AddRefed<WorkerPrivate> aWorkerPrivate)50 ChromeWorker::ChromeWorker(nsIGlobalObject* aGlobalObject,
51                            already_AddRefed<WorkerPrivate> aWorkerPrivate)
52     : Worker(aGlobalObject, std::move(aWorkerPrivate)) {}
53 
54 ChromeWorker::~ChromeWorker() = default;
55 
WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)56 JSObject* ChromeWorker::WrapObject(JSContext* aCx,
57                                    JS::Handle<JSObject*> aGivenProto) {
58   JS::Rooted<JSObject*> wrapper(
59       aCx, ChromeWorker_Binding::Wrap(aCx, this, aGivenProto));
60   if (wrapper) {
61     // Most DOM objects don't assume they have a reflector. If they don't have
62     // one and need one, they create it. But in workers code, we assume that the
63     // reflector is always present.  In order to guarantee that it's always
64     // present, we have to preserve it. Otherwise the GC will happily collect it
65     // as needed.
66     MOZ_ALWAYS_TRUE(TryPreserveWrapper(wrapper));
67   }
68 
69   return wrapper;
70 }
71 
72 }  // namespace dom
73 }  // namespace mozilla
74