Bug 1462772 P3 Make ServiceWorker binding objects get or create a handle to their associated registration. r=mrbkap

This commit is contained in:
Ben Kelly 2018-07-02 07:44:18 -07:00
Родитель 4866ecedf2
Коммит f3b6e1d527
4 изменённых файлов: 99 добавлений и 3 удалений

Просмотреть файл

@ -63,7 +63,7 @@ ServiceWorker::Create(nsIGlobalObject* aOwner,
return ref.forget();
}
RefPtr<ServiceWorker::Inner> inner = new ServiceWorkerImpl(info);
RefPtr<ServiceWorker::Inner> inner = new ServiceWorkerImpl(info, reg);
ref = new ServiceWorker(aOwner, aDescriptor, inner);
return ref.forget();
}
@ -86,6 +86,31 @@ ServiceWorker::ServiceWorker(nsIGlobalObject* aGlobal,
// This will update our state too.
mInner->AddServiceWorker(this);
// Attempt to get an existing binding object for the registration
// associated with this ServiceWorker.
RefPtr<ServiceWorkerRegistration> reg = aGlobal->GetServiceWorkerRegistration(
ServiceWorkerRegistrationDescriptor(mDescriptor.RegistrationId(),
mDescriptor.PrincipalInfo(),
mDescriptor.Scope(),
ServiceWorkerUpdateViaCache::Imports));
if (reg) {
MaybeAttachToRegistration(reg);
} else {
RefPtr<ServiceWorker> self = this;
mInner->GetRegistration(
[self = std::move(self)] (const ServiceWorkerRegistrationDescriptor& aDescriptor) {
nsIGlobalObject* global = self->GetParentObject();
NS_ENSURE_TRUE_VOID(global);
RefPtr<ServiceWorkerRegistration> reg =
global->GetOrCreateServiceWorkerRegistration(aDescriptor);
self->MaybeAttachToRegistration(reg);
}, [] (ErrorResult& aRv) {
// do nothing
aRv.SuppressException();
});
}
}
ServiceWorker::~ServiceWorker()
@ -94,6 +119,10 @@ ServiceWorker::~ServiceWorker()
mInner->RemoveServiceWorker(this);
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorker,
DOMEventTargetHelper,
mRegistration);
NS_IMPL_ADDREF_INHERITED(ServiceWorker, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(ServiceWorker, DOMEventTargetHelper)
@ -201,5 +230,14 @@ ServiceWorker::DisconnectFromOwner()
DOMEventTargetHelper::DisconnectFromOwner();
}
void
ServiceWorker::MaybeAttachToRegistration(ServiceWorkerRegistration* aRegistration)
{
MOZ_DIAGNOSTIC_ASSERT(aRegistration);
MOZ_DIAGNOSTIC_ASSERT(!mRegistration);
mRegistration = aRegistration;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ServiceWorkerDescriptor.h"
#include "mozilla/dom/ServiceWorkerUtils.h"
#ifdef XP_WIN
#undef PostMessage
@ -55,6 +56,12 @@ public:
virtual void
RemoveServiceWorker(ServiceWorker* aWorker) = 0;
// Get the associated registration for this ServiceWorker. The success
// callback should always be called asynchronously.
virtual void
GetRegistration(ServiceWorkerRegistrationCallback&& aSuccessCB,
ServiceWorkerFailureCallback&& aFailureCB) = 0;
virtual void
PostMessage(RefPtr<ServiceWorkerCloneData>&& aData,
const ClientInfo& aClientInfo,
@ -65,6 +72,7 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_SERVICEWORKER_IID)
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorker, DOMEventTargetHelper)
IMPL_EVENT_HANDLER(statechange)
IMPL_EVENT_HANDLER(error)
@ -102,9 +110,13 @@ private:
// This class is reference-counted and will be destroyed from Release().
~ServiceWorker();
void
MaybeAttachToRegistration(ServiceWorkerRegistration* aRegistration);
ServiceWorkerDescriptor mDescriptor;
RefPtr<Inner> mInner;
RefPtr<ServiceWorkerRegistration> mRegistration;
};
NS_DEFINE_STATIC_IID_ACCESSOR(ServiceWorker, NS_DOM_SERVICEWORKER_IID)

Просмотреть файл

@ -36,6 +36,42 @@ ServiceWorkerImpl::RemoveServiceWorker(ServiceWorker* aWorker)
mOuter = nullptr;
}
void
ServiceWorkerImpl::GetRegistration(ServiceWorkerRegistrationCallback&& aSuccessCB,
ServiceWorkerFailureCallback&& aFailureCB)
{
// While we could immediate call success with our registration descriptor
// we instead queue a runnable to do this. This ensures that GetRegistration()
// is always async to match how the IPC implementation will work. It also
// ensure that if any events are triggered from providing the registration
// that they are fired from a runnable on the correct global's event target.
if (!mOuter) {
aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
return;
}
nsIGlobalObject* global = mOuter->GetParentObject();
if (!global) {
aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
return;
}
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
"ServiceWorkerImpl::GetRegistration",
[reg = mReg, successCB = std::move(aSuccessCB)] () mutable {
successCB(reg->Descriptor());
});
nsresult rv =
global->EventTargetFor(TaskCategory::Other)->Dispatch(r.forget(),
NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
aFailureCB(CopyableErrorResult(rv));
return;
}
}
void
ServiceWorkerImpl::PostMessage(RefPtr<ServiceWorkerCloneData>&& aData,
const ClientInfo& aClientInfo,
@ -54,11 +90,14 @@ ServiceWorkerImpl::SetState(ServiceWorkerState aState)
}
ServiceWorkerImpl::ServiceWorkerImpl(ServiceWorkerInfo* aInfo)
ServiceWorkerImpl::ServiceWorkerImpl(ServiceWorkerInfo* aInfo,
ServiceWorkerRegistrationInfo* aReg)
: mInfo(aInfo)
, mReg(aReg)
, mOuter(nullptr)
{
MOZ_DIAGNOSTIC_ASSERT(mInfo);
MOZ_DIAGNOSTIC_ASSERT(mReg);
}
} // namespace dom

Просмотреть файл

@ -14,11 +14,13 @@ namespace mozilla {
namespace dom {
class ServiceWorkerInfo;
class ServiceWorkerRegistrationInfo;
class ServiceWorkerImpl final : public ServiceWorker::Inner
, public ServiceWorkerInfo::Listener
{
RefPtr<ServiceWorkerInfo> mInfo;
RefPtr<ServiceWorkerRegistrationInfo> mReg;
ServiceWorker* mOuter;
~ServiceWorkerImpl();
@ -30,6 +32,10 @@ class ServiceWorkerImpl final : public ServiceWorker::Inner
void
RemoveServiceWorker(ServiceWorker* aWorker) override;
void
GetRegistration(ServiceWorkerRegistrationCallback&& aSuccessCB,
ServiceWorkerFailureCallback&& aFailureCB) override;
void
PostMessage(RefPtr<ServiceWorkerCloneData>&& aData,
const ClientInfo& aClientInfo,
@ -40,7 +46,8 @@ class ServiceWorkerImpl final : public ServiceWorker::Inner
SetState(ServiceWorkerState aState) override;
public:
explicit ServiceWorkerImpl(ServiceWorkerInfo* aInfo);
ServiceWorkerImpl(ServiceWorkerInfo* aInfo,
ServiceWorkerRegistrationInfo* aReg);
NS_INLINE_DECL_REFCOUNTING(ServiceWorkerImpl, override);
};