зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1438945 - Part 9: RemoteWorker in SharedWorkerManager. r=asuth
--HG-- extra : rebase_source : 07a23a3f76ef06d76a456ba785186018e6fb77f1
This commit is contained in:
Родитель
7c7e94be60
Коммит
c292b31a93
|
@ -33,10 +33,10 @@
|
|||
#include "mozilla/dom/MutableBlobStreamListener.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseWorkerProxy.h"
|
||||
#include "mozilla/dom/RemoteWorkerChild.h"
|
||||
#include "mozilla/dom/Request.h"
|
||||
#include "mozilla/dom/Response.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/SharedWorkerManager.h"
|
||||
#include "mozilla/dom/URLSearchParams.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
|
@ -907,7 +907,7 @@ WorkerFetchResolver::FlushConsoleReport()
|
|||
|
||||
if (worker->IsSharedWorker()) {
|
||||
// Flush to shared worker
|
||||
worker->GetSharedWorkerManager()->FlushReportsToActorsOnMainThread(mReporter);
|
||||
worker->GetRemoteWorkerController()->FlushReportsOnMainThread(mReporter);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,9 +47,9 @@
|
|||
#include "mozilla/dom/MessageChannel.h"
|
||||
#include "mozilla/dom/MessageEventBinding.h"
|
||||
#include "mozilla/dom/PerformanceService.h"
|
||||
#include "mozilla/dom/RemoteWorkerChild.h"
|
||||
#include "mozilla/dom/WorkerBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/SharedWorkerManager.h"
|
||||
#include "mozilla/dom/IndexedDatabaseManager.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
@ -1533,7 +1533,7 @@ RuntimeService::UnregisterWorker(WorkerPrivate* aWorkerPrivate)
|
|||
|
||||
if (aWorkerPrivate->IsSharedWorker()) {
|
||||
AssertIsOnMainThread();
|
||||
aWorkerPrivate->GetSharedWorkerManager()->CloseActorsOnMainThread();
|
||||
aWorkerPrivate->GetRemoteWorkerController()->CloseWorkerOnMainThread();
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/ErrorEvent.h"
|
||||
#include "mozilla/dom/ErrorEventBinding.h"
|
||||
#include "mozilla/dom/PSharedWorker.h"
|
||||
#include "mozilla/dom/SharedWorkerManager.h"
|
||||
#include "mozilla/dom/RemoteWorkerChild.h"
|
||||
#include "mozilla/dom/ServiceWorkerManager.h"
|
||||
#include "mozilla/dom/SimpleGlobalObject.h"
|
||||
#include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
|
||||
|
@ -203,8 +202,8 @@ private:
|
|||
MOZ_ASSERT(!aWorkerPrivate->IsParentWindowPaused());
|
||||
|
||||
if (aWorkerPrivate->IsSharedWorker()) {
|
||||
aWorkerPrivate->GetSharedWorkerManager()
|
||||
->BroadcastErrorToActorsOnMainThread(&mReport,
|
||||
aWorkerPrivate->GetRemoteWorkerController()
|
||||
->ErrorPropagationOnMainThread(&mReport,
|
||||
/* isErrorEvent */ true);
|
||||
return true;
|
||||
}
|
||||
|
@ -294,8 +293,8 @@ private:
|
|||
MOZ_ASSERT(!aWorkerPrivate->IsParentWindowPaused());
|
||||
|
||||
if (aWorkerPrivate->IsSharedWorker()) {
|
||||
aWorkerPrivate->GetSharedWorkerManager()
|
||||
->BroadcastErrorToActorsOnMainThread(nullptr, false);
|
||||
aWorkerPrivate->GetRemoteWorkerController()
|
||||
->ErrorPropagationOnMainThread(nullptr, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/PerformanceStorageWorker.h"
|
||||
#include "mozilla/dom/PromiseDebugging.h"
|
||||
#include "mozilla/dom/SharedWorkerManager.h"
|
||||
#include "mozilla/dom/RemoteWorkerChild.h"
|
||||
#include "mozilla/dom/WorkerBinding.h"
|
||||
#include "mozilla/ThreadEventQueue.h"
|
||||
#include "mozilla/ThrottledEventQueue.h"
|
||||
|
@ -1888,7 +1888,7 @@ WorkerPrivate::ModifyBusyCount(bool aIncrease)
|
|||
{
|
||||
AssertIsOnParentThread();
|
||||
|
||||
NS_ASSERTION(aIncrease || mBusyCount, "Mismatched busy count mods!");
|
||||
MOZ_ASSERT(aIncrease || mBusyCount, "Mismatched busy count mods!");
|
||||
|
||||
if (aIncrease) {
|
||||
mBusyCount++;
|
||||
|
@ -4907,7 +4907,7 @@ WorkerPrivate::EndCTypesCall()
|
|||
|
||||
bool
|
||||
WorkerPrivate::ConnectMessagePort(JSContext* aCx,
|
||||
MessagePortIdentifier& aIdentifier)
|
||||
const MessagePortIdentifier& aIdentifier)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
|
@ -5075,21 +5075,21 @@ WorkerPrivate::GetPerformanceStorage()
|
|||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::SetSharedWorkerManager(SharedWorkerManager* aManager)
|
||||
WorkerPrivate::SetRemoteWorkerController(RemoteWorkerChild* aController)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aManager);
|
||||
MOZ_ASSERT(!mSharedWorkerManager);
|
||||
MOZ_ASSERT(aController);
|
||||
MOZ_ASSERT(!mRemoteWorkerController);
|
||||
|
||||
mSharedWorkerManager = aManager;
|
||||
mRemoteWorkerController = aController;
|
||||
}
|
||||
|
||||
SharedWorkerManager*
|
||||
WorkerPrivate::GetSharedWorkerManager()
|
||||
RemoteWorkerChild*
|
||||
WorkerPrivate::GetRemoteWorkerController()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(mSharedWorkerManager);
|
||||
return mSharedWorkerManager;
|
||||
MOZ_ASSERT(mRemoteWorkerController);
|
||||
return mRemoteWorkerController;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(WorkerPrivate::EventTarget)
|
||||
|
|
|
@ -44,7 +44,7 @@ class Function;
|
|||
class MessagePort;
|
||||
class MessagePortIdentifier;
|
||||
class PerformanceStorage;
|
||||
class SharedWorkerManager;
|
||||
class RemoteWorkerChild;
|
||||
class WorkerControlRunnable;
|
||||
class WorkerCSPEventListener;
|
||||
class WorkerDebugger;
|
||||
|
@ -461,7 +461,7 @@ public:
|
|||
}
|
||||
|
||||
bool
|
||||
ConnectMessagePort(JSContext* aCx, MessagePortIdentifier& aIdentifier);
|
||||
ConnectMessagePort(JSContext* aCx, const MessagePortIdentifier& aIdentifier);
|
||||
|
||||
WorkerGlobalScope*
|
||||
GetOrCreateGlobalScope(JSContext* aCx);
|
||||
|
@ -1079,11 +1079,11 @@ public:
|
|||
mLoadingWorkerScript = aLoadingWorkerScript;
|
||||
}
|
||||
|
||||
SharedWorkerManager*
|
||||
GetSharedWorkerManager();
|
||||
RemoteWorkerChild*
|
||||
GetRemoteWorkerController();
|
||||
|
||||
void
|
||||
SetSharedWorkerManager(SharedWorkerManager* aWorkerManager);
|
||||
SetRemoteWorkerController(RemoteWorkerChild* aController);
|
||||
|
||||
// We can assume that an nsPIDOMWindow will be available for Freeze, Thaw
|
||||
// as these are only used for globals going in and out of the bfcache.
|
||||
|
@ -1393,7 +1393,7 @@ private:
|
|||
nsTArray<RefPtr<WorkerRunnable>> mPreStartRunnables;
|
||||
|
||||
// Only touched on the parent thread. This is set only if IsSharedWorker().
|
||||
RefPtr<SharedWorkerManager> mSharedWorkerManager;
|
||||
RefPtr<RemoteWorkerChild> mRemoteWorkerController;
|
||||
|
||||
JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init
|
||||
TimeStamp mKillTime;
|
||||
|
|
|
@ -4,9 +4,53 @@
|
|||
|
||||
include protocol PBackground;
|
||||
|
||||
include DOMTypes;
|
||||
include RemoteWorkerTypes;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct RemoteWorkerSuspendOp
|
||||
{};
|
||||
|
||||
struct RemoteWorkerResumeOp
|
||||
{};
|
||||
|
||||
struct RemoteWorkerFreezeOp
|
||||
{};
|
||||
|
||||
struct RemoteWorkerThawOp
|
||||
{};
|
||||
|
||||
struct RemoteWorkerTerminateOp
|
||||
{};
|
||||
|
||||
struct RemoteWorkerPortIdentifierOp
|
||||
{
|
||||
MessagePortIdentifier portIdentifier;
|
||||
};
|
||||
|
||||
struct RemoteWorkerAddWindowIDOp
|
||||
{
|
||||
uint64_t windowID;
|
||||
};
|
||||
|
||||
struct RemoteWorkerRemoveWindowIDOp
|
||||
{
|
||||
uint64_t windowID;
|
||||
};
|
||||
|
||||
union RemoteWorkerOp {
|
||||
RemoteWorkerSuspendOp;
|
||||
RemoteWorkerResumeOp;
|
||||
RemoteWorkerFreezeOp;
|
||||
RemoteWorkerThawOp;
|
||||
RemoteWorkerTerminateOp;
|
||||
RemoteWorkerPortIdentifierOp;
|
||||
RemoteWorkerAddWindowIDOp;
|
||||
RemoteWorkerRemoveWindowIDOp;
|
||||
};
|
||||
|
||||
// This protocol is used to make a remote worker controllable from the parent
|
||||
// process. The parent process will receive operations from the
|
||||
// PRemoteWorkerController protocol.
|
||||
|
@ -15,9 +59,16 @@ protocol PRemoteWorker
|
|||
manager PBackground;
|
||||
|
||||
parent:
|
||||
async Created(bool aStatus);
|
||||
|
||||
async Error(ErrorValue aValue);
|
||||
|
||||
async Close();
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
|
||||
async Created(bool aStatus);
|
||||
async ExecOp(RemoteWorkerOp op);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -5,14 +5,739 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "RemoteWorkerChild.h"
|
||||
#include "RemoteWorkerService.h"
|
||||
#include "mozilla/dom/IndexedDatabaseManager.h"
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/RemoteWorkerTypes.h"
|
||||
#include "mozilla/dom/ServiceWorkerInterceptController.h"
|
||||
#include "mozilla/dom/workerinternals/ScriptLoader.h"
|
||||
#include "mozilla/dom/WorkerError.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/WorkerRef.h"
|
||||
#include "mozilla/dom/WorkerRunnable.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "nsIConsoleReportCollector.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace ipc;
|
||||
|
||||
namespace dom {
|
||||
|
||||
RemoteWorkerChild::RemoteWorkerChild()
|
||||
{}
|
||||
using workerinternals::ChannelFromScriptURLMainThread;
|
||||
|
||||
RemoteWorkerChild::~RemoteWorkerChild() = default;
|
||||
namespace {
|
||||
|
||||
nsresult
|
||||
PopulateContentSecurityPolicy(nsIContentSecurityPolicy* aCSP,
|
||||
const nsTArray<ContentSecurityPolicy>& aPolicies)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aCSP);
|
||||
MOZ_ASSERT(!aPolicies.IsEmpty());
|
||||
|
||||
for (const ContentSecurityPolicy& policy : aPolicies) {
|
||||
nsresult rv = aCSP->AppendPolicy(policy.policy(),
|
||||
policy.reportOnlyFlag(),
|
||||
policy.deliveredViaMetaTagFlag());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PopulatePrincipalContentSecurityPolicy(nsIPrincipal* aPrincipal,
|
||||
const nsTArray<ContentSecurityPolicy>& aPolicies,
|
||||
const nsTArray<ContentSecurityPolicy>& aPreloadPolicies)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
if (!aPolicies.IsEmpty()) {
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
aPrincipal->EnsureCSP(nullptr, getter_AddRefs(csp));
|
||||
nsresult rv = PopulateContentSecurityPolicy(csp, aPolicies);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aPreloadPolicies.IsEmpty()) {
|
||||
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
|
||||
aPrincipal->EnsurePreloadCSP(nullptr, getter_AddRefs(preloadCsp));
|
||||
nsresult rv = PopulateContentSecurityPolicy(preloadCsp, aPreloadPolicies);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class SharedWorkerInterfaceRequestor final : public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
SharedWorkerInterfaceRequestor()
|
||||
: mSWController(new ServiceWorkerInterceptController())
|
||||
{}
|
||||
|
||||
NS_IMETHOD
|
||||
GetInterface(const nsIID& aIID, void** aSink) override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController))) {
|
||||
// If asked for the network intercept controller, ask the outer requestor,
|
||||
// which could be the docshell.
|
||||
RefPtr<ServiceWorkerInterceptController> swController = mSWController;
|
||||
swController.forget(aSink);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
private:
|
||||
~SharedWorkerInterfaceRequestor() = default;
|
||||
|
||||
RefPtr<ServiceWorkerInterceptController> mSWController;
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(SharedWorkerInterfaceRequestor)
|
||||
NS_IMPL_RELEASE(SharedWorkerInterfaceRequestor)
|
||||
NS_IMPL_QUERY_INTERFACE(SharedWorkerInterfaceRequestor, nsIInterfaceRequestor)
|
||||
|
||||
// Normal runnable because AddPortIdentifier() is going to exec JS code.
|
||||
class MessagePortIdentifierRunnable final : public WorkerRunnable
|
||||
{
|
||||
public:
|
||||
MessagePortIdentifierRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
RemoteWorkerChild* aActor,
|
||||
const MessagePortIdentifier& aPortIdentifier)
|
||||
: WorkerRunnable(aWorkerPrivate)
|
||||
, mActor(aActor)
|
||||
, mPortIdentifier(aPortIdentifier)
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
mActor->AddPortIdentifier(aCx, aWorkerPrivate, mPortIdentifier);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Cancel() override
|
||||
{
|
||||
MessagePort::ForceClose(mPortIdentifier);
|
||||
return WorkerRunnable::Cancel();
|
||||
}
|
||||
|
||||
virtual bool
|
||||
PreDispatch(WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
// Silence bad assertions.
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void
|
||||
PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
|
||||
{
|
||||
// Silence bad assertions.
|
||||
}
|
||||
|
||||
bool
|
||||
PreRun(WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
// Silence bad assertions.
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult) override
|
||||
{
|
||||
// Silence bad assertions.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
RefPtr<RemoteWorkerChild> mActor;
|
||||
MessagePortIdentifier mPortIdentifier;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
|
||||
class RemoteWorkerChild::InitializeWorkerRunnable final : public WorkerRunnable
|
||||
{
|
||||
public:
|
||||
InitializeWorkerRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
RemoteWorkerChild* aActor)
|
||||
: WorkerRunnable(aWorkerPrivate)
|
||||
, mActor(aActor)
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
mActor->InitializeOnWorker(aWorkerPrivate);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Cancel() override
|
||||
{
|
||||
mActor->CreationFailedOnAnyThread();
|
||||
mActor->ShutdownOnWorker();
|
||||
return WorkerRunnable::Cancel();
|
||||
}
|
||||
|
||||
RefPtr<RemoteWorkerChild> mActor;
|
||||
};
|
||||
|
||||
RemoteWorkerChild::RemoteWorkerChild()
|
||||
: mIPCActive(true)
|
||||
, mWorkerState(ePending)
|
||||
{
|
||||
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
|
||||
}
|
||||
|
||||
RemoteWorkerChild::~RemoteWorkerChild()
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
|
||||
NS_ProxyRelease("RemoteWorkerChild::mWorkerPrivate",
|
||||
target, mWorkerPrivate.forget());
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mIPCActive = false;
|
||||
mPendingOps.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::ExecWorker(const RemoteWorkerData& aData)
|
||||
{
|
||||
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
|
||||
MOZ_ASSERT(mIPCActive);
|
||||
|
||||
RefPtr<RemoteWorkerChild> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("RemoteWorkerChild::ExecWorker",
|
||||
[self, aData]() {
|
||||
nsresult rv = self->ExecWorkerOnMainThread(aData);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
self->CreationFailedOnAnyThread();
|
||||
}
|
||||
});
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult
|
||||
RemoteWorkerChild::ExecWorkerOnMainThread(const RemoteWorkerData& aData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Ensure that the IndexedDatabaseManager is initialized
|
||||
Unused << NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate());
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
PrincipalInfoToPrincipal(aData.principalInfo(), &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = PopulatePrincipalContentSecurityPolicy(principal,
|
||||
aData.principalCsp(),
|
||||
aData.principalPreloadCsp());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> loadingPrincipal =
|
||||
PrincipalInfoToPrincipal(aData.loadingPrincipalInfo(), &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = PopulatePrincipalContentSecurityPolicy(loadingPrincipal,
|
||||
aData.loadingPrincipalCsp(),
|
||||
aData.loadingPrincipalPreloadCsp());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
WorkerLoadInfo info;
|
||||
rv = NS_NewURI(getter_AddRefs(info.mBaseURI), aData.baseScriptURL(),
|
||||
nullptr, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = NS_NewURI(getter_AddRefs(info.mResolvedScriptURI),
|
||||
aData.resolvedScriptURL(), nullptr, info.mBaseURI);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
info.mPrincipalInfo = new PrincipalInfo(aData.principalInfo());
|
||||
|
||||
info.mDomain = aData.domain();
|
||||
info.mPrincipal = principal;
|
||||
info.mLoadingPrincipal = loadingPrincipal;
|
||||
|
||||
nsContentUtils::StorageAccess access =
|
||||
nsContentUtils::StorageAllowedForPrincipal(info.mPrincipal);
|
||||
info.mStorageAllowed =
|
||||
access > nsContentUtils::StorageAccess::ePrivateBrowsing;
|
||||
info.mOriginAttributes =
|
||||
BasePrincipal::Cast(principal)->OriginAttributesRef();
|
||||
|
||||
// Default CSP permissions for now. These will be overrided if necessary
|
||||
// based on the script CSP headers during load in ScriptLoader.
|
||||
info.mEvalAllowed = true;
|
||||
info.mReportCSPViolations = false;
|
||||
info.mSecureContext = aData.isSecureContext()
|
||||
? WorkerLoadInfo::eSecureContext : WorkerLoadInfo::eInsecureContext;
|
||||
|
||||
WorkerPrivate::OverrideLoadInfoLoadGroup(info, info.mLoadingPrincipal);
|
||||
|
||||
RefPtr<SharedWorkerInterfaceRequestor> requestor =
|
||||
new SharedWorkerInterfaceRequestor();
|
||||
info.mInterfaceRequestor->SetOuterRequestor(requestor);
|
||||
|
||||
rv = info.SetPrincipalOnMainThread(info.mPrincipal, info.mLoadGroup);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> clientInfo;
|
||||
if (aData.clientInfo().type() == OptionalIPCClientInfo::TIPCClientInfo) {
|
||||
clientInfo.emplace(ClientInfo(aData.clientInfo().get_IPCClientInfo()));
|
||||
}
|
||||
|
||||
// Top level workers' main script use the document charset for the script
|
||||
// uri encoding.
|
||||
rv = ChannelFromScriptURLMainThread(info.mLoadingPrincipal,
|
||||
info.mBaseURI,
|
||||
nullptr /* parent document */,
|
||||
info.mLoadGroup,
|
||||
aData.originalScriptURL(),
|
||||
clientInfo,
|
||||
aData.isSharedWorker()
|
||||
? nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER
|
||||
: nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER,
|
||||
false /* default encoding */,
|
||||
getter_AddRefs(info.mChannel));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
|
||||
ErrorResult error;
|
||||
mWorkerPrivate = WorkerPrivate::Constructor(jsapi.cx(),
|
||||
aData.originalScriptURL(),
|
||||
false,
|
||||
aData.isSharedWorker()
|
||||
? WorkerTypeShared
|
||||
: WorkerTypeService,
|
||||
aData.name(),
|
||||
VoidCString(),
|
||||
&info, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
RefPtr<InitializeWorkerRunnable> runnable =
|
||||
new InitializeWorkerRunnable(mWorkerPrivate, this);
|
||||
if (NS_WARN_IF(!runnable->Dispatch())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mWorkerPrivate->SetRemoteWorkerController(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::InitializeOnWorker(WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
RefPtr<RemoteWorkerChild> self = this;
|
||||
mWorkerRef = WeakWorkerRef::Create(mWorkerPrivate, [self]() {
|
||||
self->ShutdownOnWorker();
|
||||
});
|
||||
|
||||
if (NS_WARN_IF(!mWorkerRef)) {
|
||||
CreationFailedOnAnyThread();
|
||||
ShutdownOnWorker();
|
||||
return;
|
||||
}
|
||||
|
||||
CreationSucceededOnAnyThread();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::ShutdownOnWorker()
|
||||
{
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
// This will release the worker.
|
||||
mWorkerRef = nullptr;
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
|
||||
NS_ProxyRelease("RemoteWorkerChild::mWorkerPrivate",
|
||||
target, mWorkerPrivate.forget());
|
||||
|
||||
RefPtr<RemoteWorkerChild> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("RemoteWorkerChild::ShutdownOnWorker",
|
||||
[self]() {
|
||||
self->WorkerTerminated();
|
||||
});
|
||||
|
||||
RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::WorkerTerminated()
|
||||
{
|
||||
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
|
||||
|
||||
mWorkerState = eTerminated;
|
||||
mPendingOps.Clear();
|
||||
|
||||
if (!mIPCActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
Unused << SendClose();
|
||||
mIPCActive = false;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::ErrorPropagationDispatch(nsresult aError)
|
||||
{
|
||||
MOZ_ASSERT(NS_FAILED(aError));
|
||||
|
||||
RefPtr<RemoteWorkerChild> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("RemoteWorkerChild::ErrorPropagationDispatch",
|
||||
[self, aError]() {
|
||||
self->ErrorPropagation(aError);
|
||||
});
|
||||
|
||||
RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::ErrorPropagationOnMainThread(const WorkerErrorReport* aReport,
|
||||
bool aIsErrorEvent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ErrorValue value;
|
||||
if (aIsErrorEvent) {
|
||||
nsTArray<ErrorDataNote> notes;
|
||||
for (size_t i = 0, len = aReport->mNotes.Length(); i < len; i++) {
|
||||
const WorkerErrorNote& note = aReport->mNotes.ElementAt(i);
|
||||
notes.AppendElement(ErrorDataNote(note.mLineNumber, note.mColumnNumber,
|
||||
note.mMessage, note.mFilename));
|
||||
}
|
||||
|
||||
ErrorData data(aReport->mLineNumber,
|
||||
aReport->mColumnNumber,
|
||||
aReport->mFlags,
|
||||
aReport->mMessage,
|
||||
aReport->mFilename,
|
||||
aReport->mLine,
|
||||
notes);
|
||||
value = data;
|
||||
} else {
|
||||
value = void_t();
|
||||
}
|
||||
|
||||
RefPtr<RemoteWorkerChild> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("RemoteWorkerChild::ErrorPropagationOnMainThread",
|
||||
[self, value]() {
|
||||
self->ErrorPropagation(value);
|
||||
});
|
||||
|
||||
RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::ErrorPropagation(const ErrorValue& aValue)
|
||||
{
|
||||
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
|
||||
|
||||
if (!mIPCActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
Unused << SendError(aValue);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::CloseWorkerOnMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mWorkerState == ePending) {
|
||||
mWorkerState = ePendingTerminated;
|
||||
// Already released.
|
||||
return;
|
||||
}
|
||||
|
||||
// The holder will be notified by this.
|
||||
if (mWorkerState == eRunning) {
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
mWorkerPrivate->Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::FlushReportsOnMainThread(nsIConsoleReportCollector* aReporter)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
bool reportErrorToBrowserConsole = true;
|
||||
|
||||
// Flush the reports.
|
||||
for (uint32_t i = 0, len = mWindowIDs.Length(); i < len; ++i) {
|
||||
aReporter->FlushReportsToConsole(mWindowIDs[i],
|
||||
nsIConsoleReportCollector::ReportAction::Save);
|
||||
reportErrorToBrowserConsole = false;
|
||||
}
|
||||
|
||||
// Finally report to browser console if there is no any window.
|
||||
if (reportErrorToBrowserConsole) {
|
||||
aReporter->FlushReportsToConsole(0);
|
||||
return;
|
||||
}
|
||||
|
||||
aReporter->ClearConsoleReports();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
RemoteWorkerChild::RecvExecOp(const RemoteWorkerOp& aOp)
|
||||
{
|
||||
if (!mIPCActive) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// The worker is not ready yet.
|
||||
if (mWorkerState == ePending) {
|
||||
mPendingOps.AppendElement(aOp);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (mWorkerState == eTerminated || mWorkerState == ePendingTerminated) {
|
||||
// No op.
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mWorkerState == eRunning);
|
||||
|
||||
// Main-thread operations
|
||||
if (aOp.type() == RemoteWorkerOp::TRemoteWorkerSuspendOp ||
|
||||
aOp.type() == RemoteWorkerOp::TRemoteWorkerResumeOp ||
|
||||
aOp.type() == RemoteWorkerOp::TRemoteWorkerFreezeOp ||
|
||||
aOp.type() == RemoteWorkerOp::TRemoteWorkerThawOp ||
|
||||
aOp.type() == RemoteWorkerOp::TRemoteWorkerTerminateOp ||
|
||||
aOp.type() == RemoteWorkerOp::TRemoteWorkerAddWindowIDOp ||
|
||||
aOp.type() == RemoteWorkerOp::TRemoteWorkerRemoveWindowIDOp) {
|
||||
RefPtr<RemoteWorkerChild> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("RemoteWorkerChild::RecvExecOp",
|
||||
[self, aOp]() {
|
||||
self->RecvExecOpOnMainThread(aOp);
|
||||
});
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (aOp.type() == RemoteWorkerOp::TRemoteWorkerPortIdentifierOp) {
|
||||
const RemoteWorkerPortIdentifierOp& op =
|
||||
aOp.get_RemoteWorkerPortIdentifierOp();
|
||||
RefPtr<MessagePortIdentifierRunnable> runnable =
|
||||
new MessagePortIdentifierRunnable(mWorkerPrivate, this,
|
||||
op.portIdentifier());
|
||||
if (NS_WARN_IF(!runnable->Dispatch())) {
|
||||
ErrorPropagation(NS_ERROR_FAILURE);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
MOZ_CRASH("Unknown operation.");
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::RecvExecOpOnMainThread(const RemoteWorkerOp& aOp)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (aOp.type() == RemoteWorkerOp::TRemoteWorkerSuspendOp) {
|
||||
if (mWorkerPrivate) {
|
||||
mWorkerPrivate->ParentWindowPaused();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOp.type() == RemoteWorkerOp::TRemoteWorkerResumeOp) {
|
||||
if (mWorkerPrivate) {
|
||||
mWorkerPrivate->ParentWindowResumed();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOp.type() == RemoteWorkerOp::TRemoteWorkerFreezeOp) {
|
||||
if (mWorkerPrivate) {
|
||||
mWorkerPrivate->Freeze(nullptr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOp.type() == RemoteWorkerOp::TRemoteWorkerThawOp) {
|
||||
if (mWorkerPrivate) {
|
||||
mWorkerPrivate->Thaw(nullptr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOp.type() == RemoteWorkerOp::TRemoteWorkerTerminateOp) {
|
||||
CloseWorkerOnMainThread();
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOp.type() == RemoteWorkerOp::TRemoteWorkerAddWindowIDOp) {
|
||||
mWindowIDs.AppendElement(aOp.get_RemoteWorkerAddWindowIDOp().windowID());
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOp.type() == RemoteWorkerOp::TRemoteWorkerRemoveWindowIDOp) {
|
||||
mWindowIDs.RemoveElement(aOp.get_RemoteWorkerRemoveWindowIDOp().windowID());
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_CRASH("No other operations should be scheduled on main-thread.");
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::AddPortIdentifier(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
if (NS_WARN_IF(!aWorkerPrivate->ConnectMessagePort(aCx, aPortIdentifier))) {
|
||||
ErrorPropagationDispatch(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::CreationSucceededOnAnyThread()
|
||||
{
|
||||
RefPtr<RemoteWorkerChild> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("RemoteWorkerChild::CreationSucceededOnAnyThread",
|
||||
[self]() {
|
||||
self->CreationSucceeded();
|
||||
});
|
||||
|
||||
RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::CreationSucceeded()
|
||||
{
|
||||
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
|
||||
|
||||
// The worker is created but we need to terminate it already.
|
||||
if (mWorkerState == ePendingTerminated) {
|
||||
RefPtr<RemoteWorkerChild> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("RemoteWorkerChild::CreationSucceeded",
|
||||
[self]() {
|
||||
self->CloseWorkerOnMainThread();
|
||||
});
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
mWorkerState = eRunning;
|
||||
|
||||
if (!mIPCActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const RemoteWorkerOp& op : mPendingOps) {
|
||||
RecvExecOp(op);
|
||||
}
|
||||
|
||||
mPendingOps.Clear();
|
||||
|
||||
Unused << SendCreated(true);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::CreationFailedOnAnyThread()
|
||||
{
|
||||
RefPtr<RemoteWorkerChild> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("RemoteWorkerChild::CreationFailedOnAnyThread",
|
||||
[self]() {
|
||||
self->CreationFailed();
|
||||
});
|
||||
|
||||
RemoteWorkerService::Thread()->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerChild::CreationFailed()
|
||||
{
|
||||
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
|
||||
|
||||
mWorkerState = eTerminated;
|
||||
mPendingOps.Clear();
|
||||
|
||||
if (!mIPCActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
Unused << SendCreated(false);
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
|
|
@ -8,15 +8,117 @@
|
|||
#define mozilla_dom_RemoteWorkerChild_h
|
||||
|
||||
#include "mozilla/dom/PRemoteWorkerChild.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
class nsIConsoleReportCollector;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class RemoteWorkerData;
|
||||
class WeakWorkerRef;
|
||||
class WorkerErrorReport;
|
||||
class WorkerPrivate;
|
||||
class OptionalMessagePortIdentifier;
|
||||
|
||||
class RemoteWorkerChild final : public PRemoteWorkerChild
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteWorkerChild)
|
||||
|
||||
RemoteWorkerChild();
|
||||
|
||||
void
|
||||
ExecWorker(const RemoteWorkerData& aData);
|
||||
|
||||
void
|
||||
InitializeOnWorker(WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
void
|
||||
ShutdownOnWorker();
|
||||
|
||||
void
|
||||
AddPortIdentifier(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const MessagePortIdentifier& aPortIdentifier);
|
||||
|
||||
void
|
||||
ErrorPropagationOnMainThread(const WorkerErrorReport* aReport,
|
||||
bool aIsErrorEvent);
|
||||
|
||||
void
|
||||
CloseWorkerOnMainThread();
|
||||
|
||||
void
|
||||
FlushReportsOnMainThread(nsIConsoleReportCollector* aReporter);
|
||||
|
||||
private:
|
||||
class InitializeWorkerRunnable;
|
||||
|
||||
~RemoteWorkerChild();
|
||||
|
||||
void
|
||||
ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvExecOp(const RemoteWorkerOp& aOp) override;
|
||||
|
||||
void
|
||||
RecvExecOpOnMainThread(const RemoteWorkerOp& aOp);
|
||||
|
||||
nsresult
|
||||
ExecWorkerOnMainThread(const RemoteWorkerData& aData);
|
||||
|
||||
void
|
||||
ErrorPropagation(const ErrorValue& aValue);
|
||||
|
||||
void
|
||||
ErrorPropagationDispatch(nsresult aError);
|
||||
|
||||
void
|
||||
CreationSucceededOnAnyThread();
|
||||
|
||||
void
|
||||
CreationSucceeded();
|
||||
|
||||
void
|
||||
CreationFailedOnAnyThread();
|
||||
|
||||
void
|
||||
CreationFailed();
|
||||
|
||||
void
|
||||
WorkerTerminated();
|
||||
|
||||
// Touched on main-thread only.
|
||||
nsTArray<uint64_t> mWindowIDs;
|
||||
|
||||
RefPtr<WorkerPrivate> mWorkerPrivate;
|
||||
RefPtr<WeakWorkerRef> mWorkerRef;
|
||||
bool mIPCActive;
|
||||
|
||||
enum WorkerState
|
||||
{
|
||||
// CreationSucceeded/CreationFailed not called yet.
|
||||
ePending,
|
||||
|
||||
// The worker is not created yet, but we want to terminate as soon as
|
||||
// possible.
|
||||
ePendingTerminated,
|
||||
|
||||
// Worker up and running.
|
||||
eRunning,
|
||||
|
||||
// Worker terminated.
|
||||
eTerminated,
|
||||
};
|
||||
|
||||
// Touched only on the owning thread (PBackground).
|
||||
WorkerState mWorkerState;
|
||||
|
||||
// Touched only on the owning thread (PBackground).
|
||||
nsTArray<RemoteWorkerOp> mPendingOps;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
|
|
|
@ -4,9 +4,12 @@
|
|||
* 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/. */
|
||||
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/MessagePortParent.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "RemoteWorkerController.h"
|
||||
#include "RemoteWorkerManager.h"
|
||||
#include "RemoteWorkerParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -15,20 +18,17 @@ using namespace ipc;
|
|||
namespace dom {
|
||||
|
||||
/* static */ already_AddRefed<RemoteWorkerController>
|
||||
RemoteWorkerController::Create()
|
||||
RemoteWorkerController::Create(const RemoteWorkerData& aData)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
RefPtr<RemoteWorkerController> controller = new RemoteWorkerController();
|
||||
|
||||
// This will be populated, eventually.
|
||||
RemoteWorkerData data;
|
||||
|
||||
RefPtr<RemoteWorkerManager> manager = RemoteWorkerManager::GetOrCreate();
|
||||
MOZ_ASSERT(manager);
|
||||
|
||||
manager->Launch(controller, data);
|
||||
manager->Launch(controller, aData);
|
||||
|
||||
return controller.forget();
|
||||
}
|
||||
|
@ -62,10 +62,11 @@ RemoteWorkerController::CreationFailed()
|
|||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mState == ePending || mState == eTerminated);
|
||||
|
||||
mState = eTerminated;
|
||||
mActor = nullptr;
|
||||
// TODO: maybe notification?
|
||||
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -73,11 +74,260 @@ RemoteWorkerController::CreationSucceeded()
|
|||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(mState == ePending || mState == eTerminated);
|
||||
|
||||
if (mState == eTerminated) {
|
||||
MOZ_ASSERT(!mActor);
|
||||
MOZ_ASSERT(mPendingOps.IsEmpty());
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mActor);
|
||||
mState = eReady;
|
||||
|
||||
// TODO: flush the pending op queue.
|
||||
// TODO: maybe notification?
|
||||
|
||||
for (UniquePtr<Op>& op : mPendingOps) {
|
||||
switch (op->mType) {
|
||||
case Op::eTerminate:
|
||||
Terminate();
|
||||
break;
|
||||
|
||||
case Op::eSuspend:
|
||||
Suspend();
|
||||
break;
|
||||
|
||||
case Op::eResume:
|
||||
Resume();
|
||||
break;
|
||||
|
||||
case Op::eFreeze:
|
||||
Freeze();
|
||||
break;
|
||||
|
||||
case Op::eThaw:
|
||||
Thaw();
|
||||
break;
|
||||
|
||||
case Op::ePortIdentifier:
|
||||
AddPortIdentifier(op->mPortIdentifier);
|
||||
break;
|
||||
|
||||
case Op::eAddWindowID:
|
||||
AddWindowID(op->mWindowID);
|
||||
break;
|
||||
|
||||
case Op::eRemoveWindowID:
|
||||
RemoveWindowID(op->mWindowID);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown op.");
|
||||
}
|
||||
|
||||
op->Completed();
|
||||
}
|
||||
|
||||
mPendingOps.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::ErrorPropagation(const ErrorValue& aValue)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
// TODO: error propagation
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::WorkerTerminated()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(mState == eReady);
|
||||
|
||||
// TODO: worker terminated
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::Shutdown()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(mState == ePending || mState == eReady);
|
||||
|
||||
mState = eTerminated;
|
||||
|
||||
mPendingOps.Clear();
|
||||
|
||||
if (mActor) {
|
||||
mActor->SetController(nullptr);
|
||||
Unused << mActor->SendExecOp(RemoteWorkerTerminateOp());
|
||||
mActor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::AddWindowID(uint64_t aWindowID)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(aWindowID);
|
||||
|
||||
if (mState == ePending) {
|
||||
mPendingOps.AppendElement(new Op(Op::eAddWindowID, aWindowID));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == eTerminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == eReady);
|
||||
Unused << mActor->SendExecOp(RemoteWorkerAddWindowIDOp(aWindowID));
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::RemoveWindowID(uint64_t aWindowID)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(aWindowID);
|
||||
|
||||
if (mState == ePending) {
|
||||
mPendingOps.AppendElement(new Op(Op::eRemoveWindowID, aWindowID));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == eTerminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == eReady);
|
||||
Unused << mActor->SendExecOp(RemoteWorkerRemoveWindowIDOp(aWindowID));
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::AddPortIdentifier(const MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
if (mState == ePending) {
|
||||
mPendingOps.AppendElement(new Op(aPortIdentifier));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == eTerminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == eReady);
|
||||
Unused << mActor->SendExecOp(RemoteWorkerPortIdentifierOp(aPortIdentifier));
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::Terminate()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
if (mState == eTerminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::Suspend()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
if (mState == ePending) {
|
||||
mPendingOps.AppendElement(new Op(Op::eSuspend));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == eTerminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == eReady);
|
||||
Unused << mActor->SendExecOp(RemoteWorkerSuspendOp());
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::Resume()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
if (mState == ePending) {
|
||||
mPendingOps.AppendElement(new Op(Op::eResume));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == eTerminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == eReady);
|
||||
Unused << mActor->SendExecOp(RemoteWorkerResumeOp());
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::Freeze()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
if (mState == ePending) {
|
||||
mPendingOps.AppendElement(new Op(Op::eFreeze));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == eTerminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == eReady);
|
||||
Unused << mActor->SendExecOp(RemoteWorkerFreezeOp());
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerController::Thaw()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
if (mState == ePending) {
|
||||
mPendingOps.AppendElement(new Op(Op::eThaw));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == eTerminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == eReady);
|
||||
Unused << mActor->SendExecOp(RemoteWorkerThawOp());
|
||||
}
|
||||
|
||||
RemoteWorkerController::Op::~Op()
|
||||
{
|
||||
MOZ_COUNT_DTOR(Op);
|
||||
|
||||
// We don't want to leak the port if the operation has not been processed.
|
||||
if (!mCompleted && mType == ePortIdentifier) {
|
||||
MessagePortParent::ForceClose(mPortIdentifier.uuid(),
|
||||
mPortIdentifier.destinationUuid(),
|
||||
mPortIdentifier.sequenceId());
|
||||
}
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
|
|
|
@ -78,6 +78,8 @@ namespace dom {
|
|||
* In case there were pending operations, they are now executed.
|
||||
*/
|
||||
|
||||
class ErrorValue;
|
||||
class MessagePortIdentifier;
|
||||
class RemoteWorkerManager;
|
||||
class RemoteWorkerParent;
|
||||
|
||||
|
@ -90,7 +92,31 @@ public:
|
|||
NS_INLINE_DECL_REFCOUNTING(RemoteWorkerController)
|
||||
|
||||
static already_AddRefed<RemoteWorkerController>
|
||||
Create(); // TODO parameters?
|
||||
Create(const RemoteWorkerData& aData);
|
||||
|
||||
void
|
||||
AddWindowID(uint64_t aWindowID);
|
||||
|
||||
void
|
||||
RemoveWindowID(uint64_t aWindowID);
|
||||
|
||||
void
|
||||
AddPortIdentifier(const MessagePortIdentifier& aPortIdentifier);
|
||||
|
||||
void
|
||||
Terminate();
|
||||
|
||||
void
|
||||
Suspend();
|
||||
|
||||
void
|
||||
Resume();
|
||||
|
||||
void
|
||||
Freeze();
|
||||
|
||||
void
|
||||
Thaw();
|
||||
|
||||
private:
|
||||
RemoteWorkerController();
|
||||
|
@ -99,6 +125,15 @@ private:
|
|||
void
|
||||
SetWorkerActor(RemoteWorkerParent* aActor);
|
||||
|
||||
void
|
||||
ErrorPropagation(const ErrorValue& aValue);
|
||||
|
||||
void
|
||||
WorkerTerminated();
|
||||
|
||||
void
|
||||
Shutdown();
|
||||
|
||||
void
|
||||
CreationFailed();
|
||||
|
||||
|
@ -112,6 +147,55 @@ private:
|
|||
} mState;
|
||||
|
||||
RefPtr<RemoteWorkerParent> mActor;
|
||||
|
||||
struct Op {
|
||||
enum Type {
|
||||
eTerminate,
|
||||
eSuspend,
|
||||
eResume,
|
||||
eFreeze,
|
||||
eThaw,
|
||||
ePortIdentifier,
|
||||
eAddWindowID,
|
||||
eRemoveWindowID,
|
||||
};
|
||||
|
||||
explicit Op(Type aType, uint64_t aWindowID = 0)
|
||||
: mType(aType)
|
||||
, mWindowID(aWindowID)
|
||||
, mCompleted(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(Op);
|
||||
}
|
||||
|
||||
explicit Op(const MessagePortIdentifier& aPortIdentifier)
|
||||
: mType(ePortIdentifier)
|
||||
, mPortIdentifier(aPortIdentifier)
|
||||
, mCompleted(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(Op);
|
||||
}
|
||||
|
||||
// This object cannot be copied.
|
||||
Op(Op const&) = delete;
|
||||
Op& operator=(Op const&) = delete;
|
||||
|
||||
~Op();
|
||||
|
||||
void
|
||||
Completed()
|
||||
{
|
||||
mCompleted = true;
|
||||
}
|
||||
|
||||
Type mType;
|
||||
|
||||
MessagePortIdentifier mPortIdentifier;
|
||||
uint64_t mWindowID;
|
||||
bool mCompleted;
|
||||
};
|
||||
|
||||
nsTArray<UniquePtr<Op>> mPendingOps;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "RemoteWorkerParent.h"
|
||||
#include "RemoteWorkerController.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -54,6 +55,33 @@ RemoteWorkerParent::RecvCreated(const bool& aStatus)
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
RemoteWorkerParent::RecvError(const ErrorValue& aValue)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
if (mController) {
|
||||
mController->ErrorPropagation(aValue);
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
RemoteWorkerParent::RecvClose()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
if (mController) {
|
||||
mController->WorkerTerminated();
|
||||
}
|
||||
|
||||
Unused << Send__delete__(this);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteWorkerParent::SetController(RemoteWorkerController* aController)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,12 @@ private:
|
|||
void
|
||||
ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason) override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvError(const ErrorValue& aValue) override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvClose() override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvCreated(const bool& aStatus) override;
|
||||
|
||||
|
|
|
@ -69,6 +69,15 @@ RemoteWorkerService::Initialize()
|
|||
sRemoteWorkerService = service;
|
||||
}
|
||||
|
||||
/* static */ nsIThread*
|
||||
RemoteWorkerService::Thread()
|
||||
{
|
||||
StaticMutexAutoLock lock(sRemoteWorkerServiceMutex);
|
||||
MOZ_ASSERT(sRemoteWorkerService);
|
||||
MOZ_ASSERT(sRemoteWorkerService->mThread);
|
||||
return sRemoteWorkerService->mThread;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RemoteWorkerService::InitializeOnMainThread()
|
||||
{
|
||||
|
|
|
@ -27,6 +27,9 @@ public:
|
|||
static void
|
||||
Initialize();
|
||||
|
||||
static nsIThread*
|
||||
Thread();
|
||||
|
||||
private:
|
||||
RemoteWorkerService();
|
||||
~RemoteWorkerService();
|
||||
|
|
|
@ -2,11 +2,73 @@
|
|||
* 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/. */
|
||||
|
||||
include ClientIPCTypes;
|
||||
include PBackgroundSharedTypes;
|
||||
|
||||
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct ContentSecurityPolicy
|
||||
{
|
||||
nsString policy;
|
||||
bool reportOnlyFlag;
|
||||
bool deliveredViaMetaTagFlag;
|
||||
};
|
||||
|
||||
struct RemoteWorkerData
|
||||
{
|
||||
nsString originalScriptURL;
|
||||
nsCString baseScriptURL;
|
||||
nsCString resolvedScriptURL;
|
||||
|
||||
nsString name;
|
||||
|
||||
PrincipalInfo loadingPrincipalInfo;
|
||||
ContentSecurityPolicy[] loadingPrincipalCsp;
|
||||
ContentSecurityPolicy[] loadingPrincipalPreloadCsp;
|
||||
|
||||
PrincipalInfo principalInfo;
|
||||
ContentSecurityPolicy[] principalCsp;
|
||||
ContentSecurityPolicy[] principalPreloadCsp;
|
||||
|
||||
nsCString domain;
|
||||
|
||||
bool isSecureContext;
|
||||
|
||||
OptionalIPCClientInfo clientInfo;
|
||||
|
||||
bool isSharedWorker;
|
||||
};
|
||||
|
||||
// ErrorData/ErrorDataNote correspond to WorkerErrorReport/WorkerErrorNote
|
||||
// which in turn correspond to JSErrorReport/JSErrorNotes which allows JS to
|
||||
// report complicated errors such as redeclarations that involve multiple
|
||||
// distinct lines. For more generic error-propagation IPC structures, see bug
|
||||
// 1357463 on making ErrorResult usable over IPC.
|
||||
|
||||
struct ErrorDataNote {
|
||||
uint32_t lineNumber;
|
||||
uint32_t columnNumber;
|
||||
nsString message;
|
||||
nsString filename;
|
||||
};
|
||||
|
||||
struct ErrorData {
|
||||
uint32_t lineNumber;
|
||||
uint32_t columnNumber;
|
||||
uint32_t flags;
|
||||
nsString message;
|
||||
nsString filename;
|
||||
nsString line;
|
||||
ErrorDataNote[] notes;
|
||||
};
|
||||
|
||||
union ErrorValue {
|
||||
nsresult;
|
||||
ErrorData;
|
||||
void_t;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
include protocol PBackground;
|
||||
|
||||
include SharedWorkerTypes;
|
||||
include RemoteWorkerTypes;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/nsCSPUtils.h"
|
||||
#include "mozilla/dom/PMessagePort.h"
|
||||
#include "mozilla/dom/RemoteWorkerTypes.h"
|
||||
#include "mozilla/dom/SharedWorkerBinding.h"
|
||||
#include "mozilla/dom/SharedWorkerChild.h"
|
||||
#include "mozilla/dom/WorkerBinding.h"
|
||||
|
@ -247,7 +248,7 @@ SharedWorker::Constructor(const GlobalObject& aGlobal,
|
|||
ipcClientInfo = void_t();
|
||||
}
|
||||
|
||||
SharedWorkerLoadInfo sharedWorkerLoadInfo(nsString(aScriptURL),
|
||||
RemoteWorkerData remoteWorkerData(nsString(aScriptURL),
|
||||
baseURL,
|
||||
resolvedScriptURL,
|
||||
name,
|
||||
|
@ -259,12 +260,13 @@ SharedWorker::Constructor(const GlobalObject& aGlobal,
|
|||
principalPreloadCSP,
|
||||
loadInfo.mDomain,
|
||||
isSecureContext,
|
||||
loadInfo.mWindowID,
|
||||
ipcClientInfo,
|
||||
portIdentifier);
|
||||
true /* sharedWorker */);
|
||||
|
||||
PSharedWorkerChild* pActor =
|
||||
actorChild->SendPSharedWorkerConstructor(sharedWorkerLoadInfo);
|
||||
actorChild->SendPSharedWorkerConstructor(remoteWorkerData,
|
||||
loadInfo.mWindowID,
|
||||
portIdentifier);
|
||||
|
||||
RefPtr<SharedWorkerChild> actor = static_cast<SharedWorkerChild*>(pActor);
|
||||
MOZ_ASSERT(actor);
|
||||
|
|
|
@ -7,103 +7,28 @@
|
|||
#include "SharedWorkerManager.h"
|
||||
#include "SharedWorkerParent.h"
|
||||
#include "SharedWorkerService.h"
|
||||
#include "mozilla/dom/IndexedDatabaseManager.h"
|
||||
#include "mozilla/dom/PSharedWorker.h"
|
||||
#include "mozilla/dom/ServiceWorkerInterceptController.h"
|
||||
#include "mozilla/dom/WorkerError.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/WorkerRunnable.h"
|
||||
#include "mozilla/dom/workerinternals/ScriptLoader.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/dom/RemoteWorkerController.h"
|
||||
#include "nsIConsoleReportCollector.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using workerinternals::ChannelFromScriptURLMainThread;
|
||||
|
||||
namespace {
|
||||
|
||||
class MessagePortRunnable final : public WorkerRunnable
|
||||
{
|
||||
MessagePortIdentifier mPortIdentifier;
|
||||
|
||||
public:
|
||||
MessagePortRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const MessagePortIdentifier& aPortIdentifier)
|
||||
: WorkerRunnable(aWorkerPrivate)
|
||||
, mPortIdentifier(aPortIdentifier)
|
||||
{}
|
||||
|
||||
private:
|
||||
~MessagePortRunnable() = default;
|
||||
|
||||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
return aWorkerPrivate->ConnectMessagePort(aCx, mPortIdentifier);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Cancel() override
|
||||
{
|
||||
MessagePort::ForceClose(mPortIdentifier);
|
||||
return WorkerRunnable::Cancel();
|
||||
}
|
||||
};
|
||||
|
||||
class SharedWorkerInterfaceRequestor final : public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
SharedWorkerInterfaceRequestor()
|
||||
: mSWController(new ServiceWorkerInterceptController())
|
||||
{}
|
||||
|
||||
NS_IMETHOD
|
||||
GetInterface(const nsIID& aIID, void** aSink) override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController))) {
|
||||
// If asked for the network intercept controller, ask the outer requestor,
|
||||
// which could be the docshell.
|
||||
RefPtr<ServiceWorkerInterceptController> swController = mSWController;
|
||||
swController.forget(aSink);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
private:
|
||||
~SharedWorkerInterfaceRequestor() = default;
|
||||
|
||||
RefPtr<ServiceWorkerInterceptController> mSWController;
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(SharedWorkerInterfaceRequestor)
|
||||
NS_IMPL_RELEASE(SharedWorkerInterfaceRequestor)
|
||||
NS_IMPL_QUERY_INTERFACE(SharedWorkerInterfaceRequestor, nsIInterfaceRequestor)
|
||||
|
||||
} // anonymous
|
||||
|
||||
SharedWorkerManager::SharedWorkerManager(nsIEventTarget* aPBackgroundEventTarget,
|
||||
const SharedWorkerLoadInfo& aInfo,
|
||||
nsIPrincipal* aPrincipal,
|
||||
const RemoteWorkerData& aData,
|
||||
nsIPrincipal* aLoadingPrincipal)
|
||||
: mPBackgroundEventTarget(aPBackgroundEventTarget)
|
||||
, mInfo(aInfo)
|
||||
, mPrincipal(aPrincipal)
|
||||
, mLoadingPrincipal(aLoadingPrincipal)
|
||||
, mDomain(aData.domain())
|
||||
, mResolvedScriptURL(aData.resolvedScriptURL())
|
||||
, mName(aData.name())
|
||||
, mIsSecureContext(aData.isSecureContext())
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT(aLoadingPrincipal);
|
||||
}
|
||||
|
||||
|
@ -112,124 +37,32 @@ SharedWorkerManager::~SharedWorkerManager()
|
|||
nsCOMPtr<nsIEventTarget> target =
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
|
||||
NS_ProxyRelease("SharedWorkerManager::mPrincipal",
|
||||
target, mPrincipal.forget());
|
||||
NS_ProxyRelease("SharedWorkerManager::mLoadingPrincipal",
|
||||
target, mLoadingPrincipal.forget());
|
||||
NS_ProxyRelease("SharedWorkerManager::mWorkerPrivate",
|
||||
target, mWorkerPrivate.forget());
|
||||
NS_ProxyRelease("SharedWorkerManager::mRemoteWorkerController",
|
||||
mPBackgroundEventTarget, mRemoteWorkerController.forget());
|
||||
}
|
||||
|
||||
nsresult
|
||||
SharedWorkerManager::CreateWorkerOnMainThread()
|
||||
bool
|
||||
SharedWorkerManager::MaybeCreateRemoteWorker(const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
// Ensure that the IndexedDatabaseManager is initialized
|
||||
Unused << NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate());
|
||||
|
||||
WorkerLoadInfo info;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(info.mBaseURI),
|
||||
mInfo.baseScriptURL(),
|
||||
nullptr, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
if (!mRemoteWorkerController) {
|
||||
mRemoteWorkerController = RemoteWorkerController::Create(aData);
|
||||
if (NS_WARN_IF(!mRemoteWorkerController)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
rv = NS_NewURI(getter_AddRefs(info.mResolvedScriptURI),
|
||||
mInfo.resolvedScriptURL(), nullptr, info.mBaseURI);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
if (aWindowID) {
|
||||
mRemoteWorkerController->AddWindowID(aWindowID);
|
||||
}
|
||||
|
||||
info.mPrincipalInfo = new PrincipalInfo();
|
||||
rv = PrincipalToPrincipalInfo(mPrincipal, info.mPrincipalInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
info.mResolvedScriptURI = info.mBaseURI;
|
||||
|
||||
info.mDomain = mInfo.domain();
|
||||
info.mPrincipal = mPrincipal;
|
||||
info.mLoadingPrincipal = mLoadingPrincipal;
|
||||
|
||||
nsContentUtils::StorageAccess access =
|
||||
nsContentUtils::StorageAllowedForPrincipal(info.mPrincipal);
|
||||
info.mStorageAllowed =
|
||||
access > nsContentUtils::StorageAccess::ePrivateBrowsing;
|
||||
info.mOriginAttributes =
|
||||
BasePrincipal::Cast(mPrincipal)->OriginAttributesRef();
|
||||
|
||||
// Default CSP permissions for now. These will be overrided if necessary
|
||||
// based on the script CSP headers during load in ScriptLoader.
|
||||
info.mEvalAllowed = true;
|
||||
info.mReportCSPViolations = false;
|
||||
info.mSecureContext = mInfo.isSecureContext()
|
||||
? WorkerLoadInfo::eSecureContext : WorkerLoadInfo::eInsecureContext;
|
||||
|
||||
WorkerPrivate::OverrideLoadInfoLoadGroup(info, info.mLoadingPrincipal);
|
||||
|
||||
RefPtr<SharedWorkerInterfaceRequestor> requestor =
|
||||
new SharedWorkerInterfaceRequestor();
|
||||
info.mInterfaceRequestor->SetOuterRequestor(requestor);
|
||||
|
||||
rv = info.SetPrincipalOnMainThread(info.mPrincipal, info.mLoadGroup);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> clientInfo;
|
||||
if (mInfo.clientInfo().type() == OptionalIPCClientInfo::TIPCClientInfo) {
|
||||
clientInfo.emplace(ClientInfo(mInfo.clientInfo().get_IPCClientInfo()));
|
||||
}
|
||||
|
||||
// Top level workers' main script use the document charset for the script
|
||||
// uri encoding.
|
||||
rv = ChannelFromScriptURLMainThread(info.mLoadingPrincipal,
|
||||
info.mBaseURI,
|
||||
nullptr /* parent document */,
|
||||
info.mLoadGroup,
|
||||
mInfo.originalScriptURL(),
|
||||
clientInfo,
|
||||
nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER,
|
||||
false /* default encoding */,
|
||||
getter_AddRefs(info.mChannel));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
|
||||
ErrorResult error;
|
||||
mWorkerPrivate = WorkerPrivate::Constructor(jsapi.cx(),
|
||||
mInfo.originalScriptURL(),
|
||||
false,
|
||||
WorkerTypeShared,
|
||||
mInfo.name(),
|
||||
VoidCString(),
|
||||
&info, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
mWorkerPrivate->SetSharedWorkerManager(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SharedWorkerManager::ConnectPortOnMainThread(const MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<MessagePortRunnable> runnable =
|
||||
new MessagePortRunnable(mWorkerPrivate, aPortIdentifier);
|
||||
if (NS_WARN_IF(!runnable->Dispatch())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
mRemoteWorkerController->AddPortIdentifier(aPortIdentifier);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -239,9 +72,9 @@ SharedWorkerManager::MatchOnMainThread(const nsACString& aDomain,
|
|||
nsIPrincipal* aLoadingPrincipal) const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return aDomain == mInfo.domain() &&
|
||||
aScriptURL == mInfo.resolvedScriptURL() &&
|
||||
aName == mInfo.name() &&
|
||||
return aDomain == mDomain &&
|
||||
aScriptURL == mResolvedScriptURL &&
|
||||
aName == mName &&
|
||||
// We want to be sure that the window's principal subsumes the
|
||||
// SharedWorker's loading principal and vice versa.
|
||||
mLoadingPrincipal->Subsumes(aLoadingPrincipal) &&
|
||||
|
@ -255,7 +88,21 @@ SharedWorkerManager::AddActor(SharedWorkerParent* aParent)
|
|||
MOZ_ASSERT(aParent);
|
||||
MOZ_ASSERT(!mActors.Contains(aParent));
|
||||
|
||||
uint32_t frozen = 0;
|
||||
|
||||
for (SharedWorkerParent* actor : mActors) {
|
||||
if (actor->IsFrozen()) {
|
||||
++frozen;
|
||||
}
|
||||
}
|
||||
|
||||
bool hadActors = !mActors.IsEmpty();
|
||||
|
||||
mActors.AppendElement(aParent);
|
||||
|
||||
if (hadActors && frozen == mActors.Length() - 1) {
|
||||
mRemoteWorkerController->Thaw();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -265,6 +112,11 @@ SharedWorkerManager::RemoveActor(SharedWorkerParent* aParent)
|
|||
MOZ_ASSERT(aParent);
|
||||
MOZ_ASSERT(mActors.Contains(aParent));
|
||||
|
||||
uint64_t windowID = aParent->WindowID();
|
||||
if (windowID) {
|
||||
mRemoteWorkerController->RemoveWindowID(windowID);
|
||||
}
|
||||
|
||||
mActors.RemoveElement(aParent);
|
||||
|
||||
if (!mActors.IsEmpty()) {
|
||||
|
@ -273,16 +125,8 @@ SharedWorkerManager::RemoveActor(SharedWorkerParent* aParent)
|
|||
|
||||
// Time to go.
|
||||
|
||||
RefPtr<SharedWorkerManager> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("SharedWorkerManager::RemoveActor",
|
||||
[self]() {
|
||||
self->CloseOnMainThread();
|
||||
});
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
mRemoteWorkerController->Terminate();
|
||||
mRemoteWorkerController = nullptr;
|
||||
|
||||
// SharedWorkerService exists because it is kept alive by SharedWorkerParent.
|
||||
SharedWorkerService::Get()->RemoveWorkerManager(this);
|
||||
|
@ -292,6 +136,7 @@ void
|
|||
SharedWorkerManager::UpdateSuspend()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mRemoteWorkerController);
|
||||
|
||||
uint32_t suspended = 0;
|
||||
|
||||
|
@ -305,26 +150,18 @@ SharedWorkerManager::UpdateSuspend()
|
|||
return;
|
||||
}
|
||||
|
||||
RefPtr<SharedWorkerManager> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("SharedWorkerManager::UpdateSuspend",
|
||||
[self, suspended]() {
|
||||
if (suspended) {
|
||||
self->SuspendOnMainThread();
|
||||
mRemoteWorkerController->Suspend();
|
||||
} else {
|
||||
self->ResumeOnMainThread();
|
||||
mRemoteWorkerController->Resume();
|
||||
}
|
||||
});
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
SharedWorkerManager::UpdateFrozen()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mRemoteWorkerController);
|
||||
|
||||
uint32_t frozen = 0;
|
||||
|
||||
|
@ -338,94 +175,20 @@ SharedWorkerManager::UpdateFrozen()
|
|||
return;
|
||||
}
|
||||
|
||||
RefPtr<SharedWorkerManager> self = this;
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("SharedWorkerManager::UpdateFrozen",
|
||||
[self, frozen]() {
|
||||
if (frozen) {
|
||||
self->FreezeOnMainThread();
|
||||
mRemoteWorkerController->Freeze();
|
||||
} else {
|
||||
self->ThawOnMainThread();
|
||||
mRemoteWorkerController->Thaw();
|
||||
}
|
||||
});
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
bool
|
||||
SharedWorkerManager::IsSecureContext() const
|
||||
{
|
||||
return mInfo.isSecureContext();
|
||||
}
|
||||
|
||||
void
|
||||
SharedWorkerManager::FreezeOnMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mWorkerPrivate || mWorkerPrivate->IsFrozen()) {
|
||||
// Already released.
|
||||
return;
|
||||
}
|
||||
|
||||
mWorkerPrivate->Freeze(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
SharedWorkerManager::ThawOnMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mWorkerPrivate || !mWorkerPrivate->IsFrozen()) {
|
||||
// Already released.
|
||||
return;
|
||||
}
|
||||
|
||||
mWorkerPrivate->Thaw(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
SharedWorkerManager::SuspendOnMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mWorkerPrivate) {
|
||||
// Already released.
|
||||
return;
|
||||
}
|
||||
|
||||
mWorkerPrivate->ParentWindowPaused();
|
||||
}
|
||||
|
||||
void
|
||||
SharedWorkerManager::ResumeOnMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mWorkerPrivate) {
|
||||
// Already released.
|
||||
return;
|
||||
}
|
||||
|
||||
mWorkerPrivate->ParentWindowResumed();
|
||||
}
|
||||
|
||||
void
|
||||
SharedWorkerManager::CloseOnMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mWorkerPrivate) {
|
||||
// Already released.
|
||||
return;
|
||||
}
|
||||
|
||||
mWorkerPrivate->Cancel();
|
||||
mWorkerPrivate = nullptr;
|
||||
return mIsSecureContext;
|
||||
}
|
||||
|
||||
/* TODO
|
||||
void
|
||||
SharedWorkerManager::BroadcastErrorToActorsOnMainThread(const WorkerErrorReport* aReport,
|
||||
bool aIsErrorEvent)
|
||||
|
@ -530,6 +293,7 @@ SharedWorkerManager::FlushReportsToActorsOnMainThread(nsIConsoleReportCollector*
|
|||
|
||||
aReporter->ClearConsoleReports();
|
||||
}
|
||||
*/
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
|
|
@ -7,21 +7,18 @@
|
|||
#ifndef mozilla_dom_SharedWorkerManager_h
|
||||
#define mozilla_dom_SharedWorkerManager_h
|
||||
|
||||
#include "mozilla/dom/SharedWorkerTypes.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIConsoleReportCollector;
|
||||
class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ErrorValue;
|
||||
class SharedWorkerLoadInfo;
|
||||
class MessagePortIdentifier;
|
||||
class RemoteWorkerData;
|
||||
class RemoteWorkerController;
|
||||
class SharedWorkerParent;
|
||||
class WorkerErrorReport;
|
||||
class WorkerPrivate;
|
||||
|
||||
class SharedWorkerManager final
|
||||
{
|
||||
|
@ -31,49 +28,22 @@ public:
|
|||
// Called on main-thread thread methods
|
||||
|
||||
SharedWorkerManager(nsIEventTarget* aPBackgroundEventTarget,
|
||||
const SharedWorkerLoadInfo& aInfo,
|
||||
nsIPrincipal* aPrincipal,
|
||||
const RemoteWorkerData& aData,
|
||||
nsIPrincipal* aLoadingPrincipal);
|
||||
|
||||
nsresult
|
||||
CreateWorkerOnMainThread();
|
||||
|
||||
nsresult
|
||||
ConnectPortOnMainThread(const MessagePortIdentifier& aPortIdentifier);
|
||||
|
||||
bool
|
||||
MatchOnMainThread(const nsACString& aDomain,
|
||||
const nsACString& aScriptURL,
|
||||
const nsAString& aName,
|
||||
nsIPrincipal* aLoadingPrincipal) const;
|
||||
|
||||
void
|
||||
CloseOnMainThread();
|
||||
|
||||
void
|
||||
FreezeOnMainThread();
|
||||
|
||||
void
|
||||
ThawOnMainThread();
|
||||
|
||||
void
|
||||
SuspendOnMainThread();
|
||||
|
||||
void
|
||||
ResumeOnMainThread();
|
||||
|
||||
void
|
||||
BroadcastErrorToActorsOnMainThread(const WorkerErrorReport* aReport,
|
||||
bool aIsErrorEvent);
|
||||
|
||||
void
|
||||
CloseActorsOnMainThread();
|
||||
|
||||
void
|
||||
FlushReportsToActorsOnMainThread(nsIConsoleReportCollector* aReporter);
|
||||
|
||||
// Called on PBackground thread methods
|
||||
|
||||
bool
|
||||
MaybeCreateRemoteWorker(const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier);
|
||||
|
||||
void
|
||||
AddActor(SharedWorkerParent* aParent);
|
||||
|
||||
|
@ -89,27 +59,21 @@ public:
|
|||
bool
|
||||
IsSecureContext() const;
|
||||
|
||||
void
|
||||
CloseActors();
|
||||
|
||||
void
|
||||
BroadcastErrorToActors(const ErrorValue& aValue);
|
||||
|
||||
private:
|
||||
~SharedWorkerManager();
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mPBackgroundEventTarget;
|
||||
|
||||
SharedWorkerLoadInfo mInfo;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
|
||||
nsCString mDomain;
|
||||
nsCString mResolvedScriptURL;
|
||||
nsString mName;
|
||||
bool mIsSecureContext;
|
||||
|
||||
// Raw pointers because SharedWorkerParent unregisters itself in ActorDestroy().
|
||||
nsTArray<SharedWorkerParent*> mActors;
|
||||
|
||||
// With this patch, SharedWorker are executed on the parent process.
|
||||
// This is going to change in the following parts.
|
||||
RefPtr<WorkerPrivate> mWorkerPrivate;
|
||||
RefPtr<RemoteWorkerController> mRemoteWorkerController;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "SharedWorkerParent.h"
|
||||
#include "SharedWorkerManager.h"
|
||||
#include "SharedWorkerService.h"
|
||||
#include "mozilla/dom/RemoteWorkerTypes.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
@ -20,7 +21,6 @@ namespace dom {
|
|||
SharedWorkerParent::SharedWorkerParent()
|
||||
: mBackgroundEventTarget(GetCurrentThreadEventTarget())
|
||||
, mStatus(eInit)
|
||||
, mWindowID(0)
|
||||
, mSuspended(false)
|
||||
, mFrozen(false)
|
||||
{
|
||||
|
@ -41,7 +41,9 @@ SharedWorkerParent::ActorDestroy(IProtocol::ActorDestroyReason aReason)
|
|||
}
|
||||
|
||||
void
|
||||
SharedWorkerParent::Initialize(const SharedWorkerLoadInfo& aInfo)
|
||||
SharedWorkerParent::Initialize(const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mStatus == eInit);
|
||||
|
@ -50,11 +52,10 @@ SharedWorkerParent::Initialize(const SharedWorkerLoadInfo& aInfo)
|
|||
mService = SharedWorkerService::GetOrCreate();
|
||||
MOZ_ASSERT(mService);
|
||||
|
||||
// This is the only information we currently care.
|
||||
mWindowID = aInfo.windowID();
|
||||
mWindowID = aWindowID;
|
||||
|
||||
mStatus = ePending;
|
||||
mService->GetOrCreateWorkerManager(this, aInfo);
|
||||
mService->GetOrCreateWorkerManager(this, aData, aWindowID, aPortIdentifier);
|
||||
}
|
||||
|
||||
IPCResult
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class SharedWorkerLoadInfo;
|
||||
class MessagePortIdentifier;
|
||||
class RemoteWorkerData;
|
||||
class SharedWorkerManager;
|
||||
class SharedWorkerService;
|
||||
|
||||
|
@ -26,7 +27,9 @@ public:
|
|||
SharedWorkerParent();
|
||||
|
||||
void
|
||||
Initialize(const SharedWorkerLoadInfo& aInfo);
|
||||
Initialize(const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier);
|
||||
|
||||
void
|
||||
ManagerCreated(SharedWorkerManager* aWorkerManager);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SharedWorkerService.h"
|
||||
#include "mozilla/dom/RemoteWorkerTypes.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
|
@ -75,11 +76,15 @@ class GetOrCreateWorkerManagerRunnable final : public Runnable
|
|||
{
|
||||
public:
|
||||
GetOrCreateWorkerManagerRunnable(SharedWorkerParent* aActor,
|
||||
const SharedWorkerLoadInfo& aInfo)
|
||||
const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier)
|
||||
: Runnable("GetOrCreateWorkerManagerRunnable")
|
||||
, mBackgroundEventTarget(GetCurrentThreadEventTarget())
|
||||
, mActor(aActor)
|
||||
, mInfo(aInfo)
|
||||
, mData(aData)
|
||||
, mWindowID(aWindowID)
|
||||
, mPortIdentifier(aPortIdentifier)
|
||||
{}
|
||||
|
||||
NS_IMETHOD
|
||||
|
@ -90,7 +95,8 @@ public:
|
|||
MOZ_ASSERT(service);
|
||||
|
||||
service->GetOrCreateWorkerManagerOnMainThread(mBackgroundEventTarget,
|
||||
mActor, mInfo);
|
||||
mActor, mData, mWindowID,
|
||||
mPortIdentifier);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -98,7 +104,9 @@ public:
|
|||
private:
|
||||
nsCOMPtr<nsIEventTarget> mBackgroundEventTarget;
|
||||
RefPtr<SharedWorkerParent> mActor;
|
||||
SharedWorkerLoadInfo mInfo;
|
||||
RemoteWorkerData mData;
|
||||
uint64_t mWindowID;
|
||||
MessagePortIdentifier mPortIdentifier;
|
||||
};
|
||||
|
||||
class RemoveWorkerManagerRunnable final : public Runnable
|
||||
|
@ -130,16 +138,29 @@ class WorkerManagerCreatedRunnable final : public Runnable
|
|||
{
|
||||
public:
|
||||
WorkerManagerCreatedRunnable(SharedWorkerManager* aManager,
|
||||
SharedWorkerParent* aActor)
|
||||
SharedWorkerParent* aActor,
|
||||
const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier)
|
||||
: Runnable("WorkerManagerCreatedRunnable")
|
||||
, mManager(aManager)
|
||||
, mActor(aActor)
|
||||
, mData(aData)
|
||||
, mWindowID(aWindowID)
|
||||
, mPortIdentifier(aPortIdentifier)
|
||||
{}
|
||||
|
||||
NS_IMETHOD
|
||||
Run()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (NS_WARN_IF(!mManager->MaybeCreateRemoteWorker(mData, mWindowID,
|
||||
mPortIdentifier))) {
|
||||
mActor->ErrorPropagation(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mManager->AddActor(mActor);
|
||||
mActor->ManagerCreated(mManager);
|
||||
return NS_OK;
|
||||
|
@ -148,6 +169,9 @@ public:
|
|||
private:
|
||||
RefPtr<SharedWorkerManager> mManager;
|
||||
RefPtr<SharedWorkerParent> mActor;
|
||||
RemoteWorkerData mData;
|
||||
uint64_t mWindowID;
|
||||
MessagePortIdentifier mPortIdentifier;
|
||||
};
|
||||
|
||||
class ErrorPropagationRunnable final : public Runnable
|
||||
|
@ -218,13 +242,16 @@ SharedWorkerService::~SharedWorkerService()
|
|||
|
||||
void
|
||||
SharedWorkerService::GetOrCreateWorkerManager(SharedWorkerParent* aActor,
|
||||
const SharedWorkerLoadInfo& aInfo)
|
||||
const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
// The real check happens on main-thread.
|
||||
RefPtr<GetOrCreateWorkerManagerRunnable> r =
|
||||
new GetOrCreateWorkerManagerRunnable(aActor, aInfo);
|
||||
new GetOrCreateWorkerManagerRunnable(aActor, aData, aWindowID,
|
||||
aPortIdentifier);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target = SystemGroup::EventTargetFor(TaskCategory::Other);
|
||||
nsresult rv = target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
|
@ -234,7 +261,9 @@ SharedWorkerService::GetOrCreateWorkerManager(SharedWorkerParent* aActor,
|
|||
void
|
||||
SharedWorkerService::GetOrCreateWorkerManagerOnMainThread(nsIEventTarget* aBackgroundEventTarget,
|
||||
SharedWorkerParent* aActor,
|
||||
const SharedWorkerLoadInfo& aInfo)
|
||||
const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aBackgroundEventTarget);
|
||||
|
@ -244,30 +273,30 @@ SharedWorkerService::GetOrCreateWorkerManagerOnMainThread(nsIEventTarget* aBackg
|
|||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
PrincipalInfoToPrincipal(aInfo.principalInfo(), &rv);
|
||||
PrincipalInfoToPrincipal(aData.principalInfo(), &rv);
|
||||
if (NS_WARN_IF(!principal)) {
|
||||
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor, rv);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = PopulatePrincipalContentSecurityPolicy(principal,
|
||||
aInfo.principalCsp(),
|
||||
aInfo.principalPreloadCsp());
|
||||
aData.principalCsp(),
|
||||
aData.principalPreloadCsp());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor, rv);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> loadingPrincipal =
|
||||
PrincipalInfoToPrincipal(aInfo.loadingPrincipalInfo(), &rv);
|
||||
PrincipalInfoToPrincipal(aData.loadingPrincipalInfo(), &rv);
|
||||
if (NS_WARN_IF(!loadingPrincipal)) {
|
||||
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor, rv);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = PopulatePrincipalContentSecurityPolicy(loadingPrincipal,
|
||||
aInfo.loadingPrincipalCsp(),
|
||||
aInfo.loadingPrincipalPreloadCsp());
|
||||
aData.loadingPrincipalCsp(),
|
||||
aData.loadingPrincipalPreloadCsp());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor, rv);
|
||||
return;
|
||||
|
@ -275,9 +304,9 @@ SharedWorkerService::GetOrCreateWorkerManagerOnMainThread(nsIEventTarget* aBackg
|
|||
|
||||
// Let's see if there is already a SharedWorker to share.
|
||||
for (SharedWorkerManager* workerManager : mWorkerManagers) {
|
||||
if (workerManager->MatchOnMainThread(aInfo.domain(),
|
||||
aInfo.resolvedScriptURL(),
|
||||
aInfo.name(), loadingPrincipal)) {
|
||||
if (workerManager->MatchOnMainThread(aData.domain(),
|
||||
aData.resolvedScriptURL(),
|
||||
aData.name(), loadingPrincipal)) {
|
||||
manager = workerManager;
|
||||
break;
|
||||
}
|
||||
|
@ -285,33 +314,22 @@ SharedWorkerService::GetOrCreateWorkerManagerOnMainThread(nsIEventTarget* aBackg
|
|||
|
||||
// Let's create a new one.
|
||||
if (!manager) {
|
||||
manager = new SharedWorkerManager(aBackgroundEventTarget, aInfo,
|
||||
principal, loadingPrincipal);
|
||||
|
||||
rv = manager->CreateWorkerOnMainThread();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor, rv);
|
||||
return;
|
||||
}
|
||||
manager = new SharedWorkerManager(aBackgroundEventTarget, aData,
|
||||
loadingPrincipal);
|
||||
|
||||
mWorkerManagers.AppendElement(manager);
|
||||
} else {
|
||||
// We are attaching the actor to an existing one.
|
||||
if (manager->IsSecureContext() != aInfo.isSecureContext()) {
|
||||
if (manager->IsSecureContext() != aData.isSecureContext()) {
|
||||
ErrorPropagationOnMainThread(aBackgroundEventTarget, aActor,
|
||||
NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the SharedWorker(Manager) already existed and was frozen, the existence
|
||||
// of a new, un-frozen actor should trigger the thawing of the SharedWorker.
|
||||
manager->ThawOnMainThread();
|
||||
|
||||
manager->ConnectPortOnMainThread(aInfo.portIdentifier());
|
||||
|
||||
RefPtr<WorkerManagerCreatedRunnable> r =
|
||||
new WorkerManagerCreatedRunnable(manager, aActor);
|
||||
new WorkerManagerCreatedRunnable(manager, aActor, aData, aWindowID,
|
||||
aPortIdentifier);
|
||||
aBackgroundEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ class PrincipalInfo;
|
|||
|
||||
namespace dom {
|
||||
|
||||
class MessagePortIdentifier;
|
||||
class RemoteWorkerData;
|
||||
class SharedWorkerManager;
|
||||
class SharedWorkerParent;
|
||||
|
||||
|
@ -38,12 +40,16 @@ public:
|
|||
// PBackground method only.
|
||||
void
|
||||
GetOrCreateWorkerManager(SharedWorkerParent* aActor,
|
||||
const SharedWorkerLoadInfo& aInfo);
|
||||
const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier);
|
||||
|
||||
void
|
||||
GetOrCreateWorkerManagerOnMainThread(nsIEventTarget* aBackgroundEventTarget,
|
||||
SharedWorkerParent* aActor,
|
||||
const SharedWorkerLoadInfo& aInfo);
|
||||
const RemoteWorkerData& aData,
|
||||
uint64_t aWindowID,
|
||||
const MessagePortIdentifier& aPortIdentifier);
|
||||
|
||||
// PBackground method only.
|
||||
void
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
include ClientIPCTypes;
|
||||
include DOMTypes;
|
||||
include PBackgroundSharedTypes;
|
||||
|
||||
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct ContentSecurityPolicy
|
||||
{
|
||||
nsString policy;
|
||||
bool reportOnlyFlag;
|
||||
bool deliveredViaMetaTagFlag;
|
||||
};
|
||||
|
||||
struct SharedWorkerLoadInfo
|
||||
{
|
||||
nsString originalScriptURL;
|
||||
nsCString baseScriptURL;
|
||||
nsCString resolvedScriptURL;
|
||||
|
||||
nsString name;
|
||||
|
||||
PrincipalInfo loadingPrincipalInfo;
|
||||
ContentSecurityPolicy[] loadingPrincipalCsp;
|
||||
ContentSecurityPolicy[] loadingPrincipalPreloadCsp;
|
||||
|
||||
PrincipalInfo principalInfo;
|
||||
ContentSecurityPolicy[] principalCsp;
|
||||
ContentSecurityPolicy[] principalPreloadCsp;
|
||||
|
||||
nsCString domain;
|
||||
|
||||
bool isSecureContext;
|
||||
|
||||
uint64_t windowID;
|
||||
|
||||
OptionalIPCClientInfo clientInfo;
|
||||
|
||||
MessagePortIdentifier portIdentifier;
|
||||
};
|
||||
|
||||
// ErrorData/ErrorDataNote correspond to WorkerErrorReport/WorkerErrorNote
|
||||
// which in turn correspond to JSErrorReport/JSErrorNotes which allows JS to
|
||||
// report complicated errors such as redeclarations that involve multiple
|
||||
// distinct lines. For more generic error-propagation IPC structures, see bug
|
||||
// 1357463 on making ErrorResult usable over IPC.
|
||||
|
||||
struct ErrorDataNote {
|
||||
uint32_t lineNumber;
|
||||
uint32_t columnNumber;
|
||||
nsString message;
|
||||
nsString filename;
|
||||
};
|
||||
|
||||
struct ErrorData {
|
||||
uint32_t lineNumber;
|
||||
uint32_t columnNumber;
|
||||
uint32_t flags;
|
||||
nsString message;
|
||||
nsString filename;
|
||||
nsString line;
|
||||
ErrorDataNote[] notes;
|
||||
};
|
||||
|
||||
union ErrorValue {
|
||||
nsresult;
|
||||
ErrorData;
|
||||
void_t;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -21,7 +21,6 @@ UNIFIED_SOURCES += [
|
|||
|
||||
IPDL_SOURCES += [
|
||||
'PSharedWorker.ipdl',
|
||||
'SharedWorkerTypes.ipdlh',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -294,13 +294,24 @@ BackgroundChildImpl::DeallocPPendingIPCBlobChild(PPendingIPCBlobChild* aActor)
|
|||
dom::PRemoteWorkerChild*
|
||||
BackgroundChildImpl::AllocPRemoteWorkerChild(const RemoteWorkerData& aData)
|
||||
{
|
||||
return new dom::RemoteWorkerChild();
|
||||
RefPtr<dom::RemoteWorkerChild> agent = new dom::RemoteWorkerChild();
|
||||
return agent.forget().take();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
BackgroundChildImpl::RecvPRemoteWorkerConstructor(PRemoteWorkerChild* aActor,
|
||||
const RemoteWorkerData& aData)
|
||||
{
|
||||
dom::RemoteWorkerChild* actor = static_cast<dom::RemoteWorkerChild*>(aActor);
|
||||
actor->ExecWorker(aData);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundChildImpl::DeallocPRemoteWorkerChild(dom::PRemoteWorkerChild* aActor)
|
||||
{
|
||||
delete aActor;
|
||||
RefPtr<dom::RemoteWorkerChild> actor =
|
||||
dont_AddRef(static_cast<dom::RemoteWorkerChild*>(aActor));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -321,7 +332,9 @@ BackgroundChildImpl::DeallocPRemoteWorkerServiceChild(dom::PRemoteWorkerServiceC
|
|||
}
|
||||
|
||||
dom::PSharedWorkerChild*
|
||||
BackgroundChildImpl::AllocPSharedWorkerChild(const dom::SharedWorkerLoadInfo& aInfo)
|
||||
BackgroundChildImpl::AllocPSharedWorkerChild(const dom::RemoteWorkerData& aData,
|
||||
const uint64_t& aWindowID,
|
||||
const dom::MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
RefPtr<dom::SharedWorkerChild> agent = new dom::SharedWorkerChild();
|
||||
return agent.forget().take();
|
||||
|
|
|
@ -117,6 +117,10 @@ protected:
|
|||
virtual mozilla::dom::PRemoteWorkerChild*
|
||||
AllocPRemoteWorkerChild(const RemoteWorkerData& aData) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvPRemoteWorkerConstructor(PRemoteWorkerChild* aActor,
|
||||
const RemoteWorkerData& aData) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPRemoteWorkerChild(mozilla::dom::PRemoteWorkerChild* aActor) override;
|
||||
|
||||
|
@ -127,7 +131,9 @@ protected:
|
|||
DeallocPRemoteWorkerServiceChild(mozilla::dom::PRemoteWorkerServiceChild* aActor) override;
|
||||
|
||||
virtual mozilla::dom::PSharedWorkerChild*
|
||||
AllocPSharedWorkerChild(const mozilla::dom::SharedWorkerLoadInfo& aInfo) override;
|
||||
AllocPSharedWorkerChild(const mozilla::dom::RemoteWorkerData& aData,
|
||||
const uint64_t& aWindowID,
|
||||
const mozilla::dom::MessagePortIdentifier& aPortIdentifier) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPSharedWorkerChild(mozilla::dom::PSharedWorkerChild* aActor) override;
|
||||
|
|
|
@ -427,7 +427,9 @@ BackgroundParentImpl::DeallocPRemoteWorkerServiceParent(mozilla::dom::PRemoteWor
|
|||
}
|
||||
|
||||
mozilla::dom::PSharedWorkerParent*
|
||||
BackgroundParentImpl::AllocPSharedWorkerParent(const mozilla::dom::SharedWorkerLoadInfo& aInfo)
|
||||
BackgroundParentImpl::AllocPSharedWorkerParent(const mozilla::dom::RemoteWorkerData& aData,
|
||||
const uint64_t& aWindowID,
|
||||
const mozilla::dom::MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
RefPtr<dom::SharedWorkerParent> agent =
|
||||
new mozilla::dom::SharedWorkerParent();
|
||||
|
@ -436,11 +438,13 @@ BackgroundParentImpl::AllocPSharedWorkerParent(const mozilla::dom::SharedWorkerL
|
|||
|
||||
IPCResult
|
||||
BackgroundParentImpl::RecvPSharedWorkerConstructor(PSharedWorkerParent* aActor,
|
||||
const mozilla::dom::SharedWorkerLoadInfo& aInfo)
|
||||
const mozilla::dom::RemoteWorkerData& aData,
|
||||
const uint64_t& aWindowID,
|
||||
const mozilla::dom::MessagePortIdentifier& aPortIdentifier)
|
||||
{
|
||||
mozilla::dom::SharedWorkerParent* actor =
|
||||
static_cast<mozilla::dom::SharedWorkerParent*>(aActor);
|
||||
actor->Initialize(aInfo);
|
||||
actor->Initialize(aData, aWindowID, aPortIdentifier);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -149,11 +149,15 @@ protected:
|
|||
DeallocPRemoteWorkerServiceParent(PRemoteWorkerServiceParent* aActor) override;
|
||||
|
||||
virtual mozilla::dom::PSharedWorkerParent*
|
||||
AllocPSharedWorkerParent(const mozilla::dom::SharedWorkerLoadInfo& aInfo) override;
|
||||
AllocPSharedWorkerParent(const mozilla::dom::RemoteWorkerData& aData,
|
||||
const uint64_t& aWindowID,
|
||||
const mozilla::dom::MessagePortIdentifier& aPortIdentifier) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvPSharedWorkerConstructor(PSharedWorkerParent* aActor,
|
||||
const mozilla::dom::SharedWorkerLoadInfo& aInfo) override;
|
||||
const mozilla::dom::RemoteWorkerData& aData,
|
||||
const uint64_t& aWindowID,
|
||||
const mozilla::dom::MessagePortIdentifier& aPortIdentifier) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPSharedWorkerParent(PSharedWorkerParent* aActor) override;
|
||||
|
|
|
@ -49,7 +49,6 @@ include PBackgroundIDBSharedTypes;
|
|||
include PFileSystemParams;
|
||||
include ProtocolTypes;
|
||||
include RemoteWorkerTypes;
|
||||
include SharedWorkerTypes;
|
||||
include MIDITypes;
|
||||
|
||||
include "mozilla/dom/cache/IPCUtils.h";
|
||||
|
@ -161,7 +160,9 @@ parent:
|
|||
|
||||
async PWebAuthnTransaction();
|
||||
|
||||
async PSharedWorker(SharedWorkerLoadInfo loadInfo);
|
||||
async PSharedWorker(RemoteWorkerData data,
|
||||
uint64_t windowID,
|
||||
MessagePortIdentifier portIdentifier);
|
||||
|
||||
async PTemporaryIPCBlob();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче