Bug 1572933: Introduce an attribute to raise the cache priority. r=pbro,mayhemer

For now, when we turn on `disable cache` switch in DevTools[1], web page loads
the contents without using the cache. Furthermore, DevTools as well comes to
load the contents DevTools inspects without using the cache. And, if the loaded
contents from the web page and DevTools was different, becomes impossible to
inspect the content correctly.
Thus, in order to make DevTools refer the same content the web page loaded,
makes DevTools load the contents inspecting from the cache at first, no matter
if disables the switch or not.

When turns on disable cache in DevTools, `LOAD_BYPASS_CACHE` flag is set into
`loadFlags` in the `docshell`.[2] The other hand, the content DevTools inspects
is loaded from a channel DevTools creates with `LOAD_FROM_CACHE` flag.[3]
However, because this channel is belong to same `loadGroup` of the `docshell`,
`LOAD_BYPASS_CACHE` is inherited and is choosen even if `LOAD_FROM_CACHE` is set.
Thus, in this patch, we introduce an attribute `preferCacheLoadOverBypass`
which raises the priority for `LOAD_FROM_CACHE` above `LOAD_BYPASS_CACHE` and
`LOAD_BYPASS_LOCAL_CACHE`.

[1] https://developer.mozilla.org/en-US/docs/Tools/Settings#Advanced_settings
[2] https://searchfox.org/mozilla-central/source/devtools/server/actors/targets/browsing-context.js#1227
[3] https://searchfox.org/mozilla-central/source/devtools/shared/DevToolsUtils.js#542-544

Differential Revision: https://phabricator.services.mozilla.com/D44626

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Daisuke Akatsuka 2019-09-09 00:57:05 +00:00
Родитель 9b09aece8c
Коммит a65bd31ef9
10 изменённых файлов: 106 добавлений и 28 удалений

Просмотреть файл

