WorkerScope.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  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
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "WorkerScope.h"
  6. #include "jsapi.h"
  7. #include "mozilla/EventListenerManager.h"
  8. #include "mozilla/dom/BindingDeclarations.h"
  9. #include "mozilla/dom/Console.h"
  10. #include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
  11. #include "mozilla/dom/Fetch.h"
  12. #include "mozilla/dom/FunctionBinding.h"
  13. #include "mozilla/dom/IDBFactory.h"
  14. #include "mozilla/dom/ImageBitmap.h"
  15. #include "mozilla/dom/ImageBitmapBinding.h"
  16. #include "mozilla/dom/Performance.h"
  17. #include "mozilla/dom/Promise.h"
  18. #include "mozilla/dom/PromiseWorkerProxy.h"
  19. #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
  20. #include "mozilla/dom/SharedWorkerGlobalScopeBinding.h"
  21. #include "mozilla/dom/SimpleGlobalObject.h"
  22. #include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
  23. #include "mozilla/dom/WorkerGlobalScopeBinding.h"
  24. #include "mozilla/dom/WorkerLocation.h"
  25. #include "mozilla/dom/WorkerNavigator.h"
  26. #include "mozilla/dom/cache/CacheStorage.h"
  27. #include "mozilla/Services.h"
  28. #include "nsServiceManagerUtils.h"
  29. #include "nsIDocument.h"
  30. #include "nsIServiceWorkerManager.h"
  31. #include "nsIScriptTimeoutHandler.h"
  32. #include "Crypto.h"
  33. #include "Principal.h"
  34. #include "RuntimeService.h"
  35. #include "ScriptLoader.h"
  36. #include "WorkerPrivate.h"
  37. #include "WorkerRunnable.h"
  38. #include "ServiceWorkerClients.h"
  39. #include "ServiceWorkerManager.h"
  40. #include "ServiceWorkerRegistration.h"
  41. #ifdef XP_WIN
  42. #undef PostMessage
  43. #endif
  44. extern already_AddRefed<nsIScriptTimeoutHandler>
  45. NS_CreateJSTimeoutHandler(JSContext* aCx,
  46. mozilla::dom::workers::WorkerPrivate* aWorkerPrivate,
  47. mozilla::dom::Function& aFunction,
  48. const mozilla::dom::Sequence<JS::Value>& aArguments,
  49. mozilla::ErrorResult& aError);
  50. extern already_AddRefed<nsIScriptTimeoutHandler>
  51. NS_CreateJSTimeoutHandler(JSContext* aCx,
  52. mozilla::dom::workers::WorkerPrivate* aWorkerPrivate,
  53. const nsAString& aExpression);
  54. using namespace mozilla;
  55. using namespace mozilla::dom;
  56. USING_WORKERS_NAMESPACE
  57. using mozilla::dom::cache::CacheStorage;
  58. using mozilla::ipc::PrincipalInfo;
  59. WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
  60. : mWindowInteractionsAllowed(0)
  61. , mWorkerPrivate(aWorkerPrivate)
  62. {
  63. mWorkerPrivate->AssertIsOnWorkerThread();
  64. }
  65. WorkerGlobalScope::~WorkerGlobalScope()
  66. {
  67. mWorkerPrivate->AssertIsOnWorkerThread();
  68. }
  69. NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScope)
  70. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScope,
  71. DOMEventTargetHelper)
  72. tmp->mWorkerPrivate->AssertIsOnWorkerThread();
  73. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
  74. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
  75. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
  76. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
  77. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
  78. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
  79. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
  80. tmp->TraverseHostObjectURIs(cb);
  81. tmp->mWorkerPrivate->TraverseTimeouts(cb);
  82. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  83. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScope,
  84. DOMEventTargetHelper)
  85. tmp->mWorkerPrivate->AssertIsOnWorkerThread();
  86. NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
  87. NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
  88. NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
  89. NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
  90. NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
  91. NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
  92. NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
  93. tmp->UnlinkHostObjectURIs();
  94. tmp->mWorkerPrivate->UnlinkTimeouts();
  95. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  96. NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerGlobalScope,
  97. DOMEventTargetHelper)
  98. tmp->mWorkerPrivate->AssertIsOnWorkerThread();
  99. NS_IMPL_CYCLE_COLLECTION_TRACE_END
  100. NS_IMPL_ADDREF_INHERITED(WorkerGlobalScope, DOMEventTargetHelper)
  101. NS_IMPL_RELEASE_INHERITED(WorkerGlobalScope, DOMEventTargetHelper)
  102. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerGlobalScope)
  103. NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
  104. NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  105. NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
  106. JSObject*
  107. WorkerGlobalScope::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
  108. {
  109. MOZ_CRASH("We should never get here!");
  110. }
  111. Console*
  112. WorkerGlobalScope::GetConsole(ErrorResult& aRv)
  113. {
  114. mWorkerPrivate->AssertIsOnWorkerThread();
  115. if (!mConsole) {
  116. mConsole = Console::Create(nullptr, aRv);
  117. if (NS_WARN_IF(aRv.Failed())) {
  118. return nullptr;
  119. }
  120. }
  121. return mConsole;
  122. }
  123. Crypto*
  124. WorkerGlobalScope::GetCrypto(ErrorResult& aError)
  125. {
  126. mWorkerPrivate->AssertIsOnWorkerThread();
  127. if (!mCrypto) {
  128. mCrypto = new Crypto();
  129. mCrypto->Init(this);
  130. }
  131. return mCrypto;
  132. }
  133. already_AddRefed<CacheStorage>
  134. WorkerGlobalScope::GetCaches(ErrorResult& aRv)
  135. {
  136. if (!mCacheStorage) {
  137. MOZ_ASSERT(mWorkerPrivate);
  138. mCacheStorage = CacheStorage::CreateOnWorker(cache::DEFAULT_NAMESPACE, this,
  139. mWorkerPrivate, aRv);
  140. }
  141. RefPtr<CacheStorage> ref = mCacheStorage;
  142. return ref.forget();
  143. }
  144. bool
  145. WorkerGlobalScope::IsSecureContext() const
  146. {
  147. bool globalSecure =
  148. JS_GetIsSecureContext(js::GetObjectCompartment(GetWrapperPreserveColor()));
  149. MOZ_ASSERT(globalSecure == mWorkerPrivate->IsSecureContext());
  150. return globalSecure;
  151. }
  152. already_AddRefed<WorkerLocation>
  153. WorkerGlobalScope::Location()
  154. {
  155. mWorkerPrivate->AssertIsOnWorkerThread();
  156. if (!mLocation) {
  157. WorkerPrivate::LocationInfo& info = mWorkerPrivate->GetLocationInfo();
  158. mLocation = WorkerLocation::Create(info);
  159. MOZ_ASSERT(mLocation);
  160. }
  161. RefPtr<WorkerLocation> location = mLocation;
  162. return location.forget();
  163. }
  164. already_AddRefed<WorkerNavigator>
  165. WorkerGlobalScope::Navigator()
  166. {
  167. mWorkerPrivate->AssertIsOnWorkerThread();
  168. if (!mNavigator) {
  169. mNavigator = WorkerNavigator::Create(mWorkerPrivate->OnLine());
  170. MOZ_ASSERT(mNavigator);
  171. }
  172. RefPtr<WorkerNavigator> navigator = mNavigator;
  173. return navigator.forget();
  174. }
  175. already_AddRefed<WorkerNavigator>
  176. WorkerGlobalScope::GetExistingNavigator() const
  177. {
  178. mWorkerPrivate->AssertIsOnWorkerThread();
  179. RefPtr<WorkerNavigator> navigator = mNavigator;
  180. return navigator.forget();
  181. }
  182. void
  183. WorkerGlobalScope::Close(JSContext* aCx, ErrorResult& aRv)
  184. {
  185. mWorkerPrivate->AssertIsOnWorkerThread();
  186. if (mWorkerPrivate->IsServiceWorker()) {
  187. aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
  188. } else {
  189. mWorkerPrivate->CloseInternal(aCx);
  190. }
  191. }
  192. OnErrorEventHandlerNonNull*
  193. WorkerGlobalScope::GetOnerror()
  194. {
  195. mWorkerPrivate->AssertIsOnWorkerThread();
  196. EventListenerManager* elm = GetExistingListenerManager();
  197. return elm ? elm->GetOnErrorEventHandler() : nullptr;
  198. }
  199. void
  200. WorkerGlobalScope::SetOnerror(OnErrorEventHandlerNonNull* aHandler)
  201. {
  202. mWorkerPrivate->AssertIsOnWorkerThread();
  203. EventListenerManager* elm = GetOrCreateListenerManager();
  204. if (elm) {
  205. elm->SetEventHandler(aHandler);
  206. }
  207. }
  208. void
  209. WorkerGlobalScope::ImportScripts(const Sequence<nsString>& aScriptURLs,
  210. ErrorResult& aRv)
  211. {
  212. mWorkerPrivate->AssertIsOnWorkerThread();
  213. scriptloader::Load(mWorkerPrivate, aScriptURLs, WorkerScript, aRv);
  214. }
  215. int32_t
  216. WorkerGlobalScope::SetTimeout(JSContext* aCx,
  217. Function& aHandler,
  218. const int32_t aTimeout,
  219. const Sequence<JS::Value>& aArguments,
  220. ErrorResult& aRv)
  221. {
  222. mWorkerPrivate->AssertIsOnWorkerThread();
  223. nsCOMPtr<nsIScriptTimeoutHandler> handler =
  224. NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aArguments, aRv);
  225. if (NS_WARN_IF(aRv.Failed())) {
  226. return 0;
  227. }
  228. return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, false, aRv);
  229. }
  230. int32_t
  231. WorkerGlobalScope::SetTimeout(JSContext* aCx,
  232. const nsAString& aHandler,
  233. const int32_t aTimeout,
  234. const Sequence<JS::Value>& /* unused */,
  235. ErrorResult& aRv)
  236. {
  237. mWorkerPrivate->AssertIsOnWorkerThread();
  238. nsCOMPtr<nsIScriptTimeoutHandler> handler =
  239. NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler);
  240. return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, false, aRv);
  241. }
  242. void
  243. WorkerGlobalScope::ClearTimeout(int32_t aHandle)
  244. {
  245. mWorkerPrivate->AssertIsOnWorkerThread();
  246. mWorkerPrivate->ClearTimeout(aHandle);
  247. }
  248. int32_t
  249. WorkerGlobalScope::SetInterval(JSContext* aCx,
  250. Function& aHandler,
  251. const Optional<int32_t>& aTimeout,
  252. const Sequence<JS::Value>& aArguments,
  253. ErrorResult& aRv)
  254. {
  255. mWorkerPrivate->AssertIsOnWorkerThread();
  256. bool isInterval = aTimeout.WasPassed();
  257. int32_t timeout = aTimeout.WasPassed() ? aTimeout.Value() : 0;
  258. nsCOMPtr<nsIScriptTimeoutHandler> handler =
  259. NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aArguments, aRv);
  260. if (NS_WARN_IF(aRv.Failed())) {
  261. return 0;
  262. }
  263. return mWorkerPrivate->SetTimeout(aCx, handler, timeout, isInterval, aRv);
  264. }
  265. int32_t
  266. WorkerGlobalScope::SetInterval(JSContext* aCx,
  267. const nsAString& aHandler,
  268. const Optional<int32_t>& aTimeout,
  269. const Sequence<JS::Value>& /* unused */,
  270. ErrorResult& aRv)
  271. {
  272. mWorkerPrivate->AssertIsOnWorkerThread();
  273. Sequence<JS::Value> dummy;
  274. bool isInterval = aTimeout.WasPassed();
  275. int32_t timeout = aTimeout.WasPassed() ? aTimeout.Value() : 0;
  276. nsCOMPtr<nsIScriptTimeoutHandler> handler =
  277. NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler);
  278. return mWorkerPrivate->SetTimeout(aCx, handler, timeout, isInterval, aRv);
  279. }
  280. void
  281. WorkerGlobalScope::ClearInterval(int32_t aHandle)
  282. {
  283. mWorkerPrivate->AssertIsOnWorkerThread();
  284. mWorkerPrivate->ClearTimeout(aHandle);
  285. }
  286. void
  287. WorkerGlobalScope::Atob(const nsAString& aAtob, nsAString& aOutput, ErrorResult& aRv) const
  288. {
  289. mWorkerPrivate->AssertIsOnWorkerThread();
  290. aRv = nsContentUtils::Atob(aAtob, aOutput);
  291. }
  292. void
  293. WorkerGlobalScope::Btoa(const nsAString& aBtoa, nsAString& aOutput, ErrorResult& aRv) const
  294. {
  295. mWorkerPrivate->AssertIsOnWorkerThread();
  296. aRv = nsContentUtils::Btoa(aBtoa, aOutput);
  297. }
  298. void
  299. WorkerGlobalScope::GetOrigin(nsAString& aOrigin) const
  300. {
  301. mWorkerPrivate->AssertIsOnWorkerThread();
  302. aOrigin = mWorkerPrivate->Origin();
  303. }
  304. void
  305. WorkerGlobalScope::Dump(const Optional<nsAString>& aString) const
  306. {
  307. mWorkerPrivate->AssertIsOnWorkerThread();
  308. if (!aString.WasPassed()) {
  309. return;
  310. }
  311. #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
  312. if (!mWorkerPrivate->DumpEnabled()) {
  313. return;
  314. }
  315. #endif
  316. NS_ConvertUTF16toUTF8 str(aString.Value());
  317. MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug, ("[Worker.Dump] %s", str.get()));
  318. fputs(str.get(), stdout);
  319. fflush(stdout);
  320. }
  321. Performance*
  322. WorkerGlobalScope::GetPerformance()
  323. {
  324. mWorkerPrivate->AssertIsOnWorkerThread();
  325. if (!mPerformance) {
  326. mPerformance = Performance::CreateForWorker(mWorkerPrivate);
  327. }
  328. return mPerformance;
  329. }
  330. already_AddRefed<Promise>
  331. WorkerGlobalScope::Fetch(const RequestOrUSVString& aInput,
  332. const RequestInit& aInit, ErrorResult& aRv)
  333. {
  334. return FetchRequest(this, aInput, aInit, aRv);
  335. }
  336. already_AddRefed<IDBFactory>
  337. WorkerGlobalScope::GetIndexedDB(ErrorResult& aErrorResult)
  338. {
  339. mWorkerPrivate->AssertIsOnWorkerThread();
  340. RefPtr<IDBFactory> indexedDB = mIndexedDB;
  341. if (!indexedDB) {
  342. if (!mWorkerPrivate->IsStorageAllowed()) {
  343. NS_WARNING("IndexedDB is not allowed in this worker!");
  344. aErrorResult = NS_ERROR_DOM_SECURITY_ERR;
  345. return nullptr;
  346. }
  347. JSContext* cx = mWorkerPrivate->GetJSContext();
  348. MOZ_ASSERT(cx);
  349. JS::Rooted<JSObject*> owningObject(cx, GetGlobalJSObject());
  350. MOZ_ASSERT(owningObject);
  351. const PrincipalInfo& principalInfo = mWorkerPrivate->GetPrincipalInfo();
  352. nsresult rv =
  353. IDBFactory::CreateForWorker(cx,
  354. owningObject,
  355. principalInfo,
  356. mWorkerPrivate->WindowID(),
  357. getter_AddRefs(indexedDB));
  358. if (NS_WARN_IF(NS_FAILED(rv))) {
  359. aErrorResult = rv;
  360. return nullptr;
  361. }
  362. mIndexedDB = indexedDB;
  363. }
  364. return indexedDB.forget();
  365. }
  366. already_AddRefed<Promise>
  367. WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
  368. ErrorResult& aRv)
  369. {
  370. if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
  371. aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
  372. return nullptr;
  373. }
  374. return ImageBitmap::Create(this, aImage, Nothing(), aRv);
  375. }
  376. already_AddRefed<Promise>
  377. WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
  378. int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
  379. ErrorResult& aRv)
  380. {
  381. if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
  382. aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
  383. return nullptr;
  384. }
  385. return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
  386. }
  387. already_AddRefed<mozilla::dom::Promise>
  388. WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
  389. int32_t aOffset, int32_t aLength,
  390. ImageBitmapFormat aFormat,
  391. const Sequence<ChannelPixelLayout>& aLayout,
  392. ErrorResult& aRv)
  393. {
  394. JSContext* cx = GetCurrentThreadJSContext();
  395. MOZ_ASSERT(cx);
  396. if (!ImageBitmap::ExtensionsEnabled(cx, nullptr)) {
  397. aRv.Throw(NS_ERROR_TYPE_ERR);
  398. return nullptr;
  399. }
  400. if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
  401. return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
  402. aRv);
  403. } else {
  404. aRv.Throw(NS_ERROR_TYPE_ERR);
  405. return nullptr;
  406. }
  407. }
  408. DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
  409. : WorkerGlobalScope(aWorkerPrivate)
  410. {
  411. }
  412. bool
  413. DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
  414. JS::MutableHandle<JSObject*> aReflector)
  415. {
  416. mWorkerPrivate->AssertIsOnWorkerThread();
  417. MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker());
  418. JS::CompartmentOptions options;
  419. mWorkerPrivate->CopyJSCompartmentOptions(options);
  420. const bool usesSystemPrincipal = mWorkerPrivate->UsesSystemPrincipal();
  421. // Note that xpc::ShouldDiscardSystemSource() and
  422. // xpc::ExtraWarningsForSystemJS() read prefs that are cached on the main
  423. // thread. This is benignly racey.
  424. const bool discardSource = usesSystemPrincipal &&
  425. xpc::ShouldDiscardSystemSource();
  426. const bool extraWarnings = usesSystemPrincipal &&
  427. xpc::ExtraWarningsForSystemJS();
  428. JS::CompartmentBehaviors& behaviors = options.behaviors();
  429. behaviors.setDiscardSource(discardSource)
  430. .extraWarningsOverride().set(extraWarnings);
  431. const bool sharedMemoryEnabled = xpc::SharedMemoryEnabled();
  432. JS::CompartmentCreationOptions& creationOptions = options.creationOptions();
  433. creationOptions.setSharedMemoryAndAtomicsEnabled(sharedMemoryEnabled);
  434. return DedicatedWorkerGlobalScopeBinding::Wrap(aCx, this, this,
  435. options,
  436. GetWorkerPrincipal(),
  437. true, aReflector);
  438. }
  439. void
  440. DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx,
  441. JS::Handle<JS::Value> aMessage,
  442. const Optional<Sequence<JS::Value>>& aTransferable,
  443. ErrorResult& aRv)
  444. {
  445. mWorkerPrivate->AssertIsOnWorkerThread();
  446. mWorkerPrivate->PostMessageToParent(aCx, aMessage, aTransferable, aRv);
  447. }
  448. SharedWorkerGlobalScope::SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
  449. const nsCString& aName)
  450. : WorkerGlobalScope(aWorkerPrivate), mName(aName)
  451. {
  452. }
  453. bool
  454. SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
  455. JS::MutableHandle<JSObject*> aReflector)
  456. {
  457. mWorkerPrivate->AssertIsOnWorkerThread();
  458. MOZ_ASSERT(mWorkerPrivate->IsSharedWorker());
  459. JS::CompartmentOptions options;
  460. mWorkerPrivate->CopyJSCompartmentOptions(options);
  461. return SharedWorkerGlobalScopeBinding::Wrap(aCx, this, this, options,
  462. GetWorkerPrincipal(),
  463. true, aReflector);
  464. }
  465. NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope,
  466. mClients, mRegistration)
  467. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope)
  468. NS_INTERFACE_MAP_END_INHERITING(WorkerGlobalScope)
  469. NS_IMPL_ADDREF_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
  470. NS_IMPL_RELEASE_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
  471. ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
  472. const nsACString& aScope)
  473. : WorkerGlobalScope(aWorkerPrivate),
  474. mScope(NS_ConvertUTF8toUTF16(aScope))
  475. {
  476. }
  477. ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope()
  478. {
  479. }
  480. bool
  481. ServiceWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
  482. JS::MutableHandle<JSObject*> aReflector)
  483. {
  484. mWorkerPrivate->AssertIsOnWorkerThread();
  485. MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
  486. JS::CompartmentOptions options;
  487. mWorkerPrivate->CopyJSCompartmentOptions(options);
  488. return ServiceWorkerGlobalScopeBinding::Wrap(aCx, this, this, options,
  489. GetWorkerPrincipal(),
  490. true, aReflector);
  491. }
  492. ServiceWorkerClients*
  493. ServiceWorkerGlobalScope::Clients()
  494. {
  495. if (!mClients) {
  496. mClients = new ServiceWorkerClients(this);
  497. }
  498. return mClients;
  499. }
  500. ServiceWorkerRegistration*
  501. ServiceWorkerGlobalScope::Registration()
  502. {
  503. if (!mRegistration) {
  504. mRegistration =
  505. ServiceWorkerRegistration::CreateForWorker(mWorkerPrivate, mScope);
  506. }
  507. return mRegistration;
  508. }
  509. namespace {
  510. class SkipWaitingResultRunnable final : public WorkerRunnable
  511. {
  512. RefPtr<PromiseWorkerProxy> mPromiseProxy;
  513. public:
  514. SkipWaitingResultRunnable(WorkerPrivate* aWorkerPrivate,
  515. PromiseWorkerProxy* aPromiseProxy)
  516. : WorkerRunnable(aWorkerPrivate)
  517. , mPromiseProxy(aPromiseProxy)
  518. {
  519. AssertIsOnMainThread();
  520. }
  521. virtual bool
  522. WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
  523. {
  524. MOZ_ASSERT(aWorkerPrivate);
  525. aWorkerPrivate->AssertIsOnWorkerThread();
  526. RefPtr<Promise> promise = mPromiseProxy->WorkerPromise();
  527. promise->MaybeResolveWithUndefined();
  528. // Release the reference on the worker thread.
  529. mPromiseProxy->CleanUp();
  530. return true;
  531. }
  532. };
  533. class WorkerScopeSkipWaitingRunnable final : public Runnable
  534. {
  535. RefPtr<PromiseWorkerProxy> mPromiseProxy;
  536. nsCString mScope;
  537. public:
  538. WorkerScopeSkipWaitingRunnable(PromiseWorkerProxy* aPromiseProxy,
  539. const nsCString& aScope)
  540. : mPromiseProxy(aPromiseProxy)
  541. , mScope(aScope)
  542. {
  543. MOZ_ASSERT(aPromiseProxy);
  544. }
  545. NS_IMETHOD
  546. Run() override
  547. {
  548. AssertIsOnMainThread();
  549. MutexAutoLock lock(mPromiseProxy->Lock());
  550. if (mPromiseProxy->CleanedUp()) {
  551. return NS_OK;
  552. }
  553. WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
  554. MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
  555. RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
  556. if (swm) {
  557. swm->SetSkipWaitingFlag(workerPrivate->GetPrincipal(), mScope,
  558. workerPrivate->ServiceWorkerID());
  559. }
  560. RefPtr<SkipWaitingResultRunnable> runnable =
  561. new SkipWaitingResultRunnable(workerPrivate, mPromiseProxy);
  562. if (!runnable->Dispatch()) {
  563. NS_WARNING("Failed to dispatch SkipWaitingResultRunnable to the worker.");
  564. }
  565. return NS_OK;
  566. }
  567. };
  568. } // namespace
  569. already_AddRefed<Promise>
  570. ServiceWorkerGlobalScope::SkipWaiting(ErrorResult& aRv)
  571. {
  572. mWorkerPrivate->AssertIsOnWorkerThread();
  573. MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
  574. RefPtr<Promise> promise = Promise::Create(this, aRv);
  575. if (NS_WARN_IF(aRv.Failed())) {
  576. return nullptr;
  577. }
  578. RefPtr<PromiseWorkerProxy> promiseProxy =
  579. PromiseWorkerProxy::Create(mWorkerPrivate, promise);
  580. if (!promiseProxy) {
  581. promise->MaybeResolveWithUndefined();
  582. return promise.forget();
  583. }
  584. RefPtr<WorkerScopeSkipWaitingRunnable> runnable =
  585. new WorkerScopeSkipWaitingRunnable(promiseProxy,
  586. NS_ConvertUTF16toUTF8(mScope));
  587. MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
  588. return promise.forget();
  589. }
  590. bool
  591. ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj)
  592. {
  593. WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
  594. MOZ_ASSERT(worker);
  595. worker->AssertIsOnWorkerThread();
  596. return worker->OpenWindowEnabled();
  597. }
  598. WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
  599. WorkerPrivate* aWorkerPrivate)
  600. : mWorkerPrivate(aWorkerPrivate)
  601. {
  602. mWorkerPrivate->AssertIsOnWorkerThread();
  603. }
  604. WorkerDebuggerGlobalScope::~WorkerDebuggerGlobalScope()
  605. {
  606. mWorkerPrivate->AssertIsOnWorkerThread();
  607. }
  608. NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerDebuggerGlobalScope)
  609. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerDebuggerGlobalScope,
  610. DOMEventTargetHelper)
  611. tmp->mWorkerPrivate->AssertIsOnWorkerThread();
  612. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
  613. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  614. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerDebuggerGlobalScope,
  615. DOMEventTargetHelper)
  616. tmp->mWorkerPrivate->AssertIsOnWorkerThread();
  617. NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
  618. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  619. NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerDebuggerGlobalScope,
  620. DOMEventTargetHelper)
  621. tmp->mWorkerPrivate->AssertIsOnWorkerThread();
  622. NS_IMPL_CYCLE_COLLECTION_TRACE_END
  623. NS_IMPL_ADDREF_INHERITED(WorkerDebuggerGlobalScope, DOMEventTargetHelper)
  624. NS_IMPL_RELEASE_INHERITED(WorkerDebuggerGlobalScope, DOMEventTargetHelper)
  625. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerDebuggerGlobalScope)
  626. NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
  627. NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
  628. bool
  629. WorkerDebuggerGlobalScope::WrapGlobalObject(JSContext* aCx,
  630. JS::MutableHandle<JSObject*> aReflector)
  631. {
  632. mWorkerPrivate->AssertIsOnWorkerThread();
  633. JS::CompartmentOptions options;
  634. mWorkerPrivate->CopyJSCompartmentOptions(options);
  635. return WorkerDebuggerGlobalScopeBinding::Wrap(aCx, this, this, options,
  636. GetWorkerPrincipal(), true,
  637. aReflector);
  638. }
  639. void
  640. WorkerDebuggerGlobalScope::GetGlobal(JSContext* aCx,
  641. JS::MutableHandle<JSObject*> aGlobal,
  642. ErrorResult& aRv)
  643. {
  644. WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
  645. if (!scope) {
  646. aRv.Throw(NS_ERROR_FAILURE);
  647. }
  648. aGlobal.set(scope->GetWrapper());
  649. }
  650. void
  651. WorkerDebuggerGlobalScope::CreateSandbox(JSContext* aCx, const nsAString& aName,
  652. JS::Handle<JSObject*> aPrototype,
  653. JS::MutableHandle<JSObject*> aResult,
  654. ErrorResult& aRv)
  655. {
  656. mWorkerPrivate->AssertIsOnWorkerThread();
  657. aResult.set(nullptr);
  658. JS::Rooted<JS::Value> protoVal(aCx);
  659. protoVal.setObjectOrNull(aPrototype);
  660. JS::Rooted<JSObject*> sandbox(aCx,
  661. SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox,
  662. protoVal));
  663. if (!sandbox) {
  664. aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
  665. return;
  666. }
  667. if (!JS_WrapObject(aCx, &sandbox)) {
  668. aRv.NoteJSContextException(aCx);
  669. return;
  670. }
  671. aResult.set(sandbox);
  672. }
  673. void
  674. WorkerDebuggerGlobalScope::LoadSubScript(JSContext* aCx,
  675. const nsAString& aURL,
  676. const Optional<JS::Handle<JSObject*>>& aSandbox,
  677. ErrorResult& aRv)
  678. {
  679. mWorkerPrivate->AssertIsOnWorkerThread();
  680. Maybe<JSAutoCompartment> ac;
  681. if (aSandbox.WasPassed()) {
  682. JS::Rooted<JSObject*> sandbox(aCx, js::CheckedUnwrap(aSandbox.Value()));
  683. if (!IsDebuggerSandbox(sandbox)) {
  684. aRv.Throw(NS_ERROR_INVALID_ARG);
  685. return;
  686. }
  687. ac.emplace(aCx, sandbox);
  688. }
  689. nsTArray<nsString> urls;
  690. urls.AppendElement(aURL);
  691. scriptloader::Load(mWorkerPrivate, urls, DebuggerScript, aRv);
  692. }
  693. void
  694. WorkerDebuggerGlobalScope::EnterEventLoop()
  695. {
  696. mWorkerPrivate->EnterDebuggerEventLoop();
  697. }
  698. void
  699. WorkerDebuggerGlobalScope::LeaveEventLoop()
  700. {
  701. mWorkerPrivate->LeaveDebuggerEventLoop();
  702. }
  703. void
  704. WorkerDebuggerGlobalScope::PostMessage(const nsAString& aMessage)
  705. {
  706. mWorkerPrivate->PostMessageToDebugger(aMessage);
  707. }
  708. void
  709. WorkerDebuggerGlobalScope::SetImmediate(Function& aHandler, ErrorResult& aRv)
  710. {
  711. mWorkerPrivate->SetDebuggerImmediate(aHandler, aRv);
  712. }
  713. void
  714. WorkerDebuggerGlobalScope::ReportError(JSContext* aCx,
  715. const nsAString& aMessage)
  716. {
  717. JS::AutoFilename chars;
  718. uint32_t lineno = 0;
  719. JS::DescribeScriptedCaller(aCx, &chars, &lineno);
  720. nsString filename(NS_ConvertUTF8toUTF16(chars.get()));
  721. mWorkerPrivate->ReportErrorToDebugger(filename, lineno, aMessage);
  722. }
  723. void
  724. WorkerDebuggerGlobalScope::RetrieveConsoleEvents(JSContext* aCx,
  725. nsTArray<JS::Value>& aEvents,
  726. ErrorResult& aRv)
  727. {
  728. WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
  729. if (!scope) {
  730. aRv.Throw(NS_ERROR_FAILURE);
  731. return;
  732. }
  733. RefPtr<Console> console = scope->GetConsole(aRv);
  734. if (NS_WARN_IF(aRv.Failed())) {
  735. return;
  736. }
  737. console->RetrieveConsoleEvents(aCx, aEvents, aRv);
  738. }
  739. void
  740. WorkerDebuggerGlobalScope::SetConsoleEventHandler(JSContext* aCx,
  741. AnyCallback* aHandler,
  742. ErrorResult& aRv)
  743. {
  744. WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
  745. if (!scope) {
  746. aRv.Throw(NS_ERROR_FAILURE);
  747. return;
  748. }
  749. RefPtr<Console> console = scope->GetConsole(aRv);
  750. if (NS_WARN_IF(aRv.Failed())) {
  751. return;
  752. }
  753. console->SetConsoleEventHandler(aHandler);
  754. }
  755. Console*
  756. WorkerDebuggerGlobalScope::GetConsole(ErrorResult& aRv)
  757. {
  758. mWorkerPrivate->AssertIsOnWorkerThread();
  759. // Debugger console has its own console object.
  760. if (!mConsole) {
  761. mConsole = Console::Create(nullptr, aRv);
  762. if (NS_WARN_IF(aRv.Failed())) {
  763. return nullptr;
  764. }
  765. }
  766. return mConsole;
  767. }
  768. void
  769. WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
  770. const Optional<nsAString>& aString) const
  771. {
  772. WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
  773. if (scope) {
  774. scope->Dump(aString);
  775. }
  776. }
  777. BEGIN_WORKERS_NAMESPACE
  778. bool
  779. IsWorkerGlobal(JSObject* object)
  780. {
  781. return IS_INSTANCE_OF(WorkerGlobalScope, object);
  782. }
  783. bool
  784. IsDebuggerGlobal(JSObject* object)
  785. {
  786. return IS_INSTANCE_OF(WorkerDebuggerGlobalScope, object);
  787. }
  788. bool
  789. IsDebuggerSandbox(JSObject* object)
  790. {
  791. return SimpleGlobalObject::SimpleGlobalType(object) ==
  792. SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox;
  793. }
  794. END_WORKERS_NAMESPACE