/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef CacheStorage_h_
#define CacheStorage_h_
#include "nsICacheStorage.h"
#include "CacheEntry.h"
#include "LoadContextInfo.h"
#include "nsILoadContextInfo.h"
#include "nsTArray.h"
#include "nsTHashMap.h"
class nsIURI;
namespace mozilla {
namespace net {
// This dance is needed to make CacheEntryTable declarable-only in headers
// w/o exporting CacheEntry.h file to make nsNetModule.cpp compilable.
using TCacheEntryTable = nsRefPtrHashtable<nsCStringHashKey, CacheEntry>;
class CacheEntryTable : public TCacheEntryTable {
public:
enum EType { MEMORY_ONLY, ALL_ENTRIES };
explicit CacheEntryTable(EType aType) : mType(aType) {}
CacheEntryTable() =
delete;
EType Type()
const {
return mType; }
// Secondary index for No-Vary-Search cache lookup.
//
// Without NVS, a cache lookup is a single exact-key hash lookup on this
// table. With NVS, a response can declare that certain query parameters do
// not affect the response (e.g. "No-Vary-Search: params=(\"utm_source\")"),
// meaning /page?q=hello&utm_source=email should hit the same cache entry as
// /page?q=hello. An exact-key lookup misses in this case, so we need a way
// to find candidate entries that share the same base path.
//
// This index maps scheme://host:port/path (no query string) to the list of
// full entry keys — the cache storage keys used to look up CacheEntry
// objects in this table — for all entries that carry NVS metadata. On an
// exact-key miss, AddStorageEntry() consults this index to find candidates
// and checks each one for URL equivalence under its stored NVS header.
//
// A "full entry key" is the string passed to CacheEntry::HashingKey(), of
// the form "https://example.com/page?q=hello", uniquely identifying the
// cached response within this CacheEntryTable.
//
// Protected by CacheStorageService::sLock.
nsTHashMap<nsCStringHashKey, nsTArray<nsCString>> mNoVarySearchIndex;
void NoteNoVarySearchEntry(
const nsACString& aBasePath,
const nsACString& aFullKey) {
mNoVarySearchIndex.LookupOrInsert(aBasePath).AppendElement(aFullKey);
}
void RemoveNoVarySearchEntry(
const nsACString& aBasePath,
const nsACString& aFullKey) {
auto entry = mNoVarySearchIndex.Lookup(aBasePath);
if (!entry) {
return;
}
entry->RemoveElement(aFullKey);
if (entry->IsEmpty()) {
mNoVarySearchIndex.Remove(aBasePath);
}
}
private:
EType
const mType;
};
class CacheStorage : public nsICacheStorage {
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSICACHESTORAGE
public:
CacheStorage(nsILoadContextInfo* aInfo,
bool aAllowDisk,
bool aSkipSizeCheck,
bool aPinning);
protected:
virtual ~CacheStorage() =
default;
RefPtr<LoadContextInfo> mLoadContextInfo;
bool mWriteToDisk :
1;
bool mSkipSizeCheck :
1;
bool mPinning :
1;
public:
nsILoadContextInfo* LoadInfo()
const {
return mLoadContextInfo; }
bool WriteToDisk()
const {
return mWriteToDisk &&
(!mLoadContextInfo || !mLoadContextInfo->IsPrivate());
}
bool SkipSizeCheck()
const {
return mSkipSizeCheck; }
bool Pinning()
const {
return mPinning; }
};
}
// namespace net
}
// namespace mozilla
#endif