Bug 1174106 - Part 3: ImportScripts() in SW should use the same http cache bypass settings as its top level SW script; r?rickychien
MozReview-Commit-ID: AxPStlhMjkQ
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -216,16 +216,17 @@ ChannelFromScriptURL(nsIPrincipal* princ
return rv;
}
struct ScriptLoadInfo
{
ScriptLoadInfo()
: mScriptTextBuf(nullptr)
, mScriptTextLength(0)
+ , mHttpCacheSetting(WorkerLoadInfo::Normal)
, mLoadResult(NS_ERROR_NOT_INITIALIZED)
, mLoadingFinished(false)
, mExecutionScheduled(false)
, mExecutionResult(false)
, mCacheStatus(Uncached)
{ }
~ScriptLoadInfo()
@@ -256,16 +257,18 @@ struct ScriptLoadInfo
// The reader stream the cache entry should be filled from, for those cases
// when we're going to have an mCachePromise.
nsCOMPtr<nsIInputStream> mCacheReadStream;
nsCOMPtr<nsIChannel> mChannel;
char16_t* mScriptTextBuf;
size_t mScriptTextLength;
+ WorkerLoadInfo::HttpCacheSetting mHttpCacheSetting;
+
nsresult mLoadResult;
bool mLoadingFinished;
bool mExecutionScheduled;
bool mExecutionResult;
enum CacheStatus {
// By default a normal script is just loaded from the network. But for
// ServiceWorkers, we have to check if the cache contains the script and
@@ -926,16 +929,28 @@ private:
// 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.
if (mWorkerPrivate->IsServiceWorker()) {
loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
}
+ switch (loadInfo.mHttpCacheSetting) {
+ case WorkerLoadInfo::NoCache:
+ loadFlags |= nsIRequest::VALIDATE_ALWAYS;
+ break;
+ case WorkerLoadInfo::Restore:
+ loadFlags |= nsIRequest::LOAD_BYPASS_CACHE;
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+
if (!channel) {
// Only top level workers' main script use the document charset for the
// script uri encoding. Otherwise, default encoding (UTF-8) is applied.
bool useDefaultEncoding = !(!parentWorker && IsMainWorkerScript());
rv = ChannelFromScriptURL(principal, baseURI, parentDoc, loadGroup, ios,
secMan, loadInfo.mURL, IsMainWorkerScript(),
mWorkerScriptType,
mWorkerPrivate->ContentPolicyType(), loadFlags,
@@ -2241,16 +2256,23 @@ LoadMainScript(WorkerPrivate* aWorkerPri
const nsAString& aScriptURL,
WorkerScriptType aWorkerScriptType,
ErrorResult& aRv)
{
nsTArray<ScriptLoadInfo> loadInfos;
ScriptLoadInfo* info = loadInfos.AppendElement();
info->mURL = aScriptURL;
+ // For a service worker, before trying to load the main script here, the new
+ // script has already been loaded into http cache when comparing with the
+ // stale copy in the DOM cache. Thus, we don't have to actually download it
+ // again here.
+ info->mHttpCacheSetting =
+ aWorkerPrivate->IsServiceWorker() ? WorkerLoadInfo::Normal
+ : aWorkerPrivate->HttpCacheSetting();
LoadAllScripts(aWorkerPrivate, loadInfos, true, aWorkerScriptType, aRv);
}
void
Load(WorkerPrivate* aWorkerPrivate,
const nsTArray<nsString>& aScriptURLs, WorkerScriptType aWorkerScriptType,
ErrorResult& aRv)
@@ -2266,16 +2288,17 @@ Load(WorkerPrivate* aWorkerPrivate,
return;
}
nsTArray<ScriptLoadInfo> loadInfos;
loadInfos.SetLength(urlCount);
for (uint32_t index = 0; index < urlCount; index++) {
loadInfos[index].mURL = aScriptURLs[index];
+ loadInfos[index].mHttpCacheSetting = aWorkerPrivate->HttpCacheSetting();
}
LoadAllScripts(aWorkerPrivate, loadInfos, false, aWorkerScriptType, aRv);
}
} // namespace scriptloader
END_WORKERS_NAMESPACE
--- a/dom/workers/ServiceWorkerInfo.cpp
+++ b/dom/workers/ServiceWorkerInfo.cpp
@@ -166,25 +166,27 @@ ServiceWorkerInfo::UpdateState(ServiceWo
if (mState == ServiceWorkerState::Redundant) {
serviceWorkerScriptCache::PurgeCache(mPrincipal, mCacheName);
}
}
ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
- const nsAString& aCacheName)
+ const nsAString& aCacheName,
+ WorkerLoadInfo::HttpCacheSetting aHttpCacheSetting)
: mPrincipal(aPrincipal)
, mScope(aScope)
, mScriptSpec(aScriptSpec)
, mCacheName(aCacheName)
, mState(ServiceWorkerState::EndGuard_)
, mServiceWorkerID(GetNextID())
, mServiceWorkerPrivate(new ServiceWorkerPrivate(this))
, mSkipWaitingFlag(false)
+ , mHttpCacheSetting(aHttpCacheSetting)
{
MOZ_ASSERT(mPrincipal);
// cache origin attributes so we can use them off main thread
mOriginAttributes = BasePrincipal::Cast(mPrincipal)->OriginAttributesRef();
MOZ_ASSERT(!mScope.IsEmpty());
MOZ_ASSERT(!mScriptSpec.IsEmpty());
MOZ_ASSERT(!mCacheName.IsEmpty());
}
--- a/dom/workers/ServiceWorkerInfo.h
+++ b/dom/workers/ServiceWorkerInfo.h
@@ -40,16 +40,17 @@ private:
// We hold rawptrs since the ServiceWorker constructor and destructor ensure
// addition and removal.
// There is a high chance of there being at least one ServiceWorker
// associated with this all the time.
AutoTArray<ServiceWorker*, 1> mInstances;
RefPtr<ServiceWorkerPrivate> mServiceWorkerPrivate;
bool mSkipWaitingFlag;
+ WorkerLoadInfo::HttpCacheSetting mHttpCacheSetting;
~ServiceWorkerInfo();
// Generates a unique id for the service worker, with zero being treated as
// invalid.
uint64_t
GetNextID() const;
@@ -83,26 +84,33 @@ public:
}
bool SkipWaitingFlag() const
{
AssertIsOnMainThread();
return mSkipWaitingFlag;
}
+ WorkerLoadInfo::HttpCacheSetting
+ HttpCacheSetting() const
+ {
+ return mHttpCacheSetting;
+ }
+
void SetSkipWaitingFlag()
{
AssertIsOnMainThread();
mSkipWaitingFlag = true;
}
ServiceWorkerInfo(nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
- const nsAString& aCacheName);
+ const nsAString& aCacheName,
+ WorkerLoadInfo::HttpCacheSetting aHttpCacheSetting);
ServiceWorkerState
State() const
{
return mState;
}
const PrincipalOriginAttributes&
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -1692,17 +1692,17 @@ ServiceWorkerManager::LoadRegistration(
return;
}
}
const nsCString& currentWorkerURL = aRegistration.currentWorkerURL();
if (!currentWorkerURL.IsEmpty()) {
registration->SetActive(
new ServiceWorkerInfo(registration->mPrincipal, registration->mScope,
- currentWorkerURL, aRegistration.cacheName()));
+ currentWorkerURL, aRegistration.cacheName(), WorkerLoadInfo::Restore));
registration->GetActive()->SetActivateStateUncheckedWithoutEvent(ServiceWorkerState::Activated);
}
}
void
ServiceWorkerManager::LoadRegistrations(
const nsTArray<ServiceWorkerRegistrationData>& aRegistrations)
{
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -1700,16 +1700,18 @@ ServiceWorkerPrivate::SpawnWorkerIfNeede
info.mResolvedScriptURI = info.mBaseURI;
MOZ_ASSERT(!mInfo->CacheName().IsEmpty());
info.mServiceWorkerCacheName = mInfo->CacheName();
info.mServiceWorkerID = mInfo->ID();
info.mLoadGroup = aLoadGroup;
info.mLoadFailedAsyncRunnable = aLoadFailedRunnable;
+ info.mHttpCacheSetting = mInfo->HttpCacheSetting();
+
rv = info.mBaseURI->GetHost(info.mDomain);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
info.mPrincipal = mInfo->GetPrincipal();
nsContentUtils::StorageAccess access =
--- a/dom/workers/ServiceWorkerUpdateJob.cpp
+++ b/dom/workers/ServiceWorkerUpdateJob.cpp
@@ -408,21 +408,33 @@ ServiceWorkerUpdateJob::ComparisonResult
if (aInCacheAndEqual) {
Finish(NS_OK);
return;
}
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_UPDATED, 1);
// Begin step 7 of the Update algorithm to evaluate the new script.
+ WorkerLoadInfo::HttpCacheSetting httpCacheSetting = WorkerLoadInfo::Normal;
+ switch (mType) {
+ case Type::Update:
+ httpCacheSetting = WorkerLoadInfo::Restore;
+ break;
+ case Type::Register:
+ httpCacheSetting = mBypassHttpCache ? WorkerLoadInfo::NoCache
+ : WorkerLoadInfo::Normal;
+ break;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Can only be triggered by register or update");
+ };
RefPtr<ServiceWorkerInfo> sw =
new ServiceWorkerInfo(mRegistration->mPrincipal,
mRegistration->mScope,
- mScriptSpec, aNewCacheName);
+ mScriptSpec, aNewCacheName, httpCacheSetting);
mRegistration->SetEvaluating(sw);
nsMainThreadPtrHandle<ServiceWorkerUpdateJob> handle(
new nsMainThreadPtrHolder<ServiceWorkerUpdateJob>(this));
RefPtr<LifeCycleEventCallback> callback = new ContinueUpdateRunnable(handle);
ServiceWorkerPrivate* workerPrivate = sw->WorkerPrivate();
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1726,16 +1726,17 @@ WorkerLoadInfo::StealFrom(WorkerLoadInfo
mFromWindow = aOther.mFromWindow;
mEvalAllowed = aOther.mEvalAllowed;
mReportCSPViolations = aOther.mReportCSPViolations;
mXHRParamsAllowed = aOther.mXHRParamsAllowed;
mPrincipalIsSystem = aOther.mPrincipalIsSystem;
mStorageAllowed = aOther.mStorageAllowed;
mServiceWorkersTestingInWindow = aOther.mServiceWorkersTestingInWindow;
mOriginAttributes = aOther.mOriginAttributes;
+ mHttpCacheSetting = aOther.mHttpCacheSetting;
}
template <class Derived>
class WorkerPrivateParent<Derived>::EventTarget final
: public nsIEventTarget
{
// This mutex protects mWorkerPrivate and must be acquired *before* the
// WorkerPrivate's mutex whenever they must both be held.
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -510,16 +510,22 @@ public:
nsIURI*
GetResolvedScriptURI() const
{
AssertIsOnMainThread();
return mLoadInfo.mResolvedScriptURI;
}
+ WorkerLoadInfo::HttpCacheSetting
+ HttpCacheSetting() const
+ {
+ return mLoadInfo.mHttpCacheSetting;
+ }
+
const nsString&
ServiceWorkerCacheName() const
{
MOZ_ASSERT(IsServiceWorker());
AssertIsOnMainThread();
return mLoadInfo.mServiceWorkerCacheName;
}
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -267,16 +267,24 @@ struct WorkerLoadInfo
bool mEvalAllowed;
bool mReportCSPViolations;
bool mXHRParamsAllowed;
bool mPrincipalIsSystem;
bool mStorageAllowed;
bool mServiceWorkersTestingInWindow;
PrincipalOriginAttributes mOriginAttributes;
+ enum HttpCacheSetting {
+ Normal,
+ NoCache,
+ Restore
+ };
+
+ HttpCacheSetting mHttpCacheSetting;
+
WorkerLoadInfo();
~WorkerLoadInfo();
void StealFrom(WorkerLoadInfo& aOther);
};
// All of these are implemented in RuntimeService.cpp