зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset bc9a43cbbdfa (bug 1227932)
--HG-- extra : rebase_source : a52df07605cf6df721f4d3e0753deb31b66c2d07
This commit is contained in:
Родитель
4059a6e5ee
Коммит
3d36e0d95d
|
@ -375,7 +375,6 @@ ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(const nsACString& a
|
|||
, mScope(aScope)
|
||||
, mPrincipal(aPrincipal)
|
||||
, mLastUpdateCheckTime(0)
|
||||
, mUpdating(false)
|
||||
, mPendingUninstall(false)
|
||||
{}
|
||||
|
||||
|
@ -864,7 +863,7 @@ class ServiceWorkerRegisterJob final : public ServiceWorkerJob,
|
|||
nsCString mScope;
|
||||
nsCString mScriptSpec;
|
||||
RefPtr<ServiceWorkerRegistrationInfo> mRegistration;
|
||||
RefPtr<ServiceWorkerUpdateFinishCallback> mCallback;
|
||||
nsTArray<RefPtr<ServiceWorkerUpdateFinishCallback>> mCallbacks;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
RefPtr<ServiceWorkerInfo> mUpdateAndInstallInfo;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
|
@ -893,7 +892,6 @@ public:
|
|||
: ServiceWorkerJob(aQueue)
|
||||
, mScope(aScope)
|
||||
, mScriptSpec(aScriptSpec)
|
||||
, mCallback(aCallback)
|
||||
, mPrincipal(aPrincipal)
|
||||
, mLoadGroup(aLoadGroup)
|
||||
, mJobType(REGISTER_JOB)
|
||||
|
@ -902,6 +900,8 @@ public:
|
|||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(mLoadGroup);
|
||||
MOZ_ASSERT(aCallback);
|
||||
|
||||
mCallbacks.AppendElement(aCallback);
|
||||
}
|
||||
|
||||
// [[Update]]
|
||||
|
@ -910,11 +910,13 @@ public:
|
|||
ServiceWorkerUpdateFinishCallback* aCallback)
|
||||
: ServiceWorkerJob(aQueue)
|
||||
, mRegistration(aRegistration)
|
||||
, mCallback(aCallback)
|
||||
, mJobType(UPDATE_JOB)
|
||||
, mCanceled(false)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aCallback);
|
||||
|
||||
mCallbacks.AppendElement(aCallback);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -923,6 +925,16 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
AppendCallback(ServiceWorkerUpdateFinishCallback* aCallback)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(!mCallbacks.Contains(aCallback));
|
||||
|
||||
mCallbacks.AppendElement(aCallback);
|
||||
}
|
||||
|
||||
void
|
||||
Cancel()
|
||||
{
|
||||
|
@ -974,6 +986,10 @@ public:
|
|||
swm->StoreRegistration(mPrincipal, mRegistration);
|
||||
} else {
|
||||
MOZ_ASSERT(mJobType == UPDATE_JOB);
|
||||
MOZ_ASSERT(mRegistration);
|
||||
MOZ_ASSERT(mRegistration->mUpdateJob == nullptr);
|
||||
|
||||
mRegistration->mUpdateJob = this;
|
||||
}
|
||||
|
||||
Update();
|
||||
|
@ -1105,6 +1121,8 @@ public:
|
|||
Fail(ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(mCallbacks.Length());
|
||||
|
||||
// With cancellation support, we may only be running with one reference
|
||||
// from another object like a stream loader or something.
|
||||
RefPtr<ServiceWorkerRegisterJob> kungFuDeathGrip = this;
|
||||
|
@ -1137,11 +1155,15 @@ public:
|
|||
aRv.ThrowTypeError<MSG_SW_INSTALL_ERROR>(scriptSpec, scope);
|
||||
}
|
||||
|
||||
if (mCallback) {
|
||||
mCallback->UpdateFailed(aRv);
|
||||
mCallback = nullptr;
|
||||
for (uint32_t i = 1; i < mCallbacks.Length(); ++i) {
|
||||
ErrorResult rv;
|
||||
aRv.CloneTo(rv);
|
||||
mCallbacks[i]->UpdateFailed(rv);
|
||||
rv.SuppressException();
|
||||
}
|
||||
|
||||
mCallbacks[0]->UpdateFailed(aRv);
|
||||
|
||||
// In case the callback does not consume the exception
|
||||
aRv.SuppressException();
|
||||
|
||||
|
@ -1157,6 +1179,7 @@ public:
|
|||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
swm->MaybeRemoveRegistration(mRegistration);
|
||||
// Ensures that the job can't do anything useful from this point on.
|
||||
mRegistration->mUpdateJob = nullptr;
|
||||
mRegistration = nullptr;
|
||||
Done(origStatus);
|
||||
}
|
||||
|
@ -1172,14 +1195,11 @@ public:
|
|||
void
|
||||
ContinueInstall()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
// mRegistration will be null if we have already Fail()ed.
|
||||
if (!mRegistration) {
|
||||
return;
|
||||
}
|
||||
|
||||
mRegistration->mUpdating = false;
|
||||
|
||||
// Even if we are canceled, ensure integrity of mSetOfScopesBeingUpdated
|
||||
// first.
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
|
@ -1255,16 +1275,12 @@ private:
|
|||
void
|
||||
Update()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Since Update() is called synchronously from Start(), we can assert this.
|
||||
MOZ_ASSERT(!mCanceled);
|
||||
MOZ_ASSERT(mRegistration);
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableMethod(this, &ServiceWorkerRegisterJob::ContinueUpdate);
|
||||
NS_DispatchToMainThread(r);
|
||||
|
||||
mRegistration->mUpdating = true;
|
||||
}
|
||||
|
||||
// Aspects of (actually the whole algorithm) of [[Update]] after
|
||||
|
@ -1307,11 +1323,12 @@ private:
|
|||
Succeed()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
// We don't have a callback for soft updates.
|
||||
if (mCallback) {
|
||||
mCallback->UpdateSucceeded(mRegistration);
|
||||
mCallback = nullptr;
|
||||
MOZ_ASSERT(mCallbacks.Length());
|
||||
|
||||
for (uint32_t i = 0; i < mCallbacks.Length(); ++i) {
|
||||
mCallbacks[i]->UpdateSucceeded(mRegistration);
|
||||
}
|
||||
mCallbacks.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1369,13 +1386,13 @@ private:
|
|||
void
|
||||
Done(nsresult aStatus)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
if (mRegistration) {
|
||||
mRegistration->mUpdating = false;
|
||||
}
|
||||
|
||||
ServiceWorkerJob::Done(aStatus);
|
||||
|
||||
if (mJobType == UPDATE_JOB && mRegistration) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mRegistration->mUpdateJob);
|
||||
mRegistration->mUpdateJob = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2647,6 +2664,23 @@ ServiceWorkerRegistrationInfo::NotifyListenersOnChange()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceWorkerRegistrationInfo::IsUpdating() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mUpdateJob != nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistrationInfo::AppendUpdateCallback(ServiceWorkerUpdateFinishCallback* aCallback)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(mUpdateJob);
|
||||
|
||||
mUpdateJob->AppendCallback(aCallback);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::LoadRegistration(
|
||||
const ServiceWorkerRegistrationData& aRegistration)
|
||||
|
@ -3493,15 +3527,55 @@ ServiceWorkerManager::InvalidateServiceWorkerRegistrationWorker(ServiceWorkerReg
|
|||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::SoftUpdate(const OriginAttributes& aOriginAttributes,
|
||||
const nsACString& aScope)
|
||||
ServiceWorkerManager::SoftUpdate(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateFinishCallback* aCallback)
|
||||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
nsAutoCString scopeKey;
|
||||
nsresult rv = PrincipalToScopeKey(aPrincipal, scopeKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
SoftUpdate(scopeKey, aScope, aCallback);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::SoftUpdate(const OriginAttributes& aOriginAttributes,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateFinishCallback* aCallback)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
nsAutoCString scopeKey;
|
||||
aOriginAttributes.CreateSuffix(scopeKey);
|
||||
SoftUpdate(scopeKey, aScope, aCallback);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Empty callback. Only use when you really want to ignore errors.
|
||||
class EmptyUpdateFinishCallback final : public ServiceWorkerUpdateFinishCallback
|
||||
{
|
||||
public:
|
||||
void
|
||||
UpdateSucceeded(ServiceWorkerRegistrationInfo* aInfo) override
|
||||
{}
|
||||
|
||||
void
|
||||
UpdateFailed(ErrorResult& aStatus) override
|
||||
{}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void
|
||||
ServiceWorkerManager::SoftUpdate(const nsACString& aScopeKey,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateFinishCallback* aCallback)
|
||||
{
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetRegistration(scopeKey, aScope);
|
||||
GetRegistration(aScopeKey, aScope);
|
||||
if (NS_WARN_IF(!registration)) {
|
||||
return;
|
||||
}
|
||||
|
@ -3527,71 +3601,28 @@ ServiceWorkerManager::SoftUpdate(const OriginAttributes& aOriginAttributes,
|
|||
// "Set registration's registering script url to newestWorker's script url."
|
||||
registration->mScriptSpec = newest->ScriptSpec();
|
||||
|
||||
// "If the registration queue for registration is empty, invoke Update algorithm,
|
||||
// or its equivalent, with client, registration as its argument."
|
||||
// TODO(catalinb): We don't implement the force bypass cache flag.
|
||||
// See: https://github.com/slightlyoff/ServiceWorker/issues/759
|
||||
if (!registration->mUpdating) {
|
||||
ServiceWorkerJobQueue* queue = GetOrCreateJobQueue(scopeKey, aScope);
|
||||
MOZ_ASSERT(queue);
|
||||
|
||||
RefPtr<ServiceWorkerRegisterJob> job =
|
||||
new ServiceWorkerRegisterJob(queue, registration, nullptr);
|
||||
queue->Append(job);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::Update(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateFinishCallback* aCallback)
|
||||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT(aCallback);
|
||||
|
||||
nsAutoCString scopeKey;
|
||||
nsresult rv = PrincipalToScopeKey(aPrincipal, scopeKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
GetRegistration(scopeKey, aScope);
|
||||
if (NS_WARN_IF(!registration)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// "If registration's uninstalling flag is set, abort these steps."
|
||||
if (registration->mPendingUninstall) {
|
||||
return;
|
||||
}
|
||||
|
||||
// "Let newestWorker be the result of running Get Newest Worker algorithm
|
||||
// passing registration as its argument.
|
||||
// If newestWorker is null, return a promise rejected with "InvalidStateError"
|
||||
RefPtr<ServiceWorkerInfo> newest = registration->Newest();
|
||||
if (!newest) {
|
||||
ErrorResult error(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
aCallback->UpdateFailed(error);
|
||||
|
||||
// In case the callback does not consume the exception
|
||||
error.SuppressException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// "Set registration's registering script url to newestWorker's script url."
|
||||
registration->mScriptSpec = newest->ScriptSpec();
|
||||
|
||||
ServiceWorkerJobQueue* queue =
|
||||
GetOrCreateJobQueue(scopeKey, aScope);
|
||||
GetOrCreateJobQueue(aScopeKey, aScope);
|
||||
MOZ_ASSERT(queue);
|
||||
|
||||
RefPtr<ServiceWorkerUpdateFinishCallback> cb(aCallback);
|
||||
if (!cb) {
|
||||
cb = new EmptyUpdateFinishCallback();
|
||||
}
|
||||
|
||||
// "Invoke Update algorithm, or its equivalent, with client, registration as
|
||||
// its argument."
|
||||
RefPtr<ServiceWorkerRegisterJob> job =
|
||||
new ServiceWorkerRegisterJob(queue, registration, aCallback);
|
||||
queue->Append(job);
|
||||
if (registration->IsUpdating()) {
|
||||
// This is used to reduce burst of update events. If there is an update
|
||||
// job in queue when we try to create a new one, drop current one and
|
||||
// merge the callback function to existing update job.
|
||||
// See. https://github.com/slightlyoff/ServiceWorker/issues/759
|
||||
registration->AppendUpdateCallback(cb);
|
||||
} else {
|
||||
RefPtr<ServiceWorkerRegisterJob> job =
|
||||
new ServiceWorkerRegisterJob(queue, registration, cb);
|
||||
queue->Append(job);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -47,9 +47,11 @@ class ServiceWorker;
|
|||
class ServiceWorkerClientInfo;
|
||||
class ServiceWorkerInfo;
|
||||
class ServiceWorkerJob;
|
||||
class ServiceWorkerRegisterJob;
|
||||
class ServiceWorkerJobQueue;
|
||||
class ServiceWorkerManagerChild;
|
||||
class ServiceWorkerPrivate;
|
||||
class ServiceWorkerUpdateFinishCallback;
|
||||
|
||||
class ServiceWorkerRegistrationInfo final
|
||||
: public nsIServiceWorkerRegistrationInfo
|
||||
|
@ -77,11 +79,7 @@ public:
|
|||
|
||||
uint64_t mLastUpdateCheckTime;
|
||||
|
||||
// According to the spec, Soft Update shouldn't queue an update job
|
||||
// if the registration queue is not empty. Because our job queue
|
||||
// works slightly different, we use a flag to determine if the registration
|
||||
// is already updating.
|
||||
bool mUpdating;
|
||||
RefPtr<ServiceWorkerRegisterJob> mUpdateJob;
|
||||
|
||||
// When unregister() is called on a registration, it is not immediately
|
||||
// removed since documents may be controlled. It is marked as
|
||||
|
@ -151,6 +149,12 @@ public:
|
|||
|
||||
void
|
||||
NotifyListenersOnChange();
|
||||
|
||||
bool
|
||||
IsUpdating() const;
|
||||
|
||||
void
|
||||
AppendUpdateCallback(ServiceWorkerUpdateFinishCallback* aCallback);
|
||||
};
|
||||
|
||||
class ServiceWorkerUpdateFinishCallback
|
||||
|
@ -369,13 +373,14 @@ public:
|
|||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Update(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateFinishCallback* aCallback);
|
||||
SoftUpdate(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateFinishCallback* aCallback = nullptr);
|
||||
|
||||
void
|
||||
SoftUpdate(const OriginAttributes& aOriginAttributes,
|
||||
const nsACString& aScope);
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateFinishCallback* aCallback = nullptr);
|
||||
|
||||
void
|
||||
PropagateSoftUpdate(const OriginAttributes& aOriginAttributes,
|
||||
|
@ -484,6 +489,11 @@ private:
|
|||
void
|
||||
MaybeRemoveRegistrationInfo(const nsACString& aScopeKey);
|
||||
|
||||
void
|
||||
SoftUpdate(const nsACString& aScopeKey,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateFinishCallback* aCallback = nullptr);
|
||||
|
||||
already_AddRefed<ServiceWorkerRegistrationInfo>
|
||||
GetRegistration(const nsACString& aScopeKey,
|
||||
const nsACString& aScope) const;
|
||||
|
|
|
@ -42,7 +42,7 @@ ServiceWorkerManagerChild::RecvNotifySoftUpdate(
|
|||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
swm->SoftUpdate(aOriginAttributes, NS_ConvertUTF16toUTF8(aScope));
|
||||
swm->SoftUpdate(aOriginAttributes, NS_ConvertUTF16toUTF8(aScope), nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -266,7 +266,8 @@ UpdateInternal(nsIPrincipal* aPrincipal,
|
|||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
swm->Update(aPrincipal, NS_ConvertUTF16toUTF8(aScope), aCallback);
|
||||
// The spec defines ServiceWorkerRegistration.update() exactly as Soft Update.
|
||||
swm->SoftUpdate(aPrincipal, NS_ConvertUTF16toUTF8(aScope), aCallback);
|
||||
}
|
||||
|
||||
class MainThreadUpdateCallback final : public ServiceWorkerUpdateFinishCallback
|
||||
|
@ -392,22 +393,14 @@ public:
|
|||
AssertIsOnMainThread();
|
||||
ErrorResult result;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
// UpdateInternal may try to reject the promise synchronously leading
|
||||
// to a deadlock.
|
||||
{
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
principal = mPromiseProxy->GetWorkerPrivate()->GetPrincipal();
|
||||
MutexAutoLock lock(mPromiseProxy->Lock());
|
||||
if (mPromiseProxy->CleanedUp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
MOZ_ASSERT(principal);
|
||||
|
||||
RefPtr<WorkerThreadUpdateCallback> cb =
|
||||
new WorkerThreadUpdateCallback(mPromiseProxy);
|
||||
UpdateInternal(principal, mScope, cb);
|
||||
UpdateInternal(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(), mScope, cb);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче