зеркало из https://github.com/mozilla/gecko-dev.git
252 строки
9.1 KiB
C++
252 строки
9.1 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef mozilla_dom_workers_scriptloader_h__
|
|
#define mozilla_dom_workers_scriptloader_h__
|
|
|
|
#include "mozilla/dom/ScriptLoadInfo.h"
|
|
#include "mozilla/dom/WorkerCommon.h"
|
|
#include "mozilla/Maybe.h"
|
|
#include "nsIContentPolicy.h"
|
|
#include "nsStringFwd.h"
|
|
#include "nsTArrayForwardDeclare.h"
|
|
|
|
class nsIChannel;
|
|
class nsICookieJarSettings;
|
|
class nsILoadGroup;
|
|
class nsIPrincipal;
|
|
class nsIReferrerInfo;
|
|
class nsIURI;
|
|
|
|
namespace mozilla {
|
|
|
|
class ErrorResult;
|
|
|
|
namespace dom {
|
|
|
|
class ClientInfo;
|
|
class Document;
|
|
struct WorkerLoadInfo;
|
|
class WorkerPrivate;
|
|
class SerializedStackHolder;
|
|
|
|
enum WorkerScriptType { WorkerScript, DebuggerScript };
|
|
|
|
namespace workerinternals {
|
|
|
|
namespace loader {
|
|
class ScriptLoaderRunnable;
|
|
class ScriptExecutorRunnable;
|
|
class CachePromiseHandler;
|
|
class CacheLoadHandler;
|
|
class CacheCreator;
|
|
class NetworkLoadHandler;
|
|
|
|
/*
|
|
* [DOMDOC] WorkerScriptLoader
|
|
*
|
|
* The WorkerScriptLoader is the primary class responsible for loading all
|
|
* Workers, including: ServiceWorkers, SharedWorkers, RemoteWorkers, and
|
|
* dedicated Workers. Our implementation also includes a subtype of dedicated
|
|
* workers: ChromeWorker, which exposes information that isn't normally
|
|
* accessible on a dedicated worker. See [1] for more information.
|
|
*
|
|
* Due to constraints around fetching, this class currently delegates the
|
|
* "Fetch" portion of its work load to the main thread. Unlike the DOM
|
|
* ScriptLoader, the WorkerScriptLoader is not persistent and is not reused for
|
|
* subsequent loads. That means for each iteration of loading (for example,
|
|
* loading the main script, followed by a load triggered by ImportScripts), we
|
|
* recreate this class, and handle the case independently.
|
|
*
|
|
* The flow of requests across the boundaries looks like this:
|
|
*
|
|
* +----------------------------+
|
|
* | new WorkerScriptLoader(..) |
|
|
* +----------------------------+
|
|
* |
|
|
* | Create the loader, along with the scriptLoadInfos
|
|
* | call DispatchLoadScripts()
|
|
* | Create ScriptLoaderRunnable
|
|
* |
|
|
* #####################################################################
|
|
* Enter Main thread
|
|
* #####################################################################
|
|
* |
|
|
* V
|
|
* +---------------+ For each request: Is a normal Worker?
|
|
* | LoadScripts() |--------------------------------------+
|
|
* +---------------+ |
|
|
* | |
|
|
* | For each request: Is a ServiceWorker? |
|
|
* | |
|
|
* V V
|
|
* +==================+ No script in cache? +====================+
|
|
* | CacheLoadHandler |------------------------>| NetworkLoadHandler |
|
|
* +==================+ +====================+
|
|
* : :
|
|
* : Loaded from Cache : Loaded by Network
|
|
* : +--------------------+ :
|
|
* +----------->| OnStreamComplete() |<---------+
|
|
* +--------------------+
|
|
* |
|
|
* | A request is ready, is it in post order?
|
|
* |
|
|
* | call DispatchPendingProcessRequests()
|
|
* | This creates ScriptExecutorRunnable
|
|
* |
|
|
* #####################################################################
|
|
* Enter worker thread
|
|
* #####################################################################
|
|
* |
|
|
* |
|
|
* V
|
|
* +-------------------------+ All Scripts Executed?
|
|
* | ProcessPendingScripts() |-------------+
|
|
* +-------------------------+ |
|
|
* |
|
|
* | yes.
|
|
* |
|
|
* V
|
|
* +------------------------+
|
|
* | ShutdownScriptLoader() |
|
|
* +------------------------+
|
|
*/
|
|
|
|
class WorkerScriptLoader final : public nsINamed {
|
|
friend class ScriptLoaderRunnable;
|
|
friend class ScriptExecutorRunnable;
|
|
friend class CachePromiseHandler;
|
|
friend class CacheLoadHandler;
|
|
friend class NetworkLoadHandler;
|
|
|
|
WorkerPrivate* const mWorkerPrivate;
|
|
UniquePtr<SerializedStackHolder> mOriginStack;
|
|
nsString mOriginStackJSON;
|
|
nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
|
|
nsTArrayView<ScriptLoadInfo> mLoadInfos;
|
|
RefPtr<CacheCreator> mCacheCreator;
|
|
Maybe<ClientInfo> mClientInfo;
|
|
Maybe<ServiceWorkerDescriptor> mController;
|
|
const bool mIsMainScript;
|
|
WorkerScriptType mWorkerScriptType;
|
|
bool mCanceledMainThread;
|
|
ErrorResult& mRv;
|
|
bool mExecutionAborted = false;
|
|
bool mMutedErrorFlag = false;
|
|
|
|
public:
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
|
|
WorkerScriptLoader(WorkerPrivate* aWorkerPrivate,
|
|
UniquePtr<SerializedStackHolder> aOriginStack,
|
|
nsIEventTarget* aSyncLoopTarget,
|
|
nsTArray<ScriptLoadInfo> aLoadInfos,
|
|
const Maybe<ClientInfo>& aClientInfo,
|
|
const Maybe<ServiceWorkerDescriptor>& aController,
|
|
bool aIsMainScript, WorkerScriptType aWorkerScriptType,
|
|
ErrorResult& aRv);
|
|
|
|
void CancelMainThreadWithBindingAborted() {
|
|
CancelMainThread(NS_BINDING_ABORTED);
|
|
}
|
|
|
|
bool DispatchLoadScripts();
|
|
|
|
protected:
|
|
nsIURI* GetBaseURI();
|
|
|
|
void MaybeExecuteFinishedScripts(const ScriptLoadInfo& aLoadInfo);
|
|
|
|
bool StoreCSP();
|
|
|
|
bool ProcessPendingRequests(JSContext* aCx,
|
|
const Span<ScriptLoadInfo> aLoadInfosToExecute);
|
|
|
|
nsresult OnStreamComplete(ScriptLoadInfo& aLoadInfo, nsresult aStatus);
|
|
|
|
// Are we loading the primary script, which is not a Debugger Script?
|
|
bool IsMainWorkerScript() const {
|
|
return mIsMainScript && mWorkerScriptType == WorkerScript;
|
|
}
|
|
|
|
// Are we loading the primary script, regardless of the script type?
|
|
bool IsMainScript() const { return mIsMainScript; }
|
|
|
|
bool IsDebuggerScript() const { return mWorkerScriptType == DebuggerScript; }
|
|
|
|
void SetController(const Maybe<ServiceWorkerDescriptor>& aDescriptor) {
|
|
mController = aDescriptor;
|
|
}
|
|
|
|
Maybe<ServiceWorkerDescriptor>& GetController() { return mController; }
|
|
|
|
CacheCreator* GetCacheCreator() { return mCacheCreator; }
|
|
|
|
bool IsCancelled() { return mCanceledMainThread; }
|
|
|
|
void CancelMainThread(nsresult aCancelResult);
|
|
|
|
void DeleteCache();
|
|
|
|
nsresult LoadScripts();
|
|
|
|
nsresult LoadScript(ScriptLoadInfo& aLoadInfo);
|
|
|
|
void ShutdownScriptLoader(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
|
bool aResult, bool aMutedError);
|
|
|
|
private:
|
|
~WorkerScriptLoader() = default;
|
|
|
|
NS_IMETHOD
|
|
GetName(nsACString& aName) override {
|
|
aName.AssignLiteral("WorkerScriptLoader");
|
|
return NS_OK;
|
|
}
|
|
|
|
void LoadingFinished(ScriptLoadInfo& aLoadInfo, nsresult aRv);
|
|
|
|
void DispatchProcessPendingRequests();
|
|
|
|
bool EvaluateScript(JSContext* aCx, ScriptLoadInfo& aLoadInfo);
|
|
|
|
void LogExceptionToConsole(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
|
};
|
|
|
|
} // namespace loader
|
|
|
|
nsresult ChannelFromScriptURLMainThread(
|
|
nsIPrincipal* aPrincipal, Document* aParentDoc, nsILoadGroup* aLoadGroup,
|
|
nsIURI* aScriptURL, const Maybe<ClientInfo>& aClientInfo,
|
|
nsContentPolicyType aContentPolicyType,
|
|
nsICookieJarSettings* aCookieJarSettings, nsIReferrerInfo* aReferrerInfo,
|
|
nsIChannel** aChannel);
|
|
|
|
nsresult ChannelFromScriptURLWorkerThread(JSContext* aCx,
|
|
WorkerPrivate* aParent,
|
|
const nsAString& aScriptURL,
|
|
WorkerLoadInfo& aLoadInfo);
|
|
|
|
void ReportLoadError(ErrorResult& aRv, nsresult aLoadResult,
|
|
const nsAString& aScriptURL);
|
|
|
|
void LoadMainScript(WorkerPrivate* aWorkerPrivate,
|
|
UniquePtr<SerializedStackHolder> aOriginStack,
|
|
const nsAString& aScriptURL,
|
|
WorkerScriptType aWorkerScriptType, ErrorResult& aRv);
|
|
|
|
void Load(WorkerPrivate* aWorkerPrivate,
|
|
UniquePtr<SerializedStackHolder> aOriginStack,
|
|
const nsTArray<nsString>& aScriptURLs,
|
|
WorkerScriptType aWorkerScriptType, ErrorResult& aRv);
|
|
|
|
} // namespace workerinternals
|
|
|
|
} // namespace dom
|
|
} // namespace mozilla
|
|
|
|
#endif /* mozilla_dom_workers_scriptloader_h__ */
|