/src/mozilla-central/dom/workers/WorkerPrivate.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifndef mozilla_dom_workers_workerprivate_h__ |
8 | | #define mozilla_dom_workers_workerprivate_h__ |
9 | | |
10 | | #include "mozilla/dom/WorkerCommon.h" |
11 | | #include "mozilla/CondVar.h" |
12 | | #include "mozilla/DOMEventTargetHelper.h" |
13 | | #include "mozilla/RelativeTimeline.h" |
14 | | #include "nsIContentSecurityPolicy.h" |
15 | | #include "nsIEventTarget.h" |
16 | | #include "nsTObserverArray.h" |
17 | | |
18 | | #include "mozilla/dom/Worker.h" |
19 | | #include "mozilla/dom/WorkerHolder.h" |
20 | | #include "mozilla/dom/WorkerLoadInfo.h" |
21 | | #include "mozilla/dom/workerinternals/JSSettings.h" |
22 | | #include "mozilla/dom/workerinternals/Queue.h" |
23 | | #include "mozilla/PerformanceCounter.h" |
24 | | |
25 | | class nsIConsoleReportCollector; |
26 | | class nsIThreadInternal; |
27 | | |
28 | | namespace mozilla { |
29 | | namespace dom { |
30 | | |
31 | | // If you change this, the corresponding list in nsIWorkerDebugger.idl needs |
32 | | // to be updated too. |
33 | | enum WorkerType |
34 | | { |
35 | | WorkerTypeDedicated, |
36 | | WorkerTypeShared, |
37 | | WorkerTypeService |
38 | | }; |
39 | | |
40 | | class ClientInfo; |
41 | | class ClientSource; |
42 | | class Function; |
43 | | class MessagePort; |
44 | | class MessagePortIdentifier; |
45 | | class PerformanceStorage; |
46 | | class SharedWorker; |
47 | | class WorkerControlRunnable; |
48 | | class WorkerCSPEventListener; |
49 | | class WorkerDebugger; |
50 | | class WorkerDebuggerGlobalScope; |
51 | | class WorkerErrorReport; |
52 | | class WorkerEventTarget; |
53 | | class WorkerGlobalScope; |
54 | | class WorkerRunnable; |
55 | | class WorkerThread; |
56 | | |
57 | | // SharedMutex is a small wrapper around an (internal) reference-counted Mutex |
58 | | // object. It exists to avoid changing a lot of code to use Mutex* instead of |
59 | | // Mutex&. |
60 | | class SharedMutex |
61 | | { |
62 | | typedef mozilla::Mutex Mutex; |
63 | | |
64 | | class RefCountedMutex final : public Mutex |
65 | | { |
66 | | public: |
67 | | explicit RefCountedMutex(const char* aName) |
68 | | : Mutex(aName) |
69 | | { } |
70 | | |
71 | | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMutex) |
72 | | |
73 | | private: |
74 | | ~RefCountedMutex() |
75 | | { } |
76 | | }; |
77 | | |
78 | | RefPtr<RefCountedMutex> mMutex; |
79 | | |
80 | | public: |
81 | | explicit SharedMutex(const char* aName) |
82 | | : mMutex(new RefCountedMutex(aName)) |
83 | | { } |
84 | | |
85 | | SharedMutex(SharedMutex& aOther) |
86 | | : mMutex(aOther.mMutex) |
87 | | { } |
88 | | |
89 | | operator Mutex&() |
90 | 0 | { |
91 | 0 | return *mMutex; |
92 | 0 | } |
93 | | |
94 | | operator const Mutex&() const |
95 | | { |
96 | | return *mMutex; |
97 | | } |
98 | | |
99 | | void |
100 | | AssertCurrentThreadOwns() const |
101 | | { |
102 | | mMutex->AssertCurrentThreadOwns(); |
103 | | } |
104 | | }; |
105 | | |
106 | | class WorkerPrivate |
107 | | : public RelativeTimeline |
108 | | { |
109 | | public: |
110 | | struct LocationInfo |
111 | | { |
112 | | nsCString mHref; |
113 | | nsCString mProtocol; |
114 | | nsCString mHost; |
115 | | nsCString mHostname; |
116 | | nsCString mPort; |
117 | | nsCString mPathname; |
118 | | nsCString mSearch; |
119 | | nsCString mHash; |
120 | | nsString mOrigin; |
121 | | }; |
122 | | |
123 | | NS_INLINE_DECL_REFCOUNTING(WorkerPrivate) |
124 | | |
125 | | static already_AddRefed<WorkerPrivate> |
126 | | Constructor(JSContext* aCx, const nsAString& aScriptURL, bool aIsChromeWorker, |
127 | | WorkerType aWorkerType, const nsAString& aWorkerName, |
128 | | const nsACString& aServiceWorkerScope, |
129 | | WorkerLoadInfo* aLoadInfo, ErrorResult& aRv); |
130 | | |
131 | | enum LoadGroupBehavior |
132 | | { |
133 | | InheritLoadGroup, |
134 | | OverrideLoadGroup |
135 | | }; |
136 | | |
137 | | static nsresult |
138 | | GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow, |
139 | | WorkerPrivate* aParent, |
140 | | const nsAString& aScriptURL, bool aIsChromeWorker, |
141 | | LoadGroupBehavior aLoadGroupBehavior, WorkerType aWorkerType, |
142 | | WorkerLoadInfo* aLoadInfo); |
143 | | |
144 | | void |
145 | | Traverse(nsCycleCollectionTraversalCallback& aCb); |
146 | | |
147 | | void |
148 | | ClearSelfAndParentEventTargetRef() |
149 | | { |
150 | | AssertIsOnParentThread(); |
151 | | MOZ_ASSERT(mSelfRef); |
152 | | mParentEventTargetRef = nullptr; |
153 | | mSelfRef = nullptr; |
154 | | } |
155 | | |
156 | | // May be called on any thread... |
157 | | bool |
158 | | Start(); |
159 | | |
160 | | // Called on the parent thread. |
161 | | bool |
162 | | Notify(WorkerStatus aStatus); |
163 | | |
164 | | bool |
165 | | Cancel() |
166 | 0 | { |
167 | 0 | return Notify(Canceling); |
168 | 0 | } |
169 | | |
170 | | bool |
171 | | Kill() |
172 | 0 | { |
173 | 0 | return Notify(Killing); |
174 | 0 | } |
175 | | |
176 | | bool |
177 | | Close(); |
178 | | |
179 | | // The passed principal must be the Worker principal in case of a |
180 | | // ServiceWorker and the loading principal for any other type. |
181 | | static void |
182 | | OverrideLoadInfoLoadGroup(WorkerLoadInfo& aLoadInfo, |
183 | | nsIPrincipal* aPrincipal); |
184 | | |
185 | | bool |
186 | | IsDebuggerRegistered() |
187 | 0 | { |
188 | 0 | AssertIsOnMainThread(); |
189 | 0 |
|
190 | 0 | // No need to lock here since this is only ever modified by the same thread. |
191 | 0 | return mDebuggerRegistered; |
192 | 0 | } |
193 | | |
194 | | void |
195 | | SetIsDebuggerRegistered(bool aDebuggerRegistered) |
196 | 0 | { |
197 | 0 | AssertIsOnMainThread(); |
198 | 0 |
|
199 | 0 | MutexAutoLock lock(mMutex); |
200 | 0 |
|
201 | 0 | MOZ_ASSERT(mDebuggerRegistered != aDebuggerRegistered); |
202 | 0 | mDebuggerRegistered = aDebuggerRegistered; |
203 | 0 |
|
204 | 0 | mCondVar.Notify(); |
205 | 0 | } |
206 | | |
207 | | void |
208 | | WaitForIsDebuggerRegistered(bool aDebuggerRegistered) |
209 | 0 | { |
210 | 0 | AssertIsOnParentThread(); |
211 | 0 |
|
212 | 0 | MOZ_ASSERT(!NS_IsMainThread()); |
213 | 0 |
|
214 | 0 | MutexAutoLock lock(mMutex); |
215 | 0 |
|
216 | 0 | while (mDebuggerRegistered != aDebuggerRegistered) { |
217 | 0 | mCondVar.Wait(); |
218 | 0 | } |
219 | 0 | } |
220 | | |
221 | | WorkerDebugger* |
222 | | Debugger() const |
223 | 0 | { |
224 | 0 | AssertIsOnMainThread(); |
225 | 0 |
|
226 | 0 | MOZ_ASSERT(mDebugger); |
227 | 0 | return mDebugger; |
228 | 0 | } |
229 | | |
230 | | void |
231 | | SetDebugger(WorkerDebugger* aDebugger) |
232 | 0 | { |
233 | 0 | AssertIsOnMainThread(); |
234 | 0 |
|
235 | 0 | MOZ_ASSERT(mDebugger != aDebugger); |
236 | 0 | mDebugger = aDebugger; |
237 | 0 | } |
238 | | |
239 | | JS::UniqueChars |
240 | | AdoptDefaultLocale() |
241 | 0 | { |
242 | 0 | MOZ_ASSERT(mDefaultLocale, |
243 | 0 | "the default locale must have been successfully set for anyone " |
244 | 0 | "to be trying to adopt it"); |
245 | 0 | return std::move(mDefaultLocale); |
246 | 0 | } |
247 | | |
248 | | void |
249 | | DoRunLoop(JSContext* aCx); |
250 | | |
251 | | bool |
252 | | InterruptCallback(JSContext* aCx); |
253 | | |
254 | | bool |
255 | | IsOnCurrentThread(); |
256 | | |
257 | | void |
258 | | CloseInternal(); |
259 | | |
260 | | bool |
261 | | FreezeInternal(); |
262 | | |
263 | | bool |
264 | | ThawInternal(); |
265 | | |
266 | | void |
267 | | PropagateFirstPartyStorageAccessGrantedInternal(); |
268 | | |
269 | | void |
270 | | TraverseTimeouts(nsCycleCollectionTraversalCallback& aCallback); |
271 | | |
272 | | void |
273 | | UnlinkTimeouts(); |
274 | | |
275 | | bool |
276 | | ModifyBusyCountFromWorker(bool aIncrease); |
277 | | |
278 | | bool |
279 | | AddChildWorker(WorkerPrivate* aChildWorker); |
280 | | |
281 | | void |
282 | | RemoveChildWorker(WorkerPrivate* aChildWorker); |
283 | | |
284 | | void |
285 | | PostMessageToParent(JSContext* aCx, |
286 | | JS::Handle<JS::Value> aMessage, |
287 | | const Sequence<JSObject*>& aTransferable, |
288 | | ErrorResult& aRv); |
289 | | |
290 | | void |
291 | | PostMessageToParentMessagePort(JSContext* aCx, |
292 | | JS::Handle<JS::Value> aMessage, |
293 | | const Sequence<JSObject*>& aTransferable, |
294 | | ErrorResult& aRv); |
295 | | |
296 | | void |
297 | | EnterDebuggerEventLoop(); |
298 | | |
299 | | void |
300 | | LeaveDebuggerEventLoop(); |
301 | | |
302 | | void |
303 | | PostMessageToDebugger(const nsAString& aMessage); |
304 | | |
305 | | void |
306 | | SetDebuggerImmediate(Function& aHandler, ErrorResult& aRv); |
307 | | |
308 | | void |
309 | | ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno, |
310 | | const nsAString& aMessage); |
311 | | |
312 | | bool |
313 | | NotifyInternal(WorkerStatus aStatus); |
314 | | |
315 | | void |
316 | | ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult, |
317 | | JSErrorReport* aReport); |
318 | | |
319 | | static void |
320 | | ReportErrorToConsole(const char* aMessage); |
321 | | |
322 | | static void |
323 | | ReportErrorToConsole(const char* aMessage, const nsTArray<nsString>& aParams); |
324 | | |
325 | | int32_t |
326 | | SetTimeout(JSContext* aCx, nsIScriptTimeoutHandler* aHandler, |
327 | | int32_t aTimeout, bool aIsInterval, |
328 | | ErrorResult& aRv); |
329 | | |
330 | | void |
331 | | ClearTimeout(int32_t aId); |
332 | | |
333 | | bool |
334 | | RunExpiredTimeouts(JSContext* aCx); |
335 | | |
336 | | bool |
337 | | RescheduleTimeoutTimer(JSContext* aCx); |
338 | | |
339 | | void |
340 | | UpdateContextOptionsInternal(JSContext* aCx, const JS::ContextOptions& aContextOptions); |
341 | | |
342 | | void |
343 | | UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages); |
344 | | |
345 | | void |
346 | | UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, uint32_t aValue); |
347 | | |
348 | | enum WorkerRanOrNot { |
349 | | WorkerNeverRan = 0, |
350 | | WorkerRan |
351 | | }; |
352 | | |
353 | | void |
354 | | ScheduleDeletion(WorkerRanOrNot aRanOrNot); |
355 | | |
356 | | bool |
357 | | CollectRuntimeStats(JS::RuntimeStats* aRtStats, bool aAnonymize); |
358 | | |
359 | | #ifdef JS_GC_ZEAL |
360 | | void |
361 | | UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency); |
362 | | #endif |
363 | | |
364 | | void |
365 | | GarbageCollectInternal(JSContext* aCx, bool aShrinking, |
366 | | bool aCollectChildren); |
367 | | |
368 | | void |
369 | | CycleCollectInternal(bool aCollectChildren); |
370 | | |
371 | | void |
372 | | OfflineStatusChangeEventInternal(bool aIsOffline); |
373 | | |
374 | | void |
375 | | MemoryPressureInternal(); |
376 | | |
377 | | void |
378 | | SetFetchHandlerWasAdded() |
379 | | { |
380 | | MOZ_ASSERT(IsServiceWorker()); |
381 | | AssertIsOnWorkerThread(); |
382 | | mFetchHandlerWasAdded = true; |
383 | | } |
384 | | |
385 | | bool |
386 | | FetchHandlerWasAdded() const |
387 | | { |
388 | | MOZ_ASSERT(IsServiceWorker()); |
389 | | AssertIsOnWorkerThread(); |
390 | | return mFetchHandlerWasAdded; |
391 | | } |
392 | | |
393 | | JSContext* |
394 | | GetJSContext() const |
395 | | { |
396 | | AssertIsOnWorkerThread(); |
397 | | return mJSContext; |
398 | | } |
399 | | |
400 | | WorkerGlobalScope* |
401 | | GlobalScope() const |
402 | | { |
403 | | AssertIsOnWorkerThread(); |
404 | | return mScope; |
405 | | } |
406 | | |
407 | | WorkerDebuggerGlobalScope* |
408 | | DebuggerGlobalScope() const |
409 | 0 | { |
410 | 0 | AssertIsOnWorkerThread(); |
411 | 0 | return mDebuggerScope; |
412 | 0 | } |
413 | | |
414 | | void |
415 | | SetThread(WorkerThread* aThread); |
416 | | |
417 | | bool |
418 | | IsOnWorkerThread() const; |
419 | | |
420 | | void |
421 | | AssertIsOnWorkerThread() const |
422 | | #ifdef DEBUG |
423 | | ; |
424 | | #else |
425 | | { } |
426 | | #endif |
427 | | |
428 | | // This may block! |
429 | | void |
430 | | BeginCTypesCall(); |
431 | | |
432 | | // This may block! |
433 | | void |
434 | | EndCTypesCall(); |
435 | | |
436 | | void |
437 | | BeginCTypesCallback() |
438 | 0 | { |
439 | 0 | // If a callback is beginning then we need to do the exact same thing as |
440 | 0 | // when a ctypes call ends. |
441 | 0 | EndCTypesCall(); |
442 | 0 | } |
443 | | |
444 | | void |
445 | | EndCTypesCallback() |
446 | 0 | { |
447 | 0 | // If a callback is ending then we need to do the exact same thing as |
448 | 0 | // when a ctypes call begins. |
449 | 0 | BeginCTypesCall(); |
450 | 0 | } |
451 | | |
452 | | bool |
453 | | ConnectMessagePort(JSContext* aCx, MessagePortIdentifier& aIdentifier); |
454 | | |
455 | | WorkerGlobalScope* |
456 | | GetOrCreateGlobalScope(JSContext* aCx); |
457 | | |
458 | | WorkerDebuggerGlobalScope* |
459 | | CreateDebuggerGlobalScope(JSContext* aCx); |
460 | | |
461 | | bool |
462 | | RegisterBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal); |
463 | | |
464 | | bool |
465 | | RegisterDebuggerBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal); |
466 | | |
467 | | bool |
468 | | OnLine() const |
469 | | { |
470 | | AssertIsOnWorkerThread(); |
471 | | return mOnLine; |
472 | | } |
473 | | |
474 | | void |
475 | | StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult); |
476 | | |
477 | | bool |
478 | | AllPendingRunnablesShouldBeCanceled() const |
479 | | { |
480 | | return mCancelAllPendingRunnables; |
481 | | } |
482 | | |
483 | | void |
484 | | ClearMainEventQueue(WorkerRanOrNot aRanOrNot); |
485 | | |
486 | | void |
487 | | ClearDebuggerEventQueue(); |
488 | | |
489 | | void |
490 | | OnProcessNextEvent(); |
491 | | |
492 | | void |
493 | | AfterProcessNextEvent(); |
494 | | |
495 | | void |
496 | | AssertValidSyncLoop(nsIEventTarget* aSyncLoopTarget) |
497 | | #ifdef DEBUG |
498 | | ; |
499 | | #else |
500 | | { } |
501 | | #endif |
502 | | |
503 | | void |
504 | | SetWorkerScriptExecutedSuccessfully() |
505 | | { |
506 | | AssertIsOnWorkerThread(); |
507 | | // Should only be called once! |
508 | | MOZ_ASSERT(!mWorkerScriptExecutedSuccessfully); |
509 | | mWorkerScriptExecutedSuccessfully = true; |
510 | | } |
511 | | |
512 | | // Only valid after CompileScriptRunnable has finished running! |
513 | | bool |
514 | | WorkerScriptExecutedSuccessfully() const |
515 | | { |
516 | | AssertIsOnWorkerThread(); |
517 | | return mWorkerScriptExecutedSuccessfully; |
518 | | } |
519 | | |
520 | | // Get the event target to use when dispatching to the main thread |
521 | | // from this Worker thread. This may be the main thread itself or |
522 | | // a ThrottledEventQueue to the main thread. |
523 | | nsIEventTarget* |
524 | | MainThreadEventTarget(); |
525 | | |
526 | | nsresult |
527 | | DispatchToMainThread(nsIRunnable* aRunnable, |
528 | | uint32_t aFlags = NS_DISPATCH_NORMAL); |
529 | | |
530 | | nsresult |
531 | | DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable, |
532 | | uint32_t aFlags = NS_DISPATCH_NORMAL); |
533 | | |
534 | | // Get an event target that will dispatch runnables as control runnables on |
535 | | // the worker thread. Implement nsICancelableRunnable if you wish to take |
536 | | // action on cancelation. |
537 | | nsISerialEventTarget* |
538 | | ControlEventTarget(); |
539 | | |
540 | | // Get an event target that will attempt to dispatch a normal WorkerRunnable, |
541 | | // but if that fails will then fall back to a control runnable. |
542 | | nsISerialEventTarget* |
543 | | HybridEventTarget(); |
544 | | |
545 | | void |
546 | | DumpCrashInformation(nsACString& aString); |
547 | | |
548 | | bool |
549 | | EnsureClientSource(); |
550 | | |
551 | | bool |
552 | | EnsureCSPEventListener(); |
553 | | |
554 | | void |
555 | | EnsurePerformanceStorage(); |
556 | | |
557 | | void |
558 | | EnsurePerformanceCounter(); |
559 | | |
560 | | Maybe<ClientInfo> |
561 | | GetClientInfo() const; |
562 | | |
563 | | const ClientState |
564 | | GetClientState() const; |
565 | | |
566 | | const Maybe<ServiceWorkerDescriptor> |
567 | | GetController(); |
568 | | |
569 | | void |
570 | | Control(const ServiceWorkerDescriptor& aServiceWorker); |
571 | | |
572 | | void |
573 | | ExecutionReady(); |
574 | | |
575 | | PerformanceStorage* |
576 | | GetPerformanceStorage(); |
577 | | |
578 | | PerformanceCounter* |
579 | | GetPerformanceCounter(); |
580 | | |
581 | | bool |
582 | | IsAcceptingEvents() |
583 | 0 | { |
584 | 0 | AssertIsOnParentThread(); |
585 | 0 |
|
586 | 0 | MutexAutoLock lock(mMutex); |
587 | 0 | return mParentStatus < Canceling; |
588 | 0 | } |
589 | | |
590 | | WorkerStatus |
591 | | ParentStatusProtected() |
592 | 0 | { |
593 | 0 | AssertIsOnParentThread(); |
594 | 0 | MutexAutoLock lock(mMutex); |
595 | 0 | return mParentStatus; |
596 | 0 | } |
597 | | |
598 | | WorkerStatus |
599 | | ParentStatus() const |
600 | | { |
601 | | mMutex.AssertCurrentThreadOwns(); |
602 | | return mParentStatus; |
603 | | } |
604 | | |
605 | | Worker* |
606 | | ParentEventTargetRef() const |
607 | 0 | { |
608 | 0 | MOZ_DIAGNOSTIC_ASSERT(mParentEventTargetRef); |
609 | 0 | return mParentEventTargetRef; |
610 | 0 | } |
611 | | |
612 | | void |
613 | | SetParentEventTargetRef(Worker* aParentEventTargetRef) |
614 | 0 | { |
615 | 0 | MOZ_DIAGNOSTIC_ASSERT(aParentEventTargetRef); |
616 | 0 | MOZ_DIAGNOSTIC_ASSERT(!mParentEventTargetRef); |
617 | 0 | mParentEventTargetRef = aParentEventTargetRef; |
618 | 0 | } |
619 | | |
620 | | bool |
621 | | ModifyBusyCount(bool aIncrease); |
622 | | |
623 | | // This method is used by RuntimeService to know what is going wrong the |
624 | | // shutting down. |
625 | | uint32_t |
626 | | BusyCount() |
627 | 0 | { |
628 | 0 | return mBusyCount; |
629 | 0 | } |
630 | | |
631 | | // Check whether this worker is a secure context. For use from the parent |
632 | | // thread only; the canonical "is secure context" boolean is stored on the |
633 | | // compartment of the worker global. The only reason we don't |
634 | | // AssertIsOnParentThread() here is so we can assert that this value matches |
635 | | // the one on the compartment, which has to be done from the worker thread. |
636 | | bool IsSecureContext() const |
637 | 0 | { |
638 | 0 | return mIsSecureContext; |
639 | 0 | } |
640 | | |
641 | | // Check whether we're running in automation. |
642 | | bool IsInAutomation() const |
643 | | { |
644 | | return mIsInAutomation; |
645 | | } |
646 | | |
647 | | TimeStamp CreationTimeStamp() const |
648 | 0 | { |
649 | 0 | return mCreationTimeStamp; |
650 | 0 | } |
651 | | |
652 | | DOMHighResTimeStamp CreationTime() const |
653 | | { |
654 | | return mCreationTimeHighRes; |
655 | | } |
656 | | |
657 | | DOMHighResTimeStamp TimeStampToDOMHighRes(const TimeStamp& aTimeStamp) const |
658 | | { |
659 | | MOZ_ASSERT(!aTimeStamp.IsNull()); |
660 | | TimeDuration duration = aTimeStamp - mCreationTimeStamp; |
661 | | return duration.ToMilliseconds(); |
662 | | } |
663 | | |
664 | | LocationInfo& |
665 | | GetLocationInfo() |
666 | | { |
667 | | return mLocationInfo; |
668 | | } |
669 | | |
670 | | void |
671 | | CopyJSSettings(workerinternals::JSSettings& aSettings) |
672 | 0 | { |
673 | 0 | mozilla::MutexAutoLock lock(mMutex); |
674 | 0 | aSettings = mJSSettings; |
675 | 0 | } |
676 | | |
677 | | void |
678 | | CopyJSRealmOptions(JS::RealmOptions& aOptions) |
679 | | { |
680 | | mozilla::MutexAutoLock lock(mMutex); |
681 | | aOptions = IsChromeWorker() ? mJSSettings.chrome.realmOptions |
682 | | : mJSSettings.content.realmOptions; |
683 | | } |
684 | | |
685 | | // The ability to be a chrome worker is orthogonal to the type of |
686 | | // worker [Dedicated|Shared|Service]. |
687 | | bool |
688 | | IsChromeWorker() const |
689 | 0 | { |
690 | 0 | return mIsChromeWorker; |
691 | 0 | } |
692 | | |
693 | | WorkerPrivate* |
694 | | GetParent() const |
695 | | { |
696 | | return mParent; |
697 | | } |
698 | | |
699 | | bool |
700 | | IsFrozen() const |
701 | 0 | { |
702 | 0 | AssertIsOnParentThread(); |
703 | 0 | return mParentFrozen; |
704 | 0 | } |
705 | | |
706 | | bool |
707 | | IsParentWindowPaused() const |
708 | 0 | { |
709 | 0 | AssertIsOnParentThread(); |
710 | 0 | return mParentWindowPausedDepth > 0; |
711 | 0 | } |
712 | | |
713 | | // When we debug a worker, we want to disconnect the window and the worker |
714 | | // communication. This happens calling this method. |
715 | | // Note: this method doesn't suspend the worker! Use Freeze/Thaw instead. |
716 | | void |
717 | | ParentWindowPaused(); |
718 | | |
719 | | void |
720 | | ParentWindowResumed(); |
721 | | |
722 | | const nsString& |
723 | | ScriptURL() const |
724 | | { |
725 | | return mScriptURL; |
726 | | } |
727 | | |
728 | | const nsString& |
729 | | WorkerName() const |
730 | 0 | { |
731 | 0 | return mWorkerName; |
732 | 0 | } |
733 | | |
734 | | WorkerType |
735 | | Type() const |
736 | 0 | { |
737 | 0 | return mWorkerType; |
738 | 0 | } |
739 | | |
740 | | bool |
741 | | IsDedicatedWorker() const |
742 | 0 | { |
743 | 0 | return mWorkerType == WorkerTypeDedicated; |
744 | 0 | } |
745 | | |
746 | | bool |
747 | | IsSharedWorker() const |
748 | | { |
749 | | return mWorkerType == WorkerTypeShared; |
750 | | } |
751 | | |
752 | | bool |
753 | | IsServiceWorker() const |
754 | | { |
755 | | return mWorkerType == WorkerTypeService; |
756 | | } |
757 | | |
758 | | nsContentPolicyType |
759 | | ContentPolicyType() const |
760 | 0 | { |
761 | 0 | return ContentPolicyType(mWorkerType); |
762 | 0 | } |
763 | | |
764 | | static nsContentPolicyType |
765 | | ContentPolicyType(WorkerType aWorkerType) |
766 | 0 | { |
767 | 0 | switch (aWorkerType) { |
768 | 0 | case WorkerTypeDedicated: |
769 | 0 | return nsIContentPolicy::TYPE_INTERNAL_WORKER; |
770 | 0 | case WorkerTypeShared: |
771 | 0 | return nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER; |
772 | 0 | case WorkerTypeService: |
773 | 0 | return nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER; |
774 | 0 | default: |
775 | 0 | MOZ_ASSERT_UNREACHABLE("Invalid worker type"); |
776 | 0 | return nsIContentPolicy::TYPE_INVALID; |
777 | 0 | } |
778 | 0 | } |
779 | | |
780 | | nsIScriptContext* |
781 | | GetScriptContext() const |
782 | | { |
783 | | AssertIsOnMainThread(); |
784 | | return mLoadInfo.mScriptContext; |
785 | | } |
786 | | |
787 | | const nsCString& |
788 | | Domain() const |
789 | 0 | { |
790 | 0 | return mLoadInfo.mDomain; |
791 | 0 | } |
792 | | |
793 | | bool |
794 | | IsFromWindow() const |
795 | | { |
796 | | return mLoadInfo.mFromWindow; |
797 | | } |
798 | | |
799 | | nsLoadFlags |
800 | | GetLoadFlags() const |
801 | 0 | { |
802 | 0 | return mLoadInfo.mLoadFlags; |
803 | 0 | } |
804 | | |
805 | | uint64_t |
806 | | WindowID() const |
807 | | { |
808 | | return mLoadInfo.mWindowID; |
809 | | } |
810 | | |
811 | | uint64_t |
812 | | ServiceWorkerID() const |
813 | | { |
814 | | return GetServiceWorkerDescriptor().Id(); |
815 | | } |
816 | | |
817 | | const nsCString& |
818 | | ServiceWorkerScope() const |
819 | | { |
820 | | return GetServiceWorkerDescriptor().Scope(); |
821 | | } |
822 | | |
823 | | nsIURI* |
824 | | GetBaseURI() const |
825 | | { |
826 | | AssertIsOnMainThread(); |
827 | | return mLoadInfo.mBaseURI; |
828 | | } |
829 | | |
830 | | void |
831 | | SetBaseURI(nsIURI* aBaseURI); |
832 | | |
833 | | nsIURI* |
834 | | GetResolvedScriptURI() const |
835 | 0 | { |
836 | 0 | AssertIsOnMainThread(); |
837 | 0 | return mLoadInfo.mResolvedScriptURI; |
838 | 0 | } |
839 | | |
840 | | const nsString& |
841 | | ServiceWorkerCacheName() const |
842 | 0 | { |
843 | 0 | MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker()); |
844 | 0 | AssertIsOnMainThread(); |
845 | 0 | return mLoadInfo.mServiceWorkerCacheName; |
846 | 0 | } |
847 | | |
848 | | const ServiceWorkerDescriptor& |
849 | | GetServiceWorkerDescriptor() const |
850 | | { |
851 | | MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker()); |
852 | | MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome()); |
853 | | return mLoadInfo.mServiceWorkerDescriptor.ref(); |
854 | | } |
855 | | |
856 | | const ServiceWorkerRegistrationDescriptor& |
857 | | GetServiceWorkerRegistrationDescriptor() const |
858 | | { |
859 | | MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker()); |
860 | | MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerRegistrationDescriptor.isSome()); |
861 | | return mLoadInfo.mServiceWorkerRegistrationDescriptor.ref(); |
862 | | } |
863 | | |
864 | | void |
865 | | UpdateServiceWorkerState(ServiceWorkerState aState) |
866 | | { |
867 | | MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker()); |
868 | | MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome()); |
869 | | return mLoadInfo.mServiceWorkerDescriptor.ref().SetState(aState); |
870 | | } |
871 | | |
872 | | const Maybe<ServiceWorkerDescriptor>& |
873 | | GetParentController() const |
874 | 0 | { |
875 | 0 | return mLoadInfo.mParentController; |
876 | 0 | } |
877 | | |
878 | | const ChannelInfo& |
879 | | GetChannelInfo() const |
880 | | { |
881 | | return mLoadInfo.mChannelInfo; |
882 | | } |
883 | | |
884 | | void |
885 | | SetChannelInfo(const ChannelInfo& aChannelInfo) |
886 | | { |
887 | | AssertIsOnMainThread(); |
888 | | MOZ_ASSERT(!mLoadInfo.mChannelInfo.IsInitialized()); |
889 | | MOZ_ASSERT(aChannelInfo.IsInitialized()); |
890 | | mLoadInfo.mChannelInfo = aChannelInfo; |
891 | | } |
892 | | |
893 | | void |
894 | | InitChannelInfo(nsIChannel* aChannel) |
895 | 0 | { |
896 | 0 | mLoadInfo.mChannelInfo.InitFromChannel(aChannel); |
897 | 0 | } |
898 | | |
899 | | void |
900 | | InitChannelInfo(const ChannelInfo& aChannelInfo) |
901 | 0 | { |
902 | 0 | mLoadInfo.mChannelInfo = aChannelInfo; |
903 | 0 | } |
904 | | |
905 | | nsIPrincipal* |
906 | | GetPrincipal() const |
907 | | { |
908 | | AssertIsOnMainThread(); |
909 | | return mLoadInfo.mPrincipal; |
910 | | } |
911 | | |
912 | | nsIPrincipal* |
913 | | GetLoadingPrincipal() const |
914 | 0 | { |
915 | 0 | AssertIsOnMainThread(); |
916 | 0 | return mLoadInfo.mLoadingPrincipal; |
917 | 0 | } |
918 | | |
919 | | const nsAString& Origin() const |
920 | | { |
921 | | return mLoadInfo.mOrigin; |
922 | | } |
923 | | |
924 | | nsILoadGroup* |
925 | | GetLoadGroup() const |
926 | | { |
927 | | AssertIsOnMainThread(); |
928 | | return mLoadInfo.mLoadGroup; |
929 | | } |
930 | | |
931 | | // This method allows the principal to be retrieved off the main thread. |
932 | | // Principals are main-thread objects so the caller must ensure that all |
933 | | // access occurs on the main thread. |
934 | | nsIPrincipal* |
935 | | GetPrincipalDontAssertMainThread() const |
936 | 0 | { |
937 | 0 | return mLoadInfo.mPrincipal; |
938 | 0 | } |
939 | | |
940 | | bool |
941 | | UsesSystemPrincipal() const |
942 | | { |
943 | | return mLoadInfo.mPrincipalIsSystem; |
944 | | } |
945 | | |
946 | | const mozilla::ipc::PrincipalInfo& |
947 | | GetPrincipalInfo() const |
948 | | { |
949 | | return *mLoadInfo.mPrincipalInfo; |
950 | | } |
951 | | |
952 | | already_AddRefed<nsIChannel> |
953 | | ForgetWorkerChannel() |
954 | 0 | { |
955 | 0 | AssertIsOnMainThread(); |
956 | 0 | return mLoadInfo.mChannel.forget(); |
957 | 0 | } |
958 | | |
959 | | nsPIDOMWindowInner* |
960 | | GetWindow() |
961 | | { |
962 | | AssertIsOnMainThread(); |
963 | | return mLoadInfo.mWindow; |
964 | | } |
965 | | |
966 | | nsIContentSecurityPolicy* |
967 | | GetCSP() const |
968 | | { |
969 | | AssertIsOnMainThread(); |
970 | | return mLoadInfo.mCSP; |
971 | | } |
972 | | |
973 | | void |
974 | | SetCSP(nsIContentSecurityPolicy* aCSP); |
975 | | |
976 | | nsresult |
977 | | SetCSPFromHeaderValues(const nsACString& aCSPHeaderValue, |
978 | | const nsACString& aCSPReportOnlyHeaderValue); |
979 | | |
980 | | void |
981 | | SetReferrerPolicyFromHeaderValue(const nsACString& aReferrerPolicyHeaderValue); |
982 | | |
983 | | net::ReferrerPolicy |
984 | | GetReferrerPolicy() const |
985 | | { |
986 | | return mLoadInfo.mReferrerPolicy; |
987 | | } |
988 | | |
989 | | void |
990 | | SetReferrerPolicy(net::ReferrerPolicy aReferrerPolicy) |
991 | | { |
992 | | mLoadInfo.mReferrerPolicy = aReferrerPolicy; |
993 | | } |
994 | | |
995 | | bool |
996 | | IsEvalAllowed() const |
997 | 0 | { |
998 | 0 | return mLoadInfo.mEvalAllowed; |
999 | 0 | } |
1000 | | |
1001 | | void |
1002 | | SetEvalAllowed(bool aEvalAllowed) |
1003 | 0 | { |
1004 | 0 | mLoadInfo.mEvalAllowed = aEvalAllowed; |
1005 | 0 | } |
1006 | | |
1007 | | bool |
1008 | | GetReportCSPViolations() const |
1009 | 0 | { |
1010 | 0 | return mLoadInfo.mReportCSPViolations; |
1011 | 0 | } |
1012 | | |
1013 | | void |
1014 | | SetReportCSPViolations(bool aReport) |
1015 | | { |
1016 | | mLoadInfo.mReportCSPViolations = aReport; |
1017 | | } |
1018 | | |
1019 | | bool |
1020 | | XHRParamsAllowed() const |
1021 | 0 | { |
1022 | 0 | return mLoadInfo.mXHRParamsAllowed; |
1023 | 0 | } |
1024 | | |
1025 | | void |
1026 | | SetXHRParamsAllowed(bool aAllowed) |
1027 | 0 | { |
1028 | 0 | mLoadInfo.mXHRParamsAllowed = aAllowed; |
1029 | 0 | } |
1030 | | |
1031 | | bool |
1032 | | IsStorageAllowed() const |
1033 | | { |
1034 | | AssertIsOnWorkerThread(); |
1035 | | return mLoadInfo.mStorageAllowed || mLoadInfo.mFirstPartyStorageAccessGranted; |
1036 | | } |
1037 | | |
1038 | | const OriginAttributes& |
1039 | | GetOriginAttributes() const |
1040 | | { |
1041 | | return mLoadInfo.mOriginAttributes; |
1042 | | } |
1043 | | |
1044 | | // Determine if the SW testing per-window flag is set by devtools |
1045 | | bool |
1046 | | ServiceWorkersTestingInWindow() const |
1047 | | { |
1048 | | return mLoadInfo.mServiceWorkersTestingInWindow; |
1049 | | } |
1050 | | |
1051 | | // Determine if the worker is currently loading its top level script. |
1052 | | bool |
1053 | | IsLoadingWorkerScript() const |
1054 | | { |
1055 | | return mLoadingWorkerScript; |
1056 | | } |
1057 | | |
1058 | | // Called by ScriptLoader to track when this worker is loading its |
1059 | | // top level script. |
1060 | | void |
1061 | | SetLoadingWorkerScript(bool aLoadingWorkerScript) |
1062 | 0 | { |
1063 | 0 | // any thread |
1064 | 0 | mLoadingWorkerScript = aLoadingWorkerScript; |
1065 | 0 | } |
1066 | | |
1067 | | void |
1068 | | QueueRunnable(nsIRunnable* aRunnable) |
1069 | 0 | { |
1070 | 0 | AssertIsOnParentThread(); |
1071 | 0 | mQueuedRunnables.AppendElement(aRunnable); |
1072 | 0 | } |
1073 | | |
1074 | | bool |
1075 | | RegisterSharedWorker(SharedWorker* aSharedWorker, MessagePort* aPort); |
1076 | | |
1077 | | void |
1078 | | BroadcastErrorToSharedWorkers(JSContext* aCx, |
1079 | | const WorkerErrorReport* aReport, |
1080 | | bool aIsErrorEvent); |
1081 | | |
1082 | | void |
1083 | | GetAllSharedWorkers(nsTArray<RefPtr<SharedWorker>>& aSharedWorkers); |
1084 | | |
1085 | | void |
1086 | | CloseSharedWorkersForWindow(nsPIDOMWindowInner* aWindow); |
1087 | | |
1088 | | void |
1089 | | CloseAllSharedWorkers(); |
1090 | | |
1091 | | void |
1092 | | FlushReportsToSharedWorkers(nsIConsoleReportCollector* aReporter); |
1093 | | |
1094 | | // We can assume that an nsPIDOMWindow will be available for Freeze, Thaw |
1095 | | // as these are only used for globals going in and out of the bfcache. |
1096 | | // |
1097 | | // XXXbz: This is a bald-faced lie given the uses in RegisterSharedWorker and |
1098 | | // CloseSharedWorkersForWindow, which pass null for aWindow to Thaw and Freeze |
1099 | | // respectively. See bug 1251722. |
1100 | | bool |
1101 | | Freeze(nsPIDOMWindowInner* aWindow); |
1102 | | |
1103 | | bool |
1104 | | Thaw(nsPIDOMWindowInner* aWindow); |
1105 | | |
1106 | | void |
1107 | | PropagateFirstPartyStorageAccessGranted(); |
1108 | | |
1109 | | void |
1110 | | EnableDebugger(); |
1111 | | |
1112 | | void |
1113 | | DisableDebugger(); |
1114 | | |
1115 | | already_AddRefed<WorkerRunnable> |
1116 | | MaybeWrapAsWorkerRunnable(already_AddRefed<nsIRunnable> aRunnable); |
1117 | | |
1118 | | bool |
1119 | | ProxyReleaseMainThreadObjects(); |
1120 | | |
1121 | | void |
1122 | | GarbageCollect(bool aShrinking); |
1123 | | |
1124 | | void |
1125 | | CycleCollect(bool aDummy); |
1126 | | |
1127 | | nsresult |
1128 | | SetPrincipalOnMainThread(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup); |
1129 | | |
1130 | | nsresult |
1131 | | SetPrincipalFromChannel(nsIChannel* aChannel); |
1132 | | |
1133 | | bool |
1134 | | FinalChannelPrincipalIsValid(nsIChannel* aChannel); |
1135 | | |
1136 | | #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED |
1137 | | bool |
1138 | | PrincipalURIMatchesScriptURL(); |
1139 | | #endif |
1140 | | |
1141 | | void |
1142 | | UpdateOverridenLoadGroup(nsILoadGroup* aBaseLoadGroup); |
1143 | | |
1144 | | void |
1145 | | WorkerScriptLoaded(); |
1146 | | |
1147 | | nsIDocument* GetDocument() const; |
1148 | | |
1149 | | void |
1150 | | MemoryPressure(bool aDummy); |
1151 | | |
1152 | | void |
1153 | | UpdateContextOptions(const JS::ContextOptions& aContextOptions); |
1154 | | |
1155 | | void |
1156 | | UpdateLanguages(const nsTArray<nsString>& aLanguages); |
1157 | | |
1158 | | void |
1159 | | UpdateJSWorkerMemoryParameter(JSGCParamKey key, uint32_t value); |
1160 | | |
1161 | | #ifdef JS_GC_ZEAL |
1162 | | void |
1163 | | UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency); |
1164 | | #endif |
1165 | | |
1166 | | void |
1167 | | OfflineStatusChangeEvent(bool aIsOffline); |
1168 | | |
1169 | | nsresult |
1170 | | Dispatch(already_AddRefed<WorkerRunnable> aRunnable, |
1171 | | nsIEventTarget* aSyncLoopTarget = nullptr); |
1172 | | |
1173 | | nsresult |
1174 | | DispatchControlRunnable(already_AddRefed<WorkerControlRunnable> aWorkerControlRunnable); |
1175 | | |
1176 | | nsresult |
1177 | | DispatchDebuggerRunnable(already_AddRefed<WorkerRunnable> aDebuggerRunnable); |
1178 | | |
1179 | | #ifdef DEBUG |
1180 | | void |
1181 | | AssertIsOnParentThread() const; |
1182 | | |
1183 | | void |
1184 | | AssertInnerWindowIsCorrect() const; |
1185 | | #else |
1186 | | void |
1187 | | AssertIsOnParentThread() const |
1188 | 0 | { } |
1189 | | |
1190 | | void |
1191 | | AssertInnerWindowIsCorrect() const |
1192 | 0 | { } |
1193 | | #endif |
1194 | | |
1195 | | #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED |
1196 | | bool |
1197 | | PrincipalIsValid() const; |
1198 | | #endif |
1199 | | |
1200 | | void |
1201 | | StartCancelingTimer(); |
1202 | | |
1203 | | private: |
1204 | | WorkerPrivate(WorkerPrivate* aParent, |
1205 | | const nsAString& aScriptURL, bool aIsChromeWorker, |
1206 | | WorkerType aWorkerType, const nsAString& aWorkerName, |
1207 | | const nsACString& aServiceWorkerScope, |
1208 | | WorkerLoadInfo& aLoadInfo); |
1209 | | |
1210 | | ~WorkerPrivate(); |
1211 | | |
1212 | | bool |
1213 | | MayContinueRunning() |
1214 | | { |
1215 | | AssertIsOnWorkerThread(); |
1216 | | |
1217 | | WorkerStatus status; |
1218 | | { |
1219 | | MutexAutoLock lock(mMutex); |
1220 | | status = mStatus; |
1221 | | } |
1222 | | |
1223 | | if (status < Canceling) { |
1224 | | return true; |
1225 | | } |
1226 | | |
1227 | | return false; |
1228 | | } |
1229 | | |
1230 | | void |
1231 | | CancelAllTimeouts(); |
1232 | | |
1233 | | enum class ProcessAllControlRunnablesResult |
1234 | | { |
1235 | | // We did not process anything. |
1236 | | Nothing, |
1237 | | // We did process something, states may have changed, but we can keep |
1238 | | // executing script. |
1239 | | MayContinue, |
1240 | | // We did process something, and should not continue executing script. |
1241 | | Abort |
1242 | | }; |
1243 | | |
1244 | | ProcessAllControlRunnablesResult |
1245 | | ProcessAllControlRunnables() |
1246 | | { |
1247 | | MutexAutoLock lock(mMutex); |
1248 | | return ProcessAllControlRunnablesLocked(); |
1249 | | } |
1250 | | |
1251 | | ProcessAllControlRunnablesResult |
1252 | | ProcessAllControlRunnablesLocked(); |
1253 | | |
1254 | | void |
1255 | | EnableMemoryReporter(); |
1256 | | |
1257 | | void |
1258 | | DisableMemoryReporter(); |
1259 | | |
1260 | | void |
1261 | | WaitForWorkerEvents(); |
1262 | | |
1263 | | // If the worker shutdown status is equal or greater then aFailStatus, this |
1264 | | // operation will fail and nullptr will be returned. See WorkerHolder.h for |
1265 | | // more information about the correct value to use. |
1266 | | already_AddRefed<nsIEventTarget> |
1267 | | CreateNewSyncLoop(WorkerStatus aFailStatus); |
1268 | | |
1269 | | bool |
1270 | | RunCurrentSyncLoop(); |
1271 | | |
1272 | | bool |
1273 | | DestroySyncLoop(uint32_t aLoopIndex); |
1274 | | |
1275 | | void |
1276 | | InitializeGCTimers(); |
1277 | | |
1278 | | enum GCTimerMode |
1279 | | { |
1280 | | PeriodicTimer = 0, |
1281 | | IdleTimer, |
1282 | | NoTimer |
1283 | | }; |
1284 | | |
1285 | | void |
1286 | | SetGCTimerMode(GCTimerMode aMode); |
1287 | | |
1288 | | void |
1289 | | ShutdownGCTimers(); |
1290 | | |
1291 | | bool |
1292 | | AddHolder(WorkerHolder* aHolder, WorkerStatus aFailStatus); |
1293 | | |
1294 | | void |
1295 | | RemoveHolder(WorkerHolder* aHolder); |
1296 | | |
1297 | | void |
1298 | | NotifyHolders(WorkerStatus aStatus); |
1299 | | |
1300 | | bool |
1301 | | HasActiveHolders() |
1302 | | { |
1303 | | return !(mChildWorkers.IsEmpty() && mTimeouts.IsEmpty() && |
1304 | | mHolders.IsEmpty()); |
1305 | | } |
1306 | | |
1307 | | class EventTarget; |
1308 | | friend class EventTarget; |
1309 | | friend class mozilla::dom::WorkerHolder; |
1310 | | friend class AutoSyncLoopHolder; |
1311 | | |
1312 | | struct TimeoutInfo; |
1313 | | |
1314 | | class MemoryReporter; |
1315 | | friend class MemoryReporter; |
1316 | | |
1317 | | friend class mozilla::dom::WorkerThread; |
1318 | | |
1319 | | SharedMutex mMutex; |
1320 | | mozilla::CondVar mCondVar; |
1321 | | |
1322 | | WorkerPrivate* mParent; |
1323 | | |
1324 | | nsString mScriptURL; |
1325 | | |
1326 | | // This is the worker name for shared workers and dedicated workers. |
1327 | | nsString mWorkerName; |
1328 | | |
1329 | | WorkerType mWorkerType; |
1330 | | |
1331 | | // The worker is owned by its thread, which is represented here. This is set |
1332 | | // in Constructor() and emptied by WorkerFinishedRunnable, and conditionally |
1333 | | // traversed by the cycle collector if the busy count is zero. |
1334 | | // |
1335 | | // There are 4 ways a worker can be terminated: |
1336 | | // 1. GC/CC - When the worker is in idle state (busycount == 0), it allows to |
1337 | | // traverse the 'hidden' mParentEventTargetRef pointer. This is the exposed |
1338 | | // Worker webidl object. Doing this, CC will be able to detect a cycle and |
1339 | | // Unlink is called. In Unlink, Worker calls Cancel(). |
1340 | | // 2. Worker::Cancel() is called - the shutdown procedure starts immediately. |
1341 | | // 3. WorkerScope::Close() is called - Similar to point 2. |
1342 | | // 4. xpcom-shutdown notification - We call Kill(). |
1343 | | RefPtr<Worker> mParentEventTargetRef; |
1344 | | RefPtr<WorkerPrivate> mSelfRef; |
1345 | | |
1346 | | // The lifetime of these objects within LoadInfo is managed explicitly; |
1347 | | // they do not need to be cycle collected. |
1348 | | WorkerLoadInfo mLoadInfo; |
1349 | | LocationInfo mLocationInfo; |
1350 | | |
1351 | | // Protected by mMutex. |
1352 | | workerinternals::JSSettings mJSSettings; |
1353 | | |
1354 | | WorkerDebugger* mDebugger; |
1355 | | |
1356 | | workerinternals::Queue<WorkerControlRunnable*, 4> mControlQueue; |
1357 | | workerinternals::Queue<WorkerRunnable*, 4> mDebuggerQueue; |
1358 | | |
1359 | | // Touched on multiple threads, protected with mMutex. |
1360 | | JSContext* mJSContext; |
1361 | | RefPtr<WorkerThread> mThread; |
1362 | | PRThread* mPRThread; |
1363 | | |
1364 | | // Things touched on worker thread only. |
1365 | | RefPtr<WorkerGlobalScope> mScope; |
1366 | | RefPtr<WorkerDebuggerGlobalScope> mDebuggerScope; |
1367 | | nsTArray<WorkerPrivate*> mChildWorkers; |
1368 | | nsTObserverArray<WorkerHolder*> mHolders; |
1369 | | nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts; |
1370 | | RefPtr<ThrottledEventQueue> mMainThreadThrottledEventQueue; |
1371 | | nsCOMPtr<nsIEventTarget> mMainThreadEventTarget; |
1372 | | RefPtr<WorkerEventTarget> mWorkerControlEventTarget; |
1373 | | RefPtr<WorkerEventTarget> mWorkerHybridEventTarget; |
1374 | | |
1375 | | struct SyncLoopInfo |
1376 | | { |
1377 | | explicit SyncLoopInfo(EventTarget* aEventTarget); |
1378 | | |
1379 | | RefPtr<EventTarget> mEventTarget; |
1380 | | bool mCompleted; |
1381 | | bool mResult; |
1382 | | #ifdef DEBUG |
1383 | | bool mHasRun; |
1384 | | #endif |
1385 | | }; |
1386 | | |
1387 | | // This is only modified on the worker thread, but in DEBUG builds |
1388 | | // AssertValidSyncLoop function iterates it on other threads. Therefore |
1389 | | // modifications are done with mMutex held *only* in DEBUG builds. |
1390 | | nsTArray<nsAutoPtr<SyncLoopInfo>> mSyncLoopStack; |
1391 | | |
1392 | | nsCOMPtr<nsITimer> mTimer; |
1393 | | nsCOMPtr<nsITimerCallback> mTimerRunnable; |
1394 | | |
1395 | | nsCOMPtr<nsITimer> mCancelingTimer; |
1396 | | |
1397 | | nsCOMPtr<nsITimer> mGCTimer; |
1398 | | |
1399 | | RefPtr<MemoryReporter> mMemoryReporter; |
1400 | | |
1401 | | // fired on the main thread if the worker script fails to load |
1402 | | nsCOMPtr<nsIRunnable> mLoadFailedRunnable; |
1403 | | |
1404 | | RefPtr<PerformanceStorage> mPerformanceStorage; |
1405 | | |
1406 | | RefPtr<WorkerCSPEventListener> mCSPEventListener; |
1407 | | |
1408 | | // Only used for top level workers. |
1409 | | nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables; |
1410 | | |
1411 | | // Protected by mMutex. |
1412 | | nsTArray<RefPtr<WorkerRunnable>> mPreStartRunnables; |
1413 | | |
1414 | | // Only touched on the parent thread (currently this is always the main |
1415 | | // thread as SharedWorkers are always top-level). |
1416 | | nsTArray<RefPtr<SharedWorker>> mSharedWorkers; |
1417 | | |
1418 | | JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init |
1419 | | TimeStamp mKillTime; |
1420 | | WorkerStatus mParentStatus; |
1421 | | WorkerStatus mStatus; |
1422 | | UniquePtr<ClientSource> mClientSource; |
1423 | | |
1424 | | // This is touched on parent thread only, but it can be read on a different |
1425 | | // thread before crashing because hanging. |
1426 | | Atomic<uint64_t> mBusyCount; |
1427 | | |
1428 | | Atomic<bool> mLoadingWorkerScript; |
1429 | | |
1430 | | TimeStamp mCreationTimeStamp; |
1431 | | DOMHighResTimeStamp mCreationTimeHighRes; |
1432 | | |
1433 | | // Things touched on worker thread only. |
1434 | | uint32_t mNumHoldersPreventingShutdownStart; |
1435 | | uint32_t mDebuggerEventLoopLevel; |
1436 | | |
1437 | | uint32_t mErrorHandlerRecursionCount; |
1438 | | uint32_t mNextTimeoutId; |
1439 | | |
1440 | | // SharedWorkers may have multiple windows paused, so this must be |
1441 | | // a count instead of just a boolean. |
1442 | | uint32_t mParentWindowPausedDepth; |
1443 | | |
1444 | | bool mFrozen; |
1445 | | bool mTimerRunning; |
1446 | | bool mRunningExpiredTimeouts; |
1447 | | bool mPendingEventQueueClearing; |
1448 | | bool mCancelAllPendingRunnables; |
1449 | | bool mPeriodicGCTimerRunning; |
1450 | | bool mIdleGCTimerRunning; |
1451 | | bool mWorkerScriptExecutedSuccessfully; |
1452 | | bool mFetchHandlerWasAdded; |
1453 | | bool mOnLine; |
1454 | | bool mMainThreadObjectsForgotten; |
1455 | | bool mIsChromeWorker; |
1456 | | bool mParentFrozen; |
1457 | | |
1458 | | // mIsSecureContext is set once in our constructor; after that it can be read |
1459 | | // from various threads. We could make this const if we were OK with setting |
1460 | | // it in the initializer list via calling some function that takes all sorts |
1461 | | // of state (loadinfo, worker type, parent). |
1462 | | // |
1463 | | // It's a bit unfortunate that we have to have an out-of-band boolean for |
1464 | | // this, but we need access to this state from the parent thread, and we can't |
1465 | | // use our global object's secure state there. |
1466 | | bool mIsSecureContext; |
1467 | | |
1468 | | bool mDebuggerRegistered; |
1469 | | |
1470 | | // mIsInAutomation is true when we're running in test automation. |
1471 | | // We expose some extra testing functions in that case. |
1472 | | bool mIsInAutomation; |
1473 | | |
1474 | | // This pointer will be null if dom.performance.enable_scheduler_timing is |
1475 | | // false (default value) |
1476 | | RefPtr<mozilla::PerformanceCounter> mPerformanceCounter; |
1477 | | }; |
1478 | | |
1479 | | class AutoSyncLoopHolder |
1480 | | { |
1481 | | WorkerPrivate* mWorkerPrivate; |
1482 | | nsCOMPtr<nsIEventTarget> mTarget; |
1483 | | uint32_t mIndex; |
1484 | | |
1485 | | public: |
1486 | | // See CreateNewSyncLoop() for more information about the correct value to use |
1487 | | // for aFailStatus. |
1488 | | AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate, WorkerStatus aFailStatus) |
1489 | | : mWorkerPrivate(aWorkerPrivate) |
1490 | | , mTarget(aWorkerPrivate->CreateNewSyncLoop(aFailStatus)) |
1491 | | , mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1) |
1492 | | { |
1493 | | aWorkerPrivate->AssertIsOnWorkerThread(); |
1494 | | } |
1495 | | |
1496 | | ~AutoSyncLoopHolder() |
1497 | | { |
1498 | | if (mWorkerPrivate && mTarget) { |
1499 | | mWorkerPrivate->AssertIsOnWorkerThread(); |
1500 | | mWorkerPrivate->StopSyncLoop(mTarget, false); |
1501 | | mWorkerPrivate->DestroySyncLoop(mIndex); |
1502 | | } |
1503 | | } |
1504 | | |
1505 | | bool |
1506 | | Run() |
1507 | | { |
1508 | | WorkerPrivate* workerPrivate = mWorkerPrivate; |
1509 | | mWorkerPrivate = nullptr; |
1510 | | |
1511 | | workerPrivate->AssertIsOnWorkerThread(); |
1512 | | |
1513 | | return workerPrivate->RunCurrentSyncLoop(); |
1514 | | } |
1515 | | |
1516 | | nsIEventTarget* |
1517 | | GetEventTarget() const |
1518 | | { |
1519 | | // This can be null if CreateNewSyncLoop() fails. |
1520 | | return mTarget; |
1521 | | } |
1522 | | }; |
1523 | | |
1524 | | } // dom namespace |
1525 | | } // mozilla namespace |
1526 | | |
1527 | | #endif /* mozilla_dom_workers_workerprivate_h__ */ |