зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1162088 - patch 1 - ServiceWorkerManager should use OriginAttributes from the principal as scopeKey, r=nsm, r=bholley
This commit is contained in:
Родитель
bf20132dbb
Коммит
a71e717b67
|
@ -21,7 +21,7 @@
|
|||
namespace mozilla {
|
||||
|
||||
void
|
||||
OriginAttributes::CreateSuffix(nsACString& aStr)
|
||||
OriginAttributes::CreateSuffix(nsACString& aStr) const
|
||||
{
|
||||
aStr.Truncate();
|
||||
MOZ_RELEASE_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||
|
@ -259,4 +259,29 @@ BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs)
|
|||
return codebase.forget();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
BasePrincipal::IsCodebasePrincipal(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
bool isNullPrincipal = true;
|
||||
nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPrincipal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isNullPrincipal || nsContentUtils::IsSystemPrincipal(aPrincipal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No expanded principals.
|
||||
nsCOMPtr<nsIExpandedPrincipal> expandedPrincipal =
|
||||
do_QueryInterface(aPrincipal);
|
||||
if (expandedPrincipal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
// Serializes non-default values into the suffix format, i.e.
|
||||
// |!key1=value1&key2=value2|. If there are no non-default attributes, this
|
||||
// returns an empty string.
|
||||
void CreateSuffix(nsACString& aStr);
|
||||
void CreateSuffix(nsACString& aStr) const;
|
||||
|
||||
void Serialize(nsIObjectOutputStream* aStream) const;
|
||||
nsresult Deserialize(nsIObjectInputStream* aStream);
|
||||
|
@ -83,6 +83,8 @@ public:
|
|||
|
||||
virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
|
||||
|
||||
static bool IsCodebasePrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
|
||||
static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/dom/workers/ServiceWorkerManager.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
@ -52,7 +53,6 @@
|
|||
#include "nsIAuthPrompt2.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsIServiceWorkerManager.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
|
@ -217,6 +217,7 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
|||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using mozilla::dom::workers::ServiceWorkerManager;
|
||||
|
||||
// True means sUseErrorPages has been added to preferences var cache.
|
||||
static bool gAddedPreferencesVarCache = false;
|
||||
|
@ -14040,13 +14041,15 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = services::GetServiceWorkerManager();
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIsNavigate) {
|
||||
return swm->IsAvailableForURI(aURI, aShouldIntercept);
|
||||
OriginAttributes attrs(GetAppId(), GetIsInBrowserElement());
|
||||
*aShouldIntercept = swm->IsAvailable(attrs, aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
|
@ -14054,13 +14057,19 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
return swm->IsControlled(doc, aShouldIntercept);
|
||||
ErrorResult rv;
|
||||
*aShouldIntercept = swm->IsControlled(doc, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = services::GetServiceWorkerManager();
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
aChannel->Cancel();
|
||||
return NS_OK;
|
||||
|
@ -14080,7 +14089,16 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
|
|||
}
|
||||
|
||||
bool isReload = mLoadType & LOAD_CMD_RELOAD;
|
||||
return swm->DispatchFetchEvent(doc, aChannel, isReload);
|
||||
|
||||
OriginAttributes attrs(GetAppId(), GetIsInBrowserElement());
|
||||
|
||||
ErrorResult error;
|
||||
swm->DispatchFetchEvent(attrs, doc, aChannel, isReload, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -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(bfb913ad-177d-49ae-bf62-efd32ca73424)]
|
||||
interface nsIServiceWorkerManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -66,16 +66,6 @@ interface nsIServiceWorkerManager : nsISupports
|
|||
// Remove ready pending Promise
|
||||
void removeReadyPromise(in nsIDOMWindow aWindow);
|
||||
|
||||
// Returns true if a ServiceWorker is available for the scope of aURI.
|
||||
bool isAvailableForURI(in nsIURI aURI);
|
||||
|
||||
// Returns true if a given document is currently controlled by a ServiceWorker
|
||||
bool isControlled(in nsIDocument aDocument);
|
||||
|
||||
// Cause a fetch event to be dispatched to the worker global associated with the given document.
|
||||
void dispatchFetchEvent(in nsIDocument aDoc, in nsIInterceptedChannel aChannel,
|
||||
in boolean aIsReload);
|
||||
|
||||
/**
|
||||
* Call this to request that document `aDoc` be controlled by a ServiceWorker
|
||||
* if a registration exists for it's scope.
|
||||
|
@ -108,8 +98,10 @@ interface nsIServiceWorkerManager : nsISupports
|
|||
|
||||
/*
|
||||
* This implements the soft update algorithm.
|
||||
* XXXbaku this can be removed when bug 1155153 lands.
|
||||
*/
|
||||
void softUpdate(in DOMString aScope);
|
||||
[implicit_jscontext] void softUpdate(in jsval aOriginAttributes,
|
||||
in DOMString aScope);
|
||||
|
||||
/*
|
||||
* Clears ServiceWorker registrations from memory and disk for the specified
|
||||
|
@ -128,14 +120,17 @@ 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);
|
||||
[implicit_jscontext] void sendPushEvent(in jsval aOriginAttributes,
|
||||
in ACString aScope,
|
||||
in DOMString aData);
|
||||
[implicit_jscontext] void sendPushSubscriptionChangeEvent(in jsval aOriginAttributes,
|
||||
in ACString scope);
|
||||
|
||||
void updateAllRegistrations();
|
||||
};
|
||||
|
|
|
@ -1406,7 +1406,13 @@ this.PushService = {
|
|||
"push-subscription-change",
|
||||
scope
|
||||
);
|
||||
globalMM.broadcastAsyncMessage('pushsubscriptionchanged', scope);
|
||||
|
||||
let data = {
|
||||
originAttributes: {}, // TODO bug 1166350
|
||||
scope: scope
|
||||
};
|
||||
|
||||
globalMM.broadcastAsyncMessage('pushsubscriptionchanged', data);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -1444,6 +1450,7 @@ this.PushService = {
|
|||
// TODO data.
|
||||
let data = {
|
||||
payload: "Short as life is, we make it still shorter by the careless waste of time.",
|
||||
originAttributes: {}, // TODO bug 1166350
|
||||
scope: aPushRecord.scope
|
||||
};
|
||||
|
||||
|
|
|
@ -10,9 +10,11 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
|||
"nsIServiceWorkerManager");
|
||||
|
||||
addMessageListener("push", function (aMessage) {
|
||||
swm.sendPushEvent(aMessage.data.scope, aMessage.data.payload);
|
||||
swm.sendPushEvent(aMessage.data.originAttributes,
|
||||
aMessage.data.scope, aMessage.data.payload);
|
||||
});
|
||||
|
||||
addMessageListener("pushsubscriptionchange", function (aMessage) {
|
||||
swm.sendPushSubscriptionChangeEvent(aMessage.data);
|
||||
swm.sendPushSubscriptionChangeEvent(aMessage.data.originAttributes,
|
||||
aMessage.data.scope);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -194,11 +194,6 @@ public:
|
|||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
nsresult rv = swm->ClaimClients(mScope, mServiceWorkerID);
|
||||
|
||||
MutexAutoLock lock(mPromiseProxy->GetCleanUpLock());
|
||||
if (mPromiseProxy->IsClean()) {
|
||||
// Don't resolve the promise if it was already released.
|
||||
|
@ -208,6 +203,12 @@ public:
|
|||
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
nsresult rv = swm->ClaimClients(workerPrivate->GetPrincipal(),
|
||||
mScope, mServiceWorkerID);
|
||||
|
||||
nsRefPtr<ResolveClaimRunnable> r =
|
||||
new ResolveClaimRunnable(workerPrivate, mPromiseProxy, rv);
|
||||
|
||||
|
|
|
@ -231,7 +231,8 @@ ServiceWorkerContainer::GetScopeForUrl(const nsAString& aUrl,
|
|||
return;
|
||||
}
|
||||
|
||||
aRv = swm->GetScopeForUrl(aUrl, aScope);
|
||||
aRv = swm->GetScopeForUrl(GetOwner()->GetExtantDoc()->NodePrincipal(),
|
||||
aUrl, aScope);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -33,6 +33,8 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class OriginAttributes;
|
||||
|
||||
namespace ipc {
|
||||
class BackgroundChild;
|
||||
}
|
||||
|
@ -46,105 +48,9 @@ namespace workers {
|
|||
class ServiceWorker;
|
||||
class ServiceWorkerClientInfo;
|
||||
class ServiceWorkerInfo;
|
||||
|
||||
class ServiceWorkerJob;
|
||||
class ServiceWorkerJobQueue;
|
||||
|
||||
class ServiceWorkerJob : public nsISupports
|
||||
{
|
||||
protected:
|
||||
// The queue keeps the jobs alive, so they can hold a rawptr back to the
|
||||
// queue.
|
||||
ServiceWorkerJobQueue* mQueue;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual void Start() = 0;
|
||||
|
||||
virtual bool
|
||||
IsRegisterJob() const { return false; }
|
||||
|
||||
protected:
|
||||
explicit ServiceWorkerJob(ServiceWorkerJobQueue* aQueue)
|
||||
: mQueue(aQueue)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ServiceWorkerJob()
|
||||
{ }
|
||||
|
||||
void
|
||||
Done(nsresult aStatus);
|
||||
};
|
||||
|
||||
class ServiceWorkerJobQueue final
|
||||
{
|
||||
friend class ServiceWorkerJob;
|
||||
|
||||
nsTArray<nsRefPtr<ServiceWorkerJob>> mJobs;
|
||||
bool mPopping;
|
||||
|
||||
public:
|
||||
explicit ServiceWorkerJobQueue()
|
||||
: mPopping(false)
|
||||
{}
|
||||
|
||||
~ServiceWorkerJobQueue()
|
||||
{
|
||||
if (!mJobs.IsEmpty()) {
|
||||
NS_WARNING("Pending/running jobs still around on shutdown!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Append(ServiceWorkerJob* aJob)
|
||||
{
|
||||
MOZ_ASSERT(aJob);
|
||||
MOZ_ASSERT(!mJobs.Contains(aJob));
|
||||
bool wasEmpty = mJobs.IsEmpty();
|
||||
mJobs.AppendElement(aJob);
|
||||
if (wasEmpty) {
|
||||
aJob->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CancelJobs();
|
||||
|
||||
// Only used by HandleError, keep it that way!
|
||||
ServiceWorkerJob*
|
||||
Peek()
|
||||
{
|
||||
if (mJobs.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return mJobs[0];
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
Pop()
|
||||
{
|
||||
MOZ_ASSERT(!mPopping,
|
||||
"Pop() called recursively, did you write a job which calls Done() synchronously from Start()?");
|
||||
AutoRestore<bool> savePopping(mPopping);
|
||||
mPopping = true;
|
||||
MOZ_ASSERT(!mJobs.IsEmpty());
|
||||
mJobs.RemoveElementAt(0);
|
||||
if (!mJobs.IsEmpty()) {
|
||||
mJobs[0]->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Done(ServiceWorkerJob* aJob)
|
||||
{
|
||||
MOZ_ASSERT(!mJobs.IsEmpty());
|
||||
MOZ_ASSERT(mJobs[0] == aJob);
|
||||
Pop();
|
||||
}
|
||||
};
|
||||
|
||||
// Needs to inherit from nsISupports because NS_ProxyRelease() does not support
|
||||
// non-ISupports classes.
|
||||
class ServiceWorkerRegistrationInfo final : public nsISupports
|
||||
|
@ -172,8 +78,8 @@ public:
|
|||
// pendingUninstall and when all controlling documents go away, removed.
|
||||
bool mPendingUninstall;
|
||||
|
||||
explicit ServiceWorkerRegistrationInfo(const nsACString& aScope,
|
||||
nsIPrincipal* aPrincipal);
|
||||
ServiceWorkerRegistrationInfo(const nsACString& aScope,
|
||||
nsIPrincipal* aPrincipal);
|
||||
|
||||
already_AddRefed<ServiceWorkerInfo>
|
||||
Newest()
|
||||
|
@ -344,6 +250,7 @@ class ServiceWorkerManager final
|
|||
friend class GetReadyPromiseRunnable;
|
||||
friend class GetRegistrationsRunnable;
|
||||
friend class GetRegistrationRunnable;
|
||||
friend class ServiceWorkerJobQueue;
|
||||
friend class ServiceWorkerRegisterJob;
|
||||
friend class ServiceWorkerRegistrationInfo;
|
||||
friend class ServiceWorkerUnregisterJob;
|
||||
|
@ -364,18 +271,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;
|
||||
|
||||
|
@ -384,18 +281,24 @@ public:
|
|||
// Set of all documents that may be controlled by a service worker.
|
||||
nsTHashtable<nsISupportsHashKey> mAllDocuments;
|
||||
|
||||
// Maps scopes to job queues.
|
||||
nsClassHashtable<nsCStringHashKey, ServiceWorkerJobQueue> mJobQueues;
|
||||
bool
|
||||
IsAvailable(const OriginAttributes& aOriginAttributes, nsIURI* aURI);
|
||||
|
||||
nsDataHashtable<nsCStringHashKey, bool> mSetOfScopesBeingUpdated;
|
||||
bool
|
||||
IsControlled(nsIDocument* aDocument, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
DispatchFetchEvent(const OriginAttributes& aOriginAttributes,
|
||||
nsIDocument* aDoc,
|
||||
nsIInterceptedChannel* aChannel,
|
||||
bool aIsReload,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
SoftUpdate(nsIPrincipal* aPrincipal, const nsACString& aScope);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetRegistration(const nsCString& aScope) const
|
||||
{
|
||||
nsRefPtr<ServiceWorkerRegistrationInfo> reg;
|
||||
mServiceWorkerRegistrationInfos.Get(aScope, getter_AddRefs(reg));
|
||||
return reg.forget();
|
||||
}
|
||||
GetRegistration(nsIPrincipal* aPrincipal, const nsACString& aScope) const;
|
||||
|
||||
ServiceWorkerRegistrationInfo*
|
||||
CreateNewRegistration(const nsCString& aScope, nsIPrincipal* aPrincipal);
|
||||
|
@ -403,12 +306,6 @@ public:
|
|||
void
|
||||
RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
ServiceWorkerJobQueue*
|
||||
GetOrCreateJobQueue(const nsCString& aScope)
|
||||
{
|
||||
return mJobQueues.LookupOrAdd(aScope);
|
||||
}
|
||||
|
||||
void StoreRegistration(nsIPrincipal* aPrincipal,
|
||||
ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
|
@ -419,6 +316,7 @@ public:
|
|||
// handling should continue.
|
||||
bool
|
||||
HandleError(JSContext* aCx,
|
||||
nsIPrincipal* aPrincipal,
|
||||
const nsCString& aScope,
|
||||
const nsString& aWorkerURL,
|
||||
nsString aMessage,
|
||||
|
@ -429,7 +327,8 @@ public:
|
|||
uint32_t aFlags);
|
||||
|
||||
void
|
||||
GetAllClients(const nsCString& aScope,
|
||||
GetAllClients(nsIPrincipal* aPrincipal,
|
||||
const nsCString& aScope,
|
||||
nsTArray<ServiceWorkerClientInfo>& aControlledDocuments);
|
||||
|
||||
void
|
||||
|
@ -437,7 +336,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();
|
||||
|
@ -448,7 +347,8 @@ public:
|
|||
// Used by remove() and removeAll() when clearing history.
|
||||
// MUST ONLY BE CALLED FROM UnregisterIfMatchesHost!
|
||||
void
|
||||
ForceUnregister(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
ForceUnregister(RegistrationDataPerPrincipal* aRegistrationData,
|
||||
ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
NS_IMETHOD
|
||||
AddRegistrationEventListener(const nsAString& aScope,
|
||||
|
@ -461,6 +361,20 @@ private:
|
|||
ServiceWorkerManager();
|
||||
~ServiceWorkerManager();
|
||||
|
||||
ServiceWorkerJobQueue*
|
||||
GetOrCreateJobQueue(const nsACString& aOriginSuffix,
|
||||
const nsACString& aScope);
|
||||
|
||||
void
|
||||
MaybeRemoveRegistrationInfo(const nsACString& aScopeKey);
|
||||
|
||||
void
|
||||
SoftUpdate(const nsACString& aScopeKey, const nsACString& aScope);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetRegistration(const nsACString& aScopeKey,
|
||||
const nsACString& aScope) const;
|
||||
|
||||
void
|
||||
AbortCurrentUpdate(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
||||
|
@ -487,7 +401,8 @@ private:
|
|||
nsISupports** aServiceWorker);
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
CreateServiceWorkerForScope(const nsACString& aScope);
|
||||
CreateServiceWorkerForScope(const OriginAttributes& aOriginAttributes,
|
||||
const nsACString& aScope);
|
||||
|
||||
void
|
||||
InvalidateServiceWorkerRegistrationWorker(ServiceWorkerRegistrationInfo* aRegistration,
|
||||
|
@ -507,16 +422,38 @@ private:
|
|||
GetServiceWorkerRegistrationInfo(nsIDocument* aDoc);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetServiceWorkerRegistrationInfo(nsIURI* aURI);
|
||||
GetServiceWorkerRegistrationInfo(nsIPrincipal* aPrincipal, nsIURI* aURI);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetServiceWorkerRegistrationInfo(const OriginAttributes& aOriginAttributes,
|
||||
nsIURI* aURI);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetServiceWorkerRegistrationInfo(const nsACString& aScopeKey,
|
||||
nsIURI* aURI);
|
||||
|
||||
// This method generates a key using appId and isInElementBrowser from the
|
||||
// principal. We don't use the origin because it can change during the
|
||||
// loading.
|
||||
static nsresult
|
||||
PrincipalToScopeKey(nsIPrincipal* aPrincipal, nsACString& aKey);
|
||||
|
||||
static void
|
||||
AddScope(nsTArray<nsCString>& aList, const nsACString& aScope);
|
||||
AddScopeAndRegistration(const nsACString& aScope,
|
||||
ServiceWorkerRegistrationInfo* aRegistation);
|
||||
|
||||
static nsCString
|
||||
FindScopeForPath(nsTArray<nsCString>& aList, const nsACString& aPath);
|
||||
static bool
|
||||
FindScopeForPath(const nsACString& aScopeKey,
|
||||
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,
|
||||
|
|
|
@ -233,35 +233,100 @@ 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(aPrincipal);
|
||||
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
// The spec defines ServiceWorkerRegistration.update() exactly as Soft Update.
|
||||
swm->SoftUpdate(aScope);
|
||||
swm->SoftUpdate(aPrincipal, NS_ConvertUTF16toUTF8(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> mFeature;
|
||||
|
||||
public:
|
||||
ReleaseRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
UpdateRunnable* aFeature)
|
||||
: MainThreadWorkerControlRunnable(aWorkerPrivate)
|
||||
, mFeature(aFeature)
|
||||
{
|
||||
MOZ_ASSERT(aFeature);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
WorkerRun(JSContext* aCx,
|
||||
workers::WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
aWorkerPrivate->RemoveFeature(aCx, mFeature);
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -454,7 +519,10 @@ public:
|
|||
void
|
||||
ServiceWorkerRegistrationMainThread::Update()
|
||||
{
|
||||
UpdateInternal(mScope);
|
||||
nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
|
||||
MOZ_ASSERT(doc);
|
||||
|
||||
UpdateInternal(doc->NodePrincipal(), mScope);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
|
@ -736,13 +804,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>
|
||||
|
|
|
@ -1600,7 +1600,8 @@ private:
|
|||
if (aWorkerPrivate->IsServiceWorker()) {
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
bool handled = swm->HandleError(aCx, aWorkerPrivate->SharedWorkerName(),
|
||||
bool handled = swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
|
||||
aWorkerPrivate->SharedWorkerName(),
|
||||
aWorkerPrivate->ScriptURL(),
|
||||
mMessage,
|
||||
mFilename, mLine, mLineNumber,
|
||||
|
|
|
@ -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.originAttributes, info.scope);
|
||||
};
|
||||
div.appendChild(updateButton);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче