Bug 1434342 P5 Support caching the ServiceWorker DOM instance on the global. r=asuth

This commit is contained in:
Ben Kelly 2018-01-31 09:10:26 -08:00
parent 00f7b788b7
commit 0ff28a0a92
7 changed files with 114 additions and 0 deletions

View File

@ -246,6 +246,7 @@
#include "mozilla/dom/NavigatorBinding.h"
#include "mozilla/dom/ImageBitmap.h"
#include "mozilla/dom/ImageBitmapBinding.h"
#include "mozilla/dom/ServiceWorker.h"
#include "mozilla/dom/ServiceWorkerRegistration.h"
#include "mozilla/dom/U2F.h"
#include "mozilla/dom/WebIDLGlobalNameHash.h"
@ -2395,6 +2396,12 @@ nsPIDOMWindowInner::GetController() const
return Move(nsGlobalWindowInner::Cast(this)->GetController());
}
RefPtr<mozilla::dom::ServiceWorker>
nsPIDOMWindowInner::GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor)
{
return Move(nsGlobalWindowInner::Cast(this)->GetOrCreateServiceWorker(aDescriptor));
}
void
nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
{
@ -6371,6 +6378,39 @@ nsGlobalWindowInner::GetController() const
return Move(controller);
}
RefPtr<ServiceWorker>
nsGlobalWindowInner::GetOrCreateServiceWorker(const ServiceWorkerDescriptor& aDescriptor)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<ServiceWorker> ref;
for (auto sw : mServiceWorkerList) {
if (sw->MatchesDescriptor(aDescriptor)) {
ref = sw;
return ref.forget();
}
}
ref = ServiceWorker::Create(this, aDescriptor);
return ref.forget();
}
void
nsGlobalWindowInner::AddServiceWorker(ServiceWorker* aServiceWorker)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(aServiceWorker);
MOZ_ASSERT(!mServiceWorkerList.Contains(aServiceWorker));
mServiceWorkerList.AppendElement(aServiceWorker);
}
void
nsGlobalWindowInner::RemoveServiceWorker(ServiceWorker* aServiceWorker)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(aServiceWorker);
MOZ_ASSERT(mServiceWorkerList.Contains(aServiceWorker));
mServiceWorkerList.RemoveElement(aServiceWorker);
}
nsresult
nsGlobalWindowInner::FireDelayedDOMEvents()
{

View File

@ -351,6 +351,15 @@ public:
mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const override;
virtual RefPtr<mozilla::dom::ServiceWorker>
GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor) override;
virtual void
AddServiceWorker(mozilla::dom::ServiceWorker* aServiceWorker) override;
virtual void
RemoveServiceWorker(mozilla::dom::ServiceWorker* aServiceWorker) override;
void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
virtual nsresult FireDelayedDOMEvents() override;
@ -1442,6 +1451,10 @@ protected:
mozilla::UniquePtr<mozilla::dom::ClientSource> mClientSource;
// Weak references added by AddServiceWorker() and cleared by
// RemoveServiceWorker() when the ServiceWorker is destroyed.
nsTArray<mozilla::dom::ServiceWorker*> mServiceWorkerList;
nsTArray<RefPtr<mozilla::dom::Promise>> mPendingPromises;
static InnerWindowByIdTable* sInnerWindowsById;

View File

@ -5,12 +5,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIGlobalObject.h"
#include "mozilla/dom/ServiceWorker.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"
#include "nsHostObjectProtocolHandler.h"
using mozilla::Maybe;
using mozilla::dom::ClientInfo;
using mozilla::dom::ServiceWorker;
using mozilla::dom::ServiceWorkerDescriptor;
nsIGlobalObject::~nsIGlobalObject()
@ -132,3 +135,22 @@ nsIGlobalObject::GetController() const
// window and worker globals can currently be controlled as a client.
return Maybe<ServiceWorkerDescriptor>();
}
RefPtr<ServiceWorker>
nsIGlobalObject::GetOrCreateServiceWorker(const ServiceWorkerDescriptor& aDescriptor)
{
MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers");
return nullptr;
}
void
nsIGlobalObject::AddServiceWorker(ServiceWorker* aServiceWorker)
{
MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers");
}
void
nsIGlobalObject::RemoveServiceWorker(ServiceWorker* aServiceWorker)
{
MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers");
}

View File

@ -24,6 +24,12 @@
class nsCycleCollectionTraversalCallback;
class nsIPrincipal;
namespace mozilla {
namespace dom {
class ServiceWorker;
} // namespace dom
} // namespace mozilla
class nsIGlobalObject : public nsISupports,
public mozilla::dom::DispatcherTrait
{
@ -86,6 +92,21 @@ public:
virtual mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>
GetController() const;
// Get the DOM object for the given descriptor or attempt to create one.
// Creation can still fail and return nullptr during shutdown, etc.
virtual RefPtr<mozilla::dom::ServiceWorker>
GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor);
// These methods allow the ServiceWorker instances to note their existence
// so that the global can use weak references to them. The global should
// not hold a strong reference to the ServiceWorker.
virtual void
AddServiceWorker(mozilla::dom::ServiceWorker* aServiceWorker);
// This method must be called by the ServiceWorker before it is destroyed.
virtual void
RemoveServiceWorker(mozilla::dom::ServiceWorker* aServiceWorker);
protected:
virtual ~nsIGlobalObject();

View File

@ -53,6 +53,7 @@ class TabGroup;
class Element;
class Navigator;
class Performance;
class ServiceWorker;
class ServiceWorkerDescriptor;
class ServiceWorkerRegistration;
class Timeout;
@ -334,6 +335,9 @@ public:
mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
RefPtr<mozilla::dom::ServiceWorker>
GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor);
void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
mozilla::dom::TabGroup* TabGroup();

View File

@ -134,5 +134,16 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
mInner->PostMessage(GetParentObject(), aCx, aMessage, aTransferable, aRv);
}
bool
ServiceWorker::MatchesDescriptor(const ServiceWorkerDescriptor& aDescriptor) const
{
// Compare everything in the descriptor except the state. That is mutable
// and may not exactly match.
return mDescriptor.PrincipalInfo() == aDescriptor.PrincipalInfo() &&
mDescriptor.Scope() == aDescriptor.Scope() &&
mDescriptor.ScriptURL() == aDescriptor.ScriptURL() &&
mDescriptor.Id() == aDescriptor.Id();
}
} // namespace dom
} // namespace mozilla

View File

@ -83,6 +83,9 @@ public:
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Sequence<JSObject*>& aTransferable, ErrorResult& aRv);
bool
MatchesDescriptor(const ServiceWorkerDescriptor& aDescriptor) const;
private:
ServiceWorker(nsIGlobalObject* aWindow,
const ServiceWorkerDescriptor& aDescriptor,