@ -543,14 +543,16 @@ function mainThreadFetch(
? channel.LOAD_FROM_CACHE
: channel.LOAD_BYPASS_CACHE;
// When loading from cache, the cacheKey allows us to target a specific
// SHEntry and offer ways to restore POST requests from cache.
if (
aOptions.loadFromCache &&
aOptions.cacheKey != 0 &&
channel instanceof Ci.nsICacheInfoChannel
) {
channel.cacheKey = aOptions.cacheKey;
if (aOptions.loadFromCache && channel instanceof Ci.nsICacheInfoChannel) {
// If DevTools intents to load the content from the cache,
// we make the LOAD_FROM_CACHE flag preferred over LOAD_BYPASS_CACHE.
channel.preferCacheLoadOverBypass = true;
// When loading from cache, the cacheKey allows us to target a specific
// SHEntry and offer ways to restore POST requests from cache.
if (aOptions.cacheKey != 0) {
channel.cacheKey = aOptions.cacheKey;
}
}
if (aOptions.window) {

Просмотреть файл

@ -101,6 +101,12 @@ interface nsICacheInfoChannel : nsISupports
*/
attribute boolean allowStaleCacheContent;
/**
* Tells the priority for LOAD_CACHE is raised over LOAD_BYPASS_CACHE or
* LOAD_BYPASS_LOCAL_CACHE in case those flags are set at the same time.
*/
attribute boolean preferCacheLoadOverBypass;
/**
* Calling this method instructs the channel to serve the alternative data
* if that was previously saved in the cache, otherwise it will serve the

Просмотреть файл

@ -173,7 +173,7 @@ struct ParentLoadInfoForwarderArgs
// tainting value.
uint32_t tainting;
// This flag is used for any browsing context where we should not sniff
// the content type. E.g if an iframe has the XCTO nosniff header, then
// that flag is set to true so we skip content sniffing for that browsing
@ -264,6 +264,7 @@ struct HttpChannelOpenArgs
bool blockAuthPrompt;
bool suspendAfterSynthesizeResponse;
bool allowStaleCacheContent;
bool preferCacheLoadOverBypass;
nsCString contentTypeHint;
uint32_t corsMode;
uint32_t redirectMode;

Просмотреть файл

@ -206,6 +206,7 @@ HttpBaseChannel::HttpBaseChannel()
mResponseCouldBeSynthesized(false),
mBlockAuthPrompt(false),
mAllowStaleCacheContent(false),
mPreferCacheLoadOverBypass(false),
mAddedAsNonTailRequest(false),
mAsyncOpenWaitingForStreamLength(false),
mUpgradableToSecure(true),

Просмотреть файл

@ -773,6 +773,10 @@ class HttpBaseChannel : public nsHashPropertyBag,
// Used to enforce that flag's behavior but not expose it externally.
uint32_t mAllowStaleCacheContent : 1;
// If true, we prefer the LOAD_FROM_CACHE flag over LOAD_BYPASS_CACHE or
// LOAD_BYPASS_LOCAL_CACHE.
uint32_t mPreferCacheLoadOverBypass : 1;
// True iff this request has been calculated in its request context as
// a non tail request. We must remove it again when this channel is done.
uint32_t mAddedAsNonTailRequest : 1;

Просмотреть файл

@ -2879,6 +2879,7 @@ nsresult HttpChannelChild::ContinueAsyncOpen() {
openArgs.blockAuthPrompt() = mBlockAuthPrompt;
openArgs.allowStaleCacheContent() = mAllowStaleCacheContent;
openArgs.preferCacheLoadOverBypass() = mPreferCacheLoadOverBypass;
openArgs.contentTypeHint() = mContentTypeHint;
@ -3187,6 +3188,30 @@ HttpChannelChild::GetAllowStaleCacheContent(bool* aAllowStaleCacheContent) {
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetPreferCacheLoadOverBypass(
bool aPreferCacheLoadOverBypass) {
if (mSynthesizedCacheInfo) {
return mSynthesizedCacheInfo->SetPreferCacheLoadOverBypass(
aPreferCacheLoadOverBypass);
}
mPreferCacheLoadOverBypass = aPreferCacheLoadOverBypass;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetPreferCacheLoadOverBypass(
bool* aPreferCacheLoadOverBypass) {
if (mSynthesizedCacheInfo) {
return mSynthesizedCacheInfo->GetPreferCacheLoadOverBypass(
aPreferCacheLoadOverBypass);
}
NS_ENSURE_ARG(aPreferCacheLoadOverBypass);
*aPreferCacheLoadOverBypass = mPreferCacheLoadOverBypass;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::PreferAlternativeDataType(const nsACString& aType,
const nsACString& aContentType,

Просмотреть файл

@ -152,14 +152,14 @@ bool HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs) {
a.cacheKey(), a.requestContextID(), a.preflightArgs(),
a.initialRwin(), a.blockAuthPrompt(),
a.suspendAfterSynthesizeResponse(), a.allowStaleCacheContent(),
a.contentTypeHint(), a.corsMode(), a.redirectMode(), a.channelId(),
a.integrityMetadata(), a.contentWindowId(),
a.preferredAlternativeTypes(), a.topLevelOuterContentWindowId(),
a.launchServiceWorkerStart(), a.launchServiceWorkerEnd(),
a.dispatchFetchEventStart(), a.dispatchFetchEventEnd(),
a.handleFetchEventStart(), a.handleFetchEventEnd(),
a.forceMainDocumentChannel(), a.navigationStartTimeStamp(),
a.hasSandboxedAuxiliaryNavigations());
a.preferCacheLoadOverBypass(), a.contentTypeHint(), a.corsMode(),
a.redirectMode(), a.channelId(), a.integrityMetadata(),
a.contentWindowId(), a.preferredAlternativeTypes(),
a.topLevelOuterContentWindowId(), a.launchServiceWorkerStart(),
a.launchServiceWorkerEnd(), a.dispatchFetchEventStart(),
a.dispatchFetchEventEnd(), a.handleFetchEventStart(),
a.handleFetchEventEnd(), a.forceMainDocumentChannel(),
a.navigationStartTimeStamp(), a.hasSandboxedAuxiliaryNavigations());
}
case HttpChannelCreationArgs::THttpChannelConnectArgs: {
const HttpChannelConnectArgs& cArgs = aArgs.get_HttpChannelConnectArgs();
@ -407,10 +407,10 @@ bool HttpChannelParent::DoAsyncOpen(
const Maybe<CorsPreflightArgs>& aCorsPreflightArgs,
const uint32_t& aInitialRwin, const bool& aBlockAuthPrompt,
const bool& aSuspendAfterSynthesizeResponse,
const bool& aAllowStaleCacheContent, const nsCString& aContentTypeHint,
const uint32_t& aCorsMode, const uint32_t& aRedirectMode,
const uint64_t& aChannelId, const nsString& aIntegrityMetadata,
const uint64_t& aContentWindowId,
const bool& aAllowStaleCacheContent, const bool& aPreferCacheLoadOverBypass,
const nsCString& aContentTypeHint, const uint32_t& aCorsMode,
const uint32_t& aRedirectMode, const uint64_t& aChannelId,
const nsString& aIntegrityMetadata, const uint64_t& aContentWindowId,
const nsTArray<PreferredAlternativeDataTypeParams>&
aPreferredAlternativeTypes,
const uint64_t& aTopLevelOuterContentWindowId,
@ -588,6 +588,7 @@ bool HttpChannelParent::DoAsyncOpen(
}
cacheChannel->SetAllowStaleCacheContent(aAllowStaleCacheContent);
cacheChannel->SetPreferCacheLoadOverBypass(aPreferCacheLoadOverBypass);
// This is to mark that the results are going to the content process.
if (httpChannelImpl) {

Просмотреть файл

@ -166,7 +166,8 @@ class HttpChannelParent final : public nsIInterfaceRequestor,
const Maybe<CorsPreflightArgs>& aCorsPreflightArgs,
const uint32_t& aInitialRwin, const bool& aBlockAuthPrompt,
const bool& aSuspendAfterSynthesizeResponse,
const bool& aAllowStaleCacheContent, const nsCString& aContentTypeHint,
const bool& aAllowStaleCacheContent,
const bool& aPreferCacheLoadOverBypass, const nsCString& aContentTypeHint,
const uint32_t& aCorsMode, const uint32_t& aRedirectMode,
const uint64_t& aChannelId, const nsString& aIntegrityMetadata,
const uint64_t& aContentWindowId,

Просмотреть файл

@ -1249,6 +1249,26 @@ InterceptedHttpChannel::GetAllowStaleCacheContent(
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
InterceptedHttpChannel::GetPreferCacheLoadOverBypass(
bool* aPreferCacheLoadOverBypass) {
if (mSynthesizedCacheInfo) {
return mSynthesizedCacheInfo->GetPreferCacheLoadOverBypass(
aPreferCacheLoadOverBypass);
}
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
InterceptedHttpChannel::SetPreferCacheLoadOverBypass(
bool aPreferCacheLoadOverBypass) {
if (mSynthesizedCacheInfo) {
return mSynthesizedCacheInfo->SetPreferCacheLoadOverBypass(
aPreferCacheLoadOverBypass);
}
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
InterceptedHttpChannel::PreferAlternativeDataType(
const nsACString& aType, const nsACString& aContentType,

Просмотреть файл

@ -160,9 +160,11 @@ static uint32_t sRCWNMinWaitMs = 0;
static uint32_t sRCWNMaxWaitMs = 500;
// True if the local cache should be bypassed when processing a request.
#define BYPASS_LOCAL_CACHE(loadFlags) \
(loadFlags & (nsIRequest::LOAD_BYPASS_CACHE | \
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE))
#define BYPASS_LOCAL_CACHE(loadFlags, isPreferCacheLoadOverBypass) \
(loadFlags & (nsIRequest::LOAD_BYPASS_CACHE | \
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE) && \
!((loadFlags & nsIRequest::LOAD_FROM_CACHE) && \
isPreferCacheLoadOverBypass))
#define RECOVER_FROM_CACHE_FILE_ERROR(result) \
((result) == NS_ERROR_FILE_NOT_FOUND || \
@ -4005,12 +4007,14 @@ nsresult nsHttpChannel::OpenCacheEntryInternal(
}
if (offline || (mLoadFlags & INHIBIT_CACHING)) {
if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline) {
if (BYPASS_LOCAL_CACHE(mLoadFlags, mPreferCacheLoadOverBypass) &&
!offline) {
goto bypassCacheEntryOpen;
}
cacheEntryOpenFlags = nsICacheStorage::OPEN_READONLY;
mCacheEntryIsReadOnly = true;
} else if (BYPASS_LOCAL_CACHE(mLoadFlags) && !applicationCache) {
} else if (BYPASS_LOCAL_CACHE(mLoadFlags, mPreferCacheLoadOverBypass) &&
!applicationCache) {
cacheEntryOpenFlags = nsICacheStorage::OPEN_TRUNCATE;
} else {
cacheEntryOpenFlags =
@ -6706,7 +6710,8 @@ nsresult nsHttpChannel::BeginConnect() {
// if this somehow fails we can go on without it
Unused << gHttpHandler->AddConnectionHeader(&mRequestHead, mCaps);
if (mLoadFlags & VALIDATE_ALWAYS || BYPASS_LOCAL_CACHE(mLoadFlags))
if (mLoadFlags & VALIDATE_ALWAYS ||
BYPASS_LOCAL_CACHE(mLoadFlags, mPreferCacheLoadOverBypass))
mCaps |= NS_HTTP_REFRESH_DNS;
// Adjust mCaps according to our request headers:
@ -8661,6 +8666,18 @@ nsHttpChannel::GetAllowStaleCacheContent(bool* aAllowStaleCacheContent) {
return NS_OK;
}
NS_IMETHODIMP
nsHttpChannel::SetPreferCacheLoadOverBypass(bool aPreferCacheLoadOverBypass) {
mPreferCacheLoadOverBypass = aPreferCacheLoadOverBypass;
return NS_OK;
}
NS_IMETHODIMP
nsHttpChannel::GetPreferCacheLoadOverBypass(bool* aPreferCacheLoadOverBypass) {
NS_ENSURE_ARG(aPreferCacheLoadOverBypass);
*aPreferCacheLoadOverBypass = mPreferCacheLoadOverBypass;
return NS_OK;
}
NS_IMETHODIMP
nsHttpChannel::PreferAlternativeDataType(const nsACString& aType,
const nsACString& aContentType,