Bug 1542293 - Rewrite various nsHttpResponseHead::Get* to use Tokenizer r=valentin,mayhemer,necko-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D69353
This commit is contained in:
sonakshi 2020-04-23 17:11:44 +00:00
parent b494157695
commit fd27762dce
5 changed files with 84 additions and 82 deletions

View File

@ -17,8 +17,13 @@ CacheControlParser::CacheControlParser(nsACString const& aHeader)
mMaxStale(0),
mMinFreshSet(false),
mMinFresh(0),
mStaleWhileRevalidateSet(false),
mStaleWhileRevalidate(0),
mNoCache(false),
mNoStore(false) {
mNoStore(false),
mPublic(false),
mPrivate(false),
mImmutable(false) {
SkipWhites();
if (!CheckEOF()) {
Directive();
@ -37,6 +42,14 @@ void CacheControlParser::Directive() {
mMaxStaleSet = SecondsValue(&mMaxStale, PR_UINT32_MAX);
} else if (CheckWord("min-fresh")) {
mMinFreshSet = SecondsValue(&mMinFresh);
} else if (CheckWord("stale-while-revalidate")) {
mStaleWhileRevalidateSet = SecondsValue(&mStaleWhileRevalidate);
} else if (CheckWord("public")) {
mPublic = true;
} else if (CheckWord("private")) {
mPrivate = true;
} else if (CheckWord("immutable")) {
mImmutable = true;
} else {
IgnoreDirective();
}
@ -103,9 +116,20 @@ bool CacheControlParser::MinFresh(uint32_t* seconds) {
return mMinFreshSet;
}
bool CacheControlParser::StaleWhileRevalidate(uint32_t* seconds) {
*seconds = mStaleWhileRevalidate;
return mStaleWhileRevalidateSet;
}
bool CacheControlParser::NoCache() { return mNoCache; }
bool CacheControlParser::NoStore() { return mNoStore; }
bool CacheControlParser::Public() { return mPublic; }
bool CacheControlParser::Private() { return mPrivate; }
bool CacheControlParser::Immutable() { return mImmutable; }
} // namespace net
} // namespace mozilla

View File

@ -19,8 +19,12 @@ class CacheControlParser final : Tokenizer {
[[nodiscard]] bool MaxAge(uint32_t* seconds);
[[nodiscard]] bool MaxStale(uint32_t* seconds);
[[nodiscard]] bool MinFresh(uint32_t* seconds);
[[nodiscard]] bool StaleWhileRevalidate(uint32_t* seconds);
bool NoCache();
bool NoStore();
bool Public();
bool Private();
bool Immutable();
private:
void Directive();
@ -33,8 +37,13 @@ class CacheControlParser final : Tokenizer {
uint32_t mMaxStale;
bool mMinFreshSet;
uint32_t mMinFresh;
bool mStaleWhileRevalidateSet;
uint32_t mStaleWhileRevalidate;
bool mNoCache;
bool mNoStore;
bool mPublic;
bool mPrivate;
bool mImmutable;
};
} // namespace net

View File

@ -14,6 +14,7 @@
#include "prtime.h"
#include "plstr.h"
#include "nsURLHelper.h"
#include "CacheControlParser.h"
#include <algorithm>
namespace mozilla {
@ -41,6 +42,11 @@ nsHttpResponseHead::nsHttpResponseHead(const nsHttpResponseHead& aOther)
mCacheControlNoStore = other.mCacheControlNoStore;
mCacheControlNoCache = other.mCacheControlNoCache;
mCacheControlImmutable = other.mCacheControlImmutable;
mCacheControlStaleWhileRevalidateSet =
other.mCacheControlStaleWhileRevalidateSet;
mCacheControlStaleWhileRevalidate = other.mCacheControlStaleWhileRevalidate;
mCacheControlMaxAgeSet = other.mCacheControlMaxAgeSet;
mCacheControlMaxAge = other.mCacheControlMaxAge;
mPragmaNoCache = other.mPragmaNoCache;
}
@ -62,6 +68,11 @@ nsHttpResponseHead& nsHttpResponseHead::operator=(
mCacheControlNoStore = other.mCacheControlNoStore;
mCacheControlNoCache = other.mCacheControlNoCache;
mCacheControlImmutable = other.mCacheControlImmutable;
mCacheControlStaleWhileRevalidateSet =
other.mCacheControlStaleWhileRevalidateSet;
mCacheControlStaleWhileRevalidate = other.mCacheControlStaleWhileRevalidate;
mCacheControlMaxAgeSet = other.mCacheControlMaxAgeSet;
mCacheControlMaxAge = other.mCacheControlMaxAge;
mPragmaNoCache = other.mPragmaNoCache;
return *this;
@ -782,22 +793,16 @@ bool nsHttpResponseHead::MustValidateIfExpired() {
bool nsHttpResponseHead::StaleWhileRevalidate(uint32_t now,
uint32_t expiration) {
nsresult rv;
RecursiveMutexAutoLock monitor(mRecursiveMutex);
if (expiration <= 0) {
return false;
}
uint32_t revalidateWindow;
rv = GetStaleWhileRevalidateValue(&revalidateWindow);
if (NS_FAILED(rv)) {
if (expiration <= 0 || !mCacheControlStaleWhileRevalidateSet) {
return false;
}
// 'expiration' is the expiration time (an absolute unit), the swr window
// extends the expiration time.
CheckedInt<uint32_t> stallValidUntil = expiration;
stallValidUntil += revalidateWindow;
stallValidUntil += mCacheControlStaleWhileRevalidate;
if (!stallValidUntil.isValid()) {
// overflow means an indefinite stale window
return true;
@ -901,6 +906,10 @@ void nsHttpResponseHead::Reset() {
mCacheControlNoStore = false;
mCacheControlNoCache = false;
mCacheControlImmutable = false;
mCacheControlStaleWhileRevalidateSet = false;
mCacheControlStaleWhileRevalidate = 0;
mCacheControlMaxAgeSet = false;
mCacheControlMaxAge = 0;
mPragmaNoCache = false;
mStatusText.Truncate();
mContentType.Truncate();
@ -941,59 +950,11 @@ nsresult nsHttpResponseHead::GetMaxAgeValue(uint32_t* result) {
}
nsresult nsHttpResponseHead::GetMaxAgeValue_locked(uint32_t* result) const {
const char* val = mHeaders.PeekHeader(nsHttp::Cache_Control);
if (!val) return NS_ERROR_NOT_AVAILABLE;
const char* p = nsHttp::FindToken(val, "max-age", HTTP_HEADER_VALUE_SEPS "=");
if (!p) return NS_ERROR_NOT_AVAILABLE;
p += 7;
while (*p == ' ' || *p == '\t') ++p;
if (*p != '=') return NS_ERROR_NOT_AVAILABLE;
++p;
while (*p == ' ' || *p == '\t') ++p;
int maxAgeValue = atoi(p);
if (maxAgeValue < 0) maxAgeValue = 0;
*result = static_cast<uint32_t>(maxAgeValue);
return NS_OK;
}
// Get the stale-while-revalidate directive value, if present
nsresult nsHttpResponseHead::GetStaleWhileRevalidateValue(uint32_t* result) {
RecursiveMutexAutoLock monitor(mRecursiveMutex);
return GetStaleWhileRevalidateValue_locked(result);
}
nsresult nsHttpResponseHead::GetStaleWhileRevalidateValue_locked(
uint32_t* result) const {
const char* val = mHeaders.PeekHeader(nsHttp::Cache_Control);
if (!val) {
if (!mCacheControlMaxAgeSet) {
return NS_ERROR_NOT_AVAILABLE;
}
// Rewrite (best all FindToken users) to mozilla::Tokenizer, bug 1542293.
const char* p = nsHttp::FindToken(val, "stale-while-revalidate",
HTTP_HEADER_VALUE_SEPS "=");
if (!p) {
return NS_ERROR_NOT_AVAILABLE;
}
p += 22;
while (*p == ' ' || *p == '\t') {
++p;
}
if (*p != '=') {
return NS_ERROR_NOT_AVAILABLE;
}
++p;
while (*p == ' ' || *p == '\t') {
++p;
}
int revalidateWindow = atoi(p);
if (revalidateWindow < 0) {
revalidateWindow = 0;
}
*result = static_cast<uint32_t>(revalidateWindow);
*result = mCacheControlMaxAge;
return NS_OK;
}
@ -1048,6 +1009,12 @@ bool nsHttpResponseHead::operator==(const nsHttpResponseHead& aOther) const {
mCacheControlNoCache == aOther.mCacheControlNoCache &&
mCacheControlNoStore == aOther.mCacheControlNoStore &&
mCacheControlImmutable == aOther.mCacheControlImmutable &&
mCacheControlStaleWhileRevalidateSet ==
aOther.mCacheControlStaleWhileRevalidateSet &&
mCacheControlStaleWhileRevalidate ==
aOther.mCacheControlStaleWhileRevalidate &&
mCacheControlMaxAgeSet == aOther.mCacheControlMaxAgeSet &&
mCacheControlMaxAge == aOther.mCacheControlMaxAge &&
mPragmaNoCache == aOther.mPragmaNoCache;
}
@ -1153,31 +1120,25 @@ void nsHttpResponseHead::ParseCacheControl(const char* val) {
mCacheControlNoCache = false;
mCacheControlNoStore = false;
mCacheControlImmutable = false;
mCacheControlStaleWhileRevalidateSet = false;
mCacheControlStaleWhileRevalidate = 0;
mCacheControlMaxAgeSet = false;
mCacheControlMaxAge = 0;
return;
}
// search header value for occurrence of "public"
if (nsHttp::FindToken(val, "public", HTTP_HEADER_VALUE_SEPS)) {
mCacheControlPublic = true;
}
nsDependentCString cacheControlRequestHeader(val);
CacheControlParser cacheControlRequest(cacheControlRequestHeader);
// search header value for occurrence of "private"
if (nsHttp::FindToken(val, "private", HTTP_HEADER_VALUE_SEPS))
mCacheControlPrivate = true;
// search header value for occurrence(s) of "no-cache" but ignore
// occurrence(s) of "no-cache=blah"
if (nsHttp::FindToken(val, "no-cache", HTTP_HEADER_VALUE_SEPS))
mCacheControlNoCache = true;
// search header value for occurrence of "no-store"
if (nsHttp::FindToken(val, "no-store", HTTP_HEADER_VALUE_SEPS))
mCacheControlNoStore = true;
// search header value for occurrence of "immutable"
if (nsHttp::FindToken(val, "immutable", HTTP_HEADER_VALUE_SEPS)) {
mCacheControlImmutable = true;
}
mCacheControlPublic = cacheControlRequest.Public();
mCacheControlPrivate = cacheControlRequest.Private();
mCacheControlNoCache = cacheControlRequest.NoCache();
mCacheControlNoStore = cacheControlRequest.NoStore();
mCacheControlImmutable = cacheControlRequest.Immutable();
mCacheControlStaleWhileRevalidateSet =
cacheControlRequest.StaleWhileRevalidate(
&mCacheControlStaleWhileRevalidate);
mCacheControlMaxAgeSet = cacheControlRequest.MaxAge(&mCacheControlMaxAge);
}
void nsHttpResponseHead::ParsePragma(const char* val) {

View File

@ -47,6 +47,10 @@ class nsHttpResponseHead {
mCacheControlNoStore(false),
mCacheControlNoCache(false),
mCacheControlImmutable(false),
mCacheControlStaleWhileRevalidateSet(false),
mCacheControlStaleWhileRevalidate(0),
mCacheControlMaxAgeSet(false),
mCacheControlMaxAge(0),
mPragmaNoCache(false),
mRecursiveMutex("nsHttpResponseHead.mRecursiveMutex"),
mInVisitHeaders(false) {}
@ -202,6 +206,10 @@ class nsHttpResponseHead {
bool mCacheControlNoStore;
bool mCacheControlNoCache;
bool mCacheControlImmutable;
bool mCacheControlStaleWhileRevalidateSet;
uint32_t mCacheControlStaleWhileRevalidate;
bool mCacheControlMaxAgeSet;
uint32_t mCacheControlMaxAge;
bool mPragmaNoCache;
// We are using RecursiveMutex instead of a Mutex because VisitHeader

View File

@ -43,7 +43,7 @@ function test_handler(metadata, response) {
function cached_handler(metadata, response) {
response.setHeader("Content-Type", "text/plain");
response.setHeader("Cache-Control", "Cache-Control: max-age=3600");
response.setHeader("Cache-Control", "max-age=3600");
response.setHeader("ETag", "test-etag1");
response.setStatusLine(metadata.httpVersion, 200, "OK");