diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 4d94e7e1f0..d105d68113 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -11044,9 +11044,15 @@ nsDocShell::DoChannelLoad(nsIChannel* aChannel, break; } - case LOAD_RELOAD_CHARSET_CHANGE: - loadFlags |= nsIRequest::LOAD_FROM_CACHE; + case LOAD_RELOAD_CHARSET_CHANGE: { + // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we only want + // to force cache load for this channel, not the whole loadGroup. + nsCOMPtr cachingChannel = do_QueryInterface(aChannel); + if (cachingChannel) { + cachingChannel->SetAllowStaleCacheContent(true); + } break; + } case LOAD_RELOAD_NORMAL: case LOAD_REFRESH: diff --git a/netwerk/base/nsICacheInfoChannel.idl b/netwerk/base/nsICacheInfoChannel.idl index 9f571ab5f2..a610eb1ac8 100644 --- a/netwerk/base/nsICacheInfoChannel.idl +++ b/netwerk/base/nsICacheInfoChannel.idl @@ -4,7 +4,7 @@ #include "nsISupports.idl" -[scriptable, uuid (299d69b4-ee86-4541-802d-7642671ebf97)] +[scriptable, uuid(72c34415-c6eb-48af-851f-772fa9ee5972)] interface nsICacheInfoChannel : nsISupports { /** @@ -26,4 +26,11 @@ interface nsICacheInfoChannel : nsISupports * and after the channel fires its OnStopRequest notification. */ boolean isFromCache(); + + /** + * Tells the channel to behave as if the LOAD_FROM_CACHE flag has been set, + * but without affecting the loads for the entire loadGroup in case of this + * channel being the default load group's channel. + */ + attribute boolean allowStaleCacheContent; }; diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index 5da32e617e..ed5699b76b 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -58,6 +58,7 @@ struct HttpChannelOpenArgs uint32_t securityFlags; uint32_t contentPolicyType; uint32_t innerWindowID; + bool allowStaleCacheContent; }; struct HttpChannelConnectArgs diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index c748d4a7a4..964247d2d6 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -72,6 +72,7 @@ HttpBaseChannel::HttpBaseChannel() , mAllRedirectsSameOrigin(true) , mAllRedirectsPassTimingAllowCheck(true) , mForceNoIntercept(false) + , mAllowStaleCacheContent(false) , mSuspendCount(0) , mProxyResolveFlags(0) , mProxyURI(nullptr) diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index 8bc154a97f..1d94c4d371 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -370,6 +370,10 @@ protected: // True if this channel should skip any interception checks uint32_t mForceNoIntercept : 1; + // If true, we behave as if the LOAD_FROM_CACHE flag has been set. + // Used to enforce that flag's behavior but not expose it externally. + uint32_t mAllowStaleCacheContent : 1; + // Current suspension depth for this channel object uint32_t mSuspendCount; diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index 944894343d..f1157b34ce 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -1630,6 +1630,8 @@ HttpChannelChild::ContinueAsyncOpen() openArgs.chooseApplicationCache() = mChooseApplicationCache; openArgs.appCacheClientID() = appCacheClientId; openArgs.allowSpdy() = mAllowSpdy; + + openArgs.allowStaleCacheContent() = mAllowStaleCacheContent; propagateLoadInfo(mLoadInfo, openArgs); @@ -1773,6 +1775,20 @@ HttpChannelChild::IsFromCache(bool *value) return NS_OK; } +NS_IMETHODIMP +HttpChannelChild::SetAllowStaleCacheContent(bool aAllowStaleCacheContent) +{ + mAllowStaleCacheContent = aAllowStaleCacheContent; + return NS_OK; +} +NS_IMETHODIMP +HttpChannelChild::GetAllowStaleCacheContent(bool *aAllowStaleCacheContent) +{ + NS_ENSURE_ARG(aAllowStaleCacheContent); + *aAllowStaleCacheContent = mAllowStaleCacheContent; + return NS_OK; +} + //----------------------------------------------------------------------------- // HttpChannelChild::nsIResumableChannel //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 5fef3515ee..dc930b7232 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -110,7 +110,8 @@ HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs) a.entityID(), a.chooseApplicationCache(), a.appCacheClientID(), a.allowSpdy(), a.fds(), a.requestingPrincipalInfo(), a.triggeringPrincipalInfo(), - a.securityFlags(), a.contentPolicyType(), a.innerWindowID()); + a.securityFlags(), a.contentPolicyType(), a.innerWindowID(), + a.allowStaleCacheContent()); } case HttpChannelCreationArgs::THttpChannelConnectArgs: { @@ -201,7 +202,8 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI, const ipc::PrincipalInfo& aTriggeringPrincipalInfo, const uint32_t& aSecurityFlags, const uint32_t& aContentPolicyType, - const uint32_t& aInnerWindowID) + const uint32_t& aInnerWindowID, + const bool& aAllowStaleCacheContent) { nsCOMPtr uri = DeserializeURI(aURI); if (!uri) { @@ -318,6 +320,8 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI, mChannel->SetUploadStreamHasHeaders(uploadStreamHasHeaders); } + mChannel->SetAllowStaleCacheContent(aAllowStaleCacheContent); + if (priority != nsISupportsPriority::PRIORITY_NORMAL) { mChannel->SetPriority(priority); } diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h index a1d151a649..e69ee32c3e 100644 --- a/netwerk/protocol/http/HttpChannelParent.h +++ b/netwerk/protocol/http/HttpChannelParent.h @@ -115,7 +115,8 @@ protected: const ipc::PrincipalInfo& aTriggeringPrincipalInfo, const uint32_t& aSecurityFlags, const uint32_t& aContentPolicyType, - const uint32_t& aInnerWindowID); + const uint32_t& aInnerWindowID, + const bool& aAllowStaleCacheContent); virtual bool RecvSetPriority(const uint16_t& priority) override; virtual bool RecvSetClassOfService(const uint32_t& cos) override; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index e3cb45f447..1c78435005 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -463,6 +463,10 @@ nsHttpChannel::SpeculativeConnect() LOAD_NO_NETWORK_IO | LOAD_CHECK_OFFLINE_CACHE)) return; + if (mAllowStaleCacheContent) { + return; + } + nsCOMPtr callbacks; NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup, getter_AddRefs(callbacks)); @@ -3139,7 +3143,7 @@ nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, nsIApplicationCache* appC doValidation = false; } // If the LOAD_FROM_CACHE flag is set, any cached data can simply be used - else if (mLoadFlags & nsIRequest::LOAD_FROM_CACHE) { + else if (mLoadFlags & nsIRequest::LOAD_FROM_CACHE || mAllowStaleCacheContent) { LOG(("NOT validating based on LOAD_FROM_CACHE load flag\n")); doValidation = false; } @@ -6080,6 +6084,22 @@ nsHttpChannel::SetCacheTokenCachedCharset(const nsACString &aCharset) PromiseFlatCString(aCharset).get()); } +NS_IMETHODIMP +nsHttpChannel::SetAllowStaleCacheContent(bool aAllowStaleCacheContent) +{ + LOG(("nsHttpChannel::SetAllowStaleCacheContent [this=%p, allow=%d]", + this, aAllowStaleCacheContent)); + mAllowStaleCacheContent = aAllowStaleCacheContent; + return NS_OK; +} +NS_IMETHODIMP +nsHttpChannel::GetAllowStaleCacheContent(bool *aAllowStaleCacheContent) +{ + NS_ENSURE_ARG(aAllowStaleCacheContent); + *aAllowStaleCacheContent = mAllowStaleCacheContent; + return NS_OK; +} + //----------------------------------------------------------------------------- // nsHttpChannel::nsICachingChannel //-----------------------------------------------------------------------------