Bug 1353636 - Part 1: Move from nsLoadFlags to UpdateViaCache. r=bkelly

--HG--
extra : rebase_source : 063c490f52a006f1c46f63cd07e9f93b6d15ccde
This commit is contained in:
Ho-Pang Hsu 2017-08-16 14:18:52 +08:00
parent 9de84f5fed
commit 3f781402a4
16 changed files with 144 additions and 77 deletions

View File

@ -65,6 +65,11 @@ interface nsIServiceWorkerRegistrationInfoListener : nsISupports
[scriptable, builtinclass, uuid(ddbc1fd4-2f2e-4fca-a395-6e010bbedfe3)]
interface nsIServiceWorkerRegistrationInfo : nsISupports
{
// State values below should match the ServiceWorkerUpdateViaCache enumeration.
const unsigned short UPDATE_VIA_CACHE_IMPORTS = 0;
const unsigned short UPDATE_VIA_CACHE_ALL = 1;
const unsigned short UPDATE_VIA_CACHE_NONE = 2;
readonly attribute nsIPrincipal principal;
readonly attribute DOMString scope;
@ -110,7 +115,7 @@ interface nsIServiceWorkerManager : nsISupports
nsISupports register(in mozIDOMWindow aWindow,
in nsIURI aScope,
in nsIURI aScriptURI,
in nsLoadFlags aLoadFlags);
in uint16_t aUpdateViaCache);
/**
* Unregister an existing ServiceWorker registration for `aScope`.

View File

@ -42,4 +42,5 @@ partial interface ServiceWorkerContainer {
dictionary RegistrationOptions {
USVString scope;
ServiceWorkerUpdateViaCache updateViaCache = "imports";
};

View File

@ -28,6 +28,12 @@ interface ServiceWorkerRegistration : EventTarget {
attribute EventHandler onupdatefound;
};
enum ServiceWorkerUpdateViaCache {
"imports",
"all",
"none"
};
// https://w3c.github.io/push-api/
partial interface ServiceWorkerRegistration {
[Throws, Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled"]

View File

@ -199,13 +199,10 @@ ServiceWorkerContainer::Register(const nsAString& aScriptURL,
}
}
// This is a quick fix for temporarily turning off script loading setting when
// registering a service worker. This should be removed in Bug 1353636.
nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
// The spec says that the "client" passed to Register() must be the global
// where the ServiceWorkerContainer was retrieved from.
aRv = swm->Register(GetOwner(), scopeURI, scriptURI, loadFlags,
aRv = swm->Register(GetOwner(), scopeURI, scriptURI,
static_cast<uint16_t>(aOptions.mUpdateViaCache),
getter_AddRefs(promise));
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;

View File

@ -209,13 +209,13 @@ ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
const nsAString& aCacheName,
nsLoadFlags aLoadFlags)
nsLoadFlags aImportsLoadFlags)
: mPrincipal(aPrincipal)
, mScope(aScope)
, mScriptSpec(aScriptSpec)
, mCacheName(aCacheName)
, mLoadFlags(aLoadFlags)
, mState(ServiceWorkerState::EndGuard_)
, mImportsLoadFlags(aImportsLoadFlags)
, mServiceWorkerID(GetNextID())
, mCreationTime(PR_Now())
, mCreationTimeStamp(TimeStamp::Now())
@ -232,6 +232,11 @@ ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,
MOZ_ASSERT(!mScope.IsEmpty());
MOZ_ASSERT(!mScriptSpec.IsEmpty());
MOZ_ASSERT(!mCacheName.IsEmpty());
// Scripts of a service worker should always be loaded bypass service workers.
// Otherwise, we might not be able to update a service worker correctly, if
// there is a service worker generating the script.
MOZ_DIAGNOSTIC_ASSERT(mImportsLoadFlags & nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
}
ServiceWorkerInfo::~ServiceWorkerInfo()

View File

@ -31,10 +31,19 @@ private:
const nsCString mScope;
const nsCString mScriptSpec;
const nsString mCacheName;
const nsLoadFlags mLoadFlags;
ServiceWorkerState mState;
OriginAttributes mOriginAttributes;
// This LoadFlags is only applied to imported scripts, since the main script
// has already been downloaded when performing the bytecheck. This LoadFlag is
// composed of three parts:
// 1. nsIChannel::LOAD_BYPASS_SERVICE_WORKER
// 2. (Optional) nsIRequest::VALIDATE_ALWAYS
// depends on ServiceWorkerUpdateViaCache of its registration.
// 3. (optional) nsIRequest::LOAD_BYPASS_CACHE
// depends on whether the update timer is expired.
const nsLoadFlags mImportsLoadFlags;
// This id is shared with WorkerPrivate to match requests issued by service
// workers to their corresponding serviceWorkerInfo.
uint64_t mServiceWorkerID;
@ -137,9 +146,9 @@ public:
}
nsLoadFlags
GetLoadFlags() const
GetImportsLoadFlags() const
{
return mLoadFlags;
return mImportsLoadFlags;
}
uint64_t

View File

@ -133,6 +133,19 @@ static_assert(nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED == static_
static_assert(6 == static_cast<uint32_t>(RequestCache::EndGuard_),
"RequestCache enumeration value should match Necko Cache mode value.");
static_assert(static_cast<uint16_t>(ServiceWorkerUpdateViaCache::Imports) ==
nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
"nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_*"
" should match ServiceWorkerUpdateViaCache enumeration.");
static_assert(static_cast<uint16_t>(ServiceWorkerUpdateViaCache::All) ==
nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_ALL,
"nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_*"
" should match ServiceWorkerUpdateViaCache enumeration.");
static_assert(static_cast<uint16_t>(ServiceWorkerUpdateViaCache::None) ==
nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_NONE,
"nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_*"
" should match ServiceWorkerUpdateViaCache enumeration.");
static StaticRefPtr<ServiceWorkerManager> gInstance;
struct ServiceWorkerManager::RegistrationDataPerPrincipal final
@ -196,7 +209,12 @@ PopulateRegistrationData(nsIPrincipal* aPrincipal,
aRegistration->GetActive()->GetActivatedTime();
}
aData.loadFlags() = aRegistration->GetLoadFlags();
// This is a workaround before we update SERVICEWORKERREGISTRAR_VERSION and
// the related implementation.
ServiceWorkerUpdateViaCache uvc = aRegistration->GetUpdateViaCache();
aData.loadFlags() =
uvc == ServiceWorkerUpdateViaCache::None ? nsIRequest::LOAD_NORMAL
: nsIRequest::VALIDATE_ALWAYS;
aData.lastUpdateTime() = aRegistration->GetLastUpdateTime();
@ -804,7 +822,7 @@ NS_IMETHODIMP
ServiceWorkerManager::Register(mozIDOMWindow* aWindow,
nsIURI* aScopeURI,
nsIURI* aScriptURI,
nsLoadFlags aLoadFlags,
uint16_t aUpdateViaCache,
nsISupports** aPromise)
{
AssertIsOnMainThread();
@ -929,9 +947,11 @@ ServiceWorkerManager::Register(mozIDOMWindow* aWindow,
nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
MOZ_ALWAYS_SUCCEEDS(loadGroup->SetNotificationCallbacks(ir));
RefPtr<ServiceWorkerRegisterJob> job =
new ServiceWorkerRegisterJob(documentPrincipal, cleanedScope, spec,
loadGroup, aLoadFlags);
RefPtr<ServiceWorkerRegisterJob> job = new ServiceWorkerRegisterJob(
documentPrincipal, cleanedScope, spec, loadGroup,
static_cast<ServiceWorkerUpdateViaCache>(aUpdateViaCache)
);
job->AppendResultCallback(cb);
queue->ScheduleJob(job);
@ -2033,11 +2053,17 @@ ServiceWorkerManager::LoadRegistration(
return;
}
// This is a workaround before we update SERVICEWORKERREGISTRAR_VERSION and
// the related implementation.
nsLoadFlags flags = aRegistration.loadFlags();
ServiceWorkerUpdateViaCache uvc =
flags == nsIRequest::VALIDATE_ALWAYS ? ServiceWorkerUpdateViaCache::Imports
: ServiceWorkerUpdateViaCache::All;
RefPtr<ServiceWorkerRegistrationInfo> registration =
GetRegistration(principal, aRegistration.scope());
if (!registration) {
registration = CreateNewRegistration(aRegistration.scope(), principal,
aRegistration.loadFlags());
registration = CreateNewRegistration(aRegistration.scope(), principal, uvc);
} else {
// If active worker script matches our expectations for a "current worker",
// then we are done. Since scripts with the same URL might have different
@ -2060,7 +2086,7 @@ ServiceWorkerManager::LoadRegistration(
registration->mScope,
currentWorkerURL,
aRegistration.cacheName(),
registration->GetLoadFlags()));
nsIChannel::LOAD_BYPASS_SERVICE_WORKER | flags));
registration->GetActive()->SetHandlesFetch(aRegistration.currentWorkerHandlesFetch());
registration->GetActive()->SetInstalledTime(aRegistration.currentWorkerInstalledTime());
registration->GetActive()->SetActivatedTime(aRegistration.currentWorkerActivatedTime());
@ -3120,7 +3146,7 @@ ServiceWorkerManager::SoftUpdateInternal(const OriginAttributes& aOriginAttribut
RefPtr<ServiceWorkerUpdateJob> job =
new ServiceWorkerUpdateJob(principal, registration->mScope,
newest->ScriptSpec(), nullptr,
registration->GetLoadFlags());
registration->GetUpdateViaCache());
RefPtr<UpdateJobCallback> cb = new UpdateJobCallback(aCallback);
job->AppendResultCallback(cb);
@ -3203,7 +3229,7 @@ ServiceWorkerManager::UpdateInternal(nsIPrincipal* aPrincipal,
RefPtr<ServiceWorkerUpdateJob> job =
new ServiceWorkerUpdateJob(aPrincipal, registration->mScope,
newest->ScriptSpec(), nullptr,
registration->GetLoadFlags());
registration->GetUpdateViaCache());
RefPtr<UpdateJobCallback> cb = new UpdateJobCallback(aCallback);
job->AppendResultCallback(cb);
@ -3548,9 +3574,10 @@ ServiceWorkerManager::GetRegistration(const nsACString& aScopeKey,
}
already_AddRefed<ServiceWorkerRegistrationInfo>
ServiceWorkerManager::CreateNewRegistration(const nsCString& aScope,
nsIPrincipal* aPrincipal,
nsLoadFlags aLoadFlags)
ServiceWorkerManager::CreateNewRegistration(
const nsCString& aScope,
nsIPrincipal* aPrincipal,
ServiceWorkerUpdateViaCache aUpdateViaCache)
{
#ifdef DEBUG
AssertIsOnMainThread();
@ -3564,7 +3591,8 @@ ServiceWorkerManager::CreateNewRegistration(const nsCString& aScope,
#endif
RefPtr<ServiceWorkerRegistrationInfo> registration =
new ServiceWorkerRegistrationInfo(aScope, aPrincipal, aLoadFlags);
new ServiceWorkerRegistrationInfo(aScope, aPrincipal, aUpdateViaCache);
// From now on ownership of registration is with
// mServiceWorkerRegistrationInfos.
AddScopeAndRegistration(aScope, registration);

View File

@ -201,7 +201,7 @@ public:
already_AddRefed<ServiceWorkerRegistrationInfo>
CreateNewRegistration(const nsCString& aScope,
nsIPrincipal* aPrincipal,
nsLoadFlags aLoadFlags);
ServiceWorkerUpdateViaCache aUpdateViaCache);
void
RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration);

View File

@ -1806,7 +1806,7 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
// If we are loading a script for a ServiceWorker then we must not
// try to intercept it. If the interception matches the current
// ServiceWorker's scope then we could deadlock the load.
info.mLoadFlags = mInfo->GetLoadFlags() |
info.mLoadFlags = mInfo->GetImportsLoadFlags() |
nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
rv = info.mBaseURI->GetHost(info.mDomain);

View File

@ -12,13 +12,14 @@ namespace mozilla {
namespace dom {
namespace workers {
ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
nsILoadGroup* aLoadGroup,
nsLoadFlags aLoadFlags)
ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
nsILoadGroup* aLoadGroup,
ServiceWorkerUpdateViaCache aUpdateViaCache)
: ServiceWorkerUpdateJob(Type::Register, aPrincipal, aScope, aScriptSpec,
aLoadGroup, aLoadFlags)
aLoadGroup, aUpdateViaCache)
{
}
@ -37,8 +38,8 @@ ServiceWorkerRegisterJob::AsyncExecute()
swm->GetRegistration(mPrincipal, mScope);
if (registration) {
bool isSameLoadFlags = registration->GetLoadFlags() == GetLoadFlags();
registration->SetLoadFlags(GetLoadFlags());
bool sameUVC = GetUpdateViaCache() == registration->GetUpdateViaCache();
registration->SetUpdateViaCache(GetUpdateViaCache());
// If we are resurrecting an uninstalling registration, then persist
// it to disk again. We preemptively removed it earlier during
@ -49,14 +50,14 @@ ServiceWorkerRegisterJob::AsyncExecute()
}
registration->mPendingUninstall = false;
RefPtr<ServiceWorkerInfo> newest = registration->Newest();
if (newest && mScriptSpec.Equals(newest->ScriptSpec()) && isSameLoadFlags) {
if (newest && mScriptSpec.Equals(newest->ScriptSpec()) && sameUVC) {
SetRegistration(registration);
Finish(NS_OK);
return;
}
} else {
registration = swm->CreateNewRegistration(mScope, mPrincipal,
GetLoadFlags());
GetUpdateViaCache());
if (!registration) {
FailUpdateJob(NS_ERROR_DOM_ABORT_ERR);
return;

View File

@ -23,7 +23,7 @@ public:
const nsACString& aScope,
const nsACString& aScriptSpec,
nsILoadGroup* aLoadGroup,
nsLoadFlags aLoadFlags);
ServiceWorkerUpdateViaCache aUpdateViaCache);
private:
// Implement the Register algorithm steps and then call the parent class

View File

@ -77,15 +77,16 @@ ServiceWorkerRegistrationInfo::Clear()
NotifyChromeRegistrationListeners();
}
ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(const nsACString& aScope,
nsIPrincipal* aPrincipal,
nsLoadFlags aLoadFlags)
ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
const nsACString& aScope,
nsIPrincipal* aPrincipal,
ServiceWorkerUpdateViaCache aUpdateViaCache)
: mControlledDocumentsCounter(0)
, mUpdateState(NoUpdate)
, mCreationTime(PR_Now())
, mCreationTimeStamp(TimeStamp::Now())
, mLastUpdateTime(0)
, mLoadFlags(aLoadFlags)
, mUpdateViaCache(aUpdateViaCache)
, mScope(aScope)
, mPrincipal(aPrincipal)
, mPendingUninstall(false)
@ -637,16 +638,17 @@ ServiceWorkerRegistrationInfo::IsIdle() const
return !mActiveWorker || mActiveWorker->WorkerPrivate()->IsIdle();
}
nsLoadFlags
ServiceWorkerRegistrationInfo::GetLoadFlags() const
ServiceWorkerUpdateViaCache
ServiceWorkerRegistrationInfo::GetUpdateViaCache() const
{
return mLoadFlags;
return mUpdateViaCache;
}
void
ServiceWorkerRegistrationInfo::SetLoadFlags(nsLoadFlags aLoadFlags)
ServiceWorkerRegistrationInfo::SetUpdateViaCache(
ServiceWorkerUpdateViaCache aUpdateViaCache)
{
mLoadFlags = aLoadFlags;
mUpdateViaCache = aUpdateViaCache;
}
int64_t

View File

@ -8,6 +8,7 @@
#define mozilla_dom_workers_serviceworkerregistrationinfo_h
#include "mozilla/dom/workers/ServiceWorkerInfo.h"
#include "mozilla/dom/ServiceWorkerRegistrationBinding.h"
namespace mozilla {
namespace dom {
@ -31,7 +32,7 @@ class ServiceWorkerRegistrationInfo final
// The time of update is 0, if SWR've never been updated yet.
PRTime mLastUpdateTime;
nsLoadFlags mLoadFlags;
ServiceWorkerUpdateViaCache mUpdateViaCache;
RefPtr<ServiceWorkerInfo> mEvaluatingWorker;
RefPtr<ServiceWorkerInfo> mActiveWorker;
@ -57,7 +58,7 @@ public:
ServiceWorkerRegistrationInfo(const nsACString& aScope,
nsIPrincipal* aPrincipal,
nsLoadFlags aLoadFlags);
ServiceWorkerUpdateViaCache aUpdateViaCache);
already_AddRefed<ServiceWorkerInfo>
Newest() const
@ -183,11 +184,11 @@ public:
bool
IsIdle() const;
nsLoadFlags
GetLoadFlags() const;
ServiceWorkerUpdateViaCache
GetUpdateViaCache() const;
void
SetLoadFlags(nsLoadFlags aLoadFlags);
SetUpdateViaCache(ServiceWorkerUpdateViaCache aUpdateViaCache);
int64_t
GetLastUpdateTime() const;

View File

@ -677,7 +677,14 @@ CompareNetwork::Initialize(nsIPrincipal* aPrincipal,
}
// Update LoadFlags for propagating to ServiceWorkerInfo.
mLoadFlags |= mRegistration->GetLoadFlags();
mLoadFlags = nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
ServiceWorkerUpdateViaCache uvc = mRegistration->GetUpdateViaCache();
if (uvc == ServiceWorkerUpdateViaCache::None ||
(uvc == ServiceWorkerUpdateViaCache::Imports && mIsMainScript)) {
mLoadFlags |= nsIRequest::VALIDATE_ALWAYS;
}
if (mRegistration->IsLastUpdateCheckTimeOverOneDay()) {
mLoadFlags |= nsIRequest::LOAD_BYPASS_CACHE;
}

View File

@ -169,14 +169,15 @@ public:
}
};
ServiceWorkerUpdateJob::ServiceWorkerUpdateJob(nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
nsILoadGroup* aLoadGroup,
nsLoadFlags aLoadFlags)
ServiceWorkerUpdateJob::ServiceWorkerUpdateJob(
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
nsILoadGroup* aLoadGroup,
ServiceWorkerUpdateViaCache aUpdateViaCache)
: ServiceWorkerJob(Type::Update, aPrincipal, aScope, aScriptSpec)
, mLoadGroup(aLoadGroup)
, mLoadFlags(aLoadFlags)
, mUpdateViaCache(aUpdateViaCache)
{
}
@ -188,15 +189,16 @@ ServiceWorkerUpdateJob::GetRegistration() const
return ref.forget();
}
ServiceWorkerUpdateJob::ServiceWorkerUpdateJob(Type aType,
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
nsILoadGroup* aLoadGroup,
nsLoadFlags aLoadFlags)
ServiceWorkerUpdateJob::ServiceWorkerUpdateJob(
Type aType,
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
nsILoadGroup* aLoadGroup,
ServiceWorkerUpdateViaCache aUpdateViaCache)
: ServiceWorkerJob(aType, aPrincipal, aScope, aScriptSpec)
, mLoadGroup(aLoadGroup)
, mLoadFlags(aLoadFlags)
, mUpdateViaCache(aUpdateViaCache)
{
}
@ -327,10 +329,10 @@ ServiceWorkerUpdateJob::Update()
}
}
nsLoadFlags
ServiceWorkerUpdateJob::GetLoadFlags() const
ServiceWorkerUpdateViaCache
ServiceWorkerUpdateJob::GetUpdateViaCache() const
{
return mLoadFlags;
return mUpdateViaCache;
}
void
@ -381,8 +383,6 @@ ServiceWorkerUpdateJob::ComparisonResult(nsresult aStatus,
}
}
mLoadFlags = aLoadFlags;
nsAutoCString defaultAllowedPrefix;
rv = GetRequiredScopeStringPrefix(scriptURI, defaultAllowedPrefix,
eUseDirectory);
@ -429,13 +429,17 @@ ServiceWorkerUpdateJob::ComparisonResult(nsresult aStatus,
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_UPDATED, 1);
// Begin step 7 of the Update algorithm to evaluate the new script.
nsLoadFlags flags = aLoadFlags;
if (GetUpdateViaCache() == ServiceWorkerUpdateViaCache::None) {
flags |= nsIRequest::VALIDATE_ALWAYS;
}
RefPtr<ServiceWorkerInfo> sw =
new ServiceWorkerInfo(mRegistration->mPrincipal,
mRegistration->mScope,
mScriptSpec,
aNewCacheName,
mLoadFlags);
flags);
mRegistration->SetEvaluating(sw);

View File

@ -8,6 +8,7 @@
#define mozilla_dom_workers_serviceworkerupdatejob_h
#include "ServiceWorkerJob.h"
#include "ServiceWorkerRegistration.h"
namespace mozilla {
namespace dom {
@ -28,7 +29,7 @@ public:
const nsACString& aScope,
const nsACString& aScriptSpec,
nsILoadGroup* aLoadGroup,
nsLoadFlags aLoadFlags);
ServiceWorkerUpdateViaCache aUpdateViaCache);
already_AddRefed<ServiceWorkerRegistrationInfo>
GetRegistration() const;
@ -40,7 +41,7 @@ protected:
const nsACString& aScope,
const nsACString& aScriptSpec,
nsILoadGroup* aLoadGroup,
nsLoadFlags aLoadFlags);
ServiceWorkerUpdateViaCache aUpdateViaCache);
virtual ~ServiceWorkerUpdateJob();
@ -70,8 +71,8 @@ protected:
void
Update();
nsLoadFlags
GetLoadFlags() const;
ServiceWorkerUpdateViaCache
GetUpdateViaCache() const;
private:
class CompareCallback;
@ -100,7 +101,7 @@ private:
ContinueAfterInstallEvent(bool aInstallEventSuccess);
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsLoadFlags mLoadFlags;
ServiceWorkerUpdateViaCache mUpdateViaCache;
RefPtr<ServiceWorkerRegistrationInfo> mRegistration;
};