зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1162088 - ServiceWorkerManager should use the principal+scope for the initialization of ServiceWorkers, r=nsm,ehsan
This commit is contained in:
Родитель
25e7d5ffdc
Коммит
1d31da42fd
|
@ -13994,18 +13994,19 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
if (!doc) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = services::GetServiceWorkerManager();
|
||||
if (!swm) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIsNavigate) {
|
||||
return swm->IsAvailableForURI(aURI, aShouldIntercept);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
if (!doc) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
return swm->IsAvailableForURI(principal, aURI, aShouldIntercept);
|
||||
}
|
||||
|
||||
return swm->IsControlled(doc, aShouldIntercept);
|
||||
|
@ -14024,13 +14025,9 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
|
|||
nsresult rv = aChannel->GetIsNavigation(&isNavigation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
|
||||
if (!isNavigation) {
|
||||
doc = GetDocument();
|
||||
if (!doc) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
if (!doc) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
bool isReload = mLoadType & LOAD_CMD_RELOAD;
|
||||
|
|
|
@ -20,7 +20,7 @@ interface nsIServiceWorkerUnregisterCallback : nsISupports
|
|||
void unregisterFailed();
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(8ce0d197-5740-4ddf-aa4a-e5a63e611d03)]
|
||||
[scriptable, builtinclass, uuid(103763c8-53ba-42e4-8b26-e601d5bc4afe)]
|
||||
interface nsIServiceWorkerInfo : nsISupports
|
||||
{
|
||||
readonly attribute nsIPrincipal principal;
|
||||
|
@ -33,7 +33,7 @@ interface nsIServiceWorkerInfo : nsISupports
|
|||
readonly attribute DOMString waitingCacheName;
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(384c9aec-29e5-4bdb-abc2-fba10da83e17)]
|
||||
[scriptable, builtinclass, uuid(f9375a26-6f56-417a-b4f7-7ddffa4bd873)]
|
||||
interface nsIServiceWorkerManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -67,7 +67,7 @@ interface nsIServiceWorkerManager : nsISupports
|
|||
void removeReadyPromise(in nsIDOMWindow aWindow);
|
||||
|
||||
// Returns true if a ServiceWorker is available for the scope of aURI.
|
||||
bool isAvailableForURI(in nsIURI aURI);
|
||||
bool isAvailableForURI(in nsIPrincipal aPrincipal, in nsIURI aURI);
|
||||
|
||||
// Returns true if a given document is currently controlled by a ServiceWorker
|
||||
bool isControlled(in nsIDocument aDocument);
|
||||
|
@ -109,7 +109,7 @@ interface nsIServiceWorkerManager : nsISupports
|
|||
/*
|
||||
* This implements the soft update algorithm.
|
||||
*/
|
||||
void softUpdate(in DOMString aScope);
|
||||
void softUpdate(in nsIPrincipal aPrincipal, in DOMString aScope);
|
||||
|
||||
/*
|
||||
* Clears ServiceWorker registrations from memory and disk for the specified
|
||||
|
@ -128,14 +128,16 @@ interface nsIServiceWorkerManager : nsISupports
|
|||
void removeAll();
|
||||
|
||||
// Testing
|
||||
DOMString getScopeForUrl(in DOMString path);
|
||||
DOMString getScopeForUrl(in nsIPrincipal aPrincipal, in DOMString aPath);
|
||||
|
||||
// This is meant to be used only by about:serviceworkers. It returns an array
|
||||
// of nsIServiceWorkerInfo.
|
||||
nsIArray getAllRegistrations();
|
||||
|
||||
void sendPushEvent(in ACString scope, in DOMString data);
|
||||
void sendPushSubscriptionChangeEvent(in ACString scope);
|
||||
void sendPushEvent(in nsIPrincipal aPrincipal, in ACString aScope,
|
||||
in DOMString aData);
|
||||
void sendPushSubscriptionChangeEvent(in nsIPrincipal aPrincipal,
|
||||
in ACString scope);
|
||||
|
||||
void updateAllRegistrations();
|
||||
};
|
||||
|
|
|
@ -10,9 +10,11 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
|||
"nsIServiceWorkerManager");
|
||||
|
||||
addMessageListener("push", function (aMessage) {
|
||||
swm.sendPushEvent(aMessage.data.scope, aMessage.data.payload);
|
||||
let principal = content.document.nodePrincipal;
|
||||
swm.sendPushEvent(principal, aMessage.data.scope, aMessage.data.payload);
|
||||
});
|
||||
|
||||
addMessageListener("pushsubscriptionchange", function (aMessage) {
|
||||
swm.sendPushSubscriptionChangeEvent(aMessage.data);
|
||||
let principal = content.document.nodePrincipal;
|
||||
swm.sendPushSubscriptionChangeEvent(principal, aMessage.data);
|
||||
});
|
||||
|
|
|
@ -114,7 +114,7 @@ public:
|
|||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
nsTArray<ServiceWorkerClientInfo> result;
|
||||
|
||||
swm->GetAllClients(mScope, result);
|
||||
swm->GetAllClients(mWorkerPrivate->GetPrincipal(), mScope, result);
|
||||
nsRefPtr<ResolvePromiseWorkerRunnable> r =
|
||||
new ResolvePromiseWorkerRunnable(mWorkerPrivate, mPromiseProxy, result);
|
||||
|
||||
|
@ -197,7 +197,9 @@ public:
|
|||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
nsresult rv = swm->ClaimClients(mScope, mServiceWorkerID);
|
||||
nsresult rv =
|
||||
swm->ClaimClients(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(),
|
||||
mScope, mServiceWorkerID);
|
||||
|
||||
MutexAutoLock lock(mPromiseProxy->GetCleanUpLock());
|
||||
if (mPromiseProxy->IsClean()) {
|
||||
|
|
|
@ -225,13 +225,19 @@ ServiceWorkerContainer::GetScopeForUrl(const nsAString& aUrl,
|
|||
nsString& aScope,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
|
||||
MOZ_ASSERT(doc);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
MOZ_ASSERT(principal);
|
||||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
|
||||
if (!swm) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = swm->GetScopeForUrl(aUrl, aScope);
|
||||
aRv = swm->GetScopeForUrl(principal, aUrl, aScope);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "ServiceWorker.h"
|
||||
#include "ServiceWorkerClient.h"
|
||||
#include "ServiceWorkerContainer.h"
|
||||
#include "ServiceWorkerRegistrar.h"
|
||||
#include "ServiceWorkerRegistration.h"
|
||||
#include "ServiceWorkerScriptCache.h"
|
||||
#include "ServiceWorkerEvents.h"
|
||||
|
@ -81,6 +82,24 @@ static_assert(nsIHttpChannelInternal::CORS_MODE_CORS == static_cast<uint32_t>(Re
|
|||
static_assert(nsIHttpChannelInternal::CORS_MODE_CORS_WITH_FORCED_PREFLIGHT == static_cast<uint32_t>(RequestMode::Cors_with_forced_preflight),
|
||||
"RequestMode enumeration value should match Necko CORS mode value.");
|
||||
|
||||
struct ServiceWorkerManager::RegistrationDataPerPrincipal
|
||||
{
|
||||
// Ordered list of scopes for glob matching.
|
||||
// Each entry is an absolute URL representing the scope.
|
||||
// Each value of the hash table is an array of an absolute URLs representing
|
||||
// the scopes.
|
||||
//
|
||||
// An array is used for now since the number of controlled scopes per
|
||||
// domain is expected to be relatively low. If that assumption was proved
|
||||
// wrong this should be replaced with a better structure to avoid the
|
||||
// memmoves associated with inserting stuff in the middle of the array.
|
||||
nsTArray<nsCString> mOrderedScopes;
|
||||
|
||||
// Scope to registration.
|
||||
// The scope should be a fully qualified valid URL.
|
||||
nsRefPtrHashtable<nsCStringHashKey, ServiceWorkerRegistrationInfo> mInfos;
|
||||
};
|
||||
|
||||
struct ServiceWorkerManager::PendingOperation
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
|
@ -258,7 +277,7 @@ ServiceWorkerManager::ServiceWorkerManager()
|
|||
ServiceWorkerManager::~ServiceWorkerManager()
|
||||
{
|
||||
// The map will assert if it is not empty when destroyed.
|
||||
mServiceWorkerRegistrationInfos.Clear();
|
||||
mRegistrationInfos.Clear();
|
||||
}
|
||||
|
||||
class ContinueLifecycleTask : public nsISupports
|
||||
|
@ -642,7 +661,7 @@ public:
|
|||
}
|
||||
|
||||
if (mJobType == REGISTER_JOB) {
|
||||
mRegistration = swm->GetRegistration(mScope);
|
||||
mRegistration = swm->GetRegistration(mPrincipal, mScope);
|
||||
|
||||
if (mRegistration) {
|
||||
nsRefPtr<ServiceWorkerInfo> newest = mRegistration->Newest();
|
||||
|
@ -1437,8 +1456,20 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < swm->mOrderedScopes.Length(); ++i) {
|
||||
NS_ConvertUTF8toUTF16 scope(swm->mOrderedScopes[i]);
|
||||
nsAutoCString principalKey;
|
||||
rv = swm->PrincipalToScopeKey(principal, principalKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
ServiceWorkerManager::RegistrationDataPerPrincipal* data;
|
||||
if (!swm->mRegistrationInfos.Get(principalKey, &data)) {
|
||||
mPromise->MaybeResolve(array);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < data->mOrderedScopes.Length(); ++i) {
|
||||
NS_ConvertUTF8toUTF16 scope(data->mOrderedScopes[i]);
|
||||
|
||||
nsCOMPtr<nsIURI> scopeURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), scope, nullptr, nullptr);
|
||||
|
@ -1548,7 +1579,7 @@ public:
|
|||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
swm->GetServiceWorkerRegistrationInfo(uri);
|
||||
swm->GetServiceWorkerRegistrationInfo(principal, uri);
|
||||
|
||||
if (!registration) {
|
||||
mPromise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
|
@ -1724,12 +1755,15 @@ public:
|
|||
#endif /* ! MOZ_SIMPLEPUSH */
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::SendPushEvent(const nsACString& aScope, const nsAString& aData)
|
||||
ServiceWorkerManager::SendPushEvent(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
const nsAString& aData)
|
||||
{
|
||||
#ifdef MOZ_SIMPLEPUSH
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
#else
|
||||
nsRefPtr<ServiceWorker> serviceWorker = CreateServiceWorkerForScope(aScope);
|
||||
nsRefPtr<ServiceWorker> serviceWorker =
|
||||
CreateServiceWorkerForScope(aPrincipal, aScope);
|
||||
if (!serviceWorker) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1738,7 +1772,8 @@ ServiceWorkerManager::SendPushEvent(const nsACString& aScope, const nsAString& a
|
|||
new nsMainThreadPtrHolder<ServiceWorker>(serviceWorker));
|
||||
|
||||
nsRefPtr<SendPushEventRunnable> r =
|
||||
new SendPushEventRunnable(serviceWorker->GetWorkerPrivate(), aData, serviceWorkerHandle);
|
||||
new SendPushEventRunnable(serviceWorker->GetWorkerPrivate(), aData,
|
||||
serviceWorkerHandle);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
|
@ -1751,12 +1786,14 @@ ServiceWorkerManager::SendPushEvent(const nsACString& aScope, const nsAString& a
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::SendPushSubscriptionChangeEvent(const nsACString& aScope)
|
||||
ServiceWorkerManager::SendPushSubscriptionChangeEvent(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope)
|
||||
{
|
||||
#ifdef MOZ_SIMPLEPUSH
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
#else
|
||||
nsRefPtr<ServiceWorker> serviceWorker = CreateServiceWorkerForScope(aScope);
|
||||
nsRefPtr<ServiceWorker> serviceWorker =
|
||||
CreateServiceWorkerForScope(aPrincipal, aScope);
|
||||
if (!serviceWorker) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1764,7 +1801,8 @@ ServiceWorkerManager::SendPushSubscriptionChangeEvent(const nsACString& aScope)
|
|||
new nsMainThreadPtrHolder<ServiceWorker>(serviceWorker));
|
||||
|
||||
nsRefPtr<SendPushSubscriptionChangeEventRunnable> r =
|
||||
new SendPushSubscriptionChangeEventRunnable(serviceWorker->GetWorkerPrivate(), serviceWorkerHandle);
|
||||
new SendPushSubscriptionChangeEventRunnable(
|
||||
serviceWorker->GetWorkerPrivate(), serviceWorkerHandle);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
|
@ -1863,8 +1901,17 @@ bool
|
|||
ServiceWorkerManager::CheckReadyPromise(nsPIDOMWindow* aWindow,
|
||||
nsIURI* aURI, Promise* aPromise)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
MOZ_ASSERT(doc);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
MOZ_ASSERT(principal);
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetServiceWorkerRegistrationInfo(aURI);
|
||||
GetServiceWorkerRegistrationInfo(principal, aURI);
|
||||
|
||||
if (registration && registration->mActiveWorker) {
|
||||
NS_ConvertUTF8toUTF16 scope(registration->mScope);
|
||||
|
@ -1878,7 +1925,8 @@ ServiceWorkerManager::CheckReadyPromise(nsPIDOMWindow* aWindow,
|
|||
}
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
ServiceWorkerManager::CreateServiceWorkerForScope(const nsACString& aScope)
|
||||
ServiceWorkerManager::CreateServiceWorkerForScope(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
|
@ -1887,7 +1935,8 @@ ServiceWorkerManager::CreateServiceWorkerForScope(const nsACString& aScope)
|
|||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration = GetServiceWorkerRegistrationInfo(scopeURI);
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetServiceWorkerRegistrationInfo(aPrincipal, scopeURI);
|
||||
if (!registration) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1913,7 +1962,7 @@ class ServiceWorkerUnregisterJob final : public ServiceWorkerJob
|
|||
nsRefPtr<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
const nsCString mScope;
|
||||
nsCOMPtr<nsIServiceWorkerUnregisterCallback> mCallback;
|
||||
PrincipalInfo mPrincipalInfo;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
|
||||
~ServiceWorkerUnregisterJob()
|
||||
{ }
|
||||
|
@ -1922,11 +1971,11 @@ public:
|
|||
ServiceWorkerUnregisterJob(ServiceWorkerJobQueue* aQueue,
|
||||
const nsACString& aScope,
|
||||
nsIServiceWorkerUnregisterCallback* aCallback,
|
||||
PrincipalInfo& aPrincipalInfo)
|
||||
nsIPrincipal* aPrincipal)
|
||||
: ServiceWorkerJob(aQueue)
|
||||
, mScope(aScope)
|
||||
, mCallback(aCallback)
|
||||
, mPrincipalInfo(aPrincipalInfo)
|
||||
, mPrincipal(aPrincipal)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
@ -1947,12 +1996,30 @@ private:
|
|||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
PrincipalInfo principalInfo;
|
||||
if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(mPrincipal,
|
||||
&principalInfo)))) {
|
||||
return mCallback ? mCallback->UnregisterSucceeded(false) : NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
|
||||
nsAutoCString principalKey;
|
||||
nsresult rv = swm->PrincipalToScopeKey(mPrincipal, principalKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return mCallback ? mCallback->UnregisterSucceeded(false) : NS_OK;
|
||||
}
|
||||
|
||||
// "Let registration be the result of running [[Get Registration]]
|
||||
// algorithm passing scope as the argument."
|
||||
ServiceWorkerManager::RegistrationDataPerPrincipal* data;
|
||||
if (!swm->mRegistrationInfos.Get(principalKey, &data)) {
|
||||
// "If registration is null, then, resolve promise with false."
|
||||
return mCallback ? mCallback->UnregisterSucceeded(false) : NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
if (!swm->mServiceWorkerRegistrationInfos.Get(mScope, getter_AddRefs(registration))) {
|
||||
if (!data->mInfos.Get(mScope, getter_AddRefs(registration))) {
|
||||
// "If registration is null, then, resolve promise with false."
|
||||
return mCallback ? mCallback->UnregisterSucceeded(false) : NS_OK;
|
||||
}
|
||||
|
@ -1962,7 +2029,7 @@ private:
|
|||
// "Set registration's uninstalling flag."
|
||||
registration->mPendingUninstall = true;
|
||||
// "Resolve promise with true"
|
||||
nsresult rv = mCallback ? mCallback->UnregisterSucceeded(true) : NS_OK;
|
||||
rv = mCallback ? mCallback->UnregisterSucceeded(true) : NS_OK;
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1980,7 +2047,7 @@ private:
|
|||
}
|
||||
|
||||
MOZ_ASSERT(swm->mActor);
|
||||
swm->mActor->SendUnregisterServiceWorker(mPrincipalInfo,
|
||||
swm->mActor->SendUnregisterServiceWorker(principalInfo,
|
||||
NS_ConvertUTF8toUTF16(mScope));
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2021,14 +2088,8 @@ ServiceWorkerManager::Unregister(nsIPrincipal* aPrincipal,
|
|||
ServiceWorkerJobQueue* queue = GetOrCreateJobQueue(scope);
|
||||
MOZ_ASSERT(queue);
|
||||
|
||||
PrincipalInfo principalInfo;
|
||||
if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(aPrincipal,
|
||||
&principalInfo)))) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerUnregisterJob> job =
|
||||
new ServiceWorkerUnregisterJob(queue, scope, aCallback, principalInfo);
|
||||
new ServiceWorkerUnregisterJob(queue, scope, aCallback, aPrincipal);
|
||||
|
||||
if (mActor) {
|
||||
queue->Append(job);
|
||||
|
@ -2246,6 +2307,7 @@ ServiceWorkerManager::StoreRegistration(
|
|||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
nsCOMPtr<nsIDocument> document = aWindow->GetExtantDoc();
|
||||
return GetServiceWorkerRegistrationInfo(document);
|
||||
}
|
||||
|
@ -2253,26 +2315,35 @@ ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsPIDOMWindow* aWindow)
|
|||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsIDocument* aDoc)
|
||||
{
|
||||
MOZ_ASSERT(aDoc);
|
||||
nsCOMPtr<nsIURI> documentURI = aDoc->GetDocumentURI();
|
||||
return GetServiceWorkerRegistrationInfo(documentURI);
|
||||
nsCOMPtr<nsIPrincipal> principal = aDoc->NodePrincipal();
|
||||
return GetServiceWorkerRegistrationInfo(principal, documentURI);
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsIURI* aURI)
|
||||
ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsIPrincipal* aPrincipal,
|
||||
nsIURI* aURI)
|
||||
{
|
||||
nsCString spec;
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
nsAutoCString spec;
|
||||
nsresult rv = aURI->GetSpec(spec);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCString scope = FindScopeForPath(mOrderedScopes, spec);
|
||||
if (scope.IsEmpty()) {
|
||||
nsAutoCString scope;
|
||||
RegistrationDataPerPrincipal* data;
|
||||
if (!FindScopeForPath(aPrincipal, spec, &data, scope)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(data);
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
mServiceWorkerRegistrationInfos.Get(scope, getter_AddRefs(registration));
|
||||
data->mInfos.Get(scope, getter_AddRefs(registration));
|
||||
// ordered scopes and registrations better be in sync.
|
||||
MOZ_ASSERT(registration);
|
||||
|
||||
|
@ -2282,14 +2353,84 @@ ServiceWorkerManager::GetServiceWorkerRegistrationInfo(nsIURI* aURI)
|
|||
return registration.forget();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ServiceWorkerManager::AddScope(nsTArray<nsCString>& aList, const nsACString& aScope)
|
||||
/* static */ nsresult
|
||||
ServiceWorkerManager::PrincipalToScopeKey(nsIPrincipal* aPrincipal,
|
||||
nsACString& aKey)
|
||||
{
|
||||
for (uint32_t i = 0; i < aList.Length(); ++i) {
|
||||
const nsCString& current = aList[i];
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
||||
aKey.AssignLiteral(SERVICEWORKERREGISTRAR_SYSTEM_PRINCIPAL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString key;
|
||||
nsresult rv;
|
||||
|
||||
bool isNullPrincipal = true;
|
||||
rv = aPrincipal->GetIsNullPrincipal(&isNullPrincipal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// No null principals.
|
||||
if (isNullPrincipal) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint32_t appId;
|
||||
rv = aPrincipal->GetAppId(&appId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
key.AppendInt(appId);
|
||||
key.Append('-');
|
||||
|
||||
bool inBrowserElement;
|
||||
rv = aPrincipal->GetIsInBrowserElement(&inBrowserElement);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (inBrowserElement) {
|
||||
key.AppendLiteral(SERVICEWORKERREGISTRAR_TRUE);
|
||||
} else {
|
||||
key.AppendLiteral(SERVICEWORKERREGISTRAR_FALSE);
|
||||
}
|
||||
|
||||
aKey = key;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ServiceWorkerManager::AddScopeAndRegistration(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerRegistrationInfo* aInfo)
|
||||
{
|
||||
MOZ_ASSERT(aInfo);
|
||||
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
nsAutoCString principalKey;
|
||||
nsresult rv = swm->PrincipalToScopeKey(aPrincipal, principalKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
RegistrationDataPerPrincipal* data;
|
||||
if (!swm->mRegistrationInfos.Get(principalKey, &data)) {
|
||||
data = new RegistrationDataPerPrincipal();
|
||||
swm->mRegistrationInfos.Put(principalKey, data);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < data->mOrderedScopes.Length(); ++i) {
|
||||
const nsCString& current = data->mOrderedScopes[i];
|
||||
|
||||
// Perfect match!
|
||||
if (aScope.Equals(current)) {
|
||||
data->mInfos.Put(aScope, aInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2297,34 +2438,95 @@ ServiceWorkerManager::AddScope(nsTArray<nsCString>& aList, const nsACString& aSc
|
|||
// /foo/bar should be before /foo/
|
||||
// Similarly /foo/b is between the two.
|
||||
if (StringBeginsWith(aScope, current)) {
|
||||
aList.InsertElementAt(i, aScope);
|
||||
data->mOrderedScopes.InsertElementAt(i, aScope);
|
||||
data->mInfos.Put(aScope, aInfo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
aList.AppendElement(aScope);
|
||||
data->mOrderedScopes.AppendElement(aScope);
|
||||
data->mInfos.Put(aScope, aInfo);
|
||||
}
|
||||
|
||||
/* static */ nsCString
|
||||
ServiceWorkerManager::FindScopeForPath(nsTArray<nsCString>& aList, const nsACString& aPath)
|
||||
/* static */ bool
|
||||
ServiceWorkerManager::FindScopeForPath(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aPath,
|
||||
RegistrationDataPerPrincipal** aData,
|
||||
nsACString& aMatch)
|
||||
{
|
||||
nsCString match;
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT(aData);
|
||||
|
||||
for (uint32_t i = 0; i < aList.Length(); ++i) {
|
||||
const nsCString& current = aList[i];
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
nsAutoCString principalKey;
|
||||
nsresult rv = swm->PrincipalToScopeKey(aPrincipal, principalKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!swm->mRegistrationInfos.Get(principalKey, aData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < (*aData)->mOrderedScopes.Length(); ++i) {
|
||||
const nsCString& current = (*aData)->mOrderedScopes[i];
|
||||
if (StringBeginsWith(aPath, current)) {
|
||||
match = current;
|
||||
break;
|
||||
aMatch = current;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ServiceWorkerManager::RemoveScope(nsTArray<nsCString>& aList, const nsACString& aScope)
|
||||
#ifdef DEBUG
|
||||
/* static */ bool
|
||||
ServiceWorkerManager::HasScope(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope)
|
||||
{
|
||||
aList.RemoveElement(aScope);
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
nsAutoCString principalKey;
|
||||
nsresult rv = swm->PrincipalToScopeKey(aPrincipal, principalKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RegistrationDataPerPrincipal* data;
|
||||
if (!swm->mRegistrationInfos.Get(principalKey, &data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return data->mOrderedScopes.Contains(aScope);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* static */ void
|
||||
ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
{
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
nsAutoCString principalKey;
|
||||
nsresult rv = swm->PrincipalToScopeKey(aRegistration->mPrincipal, principalKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
RegistrationDataPerPrincipal* data;
|
||||
if (!swm->mRegistrationInfos.Get(principalKey, &data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
data->mInfos.Remove(aRegistration->mScope);
|
||||
data->mOrderedScopes.RemoveElement(aRegistration->mScope);
|
||||
|
||||
if (data->mOrderedScopes.IsEmpty()) {
|
||||
swm->mRegistrationInfos.Remove(principalKey);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2389,15 +2591,19 @@ ServiceWorkerManager::StopControllingADocument(ServiceWorkerRegistrationInfo* aR
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::GetScopeForUrl(const nsAString& aUrl, nsAString& aScope)
|
||||
ServiceWorkerManager::GetScopeForUrl(nsIPrincipal* aPrincipal,
|
||||
const nsAString& aUrl, nsAString& aScope)
|
||||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, nullptr, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> r = GetServiceWorkerRegistrationInfo(uri);
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> r =
|
||||
GetServiceWorkerRegistrationInfo(aPrincipal, uri);
|
||||
if (!r) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -2502,7 +2708,8 @@ ServiceWorkerManager::GetServiceWorkerForScope(nsIDOMWindow* aWindow,
|
|||
}
|
||||
////////////////////////////////////////////
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration = GetRegistration(scope);
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetRegistration(documentPrincipal, scope);
|
||||
if (NS_WARN_IF(!registration)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -2780,7 +2987,7 @@ ServiceWorkerManager::DispatchFetchEvent(nsIDocument* aDoc, nsIInterceptedChanne
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetServiceWorkerRegistrationInfo(uri);
|
||||
GetServiceWorkerRegistrationInfo(aDoc->NodePrincipal(), uri);
|
||||
if (!registration) {
|
||||
NS_WARNING("No registration found when dispatching the fetch event");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2822,12 +3029,14 @@ ServiceWorkerManager::DispatchFetchEvent(nsIDocument* aDoc, nsIInterceptedChanne
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::IsAvailableForURI(nsIURI* aURI, bool* aIsAvailable)
|
||||
ServiceWorkerManager::IsAvailableForURI(nsIPrincipal* aPrincipal, nsIURI* aURI,
|
||||
bool* aIsAvailable)
|
||||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT(aURI);
|
||||
MOZ_ASSERT(aIsAvailable);
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetServiceWorkerRegistrationInfo(aURI);
|
||||
GetServiceWorkerRegistrationInfo(aPrincipal, aURI);
|
||||
*aIsAvailable = registration && registration->mActiveWorker;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3008,13 +3217,14 @@ ServiceWorkerManager::InvalidateServiceWorkerRegistrationWorker(ServiceWorkerReg
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::SoftUpdate(const nsAString& aScope)
|
||||
ServiceWorkerManager::SoftUpdate(nsIPrincipal* aPrincipal,
|
||||
const nsAString& aScope)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
NS_ConvertUTF16toUTF8 scope(aScope);
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||
mServiceWorkerRegistrationInfos.Get(scope, getter_AddRefs(registration));
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetRegistration(aPrincipal, scope);
|
||||
if (NS_WARN_IF(!registration)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3156,10 +3366,14 @@ ClaimMatchingClients(nsISupportsHashKey* aKey, void* aData)
|
|||
} // anonymous namespace
|
||||
|
||||
void
|
||||
ServiceWorkerManager::GetAllClients(const nsCString& aScope,
|
||||
ServiceWorkerManager::GetAllClients(nsIPrincipal* aPrincipal,
|
||||
const nsCString& aScope,
|
||||
nsTArray<ServiceWorkerClientInfo>& aControlledDocuments)
|
||||
{
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration = GetRegistration(aScope);
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetRegistration(aPrincipal, aScope);
|
||||
|
||||
if (!registration) {
|
||||
// The registration was removed, leave the array empty.
|
||||
|
@ -3205,10 +3419,11 @@ ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
nsresult
|
||||
ServiceWorkerManager::ClaimClients(const nsCString& aScope, uint64_t aId)
|
||||
ServiceWorkerManager::ClaimClients(nsIPrincipal* aPrincipal,
|
||||
const nsCString& aScope, uint64_t aId)
|
||||
{
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetRegistration(aScope);
|
||||
GetRegistration(aPrincipal, aScope);
|
||||
|
||||
if (!registration || !registration->mActiveWorker ||
|
||||
!(registration->mActiveWorker->ID() == aId)) {
|
||||
|
@ -3227,6 +3442,27 @@ ServiceWorkerManager::FireControllerChange(ServiceWorkerRegistrationInfo* aRegis
|
|||
mControlledDocuments.EnumerateRead(FireControllerChangeOnMatchingDocument, aRegistration);
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
ServiceWorkerManager::GetRegistration(nsIPrincipal* aPrincipal,
|
||||
const nsCString& aScope) const
|
||||
{
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> reg;
|
||||
|
||||
nsAutoCString scopeKey;
|
||||
nsresult rv = PrincipalToScopeKey(aPrincipal, scopeKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return reg.forget();
|
||||
}
|
||||
|
||||
RegistrationDataPerPrincipal* data;
|
||||
if (!mRegistrationInfos.Get(scopeKey, &data)) {
|
||||
return reg.forget();
|
||||
}
|
||||
|
||||
data->mInfos.Get(aScope, getter_AddRefs(reg));
|
||||
return reg.forget();
|
||||
}
|
||||
|
||||
ServiceWorkerRegistrationInfo*
|
||||
ServiceWorkerManager::CreateNewRegistration(const nsCString& aScope,
|
||||
nsIPrincipal* aPrincipal)
|
||||
|
@ -3237,11 +3473,11 @@ ServiceWorkerManager::CreateNewRegistration(const nsCString& aScope,
|
|||
nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), aScope, nullptr, nullptr);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
#endif
|
||||
|
||||
ServiceWorkerRegistrationInfo* registration = new ServiceWorkerRegistrationInfo(aScope, aPrincipal);
|
||||
// From now on ownership of registration is with
|
||||
// mServiceWorkerRegistrationInfos.
|
||||
mServiceWorkerRegistrationInfos.Put(aScope, registration);
|
||||
AddScope(mOrderedScopes, aScope);
|
||||
AddScopeAndRegistration(aPrincipal, aScope, registration);
|
||||
return registration;
|
||||
}
|
||||
|
||||
|
@ -3260,8 +3496,6 @@ ServiceWorkerManager::RemoveRegistrationInternal(ServiceWorkerRegistrationInfo*
|
|||
{
|
||||
MOZ_ASSERT(aRegistration);
|
||||
MOZ_ASSERT(!aRegistration->IsControllingDocuments());
|
||||
MOZ_ASSERT(mServiceWorkerRegistrationInfos.Contains(aRegistration->mScope));
|
||||
ServiceWorkerManager::RemoveScope(mOrderedScopes, aRegistration->mScope);
|
||||
|
||||
// All callers should be either from a job in which case the actor is
|
||||
// available, or from MaybeStopControlling(), in which case, this will only be
|
||||
|
@ -3279,7 +3513,9 @@ ServiceWorkerManager::RemoveRegistrationInternal(ServiceWorkerRegistrationInfo*
|
|||
NS_WARNING("Unable to unregister serviceworker due to possible OOM");
|
||||
return;
|
||||
}
|
||||
mActor->SendUnregisterServiceWorker(principalInfo, NS_ConvertUTF8toUTF16(aRegistration->mScope));
|
||||
|
||||
mActor->SendUnregisterServiceWorker(principalInfo,
|
||||
NS_ConvertUTF8toUTF16(aRegistration->mScope));
|
||||
}
|
||||
|
||||
class ServiceWorkerDataInfo final : public nsIServiceWorkerInfo
|
||||
|
@ -3309,8 +3545,8 @@ void
|
|||
ServiceWorkerManager::RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
{
|
||||
RemoveRegistrationInternal(aRegistration);
|
||||
MOZ_ASSERT(mServiceWorkerRegistrationInfos.Contains(aRegistration->mScope));
|
||||
mServiceWorkerRegistrationInfos.Remove(aRegistration->mScope);
|
||||
MOZ_ASSERT(HasScope(aRegistration->mPrincipal, aRegistration->mScope));
|
||||
RemoveScopeAndRegistration(aRegistration);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -3384,6 +3620,17 @@ UnregisterIfMatchesHost(const nsACString& aScope,
|
|||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// If host/aData is null, unconditionally unregisters.
|
||||
PLDHashOperator
|
||||
UnregisterIfMatchesHostPerPrincipal(const nsACString& aKey,
|
||||
ServiceWorkerManager::RegistrationDataPerPrincipal* aData,
|
||||
void* aUserData)
|
||||
{
|
||||
aData->mInfos.EnumerateRead(UnregisterIfMatchesHost, aUserData);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
NS_IMPL_ISUPPORTS(ServiceWorkerDataInfo, nsIServiceWorkerInfo)
|
||||
|
||||
|
@ -3505,7 +3752,8 @@ NS_IMETHODIMP
|
|||
ServiceWorkerManager::Remove(const nsACString& aHost)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
mServiceWorkerRegistrationInfos.EnumerateRead(UnregisterIfMatchesHost, &const_cast<nsACString&>(aHost));
|
||||
mRegistrationInfos.EnumerateRead(UnregisterIfMatchesHostPerPrincipal,
|
||||
&const_cast<nsACString&>(aHost));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3513,7 +3761,7 @@ NS_IMETHODIMP
|
|||
ServiceWorkerManager::RemoveAll()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
mServiceWorkerRegistrationInfos.EnumerateRead(UnregisterIfMatchesHost, nullptr);
|
||||
mRegistrationInfos.EnumerateRead(UnregisterIfMatchesHostPerPrincipal, nullptr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3523,18 +3771,27 @@ UpdateEachRegistration(const nsACString& aKey,
|
|||
void* aUserArg) {
|
||||
auto This = static_cast<ServiceWorkerManager*>(aUserArg);
|
||||
MOZ_ASSERT(!aInfo->mScope.IsEmpty());
|
||||
nsresult res = This->SoftUpdate(NS_ConvertUTF8toUTF16(aInfo->mScope));
|
||||
nsresult res = This->SoftUpdate(aInfo->mPrincipal,
|
||||
NS_ConvertUTF8toUTF16(aInfo->mScope));
|
||||
unused << NS_WARN_IF(NS_FAILED(res));
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
UpdateEachRegistrationPerPrincipal(const nsACString& aKey,
|
||||
ServiceWorkerManager::RegistrationDataPerPrincipal* aData,
|
||||
void* aUserArg) {
|
||||
aData->mInfos.EnumerateRead(UpdateEachRegistration, aUserArg);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::UpdateAllRegistrations()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
mServiceWorkerRegistrationInfos.EnumerateRead(UpdateEachRegistration, this);
|
||||
mRegistrationInfos.EnumerateRead(UpdateEachRegistrationPerPrincipal, this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -364,18 +364,8 @@ public:
|
|||
return res;
|
||||
}
|
||||
|
||||
// Ordered list of scopes for glob matching.
|
||||
// Each entry is an absolute URL representing the scope.
|
||||
//
|
||||
// An array is used for now since the number of controlled scopes per
|
||||
// domain is expected to be relatively low. If that assumption was proved
|
||||
// wrong this should be replaced with a better structure to avoid the
|
||||
// memmoves associated with inserting stuff in the middle of the array.
|
||||
nsTArray<nsCString> mOrderedScopes;
|
||||
|
||||
// Scope to registration.
|
||||
// The scope should be a fully qualified valid URL.
|
||||
nsRefPtrHashtable<nsCStringHashKey, ServiceWorkerRegistrationInfo> mServiceWorkerRegistrationInfos;
|
||||
struct RegistrationDataPerPrincipal;
|
||||
nsClassHashtable<nsCStringHashKey, RegistrationDataPerPrincipal> mRegistrationInfos;
|
||||
|
||||
nsTObserverArray<ServiceWorkerRegistrationListener*> mServiceWorkerRegistrationListeners;
|
||||
|
||||
|
@ -390,12 +380,7 @@ public:
|
|||
nsDataHashtable<nsCStringHashKey, bool> mSetOfScopesBeingUpdated;
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetRegistration(const nsCString& aScope) const
|
||||
{
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> reg;
|
||||
mServiceWorkerRegistrationInfos.Get(aScope, getter_AddRefs(reg));
|
||||
return reg.forget();
|
||||
}
|
||||
GetRegistration(nsIPrincipal* aPrincipal, const nsCString& aScope) const;
|
||||
|
||||
ServiceWorkerRegistrationInfo*
|
||||
CreateNewRegistration(const nsCString& aScope, nsIPrincipal* aPrincipal);
|
||||
|
@ -429,7 +414,8 @@ public:
|
|||
uint32_t aFlags);
|
||||
|
||||
void
|
||||
GetAllClients(const nsCString& aScope,
|
||||
GetAllClients(nsIPrincipal* aPrincipal,
|
||||
const nsCString& aScope,
|
||||
nsTArray<ServiceWorkerClientInfo>& aControlledDocuments);
|
||||
|
||||
void
|
||||
|
@ -437,7 +423,7 @@ public:
|
|||
ServiceWorkerRegistrationInfo* aWorkerRegistration);
|
||||
|
||||
nsresult
|
||||
ClaimClients(const nsCString& aScope, uint64_t aId);
|
||||
ClaimClients(nsIPrincipal* aPrincipal, const nsCString& aScope, uint64_t aId);
|
||||
|
||||
static already_AddRefed<ServiceWorkerManager>
|
||||
GetInstance();
|
||||
|
@ -487,7 +473,8 @@ private:
|
|||
nsISupports** aServiceWorker);
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
CreateServiceWorkerForScope(const nsACString& aScope);
|
||||
CreateServiceWorkerForScope(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope);
|
||||
|
||||
void
|
||||
InvalidateServiceWorkerRegistrationWorker(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
|
@ -507,16 +494,29 @@ private:
|
|||
GetServiceWorkerRegistrationInfo(nsIDocument* aDoc);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetServiceWorkerRegistrationInfo(nsIURI* aURI);
|
||||
GetServiceWorkerRegistrationInfo(nsIPrincipal* aPrincipal, nsIURI* aURI);
|
||||
|
||||
// This method generates a key using appId and isInElementBrowser from the
|
||||
// principal. We don't use the origin because it can simple change during the
|
||||
// loading.
|
||||
static nsresult
|
||||
PrincipalToScopeKey(nsIPrincipal* aPrincipal, nsACString& aPrincipalKey);
|
||||
|
||||
static void
|
||||
AddScope(nsTArray<nsCString>& aList, const nsACString& aScope);
|
||||
AddScopeAndRegistration(nsIPrincipal* aPrincipal, const nsACString& aScope,
|
||||
ServiceWorkerRegistrationInfo* aRegistation);
|
||||
|
||||
static nsCString
|
||||
FindScopeForPath(nsTArray<nsCString>& aList, const nsACString& aPath);
|
||||
static bool
|
||||
FindScopeForPath(nsIPrincipal* aPrincipal, const nsACString& aPath,
|
||||
RegistrationDataPerPrincipal** aData, nsACString& aMatch);
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool
|
||||
HasScope(nsIPrincipal* aPrincipal, const nsACString& aScope);
|
||||
#endif
|
||||
|
||||
static void
|
||||
RemoveScope(nsTArray<nsCString>& aList, const nsACString& aScope);
|
||||
RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
void
|
||||
QueueFireEventOnServiceWorkerRegistrations(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
|
|
|
@ -236,35 +236,98 @@ ServiceWorkerRegistrationMainThread::InvalidateWorkers(WhichServiceWorker aWhich
|
|||
namespace {
|
||||
|
||||
void
|
||||
UpdateInternal(const nsAString& aScope)
|
||||
UpdateInternal(nsIPrincipal* aPrincipal, const nsAString& aScope)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm =
|
||||
mozilla::services::GetServiceWorkerManager();
|
||||
MOZ_ASSERT(swm);
|
||||
// The spec defines ServiceWorkerRegistration.update() exactly as Soft Update.
|
||||
swm->SoftUpdate(aScope);
|
||||
swm->SoftUpdate(aPrincipal, aScope);
|
||||
}
|
||||
|
||||
// This Runnable needs to have a valid WorkerPrivate. For this reason it is also
|
||||
// a WorkerFeature that is registered before dispatching itself to the
|
||||
// main-thread and it's removed with ReleaseRunnable when the operation is
|
||||
// completed. This will keep the worker alive as long as necessary.
|
||||
class UpdateRunnable final : public nsRunnable
|
||||
, public WorkerFeature
|
||||
{
|
||||
public:
|
||||
explicit UpdateRunnable(const nsAString& aScope)
|
||||
: mScope(aScope)
|
||||
UpdateRunnable(WorkerPrivate* aWorkerPrivate, const nsAString& aScope)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
, mScope(aScope)
|
||||
{}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
UpdateInternal(mScope);
|
||||
UpdateInternal(mWorkerPrivate->GetPrincipal(), mScope);
|
||||
|
||||
class ReleaseRunnable final : public MainThreadWorkerControlRunnable
|
||||
{
|
||||
nsRefPtr<UpdateRunnable> mRunnable;
|
||||
|
||||
public:
|
||||
ReleaseRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
UpdateRunnable* aRunnable)
|
||||
: MainThreadWorkerControlRunnable(aWorkerPrivate)
|
||||
, mRunnable(aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(aRunnable);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
WorkerRun(JSContext* aCx,
|
||||
workers::WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
aWorkerPrivate->RemoveFeature(aCx, mRunnable);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
~ReleaseRunnable()
|
||||
{}
|
||||
};
|
||||
|
||||
nsRefPtr<WorkerControlRunnable> runnable =
|
||||
new ReleaseRunnable(mWorkerPrivate, this);
|
||||
runnable->Dispatch(nullptr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual bool Notify(JSContext* aCx, workers::Status aStatus) override
|
||||
{
|
||||
// We don't care about the notification. We just want to keep the
|
||||
// mWorkerPrivate alive.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Dispatch()
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
JSContext* cx = mWorkerPrivate->GetJSContext();
|
||||
|
||||
if (NS_WARN_IF(!mWorkerPrivate->AddFeature(cx, this))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_SUCCEEDED(NS_DispatchToMainThread(this));
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
~UpdateRunnable()
|
||||
{}
|
||||
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
const nsString mScope;
|
||||
};
|
||||
|
||||
|
@ -457,7 +520,13 @@ public:
|
|||
void
|
||||
ServiceWorkerRegistrationMainThread::Update()
|
||||
{
|
||||
UpdateInternal(mScope);
|
||||
nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
|
||||
MOZ_ASSERT(doc);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
MOZ_ASSERT(principal);
|
||||
|
||||
UpdateInternal(principal, mScope);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
|
@ -739,13 +808,12 @@ ServiceWorkerRegistrationWorkerThread::GetActive()
|
|||
void
|
||||
ServiceWorkerRegistrationWorkerThread::Update()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
worker->AssertIsOnWorkerThread();
|
||||
#endif
|
||||
nsCOMPtr<nsIRunnable> r = new UpdateRunnable(mScope);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r)));
|
||||
|
||||
nsRefPtr<UpdateRunnable> r = new UpdateRunnable(worker, mScope);
|
||||
r->Dispatch();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
|
|
|
@ -132,7 +132,7 @@ function display(info) {
|
|||
let updateButton = document.createElement("button");
|
||||
updateButton.appendChild(document.createTextNode(bundle.GetStringFromName('update')));
|
||||
updateButton.onclick = function() {
|
||||
gSWM.softUpdate(info.scope);
|
||||
gSWM.softUpdate(info.principal, info.scope);
|
||||
};
|
||||
div.appendChild(updateButton);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче