Bug 1174106 - Part 2: Load the top level SW script with http cache bypass settings; r?rickychien
MozReview-Commit-ID: 97GFyga1GOy
--- a/dom/interfaces/base/nsIServiceWorkerManager.idl
+++ b/dom/interfaces/base/nsIServiceWorkerManager.idl
@@ -93,17 +93,20 @@ interface nsIServiceWorkerManager : nsIS
/**
* Registers a ServiceWorker with script loaded from `aScriptURI` to act as
* the ServiceWorker for aScope. Requires a valid entry settings object on
* the stack. This means you must call this from content code 'within'
* a window.
*
* Returns a Promise.
*/
- nsISupports register(in mozIDOMWindow aWindow, in nsIURI aScope, in nsIURI aScriptURI);
+ nsISupports register(in mozIDOMWindow aWindow,
+ in nsIURI aScope,
+ in nsIURI aScriptURI,
+ in bool aBypassHttpCache);
/**
* Unregister an existing ServiceWorker registration for `aScope`.
* It keeps aCallback alive until the operation is concluded.
*/
void unregister(in nsIPrincipal aPrincipal,
in nsIServiceWorkerUnregisterCallback aCallback,
in DOMString aScope);
--- a/dom/workers/ServiceWorkerContainer.cpp
+++ b/dom/workers/ServiceWorkerContainer.cpp
@@ -202,19 +202,24 @@ ServiceWorkerContainer::Register(const n
}
aRv = CheckForSlashEscapedCharsInPath(scopeURI);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
}
+ // TODO: Add spec link here
+ bool bypassHttpCache =
+ aOptions.mUseCache.WasPassed() ? !aOptions.mUseCache.Value() : true;
+
// 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, getter_AddRefs(promise));
+ aRv = swm->Register(GetOwner(), scopeURI, scriptURI, bypassHttpCache,
+ getter_AddRefs(promise));
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
RefPtr<Promise> ret = static_cast<Promise*>(promise.get());
MOZ_ASSERT(ret);
return ret.forget();
}
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -486,16 +486,17 @@ IsFromAuthenticatedOrigin(nsIDocument* a
}
// If we return an error code here, the ServiceWorkerContainer will
// automatically reject the Promise.
NS_IMETHODIMP
ServiceWorkerManager::Register(mozIDOMWindow* aWindow,
nsIURI* aScopeURI,
nsIURI* aScriptURI,
+ bool aBypassHttpCache,
nsISupports** aPromise)
{
AssertIsOnMainThread();
if (NS_WARN_IF(!aWindow)) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
@@ -612,17 +613,17 @@ ServiceWorkerManager::Register(mozIDOMWi
// Create a load group that is separate from, yet related to, the document's load group.
// This allows checks for interfaces like nsILoadContext to yield the values used by the
// the document, yet will not cancel the update job if the document's load group is cancelled.
nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
MOZ_ALWAYS_SUCCEEDS(loadGroup->SetNotificationCallbacks(ir));
RefPtr<ServiceWorkerRegisterJob> job =
new ServiceWorkerRegisterJob(documentPrincipal, cleanedScope, spec,
- loadGroup);
+ loadGroup, aBypassHttpCache);
job->AppendResultCallback(cb);
queue->ScheduleJob(job);
AssertIsOnMainThread();
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_REGISTRATIONS, 1);
promise.forget(aPromise);
return NS_OK;
--- a/dom/workers/ServiceWorkerRegisterJob.cpp
+++ b/dom/workers/ServiceWorkerRegisterJob.cpp
@@ -10,19 +10,20 @@
namespace mozilla {
namespace dom {
namespace workers {
ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
- nsILoadGroup* aLoadGroup)
+ nsILoadGroup* aLoadGroup,
+ bool aBypassHttpCache)
: ServiceWorkerUpdateJob(Type::Register, aPrincipal, aScope, aScriptSpec,
- aLoadGroup)
+ aLoadGroup, aBypassHttpCache)
{
}
void
ServiceWorkerRegisterJob::AsyncExecute()
{
AssertIsOnMainThread();
@@ -40,17 +41,17 @@ ServiceWorkerRegisterJob::AsyncExecute()
// it to disk again. We preemptively removed it earlier during
// unregister so that closing the window by shutting down the browser
// results in the registration being gone on restart.
if (registration->mPendingUninstall) {
swm->StoreRegistration(mPrincipal, registration);
}
registration->mPendingUninstall = false;
RefPtr<ServiceWorkerInfo> newest = registration->Newest();
- if (newest && mScriptSpec.Equals(newest->ScriptSpec())) {
+ if (!mBypassHttpCache && newest && mScriptSpec.Equals(newest->ScriptSpec())) {
SetRegistration(registration);
Finish(NS_OK);
return;
}
} else {
registration = swm->CreateNewRegistration(mScope, mPrincipal);
}
--- a/dom/workers/ServiceWorkerRegisterJob.h
+++ b/dom/workers/ServiceWorkerRegisterJob.h
@@ -17,17 +17,18 @@ namespace workers {
// but then uses ServiceWorkerUpdateJob to implement the Update and Install
// spec algorithms.
class ServiceWorkerRegisterJob final : public ServiceWorkerUpdateJob
{
public:
ServiceWorkerRegisterJob(nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
- nsILoadGroup* aLoadGroup);
+ nsILoadGroup* aLoadGroup,
+ bool aBypassHttpCache);
private:
// Implement the Register algorithm steps and then call the parent class
// Update() to complete the job execution.
virtual void
AsyncExecute() override;
virtual ~ServiceWorkerRegisterJob();
--- a/dom/workers/ServiceWorkerScriptCache.cpp
+++ b/dom/workers/ServiceWorkerScriptCache.cpp
@@ -92,17 +92,20 @@ public:
explicit CompareNetwork(CompareManager* aManager)
: mManager(aManager)
{
MOZ_ASSERT(aManager);
AssertIsOnMainThread();
}
nsresult
- Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL, nsILoadGroup* aLoadGroup);
+ Initialize(nsIPrincipal* aPrincipal,
+ const nsAString& aURL,
+ nsILoadGroup* aLoadGroup,
+ bool aBypassHttpCache);
void
Abort()
{
AssertIsOnMainThread();
MOZ_ASSERT(mChannel);
mChannel->Cancel(NS_BINDING_ABORTED);
@@ -245,17 +248,18 @@ public:
, mInCache(false)
{
AssertIsOnMainThread();
MOZ_ASSERT(aRegistration);
}
nsresult
Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL,
- const nsAString& aCacheName, nsILoadGroup* aLoadGroup)
+ const nsAString& aCacheName, nsILoadGroup* aLoadGroup,
+ bool aBypassHttpCache)
{
AssertIsOnMainThread();
MOZ_ASSERT(aPrincipal);
mURL = aURL;
// Always create a CacheStorage since we want to write the network entry to
// the cache even if there isn't an existing one.
@@ -266,17 +270,17 @@ public:
mCacheStorage = CreateCacheStorage(jsapi.cx(), aPrincipal, result, &mSandbox);
if (NS_WARN_IF(result.Failed())) {
MOZ_ASSERT(!result.IsErrorWithMessage());
Cleanup();
return result.StealNSResult();
}
mCN = new CompareNetwork(this);
- nsresult rv = mCN->Initialize(aPrincipal, aURL, aLoadGroup);
+ nsresult rv = mCN->Initialize(aPrincipal, aURL, aLoadGroup, aBypassHttpCache);
if (NS_WARN_IF(NS_FAILED(rv))) {
Cleanup();
return rv;
}
if (!aCacheName.IsEmpty()) {
mCC = new CompareCache(this);
rv = mCC->Initialize(aPrincipal, aURL, aCacheName);
@@ -600,17 +604,17 @@ private:
bool mNetworkFinished;
bool mCacheFinished;
bool mInCache;
};
NS_IMPL_ISUPPORTS0(CompareManager)
nsresult
-CompareNetwork::Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL, nsILoadGroup* aLoadGroup)
+CompareNetwork::Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL, nsILoadGroup* aLoadGroup, bool aBypassHttpCache)
{
MOZ_ASSERT(aPrincipal);
AssertIsOnMainThread();
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -624,16 +628,20 @@ CompareNetwork::Initialize(nsIPrincipal*
nsLoadFlags flags = nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
RefPtr<ServiceWorkerRegistrationInfo> registration =
mManager->GetRegistration();
if (registration->IsLastUpdateCheckTimeOverOneDay()) {
flags |= nsIRequest::LOAD_BYPASS_CACHE;
}
+ if (aBypassHttpCache) {
+ flags |= nsIRequest::VALIDATE_ALWAYS;
+ }
+
// Note that because there is no "serviceworker" RequestContext type, we can
// use the TYPE_INTERNAL_SCRIPT content policy types when loading a service
// worker.
rv = NS_NewChannel(getter_AddRefs(mChannel),
uri, aPrincipal,
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER,
loadGroup,
@@ -1041,27 +1049,28 @@ GenerateCacheName(nsAString& aName)
return NS_OK;
}
nsresult
Compare(ServiceWorkerRegistrationInfo* aRegistration,
nsIPrincipal* aPrincipal, const nsAString& aCacheName,
const nsAString& aURL, CompareCallback* aCallback,
- nsILoadGroup* aLoadGroup)
+ nsILoadGroup* aLoadGroup, bool aBypassHttpCache)
{
AssertIsOnMainThread();
MOZ_ASSERT(aRegistration);
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(!aURL.IsEmpty());
MOZ_ASSERT(aCallback);
RefPtr<CompareManager> cm = new CompareManager(aRegistration, aCallback);
- nsresult rv = cm->Initialize(aPrincipal, aURL, aCacheName, aLoadGroup);
+ nsresult rv = cm->Initialize(aPrincipal, aURL, aCacheName, aLoadGroup,
+ aBypassHttpCache);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
} // namespace serviceWorkerScriptCache
--- a/dom/workers/ServiceWorkerScriptCache.h
+++ b/dom/workers/ServiceWorkerScriptCache.h
@@ -43,17 +43,18 @@ public:
NS_IMETHOD_(MozExternalRefCountType) AddRef() = 0;
NS_IMETHOD_(MozExternalRefCountType) Release() = 0;
};
nsresult
Compare(ServiceWorkerRegistrationInfo* aRegistration,
nsIPrincipal* aPrincipal, const nsAString& aCacheName,
- const nsAString& aURL, CompareCallback* aCallback, nsILoadGroup* aLoadGroup);
+ const nsAString& aURL, CompareCallback* aCallback,
+ nsILoadGroup* aLoadGroup, bool mBypassHttpCache);
} // namespace serviceWorkerScriptCache
} // namespace workers
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_workers_ServiceWorkerScriptCache_h
--- a/dom/workers/ServiceWorkerUpdateJob.cpp
+++ b/dom/workers/ServiceWorkerUpdateJob.cpp
@@ -180,18 +180,20 @@ ServiceWorkerUpdateJob::GetRegistration(
RefPtr<ServiceWorkerRegistrationInfo> ref = mRegistration;
return ref.forget();
}
ServiceWorkerUpdateJob::ServiceWorkerUpdateJob(Type aType,
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
- nsILoadGroup* aLoadGroup)
+ nsILoadGroup* aLoadGroup,
+ bool aBypassHttpCache)
: ServiceWorkerJob(aType, aPrincipal, aScope, aScriptSpec)
+ , mBypassHttpCache(aBypassHttpCache)
, mLoadGroup(aLoadGroup)
{
}
ServiceWorkerUpdateJob::~ServiceWorkerUpdateJob()
{
}
@@ -306,17 +308,17 @@ ServiceWorkerUpdateJob::Update()
cacheName = workerInfo->CacheName();
}
RefPtr<CompareCallback> callback = new CompareCallback(this);
nsresult rv =
serviceWorkerScriptCache::Compare(mRegistration, mPrincipal, cacheName,
NS_ConvertUTF8toUTF16(mScriptSpec),
- callback, mLoadGroup);
+ callback, mLoadGroup, mBypassHttpCache);
if (NS_WARN_IF(NS_FAILED(rv))) {
FailUpdateJob(rv);
return;
}
}
void
ServiceWorkerUpdateJob::ComparisonResult(nsresult aStatus,
--- a/dom/workers/ServiceWorkerUpdateJob.h
+++ b/dom/workers/ServiceWorkerUpdateJob.h
@@ -31,17 +31,18 @@ public:
GetRegistration() const;
protected:
// Construct an update job that is overriden as another job type.
ServiceWorkerUpdateJob(Type aType,
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
- nsILoadGroup* aLoadGroup);
+ nsILoadGroup* aLoadGroup,
+ bool mBypassHttpCache);
virtual ~ServiceWorkerUpdateJob();
// FailUpdateJob() must be called if an update job needs Finish() with
// an error.
void
FailUpdateJob(ErrorResult& aRv);
@@ -61,16 +62,18 @@ protected:
// Execute the bulk of the update job logic using the registration defined
// by a previous SetRegistration() call. This can be called by the overriden
// AsyncExecute() to complete the job. The Update() method will always call
// Finish(). This method corresponds to the spec Update algorithm.
void
Update();
+ bool mBypassHttpCache;
+
private:
class CompareCallback;
class ContinueUpdateRunnable;
class ContinueInstallRunnable;
// Utility method called after a script is loaded and compared to
// our current cached script.
void