mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 983497 - Patch 1: Infrastructure to fire events on ServiceWorkerContainers. r=ehsan,smaug
--HG-- extra : transplant_source : S1z%F3%86%E5%CF%D6%3BWW%8E%1A%90%A3%94%7E%FE%E3z
This commit is contained in:
parent
fae4030844
commit
1d4f2c7f6d
@ -141,14 +141,15 @@ public:
|
||||
virtual void EventListenerWasRemoved(const nsAString& aType,
|
||||
ErrorResult& aRv,
|
||||
JSCompartment* aCompartment = nullptr) {}
|
||||
|
||||
// Dispatch a trusted, non-cancellable and non-bubbling event to |this|.
|
||||
nsresult DispatchTrustedEvent(const nsAString& aEventName);
|
||||
protected:
|
||||
virtual ~DOMEventTargetHelper();
|
||||
|
||||
nsresult WantsUntrusted(bool* aRetVal);
|
||||
|
||||
nsRefPtr<EventListenerManager> mListenerManager;
|
||||
// Dispatch a trusted, non-cancellable and non-bubbling event to |this|.
|
||||
nsresult DispatchTrustedEvent(const nsAString& aEventName);
|
||||
// Make |event| trusted and dispatch |aEvent| to |this|.
|
||||
nsresult DispatchTrustedEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
|
@ -5,7 +5,9 @@
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[uuid(44ef0b7e-92c0-48a7-a092-5a49f2533792)]
|
||||
interface nsIURI;
|
||||
|
||||
[uuid(6117cdf1-cb10-42a3-9901-4f1bab7ffa4d)]
|
||||
interface nsIServiceWorkerManager : nsISupports
|
||||
{
|
||||
// Returns a Promise
|
||||
@ -14,6 +16,10 @@ interface nsIServiceWorkerManager : nsISupports
|
||||
// Returns a Promise
|
||||
nsISupports unregister(in nsIDOMWindow aWindow, in DOMString aScope);
|
||||
|
||||
// aTarget MUST be a ServiceWorkerContainer.
|
||||
[noscript] void AddContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
||||
[noscript] void RemoveContainerEventListener(in nsIURI aPageURI, in nsIDOMEventTarget aTarget);
|
||||
|
||||
// Testing
|
||||
DOMString getScopeForUrl(in DOMString path);
|
||||
};
|
||||
|
@ -127,6 +127,26 @@ ServiceWorkerContainer::Ready()
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// XXXnsm, maybe this can be optimized to only add when a event handler is
|
||||
// registered.
|
||||
void
|
||||
ServiceWorkerContainer::StartListeningForEvents()
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||
if (swm) {
|
||||
swm->AddContainerEventListener(mWindow->GetDocumentURI(), this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerContainer::StopListeningForEvents()
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||
if (swm) {
|
||||
swm->RemoveContainerEventListener(mWindow->GetDocumentURI(), this);
|
||||
}
|
||||
}
|
||||
|
||||
// Testing only.
|
||||
already_AddRefed<Promise>
|
||||
ServiceWorkerContainer::ClearAllServiceWorkerData(ErrorResult& aRv)
|
||||
|
@ -36,8 +36,8 @@ public:
|
||||
explicit ServiceWorkerContainer(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow)
|
||||
{
|
||||
// FIXME(nsm): Bug 983497. Here the NSW should hook into SWM to be notified of events.
|
||||
SetIsDOMBinding();
|
||||
StartListeningForEvents();
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
@ -75,6 +75,12 @@ public:
|
||||
already_AddRefed<Promise>
|
||||
Ready();
|
||||
|
||||
nsIURI*
|
||||
GetDocumentURI() const
|
||||
{
|
||||
return mWindow->GetDocumentURI();
|
||||
}
|
||||
|
||||
// Testing only.
|
||||
already_AddRefed<Promise>
|
||||
ClearAllServiceWorkerData(ErrorResult& aRv);
|
||||
@ -91,9 +97,15 @@ public:
|
||||
private:
|
||||
~ServiceWorkerContainer()
|
||||
{
|
||||
// FIXME(nsm): Bug 983497. Unhook from events.
|
||||
StopListeningForEvents();
|
||||
}
|
||||
|
||||
void
|
||||
StartListeningForEvents();
|
||||
|
||||
void
|
||||
StopListeningForEvents();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "ServiceWorkerManager.h"
|
||||
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
@ -367,10 +368,10 @@ public:
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
ServiceWorkerManager::ServiceWorkerDomainInfo* domainInfo;
|
||||
nsRefPtr<ServiceWorkerManager::ServiceWorkerDomainInfo> domainInfo;
|
||||
// XXXnsm: This pattern can be refactored if we end up using it
|
||||
// often enough.
|
||||
if (!swm->mDomainMap.Get(domain, &domainInfo)) {
|
||||
if (!swm->mDomainMap.Get(domain, getter_AddRefs(domainInfo))) {
|
||||
domainInfo = new ServiceWorkerManager::ServiceWorkerDomainInfo;
|
||||
swm->mDomainMap.Put(domain, domainInfo);
|
||||
}
|
||||
@ -681,8 +682,8 @@ ServiceWorkerManager::HandleError(JSContext* aCx,
|
||||
return;
|
||||
}
|
||||
|
||||
ServiceWorkerDomainInfo* domainInfo;
|
||||
if (!mDomainMap.Get(domain, &domainInfo)) {
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo;
|
||||
if (!mDomainMap.Get(domain, getter_AddRefs(domainInfo))) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1003,26 +1004,13 @@ ServiceWorkerManager::GetServiceWorkerRegistration(nsIDocument* aDoc)
|
||||
already_AddRefed<ServiceWorkerRegistration>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistration(nsIURI* aURI)
|
||||
{
|
||||
if (!aURI) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCString domain;
|
||||
nsresult rv = aURI->GetHost(domain);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ServiceWorkerDomainInfo* domainInfo = mDomainMap.Get(domain);
|
||||
|
||||
// XXXnsm: This pattern can be refactored if we end up using it
|
||||
// often enough.
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aURI);
|
||||
if (!domainInfo) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCString spec;
|
||||
rv = aURI->GetSpec(spec);
|
||||
nsresult rv = aURI->GetSpec(spec);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -1126,6 +1114,45 @@ ServiceWorkerManager::RemoveScope(nsTArray<nsCString>& aList, const nsACString&
|
||||
aList.RemoveElement(aScope);
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorkerManager::ServiceWorkerDomainInfo>
|
||||
ServiceWorkerManager::GetDomainInfo(nsIDocument* aDoc)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aDoc);
|
||||
nsCOMPtr<nsIURI> documentURI = aDoc->GetDocumentURI();
|
||||
return GetDomainInfo(documentURI);
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorkerManager::ServiceWorkerDomainInfo>
|
||||
ServiceWorkerManager::GetDomainInfo(nsIURI* aURI)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
nsCString domain;
|
||||
nsresult rv = aURI->GetHost(domain);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo;
|
||||
mDomainMap.Get(domain, getter_AddRefs(domainInfo));
|
||||
return domainInfo.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorkerManager::ServiceWorkerDomainInfo>
|
||||
ServiceWorkerManager::GetDomainInfo(const nsCString& aURL)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return GetDomainInfo(uri);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::GetScopeForUrl(const nsAString& aUrl, nsAString& aScope)
|
||||
{
|
||||
@ -1143,6 +1170,79 @@ ServiceWorkerManager::GetScopeForUrl(const nsAString& aUrl, nsAString& aScope)
|
||||
aScope = NS_ConvertUTF8toUTF16(r->mScope);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::AddContainerEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
|
||||
{
|
||||
MOZ_ASSERT(aDocumentURI);
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDocumentURI);
|
||||
if (!domainInfo) {
|
||||
nsCString domain;
|
||||
nsresult rv = aDocumentURI->GetHost(domain);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
domainInfo = new ServiceWorkerDomainInfo;
|
||||
mDomainMap.Put(domain, domainInfo);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(domainInfo);
|
||||
|
||||
ServiceWorkerContainer* container = static_cast<ServiceWorkerContainer*>(aListener);
|
||||
domainInfo->mServiceWorkerContainers.AppendElement(container);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::RemoveContainerEventListener(nsIURI* aDocumentURI, nsIDOMEventTarget* aListener)
|
||||
{
|
||||
MOZ_ASSERT(aDocumentURI);
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo = GetDomainInfo(aDocumentURI);
|
||||
if (!domainInfo) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ServiceWorkerContainer* container = static_cast<ServiceWorkerContainer*>(aListener);
|
||||
domainInfo->mServiceWorkerContainers.RemoveElement(container);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::FireEventOnServiceWorkerContainers(
|
||||
ServiceWorkerRegistration* aRegistration,
|
||||
const nsAString& aName)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
nsRefPtr<ServiceWorkerDomainInfo> domainInfo =
|
||||
GetDomainInfo(aRegistration->mScriptSpec);
|
||||
|
||||
if (domainInfo) {
|
||||
nsTObserverArray<ServiceWorkerContainer*>::ForwardIterator it(domainInfo->mServiceWorkerContainers);
|
||||
while (it.HasMore()) {
|
||||
nsRefPtr<ServiceWorkerContainer> target = it.GetNext();
|
||||
nsIURI* targetURI = target->GetDocumentURI();
|
||||
if (!targetURI) {
|
||||
NS_WARNING("Controlled domain cannot have page with null URI!");
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCString path;
|
||||
nsresult rv = targetURI->GetSpec(path);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCString scope = FindScopeForPath(domainInfo->mOrderedScopes, path);
|
||||
if (scope.IsEmpty() ||
|
||||
!scope.Equals(aRegistration->mScope)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
target->DispatchTrustedEvent(aName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::CreateServiceWorker(const nsACString& aScriptSpec,
|
||||
const nsACString& aScope,
|
||||
|
@ -12,10 +12,10 @@
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "mozilla/dom/ServiceWorkerContainer.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsTWeakRef.h"
|
||||
|
||||
class nsIScriptError;
|
||||
@ -210,6 +210,12 @@ public:
|
||||
// Scope to registration.
|
||||
nsRefPtrHashtable<nsCStringHashKey, ServiceWorkerRegistration> mServiceWorkerRegistrations;
|
||||
|
||||
// This array can't be stored in ServiceWorkerRegistration because one may
|
||||
// not exist when a certain window is opened, but we still want that
|
||||
// window's container to be notified if it's in scope.
|
||||
// The containers inform the SWM on creation and destruction.
|
||||
nsTObserverArray<ServiceWorkerContainer*> mServiceWorkerContainers;
|
||||
|
||||
ServiceWorkerDomainInfo()
|
||||
{ }
|
||||
|
||||
@ -232,9 +238,15 @@ public:
|
||||
ServiceWorkerManager::AddScope(mOrderedScopes, aScope);
|
||||
return registration;
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(ServiceWorkerDomainInfo)
|
||||
|
||||
private:
|
||||
~ServiceWorkerDomainInfo()
|
||||
{ }
|
||||
};
|
||||
|
||||
nsClassHashtable<nsCStringHashKey, ServiceWorkerDomainInfo> mDomainMap;
|
||||
nsRefPtrHashtable<nsCStringHashKey, ServiceWorkerDomainInfo> mDomainMap;
|
||||
|
||||
void
|
||||
ResolveRegisterPromises(ServiceWorkerRegistration* aRegistration,
|
||||
@ -296,6 +308,15 @@ private:
|
||||
ServiceWorkerDomainInfo* aDomainInfo,
|
||||
void *aUnused);
|
||||
|
||||
already_AddRefed<ServiceWorkerDomainInfo>
|
||||
GetDomainInfo(nsIDocument* aDoc);
|
||||
|
||||
already_AddRefed<ServiceWorkerDomainInfo>
|
||||
GetDomainInfo(nsIURI* aURI);
|
||||
|
||||
already_AddRefed<ServiceWorkerDomainInfo>
|
||||
GetDomainInfo(const nsCString& aURL);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistration>
|
||||
GetServiceWorkerRegistration(nsPIDOMWindow* aWindow);
|
||||
|
||||
@ -314,6 +335,10 @@ private:
|
||||
static void
|
||||
RemoveScope(nsTArray<nsCString>& aList, const nsACString& aScope);
|
||||
|
||||
void
|
||||
FireEventOnServiceWorkerContainers(ServiceWorkerRegistration* aRegistration,
|
||||
const nsAString& aName);
|
||||
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(ServiceWorkerManager,
|
||||
|
Loading…
Reference in New Issue
Block a user