Files
tubestation/dom/workers/ServiceWorkerManagerParent.cpp
Bill McCloskey 284c3f3132 Bug 1365097 - Convert NS_GetCurrentThread uses in dom (except for dom/media) (r=smaug)
For the Quatum DOM project, it's better to work in terms of event targets than
threads. This patch converts DOM code to operate on event targets rather than
threads, when possible.

MozReview-Commit-ID: 5FgvpKadUA2
2017-06-12 20:20:08 -07:00

361 lines
9.3 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/. */
#include "ServiceWorkerManagerParent.h"
#include "ServiceWorkerManagerService.h"
#include "ServiceWorkerUpdaterParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ServiceWorkerRegistrar.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/Unused.h"
#include "nsThreadUtils.h"
namespace mozilla {
using namespace ipc;
namespace dom {
namespace workers {
namespace {
uint64_t sServiceWorkerManagerParentID = 0;
class RegisterServiceWorkerCallback final : public Runnable
{
public:
RegisterServiceWorkerCallback(const ServiceWorkerRegistrationData& aData,
uint64_t aParentID)
: mData(aData)
, mParentID(aParentID)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
}
NS_IMETHOD
Run() override
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
RefPtr<dom::ServiceWorkerRegistrar> service =
dom::ServiceWorkerRegistrar::Get();
// Shutdown during the process of trying to update the registrar. Give
// up on this modification.
if (!service) {
return NS_OK;
}
service->RegisterServiceWorker(mData);
RefPtr<ServiceWorkerManagerService> managerService =
ServiceWorkerManagerService::Get();
if (managerService) {
managerService->PropagateRegistration(mParentID, mData);
}
return NS_OK;
}
private:
ServiceWorkerRegistrationData mData;
const uint64_t mParentID;
};
class UnregisterServiceWorkerCallback final : public Runnable
{
public:
UnregisterServiceWorkerCallback(const PrincipalInfo& aPrincipalInfo,
const nsString& aScope,
uint64_t aParentID)
: mPrincipalInfo(aPrincipalInfo)
, mScope(aScope)
, mParentID(aParentID)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
}
NS_IMETHOD
Run() override
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
RefPtr<dom::ServiceWorkerRegistrar> service =
dom::ServiceWorkerRegistrar::Get();
// Shutdown during the process of trying to update the registrar. Give
// up on this modification.
if (!service) {
return NS_OK;
}
service->UnregisterServiceWorker(mPrincipalInfo,
NS_ConvertUTF16toUTF8(mScope));
RefPtr<ServiceWorkerManagerService> managerService =
ServiceWorkerManagerService::Get();
if (managerService) {
managerService->PropagateUnregister(mParentID, mPrincipalInfo,
mScope);
}
return NS_OK;
}
private:
const PrincipalInfo mPrincipalInfo;
nsString mScope;
uint64_t mParentID;
};
class CheckPrincipalWithCallbackRunnable final : public Runnable
{
public:
CheckPrincipalWithCallbackRunnable(already_AddRefed<ContentParent> aParent,
const PrincipalInfo& aPrincipalInfo,
Runnable* aCallback)
: mContentParent(aParent)
, mPrincipalInfo(aPrincipalInfo)
, mCallback(aCallback)
, mBackgroundEventTarget(GetCurrentThreadEventTarget())
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(mContentParent);
MOZ_ASSERT(mCallback);
MOZ_ASSERT(mBackgroundEventTarget);
}
NS_IMETHOD Run() override
{
if (NS_IsMainThread()) {
mContentParent = nullptr;
mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
return NS_OK;
}
AssertIsOnBackgroundThread();
mCallback->Run();
mCallback = nullptr;
return NS_OK;
}
private:
RefPtr<ContentParent> mContentParent;
PrincipalInfo mPrincipalInfo;
RefPtr<Runnable> mCallback;
nsCOMPtr<nsIEventTarget> mBackgroundEventTarget;
};
} // namespace
ServiceWorkerManagerParent::ServiceWorkerManagerParent()
: mService(ServiceWorkerManagerService::GetOrCreate())
, mID(++sServiceWorkerManagerParentID)
{
AssertIsOnBackgroundThread();
mService->RegisterActor(this);
}
ServiceWorkerManagerParent::~ServiceWorkerManagerParent()
{
AssertIsOnBackgroundThread();
}
mozilla::ipc::IPCResult
ServiceWorkerManagerParent::RecvRegister(
const ServiceWorkerRegistrationData& aData)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
// Basic validation.
if (aData.scope().IsEmpty() ||
aData.principal().type() == PrincipalInfo::TNullPrincipalInfo ||
aData.principal().type() == PrincipalInfo::TSystemPrincipalInfo) {
return IPC_FAIL_NO_REASON(this);
}
RefPtr<RegisterServiceWorkerCallback> callback =
new RegisterServiceWorkerCallback(aData, mID);
RefPtr<ContentParent> parent =
BackgroundParent::GetContentParent(Manager());
// If the ContentParent is null we are dealing with a same-process actor.
if (!parent) {
callback->Run();
return IPC_OK();
}
RefPtr<CheckPrincipalWithCallbackRunnable> runnable =
new CheckPrincipalWithCallbackRunnable(parent.forget(), aData.principal(),
callback);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
return IPC_OK();
}
mozilla::ipc::IPCResult
ServiceWorkerManagerParent::RecvUnregister(const PrincipalInfo& aPrincipalInfo,
const nsString& aScope)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
// Basic validation.
if (aScope.IsEmpty() ||
aPrincipalInfo.type() == PrincipalInfo::TNullPrincipalInfo ||
aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
return IPC_FAIL_NO_REASON(this);
}
RefPtr<UnregisterServiceWorkerCallback> callback =
new UnregisterServiceWorkerCallback(aPrincipalInfo, aScope, mID);
RefPtr<ContentParent> parent =
BackgroundParent::GetContentParent(Manager());
// If the ContentParent is null we are dealing with a same-process actor.
if (!parent) {
callback->Run();
return IPC_OK();
}
RefPtr<CheckPrincipalWithCallbackRunnable> runnable =
new CheckPrincipalWithCallbackRunnable(parent.forget(), aPrincipalInfo,
callback);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
return IPC_OK();
}
mozilla::ipc::IPCResult
ServiceWorkerManagerParent::RecvPropagateSoftUpdate(const OriginAttributes& aOriginAttributes,
const nsString& aScope)
{
AssertIsOnBackgroundThread();
if (NS_WARN_IF(!mService)) {
return IPC_FAIL_NO_REASON(this);
}
mService->PropagateSoftUpdate(mID, aOriginAttributes, aScope);
return IPC_OK();
}
mozilla::ipc::IPCResult
ServiceWorkerManagerParent::RecvPropagateUnregister(const PrincipalInfo& aPrincipalInfo,
const nsString& aScope)
{
AssertIsOnBackgroundThread();
if (NS_WARN_IF(!mService)) {
return IPC_FAIL_NO_REASON(this);
}
mService->PropagateUnregister(mID, aPrincipalInfo, aScope);
return IPC_OK();
}
mozilla::ipc::IPCResult
ServiceWorkerManagerParent::RecvPropagateRemove(const nsCString& aHost)
{
AssertIsOnBackgroundThread();
if (NS_WARN_IF(!mService)) {
return IPC_FAIL_NO_REASON(this);
}
mService->PropagateRemove(mID, aHost);
return IPC_OK();
}
mozilla::ipc::IPCResult
ServiceWorkerManagerParent::RecvPropagateRemoveAll()
{
AssertIsOnBackgroundThread();
if (NS_WARN_IF(!mService)) {
return IPC_FAIL_NO_REASON(this);
}
mService->PropagateRemoveAll(mID);
return IPC_OK();
}
mozilla::ipc::IPCResult
ServiceWorkerManagerParent::RecvShutdown()
{
AssertIsOnBackgroundThread();
if (NS_WARN_IF(!mService)) {
return IPC_FAIL_NO_REASON(this);
}
mService->UnregisterActor(this);
mService = nullptr;
Unused << Send__delete__(this);
return IPC_OK();
}
PServiceWorkerUpdaterParent*
ServiceWorkerManagerParent::AllocPServiceWorkerUpdaterParent(const OriginAttributes& aOriginAttributes,
const nsCString& aScope)
{
AssertIsOnBackgroundThread();
return new ServiceWorkerUpdaterParent();
}
mozilla::ipc::IPCResult
ServiceWorkerManagerParent::RecvPServiceWorkerUpdaterConstructor(PServiceWorkerUpdaterParent* aActor,
const OriginAttributes& aOriginAttributes,
const nsCString& aScope)
{
AssertIsOnBackgroundThread();
if (NS_WARN_IF(!mService)) {
return IPC_FAIL_NO_REASON(this);
}
mService->ProcessUpdaterActor(static_cast<ServiceWorkerUpdaterParent*>(aActor),
aOriginAttributes, aScope, mID);
return IPC_OK();
}
bool
ServiceWorkerManagerParent::DeallocPServiceWorkerUpdaterParent(PServiceWorkerUpdaterParent* aActor)
{
AssertIsOnBackgroundThread();
delete aActor;
return true;
}
void
ServiceWorkerManagerParent::ActorDestroy(ActorDestroyReason aWhy)
{
AssertIsOnBackgroundThread();
if (mService) {
// This object is about to be released and with it, also mService will be
// released too.
mService->UnregisterActor(this);
}
}
} // namespace workers
} // namespace dom
} // namespace mozilla