Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef mozilla_dom_workers_workerprivate_h__ |
michael@0 | 7 | #define mozilla_dom_workers_workerprivate_h__ |
michael@0 | 8 | |
michael@0 | 9 | #include "Workers.h" |
michael@0 | 10 | |
michael@0 | 11 | #include "nsIContentSecurityPolicy.h" |
michael@0 | 12 | #include "nsPIDOMWindow.h" |
michael@0 | 13 | |
michael@0 | 14 | #include "mozilla/CondVar.h" |
michael@0 | 15 | #include "mozilla/DOMEventTargetHelper.h" |
michael@0 | 16 | #include "mozilla/TimeStamp.h" |
michael@0 | 17 | #include "mozilla/dom/BindingDeclarations.h" |
michael@0 | 18 | #include "nsCycleCollectionParticipant.h" |
michael@0 | 19 | #include "nsDataHashtable.h" |
michael@0 | 20 | #include "nsHashKeys.h" |
michael@0 | 21 | #include "nsRefPtrHashtable.h" |
michael@0 | 22 | #include "nsString.h" |
michael@0 | 23 | #include "nsTArray.h" |
michael@0 | 24 | #include "nsThreadUtils.h" |
michael@0 | 25 | #include "StructuredCloneTags.h" |
michael@0 | 26 | |
michael@0 | 27 | #include "Queue.h" |
michael@0 | 28 | #include "WorkerFeature.h" |
michael@0 | 29 | |
michael@0 | 30 | class JSAutoStructuredCloneBuffer; |
michael@0 | 31 | class nsIChannel; |
michael@0 | 32 | class nsIDocument; |
michael@0 | 33 | class nsIEventTarget; |
michael@0 | 34 | class nsIPrincipal; |
michael@0 | 35 | class nsIScriptContext; |
michael@0 | 36 | class nsIThread; |
michael@0 | 37 | class nsIThreadInternal; |
michael@0 | 38 | class nsITimer; |
michael@0 | 39 | class nsIURI; |
michael@0 | 40 | |
michael@0 | 41 | namespace JS { |
michael@0 | 42 | class RuntimeStats; |
michael@0 | 43 | } |
michael@0 | 44 | |
michael@0 | 45 | namespace mozilla { |
michael@0 | 46 | namespace dom { |
michael@0 | 47 | class Function; |
michael@0 | 48 | } |
michael@0 | 49 | } |
michael@0 | 50 | |
michael@0 | 51 | #ifdef DEBUG |
michael@0 | 52 | struct PRThread; |
michael@0 | 53 | #endif |
michael@0 | 54 | |
michael@0 | 55 | BEGIN_WORKERS_NAMESPACE |
michael@0 | 56 | |
michael@0 | 57 | class AutoSyncLoopHolder; |
michael@0 | 58 | class MessagePort; |
michael@0 | 59 | class SharedWorker; |
michael@0 | 60 | class WorkerControlRunnable; |
michael@0 | 61 | class WorkerGlobalScope; |
michael@0 | 62 | class WorkerPrivate; |
michael@0 | 63 | class WorkerRunnable; |
michael@0 | 64 | |
michael@0 | 65 | // SharedMutex is a small wrapper around an (internal) reference-counted Mutex |
michael@0 | 66 | // object. It exists to avoid changing a lot of code to use Mutex* instead of |
michael@0 | 67 | // Mutex&. |
michael@0 | 68 | class SharedMutex |
michael@0 | 69 | { |
michael@0 | 70 | typedef mozilla::Mutex Mutex; |
michael@0 | 71 | |
michael@0 | 72 | class RefCountedMutex MOZ_FINAL : public Mutex |
michael@0 | 73 | { |
michael@0 | 74 | public: |
michael@0 | 75 | RefCountedMutex(const char* aName) |
michael@0 | 76 | : Mutex(aName) |
michael@0 | 77 | { } |
michael@0 | 78 | |
michael@0 | 79 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMutex) |
michael@0 | 80 | |
michael@0 | 81 | private: |
michael@0 | 82 | ~RefCountedMutex() |
michael@0 | 83 | { } |
michael@0 | 84 | }; |
michael@0 | 85 | |
michael@0 | 86 | nsRefPtr<RefCountedMutex> mMutex; |
michael@0 | 87 | |
michael@0 | 88 | public: |
michael@0 | 89 | SharedMutex(const char* aName) |
michael@0 | 90 | : mMutex(new RefCountedMutex(aName)) |
michael@0 | 91 | { } |
michael@0 | 92 | |
michael@0 | 93 | SharedMutex(SharedMutex& aOther) |
michael@0 | 94 | : mMutex(aOther.mMutex) |
michael@0 | 95 | { } |
michael@0 | 96 | |
michael@0 | 97 | operator Mutex&() |
michael@0 | 98 | { |
michael@0 | 99 | return *mMutex; |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | operator const Mutex&() const |
michael@0 | 103 | { |
michael@0 | 104 | return *mMutex; |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | void |
michael@0 | 108 | AssertCurrentThreadOwns() const |
michael@0 | 109 | { |
michael@0 | 110 | mMutex->AssertCurrentThreadOwns(); |
michael@0 | 111 | } |
michael@0 | 112 | }; |
michael@0 | 113 | |
michael@0 | 114 | template <class Derived> |
michael@0 | 115 | class WorkerPrivateParent : public DOMEventTargetHelper |
michael@0 | 116 | { |
michael@0 | 117 | class SynchronizeAndResumeRunnable; |
michael@0 | 118 | |
michael@0 | 119 | protected: |
michael@0 | 120 | class EventTarget; |
michael@0 | 121 | friend class EventTarget; |
michael@0 | 122 | |
michael@0 | 123 | public: |
michael@0 | 124 | struct LocationInfo |
michael@0 | 125 | { |
michael@0 | 126 | nsCString mHref; |
michael@0 | 127 | nsCString mProtocol; |
michael@0 | 128 | nsCString mHost; |
michael@0 | 129 | nsCString mHostname; |
michael@0 | 130 | nsCString mPort; |
michael@0 | 131 | nsCString mPathname; |
michael@0 | 132 | nsCString mSearch; |
michael@0 | 133 | nsCString mHash; |
michael@0 | 134 | nsString mOrigin; |
michael@0 | 135 | }; |
michael@0 | 136 | |
michael@0 | 137 | struct LoadInfo |
michael@0 | 138 | { |
michael@0 | 139 | // All of these should be released in ForgetMainThreadObjects. |
michael@0 | 140 | nsCOMPtr<nsIURI> mBaseURI; |
michael@0 | 141 | nsCOMPtr<nsIURI> mResolvedScriptURI; |
michael@0 | 142 | nsCOMPtr<nsIPrincipal> mPrincipal; |
michael@0 | 143 | nsCOMPtr<nsIScriptContext> mScriptContext; |
michael@0 | 144 | nsCOMPtr<nsPIDOMWindow> mWindow; |
michael@0 | 145 | nsCOMPtr<nsIContentSecurityPolicy> mCSP; |
michael@0 | 146 | nsCOMPtr<nsIChannel> mChannel; |
michael@0 | 147 | |
michael@0 | 148 | nsCString mDomain; |
michael@0 | 149 | |
michael@0 | 150 | bool mEvalAllowed; |
michael@0 | 151 | bool mReportCSPViolations; |
michael@0 | 152 | bool mXHRParamsAllowed; |
michael@0 | 153 | bool mPrincipalIsSystem; |
michael@0 | 154 | bool mIsInPrivilegedApp; |
michael@0 | 155 | bool mIsInCertifiedApp; |
michael@0 | 156 | |
michael@0 | 157 | LoadInfo() |
michael@0 | 158 | : mEvalAllowed(false), mReportCSPViolations(false), |
michael@0 | 159 | mXHRParamsAllowed(false), mPrincipalIsSystem(false), |
michael@0 | 160 | mIsInPrivilegedApp(false), mIsInCertifiedApp(false) |
michael@0 | 161 | { } |
michael@0 | 162 | |
michael@0 | 163 | void |
michael@0 | 164 | StealFrom(LoadInfo& aOther) |
michael@0 | 165 | { |
michael@0 | 166 | MOZ_ASSERT(!mBaseURI); |
michael@0 | 167 | aOther.mBaseURI.swap(mBaseURI); |
michael@0 | 168 | |
michael@0 | 169 | MOZ_ASSERT(!mResolvedScriptURI); |
michael@0 | 170 | aOther.mResolvedScriptURI.swap(mResolvedScriptURI); |
michael@0 | 171 | |
michael@0 | 172 | MOZ_ASSERT(!mPrincipal); |
michael@0 | 173 | aOther.mPrincipal.swap(mPrincipal); |
michael@0 | 174 | |
michael@0 | 175 | MOZ_ASSERT(!mScriptContext); |
michael@0 | 176 | aOther.mScriptContext.swap(mScriptContext); |
michael@0 | 177 | |
michael@0 | 178 | MOZ_ASSERT(!mWindow); |
michael@0 | 179 | aOther.mWindow.swap(mWindow); |
michael@0 | 180 | |
michael@0 | 181 | MOZ_ASSERT(!mCSP); |
michael@0 | 182 | aOther.mCSP.swap(mCSP); |
michael@0 | 183 | |
michael@0 | 184 | MOZ_ASSERT(!mChannel); |
michael@0 | 185 | aOther.mChannel.swap(mChannel); |
michael@0 | 186 | |
michael@0 | 187 | mDomain = aOther.mDomain; |
michael@0 | 188 | mEvalAllowed = aOther.mEvalAllowed; |
michael@0 | 189 | mReportCSPViolations = aOther.mReportCSPViolations; |
michael@0 | 190 | mXHRParamsAllowed = aOther.mXHRParamsAllowed; |
michael@0 | 191 | mPrincipalIsSystem = aOther.mPrincipalIsSystem; |
michael@0 | 192 | mIsInPrivilegedApp = aOther.mIsInPrivilegedApp; |
michael@0 | 193 | mIsInCertifiedApp = aOther.mIsInCertifiedApp; |
michael@0 | 194 | } |
michael@0 | 195 | }; |
michael@0 | 196 | |
michael@0 | 197 | enum WorkerType |
michael@0 | 198 | { |
michael@0 | 199 | WorkerTypeDedicated, |
michael@0 | 200 | WorkerTypeShared |
michael@0 | 201 | }; |
michael@0 | 202 | |
michael@0 | 203 | protected: |
michael@0 | 204 | typedef mozilla::ErrorResult ErrorResult; |
michael@0 | 205 | |
michael@0 | 206 | SharedMutex mMutex; |
michael@0 | 207 | mozilla::CondVar mCondVar; |
michael@0 | 208 | mozilla::CondVar mMemoryReportCondVar; |
michael@0 | 209 | |
michael@0 | 210 | // Protected by mMutex. |
michael@0 | 211 | nsRefPtr<EventTarget> mEventTarget; |
michael@0 | 212 | nsTArray<nsRefPtr<WorkerRunnable>> mPreStartRunnables; |
michael@0 | 213 | |
michael@0 | 214 | private: |
michael@0 | 215 | WorkerPrivate* mParent; |
michael@0 | 216 | nsString mScriptURL; |
michael@0 | 217 | nsCString mSharedWorkerName; |
michael@0 | 218 | LocationInfo mLocationInfo; |
michael@0 | 219 | // The lifetime of these objects within LoadInfo is managed explicitly; |
michael@0 | 220 | // they do not need to be cycle collected. |
michael@0 | 221 | LoadInfo mLoadInfo; |
michael@0 | 222 | |
michael@0 | 223 | // Only used for top level workers. |
michael@0 | 224 | nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables; |
michael@0 | 225 | nsRevocableEventPtr<SynchronizeAndResumeRunnable> mSynchronizeRunnable; |
michael@0 | 226 | |
michael@0 | 227 | // Only for ChromeWorkers without window and only touched on the main thread. |
michael@0 | 228 | nsTArray<nsCString> mHostObjectURIs; |
michael@0 | 229 | |
michael@0 | 230 | // Protected by mMutex. |
michael@0 | 231 | JSSettings mJSSettings; |
michael@0 | 232 | |
michael@0 | 233 | // Only touched on the parent thread (currently this is always the main |
michael@0 | 234 | // thread as SharedWorkers are always top-level). |
michael@0 | 235 | nsDataHashtable<nsUint64HashKey, SharedWorker*> mSharedWorkers; |
michael@0 | 236 | |
michael@0 | 237 | uint64_t mBusyCount; |
michael@0 | 238 | uint64_t mMessagePortSerial; |
michael@0 | 239 | Status mParentStatus; |
michael@0 | 240 | bool mParentSuspended; |
michael@0 | 241 | bool mIsChromeWorker; |
michael@0 | 242 | bool mMainThreadObjectsForgotten; |
michael@0 | 243 | WorkerType mWorkerType; |
michael@0 | 244 | TimeStamp mCreationTimeStamp; |
michael@0 | 245 | |
michael@0 | 246 | protected: |
michael@0 | 247 | // The worker is owned by its thread, which is represented here. This is set |
michael@0 | 248 | // in Construct() and emptied by WorkerFinishedRunnable, and conditionally |
michael@0 | 249 | // traversed by the cycle collector if the busy count is zero. |
michael@0 | 250 | nsRefPtr<WorkerPrivate> mSelfRef; |
michael@0 | 251 | |
michael@0 | 252 | WorkerPrivateParent(JSContext* aCx, WorkerPrivate* aParent, |
michael@0 | 253 | const nsAString& aScriptURL, bool aIsChromeWorker, |
michael@0 | 254 | WorkerType aWorkerType, |
michael@0 | 255 | const nsACString& aSharedWorkerName, |
michael@0 | 256 | LoadInfo& aLoadInfo); |
michael@0 | 257 | |
michael@0 | 258 | ~WorkerPrivateParent(); |
michael@0 | 259 | |
michael@0 | 260 | private: |
michael@0 | 261 | Derived* |
michael@0 | 262 | ParentAsWorkerPrivate() const |
michael@0 | 263 | { |
michael@0 | 264 | return static_cast<Derived*>(const_cast<WorkerPrivateParent*>(this)); |
michael@0 | 265 | } |
michael@0 | 266 | |
michael@0 | 267 | // aCx is null when called from the finalizer |
michael@0 | 268 | bool |
michael@0 | 269 | NotifyPrivate(JSContext* aCx, Status aStatus); |
michael@0 | 270 | |
michael@0 | 271 | // aCx is null when called from the finalizer |
michael@0 | 272 | bool |
michael@0 | 273 | TerminatePrivate(JSContext* aCx) |
michael@0 | 274 | { |
michael@0 | 275 | return NotifyPrivate(aCx, Terminating); |
michael@0 | 276 | } |
michael@0 | 277 | |
michael@0 | 278 | void |
michael@0 | 279 | PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage, |
michael@0 | 280 | const Optional<Sequence<JS::Value> >& aTransferable, |
michael@0 | 281 | bool aToMessagePort, uint64_t aMessagePortSerial, |
michael@0 | 282 | ErrorResult& aRv); |
michael@0 | 283 | |
michael@0 | 284 | nsresult |
michael@0 | 285 | DispatchPrivate(WorkerRunnable* aRunnable, nsIEventTarget* aSyncLoopTarget); |
michael@0 | 286 | |
michael@0 | 287 | public: |
michael@0 | 288 | virtual JSObject* |
michael@0 | 289 | WrapObject(JSContext* aCx) MOZ_OVERRIDE; |
michael@0 | 290 | |
michael@0 | 291 | NS_DECL_ISUPPORTS_INHERITED |
michael@0 | 292 | NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerPrivateParent, |
michael@0 | 293 | DOMEventTargetHelper) |
michael@0 | 294 | |
michael@0 | 295 | void |
michael@0 | 296 | ClearSelfRef() |
michael@0 | 297 | { |
michael@0 | 298 | AssertIsOnParentThread(); |
michael@0 | 299 | MOZ_ASSERT(mSelfRef); |
michael@0 | 300 | mSelfRef = nullptr; |
michael@0 | 301 | } |
michael@0 | 302 | |
michael@0 | 303 | nsresult |
michael@0 | 304 | Dispatch(WorkerRunnable* aRunnable) |
michael@0 | 305 | { |
michael@0 | 306 | return DispatchPrivate(aRunnable, nullptr); |
michael@0 | 307 | } |
michael@0 | 308 | |
michael@0 | 309 | nsresult |
michael@0 | 310 | DispatchControlRunnable(WorkerControlRunnable* aWorkerControlRunnable); |
michael@0 | 311 | |
michael@0 | 312 | already_AddRefed<WorkerRunnable> |
michael@0 | 313 | MaybeWrapAsWorkerRunnable(nsIRunnable* aRunnable); |
michael@0 | 314 | |
michael@0 | 315 | already_AddRefed<nsIEventTarget> |
michael@0 | 316 | GetEventTarget(); |
michael@0 | 317 | |
michael@0 | 318 | // May be called on any thread... |
michael@0 | 319 | bool |
michael@0 | 320 | Start(); |
michael@0 | 321 | |
michael@0 | 322 | // Called on the parent thread. |
michael@0 | 323 | bool |
michael@0 | 324 | Notify(JSContext* aCx, Status aStatus) |
michael@0 | 325 | { |
michael@0 | 326 | return NotifyPrivate(aCx, aStatus); |
michael@0 | 327 | } |
michael@0 | 328 | |
michael@0 | 329 | bool |
michael@0 | 330 | Cancel(JSContext* aCx) |
michael@0 | 331 | { |
michael@0 | 332 | return Notify(aCx, Canceling); |
michael@0 | 333 | } |
michael@0 | 334 | |
michael@0 | 335 | bool |
michael@0 | 336 | Kill(JSContext* aCx) |
michael@0 | 337 | { |
michael@0 | 338 | return Notify(aCx, Killing); |
michael@0 | 339 | } |
michael@0 | 340 | |
michael@0 | 341 | bool |
michael@0 | 342 | Suspend(JSContext* aCx, nsPIDOMWindow* aWindow); |
michael@0 | 343 | |
michael@0 | 344 | bool |
michael@0 | 345 | Resume(JSContext* aCx, nsPIDOMWindow* aWindow); |
michael@0 | 346 | |
michael@0 | 347 | bool |
michael@0 | 348 | SynchronizeAndResume(JSContext* aCx, nsPIDOMWindow* aWindow, |
michael@0 | 349 | nsIScriptContext* aScriptContext); |
michael@0 | 350 | |
michael@0 | 351 | bool |
michael@0 | 352 | Terminate(JSContext* aCx) |
michael@0 | 353 | { |
michael@0 | 354 | AssertIsOnParentThread(); |
michael@0 | 355 | return TerminatePrivate(aCx); |
michael@0 | 356 | } |
michael@0 | 357 | |
michael@0 | 358 | bool |
michael@0 | 359 | Close(JSContext* aCx); |
michael@0 | 360 | |
michael@0 | 361 | bool |
michael@0 | 362 | ModifyBusyCount(JSContext* aCx, bool aIncrease); |
michael@0 | 363 | |
michael@0 | 364 | void |
michael@0 | 365 | ForgetMainThreadObjects(nsTArray<nsCOMPtr<nsISupports> >& aDoomed); |
michael@0 | 366 | |
michael@0 | 367 | void |
michael@0 | 368 | PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage, |
michael@0 | 369 | const Optional<Sequence<JS::Value> >& aTransferable, |
michael@0 | 370 | ErrorResult& aRv) |
michael@0 | 371 | { |
michael@0 | 372 | PostMessageInternal(aCx, aMessage, aTransferable, false, 0, aRv); |
michael@0 | 373 | } |
michael@0 | 374 | |
michael@0 | 375 | void |
michael@0 | 376 | PostMessageToMessagePort(JSContext* aCx, |
michael@0 | 377 | uint64_t aMessagePortSerial, |
michael@0 | 378 | JS::Handle<JS::Value> aMessage, |
michael@0 | 379 | const Optional<Sequence<JS::Value> >& aTransferable, |
michael@0 | 380 | ErrorResult& aRv); |
michael@0 | 381 | |
michael@0 | 382 | bool |
michael@0 | 383 | DispatchMessageEventToMessagePort( |
michael@0 | 384 | JSContext* aCx, |
michael@0 | 385 | uint64_t aMessagePortSerial, |
michael@0 | 386 | JSAutoStructuredCloneBuffer&& aBuffer, |
michael@0 | 387 | nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects); |
michael@0 | 388 | |
michael@0 | 389 | uint64_t |
michael@0 | 390 | GetInnerWindowId(); |
michael@0 | 391 | |
michael@0 | 392 | void |
michael@0 | 393 | UpdateRuntimeAndContextOptions(JSContext* aCx, |
michael@0 | 394 | const JS::RuntimeOptions& aRuntimeOptions, |
michael@0 | 395 | const JS::ContextOptions& aContentCxOptions, |
michael@0 | 396 | const JS::ContextOptions& aChromeCxOptions); |
michael@0 | 397 | |
michael@0 | 398 | void |
michael@0 | 399 | UpdatePreference(JSContext* aCx, WorkerPreference aPref, bool aValue); |
michael@0 | 400 | |
michael@0 | 401 | void |
michael@0 | 402 | UpdateJSWorkerMemoryParameter(JSContext* aCx, JSGCParamKey key, |
michael@0 | 403 | uint32_t value); |
michael@0 | 404 | |
michael@0 | 405 | #ifdef JS_GC_ZEAL |
michael@0 | 406 | void |
michael@0 | 407 | UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency); |
michael@0 | 408 | #endif |
michael@0 | 409 | |
michael@0 | 410 | void |
michael@0 | 411 | GarbageCollect(JSContext* aCx, bool aShrinking); |
michael@0 | 412 | |
michael@0 | 413 | void |
michael@0 | 414 | CycleCollect(JSContext* aCx, bool aDummy); |
michael@0 | 415 | |
michael@0 | 416 | void |
michael@0 | 417 | OfflineStatusChangeEvent(JSContext* aCx, bool aIsOffline); |
michael@0 | 418 | |
michael@0 | 419 | bool |
michael@0 | 420 | RegisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker); |
michael@0 | 421 | |
michael@0 | 422 | void |
michael@0 | 423 | UnregisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker); |
michael@0 | 424 | |
michael@0 | 425 | void |
michael@0 | 426 | BroadcastErrorToSharedWorkers(JSContext* aCx, |
michael@0 | 427 | const nsAString& aMessage, |
michael@0 | 428 | const nsAString& aFilename, |
michael@0 | 429 | const nsAString& aLine, |
michael@0 | 430 | uint32_t aLineNumber, |
michael@0 | 431 | uint32_t aColumnNumber, |
michael@0 | 432 | uint32_t aFlags); |
michael@0 | 433 | |
michael@0 | 434 | void |
michael@0 | 435 | WorkerScriptLoaded(); |
michael@0 | 436 | |
michael@0 | 437 | void |
michael@0 | 438 | QueueRunnable(nsIRunnable* aRunnable) |
michael@0 | 439 | { |
michael@0 | 440 | AssertIsOnMainThread(); |
michael@0 | 441 | mQueuedRunnables.AppendElement(aRunnable); |
michael@0 | 442 | } |
michael@0 | 443 | |
michael@0 | 444 | WorkerPrivate* |
michael@0 | 445 | GetParent() const |
michael@0 | 446 | { |
michael@0 | 447 | return mParent; |
michael@0 | 448 | } |
michael@0 | 449 | |
michael@0 | 450 | bool |
michael@0 | 451 | IsSuspended() const |
michael@0 | 452 | { |
michael@0 | 453 | AssertIsOnParentThread(); |
michael@0 | 454 | return mParentSuspended; |
michael@0 | 455 | } |
michael@0 | 456 | |
michael@0 | 457 | bool |
michael@0 | 458 | IsAcceptingEvents() |
michael@0 | 459 | { |
michael@0 | 460 | AssertIsOnParentThread(); |
michael@0 | 461 | |
michael@0 | 462 | MutexAutoLock lock(mMutex); |
michael@0 | 463 | return mParentStatus < Terminating; |
michael@0 | 464 | } |
michael@0 | 465 | |
michael@0 | 466 | Status |
michael@0 | 467 | ParentStatus() const |
michael@0 | 468 | { |
michael@0 | 469 | mMutex.AssertCurrentThreadOwns(); |
michael@0 | 470 | return mParentStatus; |
michael@0 | 471 | } |
michael@0 | 472 | |
michael@0 | 473 | JSContext* |
michael@0 | 474 | ParentJSContext() const; |
michael@0 | 475 | |
michael@0 | 476 | nsIScriptContext* |
michael@0 | 477 | GetScriptContext() const |
michael@0 | 478 | { |
michael@0 | 479 | AssertIsOnMainThread(); |
michael@0 | 480 | return mLoadInfo.mScriptContext; |
michael@0 | 481 | } |
michael@0 | 482 | |
michael@0 | 483 | const nsString& |
michael@0 | 484 | ScriptURL() const |
michael@0 | 485 | { |
michael@0 | 486 | return mScriptURL; |
michael@0 | 487 | } |
michael@0 | 488 | |
michael@0 | 489 | const nsCString& |
michael@0 | 490 | Domain() const |
michael@0 | 491 | { |
michael@0 | 492 | return mLoadInfo.mDomain; |
michael@0 | 493 | } |
michael@0 | 494 | |
michael@0 | 495 | nsIURI* |
michael@0 | 496 | GetBaseURI() const |
michael@0 | 497 | { |
michael@0 | 498 | AssertIsOnMainThread(); |
michael@0 | 499 | return mLoadInfo.mBaseURI; |
michael@0 | 500 | } |
michael@0 | 501 | |
michael@0 | 502 | void |
michael@0 | 503 | SetBaseURI(nsIURI* aBaseURI); |
michael@0 | 504 | |
michael@0 | 505 | nsIURI* |
michael@0 | 506 | GetResolvedScriptURI() const |
michael@0 | 507 | { |
michael@0 | 508 | AssertIsOnMainThread(); |
michael@0 | 509 | return mLoadInfo.mResolvedScriptURI; |
michael@0 | 510 | } |
michael@0 | 511 | |
michael@0 | 512 | TimeStamp CreationTimeStamp() const |
michael@0 | 513 | { |
michael@0 | 514 | return mCreationTimeStamp; |
michael@0 | 515 | } |
michael@0 | 516 | |
michael@0 | 517 | nsIPrincipal* |
michael@0 | 518 | GetPrincipal() const |
michael@0 | 519 | { |
michael@0 | 520 | AssertIsOnMainThread(); |
michael@0 | 521 | return mLoadInfo.mPrincipal; |
michael@0 | 522 | } |
michael@0 | 523 | |
michael@0 | 524 | // This method allows the principal to be retrieved off the main thread. |
michael@0 | 525 | // Principals are main-thread objects so the caller must ensure that all |
michael@0 | 526 | // access occurs on the main thread. |
michael@0 | 527 | nsIPrincipal* |
michael@0 | 528 | GetPrincipalDontAssertMainThread() const |
michael@0 | 529 | { |
michael@0 | 530 | return mLoadInfo.mPrincipal; |
michael@0 | 531 | } |
michael@0 | 532 | |
michael@0 | 533 | void |
michael@0 | 534 | SetPrincipal(nsIPrincipal* aPrincipal); |
michael@0 | 535 | |
michael@0 | 536 | bool |
michael@0 | 537 | UsesSystemPrincipal() const |
michael@0 | 538 | { |
michael@0 | 539 | return mLoadInfo.mPrincipalIsSystem; |
michael@0 | 540 | } |
michael@0 | 541 | |
michael@0 | 542 | bool |
michael@0 | 543 | IsInPrivilegedApp() const |
michael@0 | 544 | { |
michael@0 | 545 | return mLoadInfo.mIsInPrivilegedApp; |
michael@0 | 546 | } |
michael@0 | 547 | |
michael@0 | 548 | bool |
michael@0 | 549 | IsInCertifiedApp() const |
michael@0 | 550 | { |
michael@0 | 551 | return mLoadInfo.mIsInCertifiedApp; |
michael@0 | 552 | } |
michael@0 | 553 | |
michael@0 | 554 | already_AddRefed<nsIChannel> |
michael@0 | 555 | ForgetWorkerChannel() |
michael@0 | 556 | { |
michael@0 | 557 | AssertIsOnMainThread(); |
michael@0 | 558 | return mLoadInfo.mChannel.forget(); |
michael@0 | 559 | } |
michael@0 | 560 | |
michael@0 | 561 | nsIDocument* |
michael@0 | 562 | GetDocument() const |
michael@0 | 563 | { |
michael@0 | 564 | AssertIsOnMainThread(); |
michael@0 | 565 | return mLoadInfo.mWindow ? mLoadInfo.mWindow->GetExtantDoc() : nullptr; |
michael@0 | 566 | } |
michael@0 | 567 | |
michael@0 | 568 | nsPIDOMWindow* |
michael@0 | 569 | GetWindow() |
michael@0 | 570 | { |
michael@0 | 571 | AssertIsOnMainThread(); |
michael@0 | 572 | return mLoadInfo.mWindow; |
michael@0 | 573 | } |
michael@0 | 574 | |
michael@0 | 575 | nsIContentSecurityPolicy* |
michael@0 | 576 | GetCSP() const |
michael@0 | 577 | { |
michael@0 | 578 | AssertIsOnMainThread(); |
michael@0 | 579 | return mLoadInfo.mCSP; |
michael@0 | 580 | } |
michael@0 | 581 | |
michael@0 | 582 | void |
michael@0 | 583 | SetCSP(nsIContentSecurityPolicy* aCSP) |
michael@0 | 584 | { |
michael@0 | 585 | AssertIsOnMainThread(); |
michael@0 | 586 | mLoadInfo.mCSP = aCSP; |
michael@0 | 587 | } |
michael@0 | 588 | |
michael@0 | 589 | bool |
michael@0 | 590 | IsEvalAllowed() const |
michael@0 | 591 | { |
michael@0 | 592 | return mLoadInfo.mEvalAllowed; |
michael@0 | 593 | } |
michael@0 | 594 | |
michael@0 | 595 | void |
michael@0 | 596 | SetEvalAllowed(bool aEvalAllowed) |
michael@0 | 597 | { |
michael@0 | 598 | mLoadInfo.mEvalAllowed = aEvalAllowed; |
michael@0 | 599 | } |
michael@0 | 600 | |
michael@0 | 601 | bool |
michael@0 | 602 | GetReportCSPViolations() const |
michael@0 | 603 | { |
michael@0 | 604 | return mLoadInfo.mReportCSPViolations; |
michael@0 | 605 | } |
michael@0 | 606 | |
michael@0 | 607 | bool |
michael@0 | 608 | XHRParamsAllowed() const |
michael@0 | 609 | { |
michael@0 | 610 | return mLoadInfo.mXHRParamsAllowed; |
michael@0 | 611 | } |
michael@0 | 612 | |
michael@0 | 613 | void |
michael@0 | 614 | SetXHRParamsAllowed(bool aAllowed) |
michael@0 | 615 | { |
michael@0 | 616 | mLoadInfo.mXHRParamsAllowed = aAllowed; |
michael@0 | 617 | } |
michael@0 | 618 | |
michael@0 | 619 | LocationInfo& |
michael@0 | 620 | GetLocationInfo() |
michael@0 | 621 | { |
michael@0 | 622 | return mLocationInfo; |
michael@0 | 623 | } |
michael@0 | 624 | |
michael@0 | 625 | void |
michael@0 | 626 | CopyJSSettings(JSSettings& aSettings) |
michael@0 | 627 | { |
michael@0 | 628 | mozilla::MutexAutoLock lock(mMutex); |
michael@0 | 629 | aSettings = mJSSettings; |
michael@0 | 630 | } |
michael@0 | 631 | |
michael@0 | 632 | void |
michael@0 | 633 | CopyJSCompartmentOptions(JS::CompartmentOptions& aOptions) |
michael@0 | 634 | { |
michael@0 | 635 | mozilla::MutexAutoLock lock(mMutex); |
michael@0 | 636 | aOptions = IsChromeWorker() ? mJSSettings.chrome.compartmentOptions |
michael@0 | 637 | : mJSSettings.content.compartmentOptions; |
michael@0 | 638 | } |
michael@0 | 639 | |
michael@0 | 640 | // The ability to be a chrome worker is orthogonal to the type of |
michael@0 | 641 | // worker [Dedicated|Shared]. |
michael@0 | 642 | bool |
michael@0 | 643 | IsChromeWorker() const |
michael@0 | 644 | { |
michael@0 | 645 | return mIsChromeWorker; |
michael@0 | 646 | } |
michael@0 | 647 | |
michael@0 | 648 | bool |
michael@0 | 649 | IsDedicatedWorker() const |
michael@0 | 650 | { |
michael@0 | 651 | return mWorkerType == WorkerTypeDedicated; |
michael@0 | 652 | } |
michael@0 | 653 | |
michael@0 | 654 | bool |
michael@0 | 655 | IsSharedWorker() const |
michael@0 | 656 | { |
michael@0 | 657 | return mWorkerType == WorkerTypeShared; |
michael@0 | 658 | } |
michael@0 | 659 | |
michael@0 | 660 | const nsCString& |
michael@0 | 661 | SharedWorkerName() const |
michael@0 | 662 | { |
michael@0 | 663 | return mSharedWorkerName; |
michael@0 | 664 | } |
michael@0 | 665 | |
michael@0 | 666 | uint64_t |
michael@0 | 667 | NextMessagePortSerial() |
michael@0 | 668 | { |
michael@0 | 669 | AssertIsOnMainThread(); |
michael@0 | 670 | return mMessagePortSerial++; |
michael@0 | 671 | } |
michael@0 | 672 | |
michael@0 | 673 | void |
michael@0 | 674 | GetAllSharedWorkers(nsTArray<nsRefPtr<SharedWorker>>& aSharedWorkers); |
michael@0 | 675 | |
michael@0 | 676 | void |
michael@0 | 677 | CloseSharedWorkersForWindow(nsPIDOMWindow* aWindow); |
michael@0 | 678 | |
michael@0 | 679 | void |
michael@0 | 680 | RegisterHostObjectURI(const nsACString& aURI); |
michael@0 | 681 | |
michael@0 | 682 | void |
michael@0 | 683 | UnregisterHostObjectURI(const nsACString& aURI); |
michael@0 | 684 | |
michael@0 | 685 | void |
michael@0 | 686 | StealHostObjectURIs(nsTArray<nsCString>& aArray); |
michael@0 | 687 | |
michael@0 | 688 | IMPL_EVENT_HANDLER(message) |
michael@0 | 689 | IMPL_EVENT_HANDLER(error) |
michael@0 | 690 | |
michael@0 | 691 | #ifdef DEBUG |
michael@0 | 692 | void |
michael@0 | 693 | AssertIsOnParentThread() const; |
michael@0 | 694 | |
michael@0 | 695 | void |
michael@0 | 696 | AssertInnerWindowIsCorrect() const; |
michael@0 | 697 | #else |
michael@0 | 698 | void |
michael@0 | 699 | AssertIsOnParentThread() const |
michael@0 | 700 | { } |
michael@0 | 701 | |
michael@0 | 702 | void |
michael@0 | 703 | AssertInnerWindowIsCorrect() const |
michael@0 | 704 | { } |
michael@0 | 705 | #endif |
michael@0 | 706 | }; |
michael@0 | 707 | |
michael@0 | 708 | class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate> |
michael@0 | 709 | { |
michael@0 | 710 | friend class WorkerPrivateParent<WorkerPrivate>; |
michael@0 | 711 | typedef WorkerPrivateParent<WorkerPrivate> ParentType; |
michael@0 | 712 | friend class AutoSyncLoopHolder; |
michael@0 | 713 | |
michael@0 | 714 | struct TimeoutInfo; |
michael@0 | 715 | |
michael@0 | 716 | class MemoryReporter; |
michael@0 | 717 | friend class MemoryReporter; |
michael@0 | 718 | |
michael@0 | 719 | enum GCTimerMode |
michael@0 | 720 | { |
michael@0 | 721 | PeriodicTimer = 0, |
michael@0 | 722 | IdleTimer, |
michael@0 | 723 | NoTimer |
michael@0 | 724 | }; |
michael@0 | 725 | |
michael@0 | 726 | Queue<WorkerControlRunnable*, 4> mControlQueue; |
michael@0 | 727 | |
michael@0 | 728 | // Touched on multiple threads, protected with mMutex. |
michael@0 | 729 | JSContext* mJSContext; |
michael@0 | 730 | nsRefPtr<WorkerCrossThreadDispatcher> mCrossThreadDispatcher; |
michael@0 | 731 | nsTArray<nsCOMPtr<nsIRunnable>> mUndispatchedRunnablesForSyncLoop; |
michael@0 | 732 | nsCOMPtr<nsIThread> mThread; |
michael@0 | 733 | |
michael@0 | 734 | // Things touched on worker thread only. |
michael@0 | 735 | nsRefPtr<WorkerGlobalScope> mScope; |
michael@0 | 736 | nsTArray<ParentType*> mChildWorkers; |
michael@0 | 737 | nsTArray<WorkerFeature*> mFeatures; |
michael@0 | 738 | nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts; |
michael@0 | 739 | |
michael@0 | 740 | struct SyncLoopInfo |
michael@0 | 741 | { |
michael@0 | 742 | SyncLoopInfo(EventTarget* aEventTarget); |
michael@0 | 743 | |
michael@0 | 744 | nsRefPtr<EventTarget> mEventTarget; |
michael@0 | 745 | bool mCompleted; |
michael@0 | 746 | bool mResult; |
michael@0 | 747 | #ifdef DEBUG |
michael@0 | 748 | bool mHasRun; |
michael@0 | 749 | #endif |
michael@0 | 750 | }; |
michael@0 | 751 | |
michael@0 | 752 | // This is only modified on the worker thread, but in DEBUG builds |
michael@0 | 753 | // AssertValidSyncLoop function iterates it on other threads. Therefore |
michael@0 | 754 | // modifications are done with mMutex held *only* in DEBUG builds. |
michael@0 | 755 | nsTArray<nsAutoPtr<SyncLoopInfo>> mSyncLoopStack; |
michael@0 | 756 | |
michael@0 | 757 | nsCOMPtr<nsITimer> mTimer; |
michael@0 | 758 | |
michael@0 | 759 | nsCOMPtr<nsITimer> mGCTimer; |
michael@0 | 760 | nsCOMPtr<nsIEventTarget> mPeriodicGCTimerTarget; |
michael@0 | 761 | nsCOMPtr<nsIEventTarget> mIdleGCTimerTarget; |
michael@0 | 762 | |
michael@0 | 763 | nsRefPtr<MemoryReporter> mMemoryReporter; |
michael@0 | 764 | |
michael@0 | 765 | nsRefPtrHashtable<nsUint64HashKey, MessagePort> mWorkerPorts; |
michael@0 | 766 | |
michael@0 | 767 | TimeStamp mKillTime; |
michael@0 | 768 | uint32_t mErrorHandlerRecursionCount; |
michael@0 | 769 | uint32_t mNextTimeoutId; |
michael@0 | 770 | Status mStatus; |
michael@0 | 771 | bool mSuspended; |
michael@0 | 772 | bool mTimerRunning; |
michael@0 | 773 | bool mRunningExpiredTimeouts; |
michael@0 | 774 | bool mCloseHandlerStarted; |
michael@0 | 775 | bool mCloseHandlerFinished; |
michael@0 | 776 | bool mMemoryReporterRunning; |
michael@0 | 777 | bool mBlockedForMemoryReporter; |
michael@0 | 778 | bool mCancelAllPendingRunnables; |
michael@0 | 779 | bool mPeriodicGCTimerRunning; |
michael@0 | 780 | bool mIdleGCTimerRunning; |
michael@0 | 781 | |
michael@0 | 782 | #ifdef DEBUG |
michael@0 | 783 | PRThread* mPRThread; |
michael@0 | 784 | #endif |
michael@0 | 785 | |
michael@0 | 786 | bool mPreferences[WORKERPREF_COUNT]; |
michael@0 | 787 | bool mOnLine; |
michael@0 | 788 | |
michael@0 | 789 | protected: |
michael@0 | 790 | ~WorkerPrivate(); |
michael@0 | 791 | |
michael@0 | 792 | public: |
michael@0 | 793 | static already_AddRefed<WorkerPrivate> |
michael@0 | 794 | Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL, |
michael@0 | 795 | ErrorResult& aRv); |
michael@0 | 796 | |
michael@0 | 797 | static already_AddRefed<WorkerPrivate> |
michael@0 | 798 | Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL, |
michael@0 | 799 | bool aIsChromeWorker, WorkerType aWorkerType, |
michael@0 | 800 | const nsACString& aSharedWorkerName, |
michael@0 | 801 | LoadInfo* aLoadInfo, ErrorResult& aRv); |
michael@0 | 802 | |
michael@0 | 803 | static bool |
michael@0 | 804 | WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */); |
michael@0 | 805 | |
michael@0 | 806 | static nsresult |
michael@0 | 807 | GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow, WorkerPrivate* aParent, |
michael@0 | 808 | const nsAString& aScriptURL, bool aIsChromeWorker, |
michael@0 | 809 | LoadInfo* aLoadInfo); |
michael@0 | 810 | |
michael@0 | 811 | void |
michael@0 | 812 | DoRunLoop(JSContext* aCx); |
michael@0 | 813 | |
michael@0 | 814 | bool |
michael@0 | 815 | InterruptCallback(JSContext* aCx); |
michael@0 | 816 | |
michael@0 | 817 | nsresult |
michael@0 | 818 | IsOnCurrentThread(bool* aIsOnCurrentThread); |
michael@0 | 819 | |
michael@0 | 820 | bool |
michael@0 | 821 | CloseInternal(JSContext* aCx) |
michael@0 | 822 | { |
michael@0 | 823 | AssertIsOnWorkerThread(); |
michael@0 | 824 | return NotifyInternal(aCx, Closing); |
michael@0 | 825 | } |
michael@0 | 826 | |
michael@0 | 827 | bool |
michael@0 | 828 | SuspendInternal(JSContext* aCx); |
michael@0 | 829 | |
michael@0 | 830 | bool |
michael@0 | 831 | ResumeInternal(JSContext* aCx); |
michael@0 | 832 | |
michael@0 | 833 | void |
michael@0 | 834 | TraceTimeouts(const TraceCallbacks& aCallbacks, void* aClosure) const; |
michael@0 | 835 | |
michael@0 | 836 | bool |
michael@0 | 837 | ModifyBusyCountFromWorker(JSContext* aCx, bool aIncrease); |
michael@0 | 838 | |
michael@0 | 839 | bool |
michael@0 | 840 | AddChildWorker(JSContext* aCx, ParentType* aChildWorker); |
michael@0 | 841 | |
michael@0 | 842 | void |
michael@0 | 843 | RemoveChildWorker(JSContext* aCx, ParentType* aChildWorker); |
michael@0 | 844 | |
michael@0 | 845 | bool |
michael@0 | 846 | AddFeature(JSContext* aCx, WorkerFeature* aFeature); |
michael@0 | 847 | |
michael@0 | 848 | void |
michael@0 | 849 | RemoveFeature(JSContext* aCx, WorkerFeature* aFeature); |
michael@0 | 850 | |
michael@0 | 851 | void |
michael@0 | 852 | NotifyFeatures(JSContext* aCx, Status aStatus); |
michael@0 | 853 | |
michael@0 | 854 | bool |
michael@0 | 855 | HasActiveFeatures() |
michael@0 | 856 | { |
michael@0 | 857 | return !(mChildWorkers.IsEmpty() && mTimeouts.IsEmpty() && |
michael@0 | 858 | mFeatures.IsEmpty()); |
michael@0 | 859 | } |
michael@0 | 860 | |
michael@0 | 861 | void |
michael@0 | 862 | PostMessageToParent(JSContext* aCx, |
michael@0 | 863 | JS::Handle<JS::Value> aMessage, |
michael@0 | 864 | const Optional<Sequence<JS::Value>>& aTransferable, |
michael@0 | 865 | ErrorResult& aRv) |
michael@0 | 866 | { |
michael@0 | 867 | PostMessageToParentInternal(aCx, aMessage, aTransferable, false, 0, aRv); |
michael@0 | 868 | } |
michael@0 | 869 | |
michael@0 | 870 | void |
michael@0 | 871 | PostMessageToParentMessagePort( |
michael@0 | 872 | JSContext* aCx, |
michael@0 | 873 | uint64_t aMessagePortSerial, |
michael@0 | 874 | JS::Handle<JS::Value> aMessage, |
michael@0 | 875 | const Optional<Sequence<JS::Value>>& aTransferable, |
michael@0 | 876 | ErrorResult& aRv); |
michael@0 | 877 | |
michael@0 | 878 | bool |
michael@0 | 879 | NotifyInternal(JSContext* aCx, Status aStatus); |
michael@0 | 880 | |
michael@0 | 881 | void |
michael@0 | 882 | ReportError(JSContext* aCx, const char* aMessage, JSErrorReport* aReport); |
michael@0 | 883 | |
michael@0 | 884 | int32_t |
michael@0 | 885 | SetTimeout(JSContext* aCx, |
michael@0 | 886 | Function* aHandler, |
michael@0 | 887 | const nsAString& aStringHandler, |
michael@0 | 888 | int32_t aTimeout, |
michael@0 | 889 | const Sequence<JS::Value>& aArguments, |
michael@0 | 890 | bool aIsInterval, |
michael@0 | 891 | ErrorResult& aRv); |
michael@0 | 892 | |
michael@0 | 893 | void |
michael@0 | 894 | ClearTimeout(int32_t aId); |
michael@0 | 895 | |
michael@0 | 896 | bool |
michael@0 | 897 | RunExpiredTimeouts(JSContext* aCx); |
michael@0 | 898 | |
michael@0 | 899 | bool |
michael@0 | 900 | RescheduleTimeoutTimer(JSContext* aCx); |
michael@0 | 901 | |
michael@0 | 902 | void |
michael@0 | 903 | CloseHandlerStarted() |
michael@0 | 904 | { |
michael@0 | 905 | AssertIsOnWorkerThread(); |
michael@0 | 906 | mCloseHandlerStarted = true; |
michael@0 | 907 | } |
michael@0 | 908 | |
michael@0 | 909 | void |
michael@0 | 910 | CloseHandlerFinished() |
michael@0 | 911 | { |
michael@0 | 912 | AssertIsOnWorkerThread(); |
michael@0 | 913 | mCloseHandlerFinished = true; |
michael@0 | 914 | } |
michael@0 | 915 | |
michael@0 | 916 | void |
michael@0 | 917 | UpdateRuntimeAndContextOptionsInternal( |
michael@0 | 918 | JSContext* aCx, |
michael@0 | 919 | const JS::RuntimeOptions& aRuntimeOptions, |
michael@0 | 920 | const JS::ContextOptions& aContentCxOptions, |
michael@0 | 921 | const JS::ContextOptions& aChromeCxOptions); |
michael@0 | 922 | |
michael@0 | 923 | void |
michael@0 | 924 | UpdatePreferenceInternal(JSContext* aCx, WorkerPreference aPref, bool aValue); |
michael@0 | 925 | |
michael@0 | 926 | void |
michael@0 | 927 | UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, uint32_t aValue); |
michael@0 | 928 | |
michael@0 | 929 | enum WorkerRanOrNot { |
michael@0 | 930 | WorkerNeverRan = 0, |
michael@0 | 931 | WorkerRan |
michael@0 | 932 | }; |
michael@0 | 933 | |
michael@0 | 934 | void |
michael@0 | 935 | ScheduleDeletion(WorkerRanOrNot aRanOrNot); |
michael@0 | 936 | |
michael@0 | 937 | bool |
michael@0 | 938 | BlockAndCollectRuntimeStats(JS::RuntimeStats* aRtStats); |
michael@0 | 939 | |
michael@0 | 940 | #ifdef JS_GC_ZEAL |
michael@0 | 941 | void |
michael@0 | 942 | UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency); |
michael@0 | 943 | #endif |
michael@0 | 944 | |
michael@0 | 945 | void |
michael@0 | 946 | GarbageCollectInternal(JSContext* aCx, bool aShrinking, |
michael@0 | 947 | bool aCollectChildren); |
michael@0 | 948 | |
michael@0 | 949 | void |
michael@0 | 950 | CycleCollectInternal(JSContext* aCx, bool aCollectChildren); |
michael@0 | 951 | |
michael@0 | 952 | void |
michael@0 | 953 | OfflineStatusChangeEventInternal(JSContext* aCx, bool aIsOffline); |
michael@0 | 954 | |
michael@0 | 955 | JSContext* |
michael@0 | 956 | GetJSContext() const |
michael@0 | 957 | { |
michael@0 | 958 | AssertIsOnWorkerThread(); |
michael@0 | 959 | return mJSContext; |
michael@0 | 960 | } |
michael@0 | 961 | |
michael@0 | 962 | WorkerGlobalScope* |
michael@0 | 963 | GlobalScope() const |
michael@0 | 964 | { |
michael@0 | 965 | AssertIsOnWorkerThread(); |
michael@0 | 966 | return mScope; |
michael@0 | 967 | } |
michael@0 | 968 | |
michael@0 | 969 | void |
michael@0 | 970 | SetThread(nsIThread* aThread); |
michael@0 | 971 | |
michael@0 | 972 | void |
michael@0 | 973 | AssertIsOnWorkerThread() const |
michael@0 | 974 | #ifdef DEBUG |
michael@0 | 975 | ; |
michael@0 | 976 | #else |
michael@0 | 977 | { } |
michael@0 | 978 | #endif |
michael@0 | 979 | |
michael@0 | 980 | WorkerCrossThreadDispatcher* |
michael@0 | 981 | GetCrossThreadDispatcher(); |
michael@0 | 982 | |
michael@0 | 983 | // This may block! |
michael@0 | 984 | void |
michael@0 | 985 | BeginCTypesCall(); |
michael@0 | 986 | |
michael@0 | 987 | // This may block! |
michael@0 | 988 | void |
michael@0 | 989 | EndCTypesCall(); |
michael@0 | 990 | |
michael@0 | 991 | void |
michael@0 | 992 | BeginCTypesCallback() |
michael@0 | 993 | { |
michael@0 | 994 | // If a callback is beginning then we need to do the exact same thing as |
michael@0 | 995 | // when a ctypes call ends. |
michael@0 | 996 | EndCTypesCall(); |
michael@0 | 997 | } |
michael@0 | 998 | |
michael@0 | 999 | void |
michael@0 | 1000 | EndCTypesCallback() |
michael@0 | 1001 | { |
michael@0 | 1002 | // If a callback is ending then we need to do the exact same thing as |
michael@0 | 1003 | // when a ctypes call begins. |
michael@0 | 1004 | BeginCTypesCall(); |
michael@0 | 1005 | } |
michael@0 | 1006 | |
michael@0 | 1007 | bool |
michael@0 | 1008 | ConnectMessagePort(JSContext* aCx, uint64_t aMessagePortSerial); |
michael@0 | 1009 | |
michael@0 | 1010 | void |
michael@0 | 1011 | DisconnectMessagePort(uint64_t aMessagePortSerial); |
michael@0 | 1012 | |
michael@0 | 1013 | MessagePort* |
michael@0 | 1014 | GetMessagePort(uint64_t aMessagePortSerial); |
michael@0 | 1015 | |
michael@0 | 1016 | JSObject* |
michael@0 | 1017 | CreateGlobalScope(JSContext* aCx); |
michael@0 | 1018 | |
michael@0 | 1019 | bool |
michael@0 | 1020 | RegisterBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal); |
michael@0 | 1021 | |
michael@0 | 1022 | bool |
michael@0 | 1023 | DumpEnabled() const |
michael@0 | 1024 | { |
michael@0 | 1025 | AssertIsOnWorkerThread(); |
michael@0 | 1026 | return mPreferences[WORKERPREF_DUMP]; |
michael@0 | 1027 | } |
michael@0 | 1028 | |
michael@0 | 1029 | bool |
michael@0 | 1030 | OnLine() const |
michael@0 | 1031 | { |
michael@0 | 1032 | AssertIsOnWorkerThread(); |
michael@0 | 1033 | return mOnLine; |
michael@0 | 1034 | } |
michael@0 | 1035 | |
michael@0 | 1036 | void |
michael@0 | 1037 | StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult); |
michael@0 | 1038 | |
michael@0 | 1039 | bool |
michael@0 | 1040 | AllPendingRunnablesShouldBeCanceled() const |
michael@0 | 1041 | { |
michael@0 | 1042 | return mCancelAllPendingRunnables; |
michael@0 | 1043 | } |
michael@0 | 1044 | |
michael@0 | 1045 | void |
michael@0 | 1046 | OnProcessNextEvent(uint32_t aRecursionDepth); |
michael@0 | 1047 | |
michael@0 | 1048 | void |
michael@0 | 1049 | AfterProcessNextEvent(uint32_t aRecursionDepth); |
michael@0 | 1050 | |
michael@0 | 1051 | void |
michael@0 | 1052 | AssertValidSyncLoop(nsIEventTarget* aSyncLoopTarget) |
michael@0 | 1053 | #ifdef DEBUG |
michael@0 | 1054 | ; |
michael@0 | 1055 | #else |
michael@0 | 1056 | { } |
michael@0 | 1057 | #endif |
michael@0 | 1058 | |
michael@0 | 1059 | private: |
michael@0 | 1060 | WorkerPrivate(JSContext* aCx, WorkerPrivate* aParent, |
michael@0 | 1061 | const nsAString& aScriptURL, bool aIsChromeWorker, |
michael@0 | 1062 | WorkerType aWorkerType, const nsACString& aSharedWorkerName, |
michael@0 | 1063 | LoadInfo& aLoadInfo); |
michael@0 | 1064 | |
michael@0 | 1065 | void |
michael@0 | 1066 | ClearMainEventQueue(WorkerRanOrNot aRanOrNot); |
michael@0 | 1067 | |
michael@0 | 1068 | bool |
michael@0 | 1069 | MayContinueRunning() |
michael@0 | 1070 | { |
michael@0 | 1071 | AssertIsOnWorkerThread(); |
michael@0 | 1072 | |
michael@0 | 1073 | Status status; |
michael@0 | 1074 | { |
michael@0 | 1075 | MutexAutoLock lock(mMutex); |
michael@0 | 1076 | status = mStatus; |
michael@0 | 1077 | } |
michael@0 | 1078 | |
michael@0 | 1079 | if (status >= Killing) { |
michael@0 | 1080 | return false; |
michael@0 | 1081 | } |
michael@0 | 1082 | if (status >= Running) { |
michael@0 | 1083 | return mKillTime.IsNull() || RemainingRunTimeMS() > 0; |
michael@0 | 1084 | } |
michael@0 | 1085 | return true; |
michael@0 | 1086 | } |
michael@0 | 1087 | |
michael@0 | 1088 | uint32_t |
michael@0 | 1089 | RemainingRunTimeMS() const; |
michael@0 | 1090 | |
michael@0 | 1091 | void |
michael@0 | 1092 | CancelAllTimeouts(JSContext* aCx); |
michael@0 | 1093 | |
michael@0 | 1094 | bool |
michael@0 | 1095 | ScheduleKillCloseEventRunnable(JSContext* aCx); |
michael@0 | 1096 | |
michael@0 | 1097 | bool |
michael@0 | 1098 | ProcessAllControlRunnables() |
michael@0 | 1099 | { |
michael@0 | 1100 | MutexAutoLock lock(mMutex); |
michael@0 | 1101 | return ProcessAllControlRunnablesLocked(); |
michael@0 | 1102 | } |
michael@0 | 1103 | |
michael@0 | 1104 | bool |
michael@0 | 1105 | ProcessAllControlRunnablesLocked(); |
michael@0 | 1106 | |
michael@0 | 1107 | void |
michael@0 | 1108 | EnableMemoryReporter(); |
michael@0 | 1109 | |
michael@0 | 1110 | void |
michael@0 | 1111 | DisableMemoryReporter(); |
michael@0 | 1112 | |
michael@0 | 1113 | void |
michael@0 | 1114 | WaitForWorkerEvents(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1115 | |
michael@0 | 1116 | void |
michael@0 | 1117 | PostMessageToParentInternal(JSContext* aCx, |
michael@0 | 1118 | JS::Handle<JS::Value> aMessage, |
michael@0 | 1119 | const Optional<Sequence<JS::Value>>& aTransferable, |
michael@0 | 1120 | bool aToMessagePort, |
michael@0 | 1121 | uint64_t aMessagePortSerial, |
michael@0 | 1122 | ErrorResult& aRv); |
michael@0 | 1123 | |
michael@0 | 1124 | void |
michael@0 | 1125 | GetAllPreferences(bool aPreferences[WORKERPREF_COUNT]) const |
michael@0 | 1126 | { |
michael@0 | 1127 | AssertIsOnWorkerThread(); |
michael@0 | 1128 | memcpy(aPreferences, mPreferences, WORKERPREF_COUNT * sizeof(bool)); |
michael@0 | 1129 | } |
michael@0 | 1130 | |
michael@0 | 1131 | already_AddRefed<nsIEventTarget> |
michael@0 | 1132 | CreateNewSyncLoop(); |
michael@0 | 1133 | |
michael@0 | 1134 | bool |
michael@0 | 1135 | RunCurrentSyncLoop(); |
michael@0 | 1136 | |
michael@0 | 1137 | bool |
michael@0 | 1138 | DestroySyncLoop(uint32_t aLoopIndex, nsIThreadInternal* aThread = nullptr); |
michael@0 | 1139 | |
michael@0 | 1140 | void |
michael@0 | 1141 | InitializeGCTimers(); |
michael@0 | 1142 | |
michael@0 | 1143 | void |
michael@0 | 1144 | SetGCTimerMode(GCTimerMode aMode); |
michael@0 | 1145 | |
michael@0 | 1146 | void |
michael@0 | 1147 | ShutdownGCTimers(); |
michael@0 | 1148 | }; |
michael@0 | 1149 | |
michael@0 | 1150 | // This class is only used to trick the DOM bindings. We never create |
michael@0 | 1151 | // instances of it, and static_casting to it is fine since it doesn't add |
michael@0 | 1152 | // anything to WorkerPrivate. |
michael@0 | 1153 | class ChromeWorkerPrivate : public WorkerPrivate |
michael@0 | 1154 | { |
michael@0 | 1155 | public: |
michael@0 | 1156 | static already_AddRefed<ChromeWorkerPrivate> |
michael@0 | 1157 | Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL, |
michael@0 | 1158 | ErrorResult& rv); |
michael@0 | 1159 | |
michael@0 | 1160 | static bool |
michael@0 | 1161 | WorkerAvailable(JSContext* /* unused */, JSObject* /* unused */); |
michael@0 | 1162 | |
michael@0 | 1163 | private: |
michael@0 | 1164 | ChromeWorkerPrivate() MOZ_DELETE; |
michael@0 | 1165 | ChromeWorkerPrivate(const ChromeWorkerPrivate& aRHS) MOZ_DELETE; |
michael@0 | 1166 | ChromeWorkerPrivate& operator =(const ChromeWorkerPrivate& aRHS) MOZ_DELETE; |
michael@0 | 1167 | }; |
michael@0 | 1168 | |
michael@0 | 1169 | WorkerPrivate* |
michael@0 | 1170 | GetWorkerPrivateFromContext(JSContext* aCx); |
michael@0 | 1171 | |
michael@0 | 1172 | WorkerPrivate* |
michael@0 | 1173 | GetCurrentThreadWorkerPrivate(); |
michael@0 | 1174 | |
michael@0 | 1175 | bool |
michael@0 | 1176 | IsCurrentThreadRunningChromeWorker(); |
michael@0 | 1177 | |
michael@0 | 1178 | JSContext* |
michael@0 | 1179 | GetCurrentThreadJSContext(); |
michael@0 | 1180 | |
michael@0 | 1181 | enum WorkerStructuredDataType |
michael@0 | 1182 | { |
michael@0 | 1183 | DOMWORKER_SCTAG_FILE = SCTAG_DOM_MAX, |
michael@0 | 1184 | DOMWORKER_SCTAG_BLOB, |
michael@0 | 1185 | |
michael@0 | 1186 | DOMWORKER_SCTAG_END |
michael@0 | 1187 | }; |
michael@0 | 1188 | |
michael@0 | 1189 | JSStructuredCloneCallbacks* |
michael@0 | 1190 | WorkerStructuredCloneCallbacks(bool aMainRuntime); |
michael@0 | 1191 | |
michael@0 | 1192 | JSStructuredCloneCallbacks* |
michael@0 | 1193 | ChromeWorkerStructuredCloneCallbacks(bool aMainRuntime); |
michael@0 | 1194 | |
michael@0 | 1195 | class AutoSyncLoopHolder |
michael@0 | 1196 | { |
michael@0 | 1197 | WorkerPrivate* mWorkerPrivate; |
michael@0 | 1198 | nsCOMPtr<nsIEventTarget> mTarget; |
michael@0 | 1199 | uint32_t mIndex; |
michael@0 | 1200 | |
michael@0 | 1201 | public: |
michael@0 | 1202 | AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate) |
michael@0 | 1203 | : mWorkerPrivate(aWorkerPrivate) |
michael@0 | 1204 | , mTarget(aWorkerPrivate->CreateNewSyncLoop()) |
michael@0 | 1205 | , mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1) |
michael@0 | 1206 | { |
michael@0 | 1207 | aWorkerPrivate->AssertIsOnWorkerThread(); |
michael@0 | 1208 | } |
michael@0 | 1209 | |
michael@0 | 1210 | ~AutoSyncLoopHolder() |
michael@0 | 1211 | { |
michael@0 | 1212 | if (mWorkerPrivate) { |
michael@0 | 1213 | mWorkerPrivate->AssertIsOnWorkerThread(); |
michael@0 | 1214 | mWorkerPrivate->StopSyncLoop(mTarget, false); |
michael@0 | 1215 | mWorkerPrivate->DestroySyncLoop(mIndex); |
michael@0 | 1216 | } |
michael@0 | 1217 | } |
michael@0 | 1218 | |
michael@0 | 1219 | bool |
michael@0 | 1220 | Run() |
michael@0 | 1221 | { |
michael@0 | 1222 | WorkerPrivate* workerPrivate = mWorkerPrivate; |
michael@0 | 1223 | mWorkerPrivate = nullptr; |
michael@0 | 1224 | |
michael@0 | 1225 | workerPrivate->AssertIsOnWorkerThread(); |
michael@0 | 1226 | |
michael@0 | 1227 | return workerPrivate->RunCurrentSyncLoop(); |
michael@0 | 1228 | } |
michael@0 | 1229 | |
michael@0 | 1230 | nsIEventTarget* |
michael@0 | 1231 | EventTarget() const |
michael@0 | 1232 | { |
michael@0 | 1233 | return mTarget; |
michael@0 | 1234 | } |
michael@0 | 1235 | }; |
michael@0 | 1236 | |
michael@0 | 1237 | END_WORKERS_NAMESPACE |
michael@0 | 1238 | |
michael@0 | 1239 | #endif /* mozilla_dom_workers_workerprivate_h__ */ |