Bug 1167809 - Add skip size check flag to cache for use with ServiceWorkers. r=mayhemer

For non-e10s Service Worker, we use Cache entries to achieve interception.
While this is a temporary measure, the fact that cache enforces size limits on
cache entries (which make sense for the purpose it was designed) prevents large
files from being served via a Service Worker. This patch adds a skip size check
flag to CacheStorage that is relayed to CacheEntry and CacheFile. It is set to
false by default leading to normal cache behaviour.
The patch also adds nsICacheStorageService.synthesizedCacheStorage() that
retrieves a cache storage with this flag set to true, which is used by
nsHttpChannel in case of possible interception.
This commit is contained in:
Nikhil Marathe 2015-09-03 16:05:42 -07:00
parent d5a2e4ac81
commit cb21e8e41f
12 changed files with 62 additions and 14 deletions

View File

@ -25,7 +25,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(AppCacheStorage, CacheStorage)
AppCacheStorage::AppCacheStorage(nsILoadContextInfo* aInfo,
nsIApplicationCache* aAppCache)
: CacheStorage(aInfo, true /* disk */, false /* lookup app cache */)
: CacheStorage(aInfo, true /* disk */, false /* lookup app cache */, false /* skip size check */)
, mAppCache(aAppCache)
{
MOZ_COUNT_CTOR(AppCacheStorage);

View File

@ -163,7 +163,8 @@ NS_IMPL_ISUPPORTS(CacheEntry,
CacheEntry::CacheEntry(const nsACString& aStorageID,
nsIURI* aURI,
const nsACString& aEnhanceID,
bool aUseDisk)
bool aUseDisk,
bool aSkipSizeCheck)
: mFrecency(0)
, mSortingExpirationTime(uint32_t(-1))
, mLock("CacheEntry")
@ -172,6 +173,7 @@ CacheEntry::CacheEntry(const nsACString& aStorageID,
, mEnhanceID(aEnhanceID)
, mStorageID(aStorageID)
, mUseDisk(aUseDisk)
, mSkipSizeCheck(aSkipSizeCheck)
, mIsDoomed(false)
, mSecurityInfoLoaded(false)
, mPreventCallbacks(false)
@ -391,6 +393,7 @@ bool CacheEntry::Load(bool aTruncate, bool aPriority)
rv = mFile->Init(fileKey,
aTruncate,
!mUseDisk,
mSkipSizeCheck,
aPriority,
directLoad ? nullptr : this);
}
@ -486,6 +489,7 @@ already_AddRefed<CacheEntryHandle> CacheEntry::ReopenTruncated(bool aMemoryOnly,
nsresult rv = CacheStorageService::Self()->AddStorageEntry(
GetStorageID(), GetURI(), GetEnhanceID(),
mUseDisk && !aMemoryOnly,
mSkipSizeCheck,
true, // always create
true, // truncate existing (this one)
getter_AddRefs(handle));
@ -1142,7 +1146,7 @@ NS_IMETHODIMP CacheEntry::SetPredictedDataSize(int64_t aPredictedDataSize)
{
mPredictedDataSize = aPredictedDataSize;
if (CacheObserver::EntryIsTooBig(mPredictedDataSize, mUseDisk)) {
if (!mSkipSizeCheck && CacheObserver::EntryIsTooBig(mPredictedDataSize, mUseDisk)) {
LOG(("CacheEntry::SetPredictedDataSize [this=%p] too big, dooming", this));
AsyncDoom(nullptr);

View File

@ -55,7 +55,7 @@ public:
NS_DECL_NSIRUNNABLE
CacheEntry(const nsACString& aStorageID, nsIURI* aURI, const nsACString& aEnhanceID,
bool aUseDisk);
bool aUseDisk, bool aSkipSizeCheck);
void AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags);
@ -276,6 +276,9 @@ private:
// Whether it's allowed to persist the data to disk
bool const mUseDisk;
// Whether it should skip max size check.
bool const mSkipSizeCheck;
// Set when entry is doomed with AsyncDoom() or DoomAlreadyRemoved().
// Left as a standalone flag to not bother with locking (there is no need).
bool mIsDoomed;

View File

@ -183,6 +183,7 @@ CacheFile::CacheFile()
, mOpeningFile(false)
, mReady(false)
, mMemoryOnly(false)
, mSkipSizeCheck(false)
, mOpenAsMemoryOnly(false)
, mPriority(false)
, mDataAccessed(false)
@ -212,6 +213,7 @@ nsresult
CacheFile::Init(const nsACString &aKey,
bool aCreateNew,
bool aMemoryOnly,
bool aSkipSizeCheck,
bool aPriority,
CacheFileListener *aCallback)
{
@ -222,6 +224,7 @@ CacheFile::Init(const nsACString &aKey,
mKey = aKey;
mOpenAsMemoryOnly = mMemoryOnly = aMemoryOnly;
mSkipSizeCheck = aSkipSizeCheck;
mPriority = aPriority;
// Some consumers (at least nsHTTPCompressConv) assume that Read() can read

View File

@ -56,6 +56,7 @@ public:
nsresult Init(const nsACString &aKey,
bool aCreateNew,
bool aMemoryOnly,
bool aSkipSizeCheck,
bool aPriority,
CacheFileListener *aCallback);
@ -193,6 +194,7 @@ private:
bool mOpeningFile;
bool mReady;
bool mMemoryOnly;
bool mSkipSizeCheck;
bool mOpenAsMemoryOnly;
bool mPriority;
bool mDataAccessed;

View File

@ -94,7 +94,7 @@ CacheFileOutputStream::Write(const char * aBuf, uint32_t aCount,
return NS_FAILED(mStatus) ? mStatus : NS_BASE_STREAM_CLOSED;
}
if (CacheObserver::EntryIsTooBig(mPos + aCount, !mFile->mMemoryOnly)) {
if (!mFile->mSkipSizeCheck && CacheObserver::EntryIsTooBig(mPos + aCount, !mFile->mMemoryOnly)) {
LOG(("CacheFileOutputStream::Write() - Entry is too big, failing and "
"dooming the entry. [this=%p]", this));

View File

@ -25,10 +25,12 @@ NS_IMPL_ISUPPORTS(CacheStorage, nsICacheStorage)
CacheStorage::CacheStorage(nsILoadContextInfo* aInfo,
bool aAllowDisk,
bool aLookupAppCache)
bool aLookupAppCache,
bool aSkipSizeCheck)
: mLoadContextInfo(GetLoadContextInfo(aInfo))
, mWriteToDisk(aAllowDisk)
, mLookupAppCache(aLookupAppCache)
, mSkipSizeCheck(aSkipSizeCheck)
{
}

View File

@ -52,7 +52,8 @@ class CacheStorage : public nsICacheStorage
public:
CacheStorage(nsILoadContextInfo* aInfo,
bool aAllowDisk,
bool aLookupAppCache);
bool aLookupAppCache,
bool aSkipSizeCheck);
protected:
virtual ~CacheStorage();
@ -62,11 +63,13 @@ protected:
nsRefPtr<LoadContextInfo> mLoadContextInfo;
bool mWriteToDisk : 1;
bool mLookupAppCache : 1;
bool mSkipSizeCheck: 1;
public:
nsILoadContextInfo* LoadInfo() const { return mLoadContextInfo; }
bool WriteToDisk() const { return mWriteToDisk && !mLoadContextInfo->IsPrivate(); }
bool LookupAppCache() const { return mLookupAppCache; }
bool SkipSizeCheck() const { return mSkipSizeCheck; }
};
} // namespace net

View File

@ -681,7 +681,7 @@ NS_IMETHODIMP CacheStorageService::MemoryCacheStorage(nsILoadContextInfo *aLoadC
nsCOMPtr<nsICacheStorage> storage;
if (CacheObserver::UseNewCache()) {
storage = new CacheStorage(aLoadContextInfo, false, false);
storage = new CacheStorage(aLoadContextInfo, false, false, false);
}
else {
storage = new _OldStorage(aLoadContextInfo, false, false, false, nullptr);
@ -706,7 +706,7 @@ NS_IMETHODIMP CacheStorageService::DiskCacheStorage(nsILoadContextInfo *aLoadCon
nsCOMPtr<nsICacheStorage> storage;
if (CacheObserver::UseNewCache()) {
storage = new CacheStorage(aLoadContextInfo, useDisk, aLookupAppCache);
storage = new CacheStorage(aLoadContextInfo, useDisk, aLookupAppCache, false);
}
else {
storage = new _OldStorage(aLoadContextInfo, useDisk, aLookupAppCache, false, nullptr);
@ -737,6 +737,24 @@ NS_IMETHODIMP CacheStorageService::AppCacheStorage(nsILoadContextInfo *aLoadCont
return NS_OK;
}
NS_IMETHODIMP CacheStorageService::SynthesizedCacheStorage(nsILoadContextInfo *aLoadContextInfo,
nsICacheStorage * *_retval)
{
NS_ENSURE_ARG(aLoadContextInfo);
NS_ENSURE_ARG(_retval);
nsCOMPtr<nsICacheStorage> storage;
if (CacheObserver::UseNewCache()) {
storage = new CacheStorage(aLoadContextInfo, false, false, true /* skip size checks for synthesized cache */);
}
else {
storage = new _OldStorage(aLoadContextInfo, false, false, false, nullptr);
}
storage.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP CacheStorageService::Clear()
{
nsresult rv;
@ -1339,7 +1357,8 @@ CacheStorageService::AddStorageEntry(CacheStorage const* aStorage,
CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey);
return AddStorageEntry(contextKey, aURI, aIdExtension,
aStorage->WriteToDisk(), aCreateIfNotExist, aReplace,
aStorage->WriteToDisk(), aStorage->SkipSizeCheck(),
aCreateIfNotExist, aReplace,
aResult);
}
@ -1348,6 +1367,7 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
nsIURI* aURI,
const nsACString & aIdExtension,
bool aWriteToDisk,
bool aSkipSizeCheck,
bool aCreateIfNotExist,
bool aReplace,
CacheEntryHandle** aResult)
@ -1410,7 +1430,7 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
// Ensure entry for the particular URL, if not read/only
if (!entryExists && (aCreateIfNotExist || aReplace)) {
// Entry is not in the hashtable or has just been truncated...
entry = new CacheEntry(aContextKey, aURI, aIdExtension, aWriteToDisk);
entry = new CacheEntry(aContextKey, aURI, aIdExtension, aWriteToDisk, aSkipSizeCheck);
entries->Put(entryKey, entry);
LOG((" new entry %p for %s", entry.get(), entryKey.get()));
}

View File

@ -278,6 +278,7 @@ private:
nsIURI* aURI,
const nsACString & aIdExtension,
bool aWriteToDisk,
bool aSkipSizeCheck,
bool aCreateIfNotExist,
bool aReplace,
CacheEntryHandle** aResult);

View File

@ -13,7 +13,7 @@ interface nsICacheStorageConsumptionObserver;
/**
* Provides access to particual cache storages of the network URI cache.
*/
[scriptable, uuid(44de2fa4-1b0e-4cd3-9e32-211e936f721e)]
[scriptable, uuid(9c9dc1d6-533e-4716-9ad8-11e08c3763b3)]
interface nsICacheStorageService : nsISupports
{
/**
@ -55,6 +55,13 @@ interface nsICacheStorageService : nsISupports
nsICacheStorage appCacheStorage(in nsILoadContextInfo aLoadContextInfo,
in nsIApplicationCache aApplicationCache);
/**
* Get storage for synthesized cache entries that we currently use for ServiceWorker interception in non-e10s mode.
*
* This cache storage has no limits on file size to allow the ServiceWorker to intercept large files.
*/
nsICacheStorage synthesizedCacheStorage(in nsILoadContextInfo aLoadContextInfo);
/**
* Evict the whole cache.
*/

View File

@ -2932,8 +2932,11 @@ nsHttpChannel::OpenCacheEntry(bool isHttps)
rv = cacheStorageService->AppCacheStorage(info,
mApplicationCache,
getter_AddRefs(cacheStorage));
}
else if (PossiblyIntercepted() || mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
} else if (PossiblyIntercepted()) {
// The synthesized cache has less restrictions on file size and so on.
rv = cacheStorageService->SynthesizedCacheStorage(info,
getter_AddRefs(cacheStorage));
} else if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
rv = cacheStorageService->MemoryCacheStorage(info, // ? choose app cache as well...
getter_AddRefs(cacheStorage));
}