diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index ec2ac207c49a..f53d501afbde 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -26,6 +26,8 @@ #include "nsIPrincipal.h" #include "nsIXPConnect.h" #include "nsUTF8Utils.h" +#include "WorkerPrivate.h" +#include "WorkerRunnable.h" #include "WrapperFactory.h" #include "xpcprivate.h" #include "XrayWrapper.h" @@ -56,6 +58,8 @@ namespace mozilla { namespace dom { +using namespace workers; + const JSErrorFormatString ErrorFormatString[] = { #define MSG_DEF(_name, _argc, _exn, _str) \ { #_name, _str, _argc, _exn }, @@ -2501,7 +2505,6 @@ ConvertJSValueToByteString(JSContext* cx, JS::Handle v, bool IsInPrivilegedApp(JSContext* aCx, JSObject* aObj) { - using mozilla::dom::workers::GetWorkerPrivateFromContext; if (!NS_IsMainThread()) { return GetWorkerPrivateFromContext(aCx)->IsInPrivilegedApp(); } @@ -2516,7 +2519,6 @@ IsInPrivilegedApp(JSContext* aCx, JSObject* aObj) bool IsInCertifiedApp(JSContext* aCx, JSObject* aObj) { - using mozilla::dom::workers::GetWorkerPrivateFromContext; if (!NS_IsMainThread()) { return GetWorkerPrivateFromContext(aCx)->IsInCertifiedApp(); } @@ -3285,6 +3287,114 @@ SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject, } } +namespace { + +// This runnable is used to write a deprecation message from a worker to the +// console running on the main-thread. +class DeprecationWarningRunnable final : public Runnable + , public WorkerFeature +{ + WorkerPrivate* mWorkerPrivate; + nsIDocument::DeprecatedOperations mOperation; + +public: + DeprecationWarningRunnable(WorkerPrivate* aWorkerPrivate, + nsIDocument::DeprecatedOperations aOperation) + : mWorkerPrivate(aWorkerPrivate) + , mOperation(aOperation) + { + MOZ_ASSERT(aWorkerPrivate); + } + + void + Dispatch() + { + if (NS_WARN_IF(!mWorkerPrivate->AddFeature(this))) { + return; + } + + if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(this)))) { + mWorkerPrivate->RemoveFeature(this); + return; + } + } + + virtual bool + Notify(Status aStatus) override + { + // We don't care about the notification. We just want to keep the + // mWorkerPrivate alive. + return true; + } + +private: + + NS_IMETHOD + Run() override + { + MOZ_ASSERT(NS_IsMainThread()); + + // Walk up to our containing page + WorkerPrivate* wp = mWorkerPrivate; + while (wp->GetParent()) { + wp = wp->GetParent(); + } + + nsPIDOMWindowInner* window = wp->GetWindow(); + if (window && window->GetExtantDoc()) { + window->GetExtantDoc()->WarnOnceAbout(mOperation); + } + + ReleaseWorker(); + return NS_OK; + } + + void + ReleaseWorker() + { + class ReleaseRunnable final : public WorkerRunnable + { + RefPtr mRunnable; + + public: + ReleaseRunnable(WorkerPrivate* aWorkerPrivate, + DeprecationWarningRunnable* aRunnable) + : WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount) + , mRunnable(aRunnable) + {} + + virtual bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override + { + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + + aWorkerPrivate->RemoveFeature(mRunnable); + return true; + } + + virtual bool + PreDispatch(WorkerPrivate* aWorkerPrivate) override + { + AssertIsOnMainThread(); + return true; + } + + virtual void + PostDispatch(WorkerPrivate* aWorkerPrivate, + bool aDispatchResult) override + { + } + }; + + RefPtr runnable = + new ReleaseRunnable(mWorkerPrivate, this); + NS_WARN_IF(!runnable->Dispatch()); + } +}; + +} // anonymous namespace + void DeprecationWarning(JSContext* aCx, JSObject* aObject, nsIDocument::DeprecatedOperations aOperation) @@ -3295,10 +3405,23 @@ DeprecationWarning(JSContext* aCx, JSObject* aObject, return; } - nsCOMPtr window = do_QueryInterface(global.GetAsSupports()); - if (window && window->GetExtantDoc()) { - window->GetExtantDoc()->WarnOnceAbout(aOperation); + if (NS_IsMainThread()) { + nsCOMPtr window = do_QueryInterface(global.GetAsSupports()); + if (window && window->GetExtantDoc()) { + window->GetExtantDoc()->WarnOnceAbout(aOperation); + } + + return; } + + WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); + if (!workerPrivate) { + return; + } + + RefPtr runnable = + new DeprecationWarningRunnable(workerPrivate, aOperation); + runnable->Dispatch(); } namespace binding_detail { @@ -3309,7 +3432,7 @@ UnprivilegedJunkScopeOrWorkerGlobal() return xpc::UnprivilegedJunkScope(); } - return workers::GetCurrentThreadWorkerGlobal(); + return GetCurrentThreadWorkerGlobal(); } } // namespace binding_detail diff --git a/dom/bindings/Exceptions.cpp b/dom/bindings/Exceptions.cpp index 6b495aa30c25..b85a9ee2995b 100644 --- a/dom/bindings/Exceptions.cpp +++ b/dom/bindings/Exceptions.cpp @@ -203,7 +203,7 @@ GetCurrentJSStack(int32_t aMaxDepth) return nullptr; } - return exceptions::CreateStack(cx, aMaxDepth); + return dom::exceptions::CreateStack(cx, aMaxDepth); } AutoForceSetExceptionOnContext::AutoForceSetExceptionOnContext(JSContext* aCx)