mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1434342 P4 Make ServiceWorker operate on an abstract Inner interface that ServiceWorkerInfo implements. r=asuth
This commit is contained in:
parent
2508c997c6
commit
00f7b788b7
@ -66,22 +66,23 @@ ServiceWorker::Create(nsIGlobalObject* aOwner,
|
||||
}
|
||||
|
||||
ServiceWorker::ServiceWorker(nsIGlobalObject* aGlobal,
|
||||
ServiceWorkerInfo* aInfo)
|
||||
const ServiceWorkerDescriptor& aDescriptor,
|
||||
ServiceWorker::Inner* aInner)
|
||||
: DOMEventTargetHelper(aGlobal)
|
||||
, mDescriptor(aDescriptor)
|
||||
, mInfo(aInfo)
|
||||
, mInner(aInner)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aInfo);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mInner);
|
||||
|
||||
// This will update our state too.
|
||||
mInfo->AppendWorker(this);
|
||||
mInner->AddServiceWorker(this);
|
||||
}
|
||||
|
||||
ServiceWorker::~ServiceWorker()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mInfo->RemoveWorker(this);
|
||||
mInner->RemoveServiceWorker(this);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ServiceWorker, DOMEventTargetHelper)
|
||||
@ -130,33 +131,7 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetParentObject());
|
||||
if (!window || !window->GetExtantDoc()) {
|
||||
NS_WARNING("Trying to call post message from an invalid dom object.");
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
|
||||
if (storageAllowed != nsContentUtils::StorageAccess::eAllow) {
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
mInfo->Scope(), "ServiceWorkerPostMessageStorageError",
|
||||
nsTArray<nsString> { NS_ConvertUTF8toUTF16(mInfo->Scope()) });
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> clientInfo = window->GetClientInfo();
|
||||
Maybe<ClientState> clientState = window->GetClientState();
|
||||
if (clientInfo.isNothing() || clientState.isNothing()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
ServiceWorkerPrivate* workerPrivate = mInfo->WorkerPrivate();
|
||||
aRv = workerPrivate->SendMessageEvent(aCx, aMessage, aTransferable,
|
||||
ClientInfoAndState(clientInfo.ref().ToIPC(),
|
||||
clientState.ref().ToIPC()));
|
||||
mInner->PostMessage(GetParentObject(), aCx, aMessage, aTransferable, aRv);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -9,24 +9,56 @@
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/ServiceWorkerBinding.h" // For ServiceWorkerState.
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef PostMessage
|
||||
#endif
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ServiceWorkerInfo;
|
||||
class ServiceWorkerManager;
|
||||
class SharedWorker;
|
||||
|
||||
bool
|
||||
ServiceWorkerVisible(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
class ServiceWorker final : public DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
// Abstract interface for the internal representation of the
|
||||
// ServiceWorker object.
|
||||
class Inner
|
||||
{
|
||||
public:
|
||||
// This will be called when a DOM ServiceWorker object is
|
||||
// created and takes a strong ref to the Inner object.
|
||||
// RemoveServiceWorker() is guaranteed to be called on the
|
||||
// current thread before the ServiceWorker is destroyed.
|
||||
//
|
||||
// In addition, the Inner object should check to see if
|
||||
// the ServiceWorker's state is correct. If not, it should
|
||||
// be updated automatically by calling SetState(). This is
|
||||
// necessary to handle race conditions where the DOM
|
||||
// ServiceWorker object is created while the state is being
|
||||
// updated in another process.
|
||||
virtual void
|
||||
AddServiceWorker(ServiceWorker* aWorker) = 0;
|
||||
|
||||
// This is called when the DOM ServiceWorker object is
|
||||
// destroyed and drops its ref to the Inner object.
|
||||
virtual void
|
||||
RemoveServiceWorker(ServiceWorker* aWorker) = 0;
|
||||
|
||||
virtual void
|
||||
PostMessage(nsIGlobalObject* aGlobal,
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv) = 0;
|
||||
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
};
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
IMPL_EVENT_HANDLER(statechange)
|
||||
@ -47,10 +79,6 @@ public:
|
||||
void
|
||||
GetScriptURL(nsString& aURL) const;
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef PostMessage
|
||||
#endif
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable, ErrorResult& aRv);
|
||||
@ -58,13 +86,13 @@ public:
|
||||
private:
|
||||
ServiceWorker(nsIGlobalObject* aWindow,
|
||||
const ServiceWorkerDescriptor& aDescriptor,
|
||||
ServiceWorkerInfo* aInfo);
|
||||
Inner* aInner);
|
||||
|
||||
// This class is reference-counted and will be destroyed from Release().
|
||||
~ServiceWorker();
|
||||
|
||||
ServiceWorkerDescriptor mDescriptor;
|
||||
const RefPtr<ServiceWorkerInfo> mInfo;
|
||||
const RefPtr<Inner> mInner;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -113,35 +113,6 @@ ServiceWorkerInfo::DetachDebugger()
|
||||
return mServiceWorkerPrivate->DetachDebugger();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerInfo::AppendWorker(ServiceWorker* aWorker)
|
||||
{
|
||||
MOZ_ASSERT(aWorker);
|
||||
#ifdef DEBUG
|
||||
nsAutoString workerURL;
|
||||
aWorker->GetScriptURL(workerURL);
|
||||
MOZ_ASSERT(workerURL.Equals(NS_ConvertUTF8toUTF16(mDescriptor.ScriptURL())));
|
||||
#endif
|
||||
MOZ_ASSERT(!mInstances.Contains(aWorker));
|
||||
|
||||
mInstances.AppendElement(aWorker);
|
||||
aWorker->SetState(State());
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerInfo::RemoveWorker(ServiceWorker* aWorker)
|
||||
{
|
||||
MOZ_ASSERT(aWorker);
|
||||
#ifdef DEBUG
|
||||
nsAutoString workerURL;
|
||||
aWorker->GetScriptURL(workerURL);
|
||||
MOZ_ASSERT(workerURL.Equals(NS_ConvertUTF8toUTF16(mDescriptor.ScriptURL())));
|
||||
#endif
|
||||
MOZ_ASSERT(mInstances.Contains(aWorker));
|
||||
|
||||
mInstances.RemoveElement(aWorker);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ChangeStateUpdater final : public Runnable
|
||||
@ -253,6 +224,72 @@ ServiceWorkerInfo::GetNextID() const
|
||||
return ++gServiceWorkerInfoCurrentID;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerInfo::AddServiceWorker(ServiceWorker* aWorker)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWorker);
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
nsAutoString workerURL;
|
||||
aWorker->GetScriptURL(workerURL);
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
workerURL.Equals(NS_ConvertUTF8toUTF16(mDescriptor.ScriptURL())));
|
||||
#endif
|
||||
MOZ_ASSERT(!mInstances.Contains(aWorker));
|
||||
|
||||
mInstances.AppendElement(aWorker);
|
||||
aWorker->SetState(State());
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerInfo::RemoveServiceWorker(ServiceWorker* aWorker)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWorker);
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
nsAutoString workerURL;
|
||||
aWorker->GetScriptURL(workerURL);
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
workerURL.Equals(NS_ConvertUTF8toUTF16(mDescriptor.ScriptURL())));
|
||||
#endif
|
||||
MOZ_ASSERT(mInstances.Contains(aWorker));
|
||||
|
||||
mInstances.RemoveElement(aWorker);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerInfo::PostMessage(nsIGlobalObject* aGlobal,
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
|
||||
if (NS_WARN_IF(!window || !window->GetExtantDoc())) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
|
||||
if (storageAllowed != nsContentUtils::StorageAccess::eAllow) {
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
Scope(), "ServiceWorkerPostMessageStorageError",
|
||||
nsTArray<nsString> { NS_ConvertUTF8toUTF16(Scope()) });
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> clientInfo = window->GetClientInfo();
|
||||
Maybe<ClientState> clientState = window->GetClientState();
|
||||
if (NS_WARN_IF(clientInfo.isNothing() || clientState.isNothing())) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mServiceWorkerPrivate->SendMessageEvent(aCx, aMessage, aTransferable,
|
||||
ClientInfoAndState(clientInfo.ref().ToIPC(),
|
||||
clientState.ref().ToIPC()));
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
ServiceWorkerInfo::GetOrCreateInstance(nsPIDOMWindowInner* aWindow)
|
||||
{
|
||||
|
@ -12,11 +12,11 @@
|
||||
#include "mozilla/dom/WorkerCommon.h"
|
||||
#include "mozilla/OriginAttributes.h"
|
||||
#include "nsIServiceWorkerManager.h"
|
||||
#include "ServiceWorker.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ServiceWorker;
|
||||
class ServiceWorkerPrivate;
|
||||
|
||||
/*
|
||||
@ -75,6 +75,19 @@ private:
|
||||
uint64_t
|
||||
GetNextID() const;
|
||||
|
||||
// ServiceWorker::Inner implementation
|
||||
virtual void
|
||||
AddServiceWorker(ServiceWorker* aWorker) override;
|
||||
|
||||
virtual void
|
||||
RemoveServiceWorker(ServiceWorker* aWorker) override;
|
||||
|
||||
virtual void
|
||||
PostMessage(nsIGlobalObject* aGlobal,
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISERVICEWORKERINFO
|
||||
@ -185,12 +198,6 @@ public:
|
||||
return mHandlesFetch != Disabled;
|
||||
}
|
||||
|
||||
void
|
||||
AppendWorker(ServiceWorker* aWorker);
|
||||
|
||||
void
|
||||
RemoveWorker(ServiceWorker* aWorker);
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
GetOrCreateInstance(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user