From ab337aa92c7ad43755f76f5370d92f0a4a54ab2a Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 2 May 2019 08:34:27 -1000 Subject: [PATCH] Bug 1392408 Part 3 - Report stacks to net monitor when loading worker scripts, r=bzbarsky. --HG-- extra : rebase_source : c4b52354dc9c71bb86cd157f0f710d01b78659e5 --- dom/bindings/Bindings.conf | 2 +- dom/workers/ScriptLoader.cpp | 36 ++++++++++++++++++++++++++++------ dom/workers/ScriptLoader.h | 9 +++++++-- dom/workers/WorkerDebugger.cpp | 4 ++-- dom/workers/WorkerPrivate.cpp | 12 ++++++++---- dom/workers/WorkerScope.cpp | 11 ++++++++--- dom/workers/WorkerScope.h | 3 ++- 7 files changed, 58 insertions(+), 19 deletions(-) diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 344d10e1426e..03c50d5974f8 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1556,7 +1556,7 @@ DOMInterfaces = { 'WorkerGlobalScope': { 'headerFile': 'mozilla/dom/WorkerScope.h', - 'implicitJSContext': [ 'createImageBitmap' ], + 'implicitJSContext': [ 'createImageBitmap', 'importScripts' ], 'concrete': False, # Rename a few things so we don't have both classes and methods # with the same name diff --git a/dom/workers/ScriptLoader.cpp b/dom/workers/ScriptLoader.cpp index d338b7dd3277..8e60a30875a5 100644 --- a/dom/workers/ScriptLoader.cpp +++ b/dom/workers/ScriptLoader.cpp @@ -549,6 +549,8 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed { friend class LoaderListener; WorkerPrivate* mWorkerPrivate; + UniquePtr mOriginStack; + nsString mOriginStackJSON; nsCOMPtr mSyncLoopTarget; nsTArray mLoadInfos; RefPtr mCacheCreator; @@ -563,6 +565,7 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed { NS_DECL_THREADSAFE_ISUPPORTS ScriptLoaderRunnable(WorkerPrivate* aWorkerPrivate, + UniquePtr aOriginStack, nsIEventTarget* aSyncLoopTarget, nsTArray& aLoadInfos, const Maybe& aClientInfo, @@ -570,6 +573,7 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed { bool aIsMainScript, WorkerScriptType aWorkerScriptType, ErrorResult& aRv) : mWorkerPrivate(aWorkerPrivate), + mOriginStack(std::move(aOriginStack)), mSyncLoopTarget(aSyncLoopTarget), mClientInfo(aClientInfo), mController(aController), @@ -836,6 +840,14 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed { mWorkerPrivate->SetLoadingWorkerScript(true); } + // Convert the origin stack to JSON (which must be done on the main + // thread) explicitly, so that we can use the stack to notify the net + // monitor about every script we load. + if (mOriginStack) { + ConvertSerializedStackToJSON(std::move(mOriginStack), + mOriginStackJSON); + } + if (!mWorkerPrivate->IsServiceWorker() || IsDebuggerScript()) { for (uint32_t index = 0, len = mLoadInfos.Length(); index < len; ++index) { @@ -962,6 +974,11 @@ class ScriptLoaderRunnable final : public nsIRunnable, public nsINamed { } } + // Associate any originating stack with the channel. + if (!mOriginStackJSON.IsEmpty()) { + NotifyNetworkMonitorAlternateStack(channel, mOriginStackJSON); + } + // We need to know which index we're on in OnStreamComplete so we know // where to put the result. RefPtr listener = new LoaderListener(this, aIndex); @@ -2081,6 +2098,7 @@ void ScriptExecutorRunnable::LogExceptionToConsole( } void LoadAllScripts(WorkerPrivate* aWorkerPrivate, + UniquePtr aOriginStack, nsTArray& aLoadInfos, bool aIsMainScript, WorkerScriptType aWorkerScriptType, ErrorResult& aRv) { aWorkerPrivate->AssertIsOnWorkerThread(); @@ -2101,8 +2119,8 @@ void LoadAllScripts(WorkerPrivate* aWorkerPrivate, } RefPtr loader = new ScriptLoaderRunnable( - aWorkerPrivate, syncLoopTarget, aLoadInfos, clientInfo, controller, - aIsMainScript, aWorkerScriptType, aRv); + aWorkerPrivate, std::move(aOriginStack), syncLoopTarget, aLoadInfos, clientInfo, + controller, aIsMainScript, aWorkerScriptType, aRv); NS_ASSERTION(aLoadInfos.IsEmpty(), "Should have swapped!"); @@ -2222,7 +2240,9 @@ void ReportLoadError(ErrorResult& aRv, nsresult aLoadResult, NS_LITERAL_CSTRING("\"")); } -void LoadMainScript(WorkerPrivate* aWorkerPrivate, const nsAString& aScriptURL, +void LoadMainScript(WorkerPrivate* aWorkerPrivate, + UniquePtr aOriginStack, + const nsAString& aScriptURL, WorkerScriptType aWorkerScriptType, ErrorResult& aRv) { nsTArray loadInfos; @@ -2234,10 +2254,13 @@ void LoadMainScript(WorkerPrivate* aWorkerPrivate, const nsAString& aScriptURL, // reserved. info->mReservedClientInfo = aWorkerPrivate->GetClientInfo(); - LoadAllScripts(aWorkerPrivate, loadInfos, true, aWorkerScriptType, aRv); + LoadAllScripts(aWorkerPrivate, std::move(aOriginStack), loadInfos, true, + aWorkerScriptType, aRv); } -void Load(WorkerPrivate* aWorkerPrivate, const nsTArray& aScriptURLs, +void Load(WorkerPrivate* aWorkerPrivate, + UniquePtr aOriginStack, + const nsTArray& aScriptURLs, WorkerScriptType aWorkerScriptType, ErrorResult& aRv) { const uint32_t urlCount = aScriptURLs.Length(); @@ -2258,7 +2281,8 @@ void Load(WorkerPrivate* aWorkerPrivate, const nsTArray& aScriptURLs, loadInfos[index].mLoadFlags = aWorkerPrivate->GetLoadFlags(); } - LoadAllScripts(aWorkerPrivate, loadInfos, false, aWorkerScriptType, aRv); + LoadAllScripts(aWorkerPrivate, std::move(aOriginStack), loadInfos, false, + aWorkerScriptType, aRv); } } // namespace workerinternals diff --git a/dom/workers/ScriptLoader.h b/dom/workers/ScriptLoader.h index 2cd25f99d8d9..adcd0d35e2f9 100644 --- a/dom/workers/ScriptLoader.h +++ b/dom/workers/ScriptLoader.h @@ -26,6 +26,7 @@ namespace dom { struct WorkerLoadInfo; class WorkerPrivate; +class SerializedStackHolder; enum WorkerScriptType { WorkerScript, DebuggerScript }; @@ -45,10 +46,14 @@ nsresult ChannelFromScriptURLWorkerThread(JSContext* aCx, void ReportLoadError(ErrorResult& aRv, nsresult aLoadResult, const nsAString& aScriptURL); -void LoadMainScript(WorkerPrivate* aWorkerPrivate, const nsAString& aScriptURL, +void LoadMainScript(WorkerPrivate* aWorkerPrivate, + UniquePtr aOriginStack, + const nsAString& aScriptURL, WorkerScriptType aWorkerScriptType, ErrorResult& aRv); -void Load(WorkerPrivate* aWorkerPrivate, const nsTArray& aScriptURLs, +void Load(WorkerPrivate* aWorkerPrivate, + UniquePtr aOriginStack, + const nsTArray& aScriptURLs, WorkerScriptType aWorkerScriptType, ErrorResult& aRv); } // namespace workerinternals diff --git a/dom/workers/WorkerDebugger.cpp b/dom/workers/WorkerDebugger.cpp index c28995a5daa0..d10525361b07 100644 --- a/dom/workers/WorkerDebugger.cpp +++ b/dom/workers/WorkerDebugger.cpp @@ -103,8 +103,8 @@ class CompileDebuggerScriptRunnable final : public WorkerDebuggerRunnable { ErrorResult rv; JSAutoRealm ar(aCx, global); - workerinternals::LoadMainScript(aWorkerPrivate, mScriptURL, DebuggerScript, - rv); + workerinternals::LoadMainScript(aWorkerPrivate, nullptr, mScriptURL, + DebuggerScript, rv); rv.WouldReportJSException(); // Explicitly ignore NS_BINDING_ABORTED on rv. Or more precisely, still // return false and don't SetWorkerScriptExecutedSuccessfully() in that diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 607fe88d6ca1..dbb65b265e08 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -302,12 +302,14 @@ class ModifyBusyCountRunnable final : public WorkerControlRunnable { class CompileScriptRunnable final : public WorkerDebuggeeRunnable { nsString mScriptURL; + UniquePtr mOriginStack; public: explicit CompileScriptRunnable(WorkerPrivate* aWorkerPrivate, + UniquePtr aOriginStack, const nsAString& aScriptURL) : WorkerDebuggeeRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount), - mScriptURL(aScriptURL) {} + mScriptURL(aScriptURL), mOriginStack(aOriginStack.release()) {} private: // We can't implement PreRun effectively, because at the point when that would @@ -337,8 +339,8 @@ class CompileScriptRunnable final : public WorkerDebuggeeRunnable { } ErrorResult rv; - workerinternals::LoadMainScript(aWorkerPrivate, mScriptURL, WorkerScript, - rv); + workerinternals::LoadMainScript(aWorkerPrivate, std::move(mOriginStack), + mScriptURL, WorkerScript, rv); rv.WouldReportJSException(); // Explicitly ignore NS_BINDING_ABORTED on rv. Or more precisely, still // return false and don't SetWorkerScriptExecutedSuccessfully() in that @@ -2256,8 +2258,10 @@ already_AddRefed WorkerPrivate::Constructor( MOZ_DIAGNOSTIC_ASSERT(worker->PrincipalIsValid()); + UniquePtr stack = GetCurrentStackForNetMonitor(aCx); + RefPtr compiler = - new CompileScriptRunnable(worker, aScriptURL); + new CompileScriptRunnable(worker, std::move(stack), aScriptURL); if (!compiler->Dispatch()) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 6ce325b8f81a..266c9435d436 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -235,10 +235,15 @@ void WorkerGlobalScope::SetOnerror(OnErrorEventHandlerNonNull* aHandler) { } } -void WorkerGlobalScope::ImportScripts(const Sequence& aScriptURLs, +void WorkerGlobalScope::ImportScripts(JSContext* aCx, + const Sequence& aScriptURLs, ErrorResult& aRv) { mWorkerPrivate->AssertIsOnWorkerThread(); - workerinternals::Load(mWorkerPrivate, aScriptURLs, WorkerScript, aRv); + + UniquePtr stack = GetCurrentStackForNetMonitor(aCx); + + workerinternals::Load(mWorkerPrivate, std::move(stack), aScriptURLs, + WorkerScript, aRv); } int32_t WorkerGlobalScope::SetTimeout(JSContext* aCx, Function& aHandler, @@ -906,7 +911,7 @@ void WorkerDebuggerGlobalScope::LoadSubScript( nsTArray urls; urls.AppendElement(aURL); - workerinternals::Load(mWorkerPrivate, urls, DebuggerScript, aRv); + workerinternals::Load(mWorkerPrivate, nullptr, urls, DebuggerScript, aRv); } void WorkerDebuggerGlobalScope::EnterEventLoop() { diff --git a/dom/workers/WorkerScope.h b/dom/workers/WorkerScope.h index 07e21114aea0..f0e0b8ceb716 100644 --- a/dom/workers/WorkerScope.h +++ b/dom/workers/WorkerScope.h @@ -105,7 +105,8 @@ class WorkerGlobalScope : public DOMEventTargetHelper, OnErrorEventHandlerNonNull* GetOnerror(); void SetOnerror(OnErrorEventHandlerNonNull* aHandler); - void ImportScripts(const Sequence& aScriptURLs, ErrorResult& aRv); + void ImportScripts(JSContext* aCx, const Sequence& aScriptURLs, + ErrorResult& aRv); int32_t SetTimeout(JSContext* aCx, Function& aHandler, const int32_t aTimeout, const Sequence& aArguments, ErrorResult& aRv);