mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1771867 - Early Hints Phase 2 - Part 8: Add list of open channels from OngoingEarlyHints to RedirectToRealChannelArgs r=necko-reviewers,valentin
Differential Revision: https://phabricator.services.mozilla.com/D161179
This commit is contained in:
parent
e4a53f90d5
commit
95a28e77f3
@ -1297,10 +1297,6 @@ void CanonicalBrowsingContext::AddFinalDiscardListener(
|
||||
mFullyDiscardedListeners.AppendElement(std::move(aListener));
|
||||
}
|
||||
|
||||
net::EarlyHintsService* CanonicalBrowsingContext::GetEarlyHintsService() {
|
||||
return &mEarlyHintsService;
|
||||
}
|
||||
|
||||
void CanonicalBrowsingContext::AdjustPrivateBrowsingCount(
|
||||
bool aPrivateBrowsing) {
|
||||
if (IsDiscarded() || !EverAttached() || IsChrome()) {
|
||||
|
@ -7,7 +7,6 @@
|
||||
#ifndef mozilla_dom_CanonicalBrowsingContext_h
|
||||
#define mozilla_dom_CanonicalBrowsingContext_h
|
||||
|
||||
#include "mozilla/net/EarlyHintsService.h"
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/dom/MediaControlKeySource.h"
|
||||
#include "mozilla/dom/BrowsingContextWebProgress.h"
|
||||
@ -363,8 +362,6 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
||||
|
||||
void AddFinalDiscardListener(std::function<void(uint64_t)>&& aListener);
|
||||
|
||||
net::EarlyHintsService* GetEarlyHintsService();
|
||||
|
||||
protected:
|
||||
// Called when the browsing context is being discarded.
|
||||
void CanonicalDiscard();
|
||||
@ -568,8 +565,6 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
||||
bool mFullyDiscarded = false;
|
||||
|
||||
nsTArray<std::function<void(uint64_t)>> mFullyDiscardedListeners;
|
||||
|
||||
net::EarlyHintsService mEarlyHintsService;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||
#include "mozilla/dom/ClientInfo.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/net/NeckoChannelParams.h"
|
||||
#include "nsDocShellLoadState.h"
|
||||
|
||||
extern mozilla::LazyLogModule gDocumentChannelLog;
|
||||
@ -96,7 +97,8 @@ bool DocumentChannelParent::Init(dom::CanonicalBrowsingContext* aContext,
|
||||
// PDocumentChannel::RedirectToRealChannelPromise given as parameter.
|
||||
auto promise = self->RedirectToRealChannel(
|
||||
std::move(aResolveValue.mStreamFilterEndpoints),
|
||||
aResolveValue.mRedirectFlags, aResolveValue.mLoadFlags);
|
||||
aResolveValue.mRedirectFlags, aResolveValue.mLoadFlags,
|
||||
std::move(aResolveValue.mEarlyHints));
|
||||
// We chain the promise the DLL is waiting on to the one returned by
|
||||
// RedirectToRealChannel. As soon as the promise returned is resolved
|
||||
// or rejected, so will the DLL's promise.
|
||||
@ -135,7 +137,8 @@ RefPtr<PDocumentChannelParent::RedirectToRealChannelPromise>
|
||||
DocumentChannelParent::RedirectToRealChannel(
|
||||
nsTArray<ipc::Endpoint<extensions::PStreamFilterParent>>&&
|
||||
aStreamFilterEndpoints,
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags) {
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags,
|
||||
nsTArray<EarlyHintConnectArgs>&& aEarlyHints) {
|
||||
if (!CanSend()) {
|
||||
return PDocumentChannelParent::RedirectToRealChannelPromise::
|
||||
CreateAndReject(ResponseRejectReason::ChannelClosed, __func__);
|
||||
@ -143,7 +146,8 @@ DocumentChannelParent::RedirectToRealChannel(
|
||||
RedirectToRealChannelArgs args;
|
||||
mDocumentLoadListener->SerializeRedirectData(
|
||||
args, false, aRedirectFlags, aLoadFlags,
|
||||
static_cast<ContentParent*>(Manager()->Manager()));
|
||||
static_cast<ContentParent*>(Manager()->Manager()),
|
||||
std::move(aEarlyHints));
|
||||
return SendRedirectToRealChannel(args, std::move(aStreamFilterEndpoints));
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@ class CanonicalBrowsingContext;
|
||||
}
|
||||
namespace net {
|
||||
|
||||
class EarlyHintConnectArgs;
|
||||
|
||||
/**
|
||||
* An actor that forwards all changes across to DocumentChannelChild, the
|
||||
* nsIChannel implementation owned by a content process docshell.
|
||||
@ -52,7 +54,8 @@ class DocumentChannelParent final
|
||||
RedirectToRealChannel(
|
||||
nsTArray<ipc::Endpoint<extensions::PStreamFilterParent>>&&
|
||||
aStreamFilterEndpoints,
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags);
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags,
|
||||
nsTArray<EarlyHintConnectArgs>&& aEarlyHints);
|
||||
|
||||
virtual ~DocumentChannelParent();
|
||||
|
||||
|
@ -1203,8 +1203,8 @@ void DocumentLoadListener::Disconnect(bool aContinueNavigating) {
|
||||
// Don't cancel ongoing early hints when continuing to load the web page.
|
||||
// Early hints are loaded earlier in the code and shouldn't get cancelled
|
||||
// here. See also: Bug 1765652
|
||||
if (GetLoadingBrowsingContext() && !aContinueNavigating) {
|
||||
GetLoadingBrowsingContext()->mEarlyHintsService.Cancel();
|
||||
if (!aContinueNavigating) {
|
||||
mEarlyHintsService.Cancel();
|
||||
}
|
||||
|
||||
if (auto* ctx = GetDocumentBrowsingContext()) {
|
||||
@ -1486,10 +1486,11 @@ bool DocumentLoadListener::ResumeSuspendedChannel(
|
||||
|
||||
void DocumentLoadListener::SerializeRedirectData(
|
||||
RedirectToRealChannelArgs& aArgs, bool aIsCrossProcess,
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags,
|
||||
ContentParent* aParent) const {
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags, ContentParent* aParent,
|
||||
nsTArray<EarlyHintConnectArgs>&& aEarlyHints) const {
|
||||
aArgs.uri() = GetChannelCreationURI();
|
||||
aArgs.loadIdentifier() = mLoadIdentifier;
|
||||
aArgs.earlyHints() = std::move(aEarlyHints);
|
||||
|
||||
// I previously used HttpBaseChannel::CloneLoadInfoForRedirect, but that
|
||||
// clears the principal to inherit, which fails tests (probably because this
|
||||
@ -2120,9 +2121,12 @@ DocumentLoadListener::RedirectToRealChannel(
|
||||
CreateAndReject(ipc::ResponseRejectReason::SendError, __func__);
|
||||
}
|
||||
|
||||
nsTArray<EarlyHintConnectArgs> ehArgs;
|
||||
mEarlyHintsService.RegisterLinksAndGetConnectArgs(ehArgs);
|
||||
|
||||
RedirectToRealChannelArgs args;
|
||||
SerializeRedirectData(args, /* aIsCrossProcess */ true, aRedirectFlags,
|
||||
aLoadFlags, cp);
|
||||
aLoadFlags, cp, std::move(ehArgs));
|
||||
if (mTiming) {
|
||||
mTiming->Anonymize(args.uri());
|
||||
args.timing() = Some(std::move(mTiming));
|
||||
@ -2158,10 +2162,14 @@ DocumentLoadListener::RedirectToRealChannel(
|
||||
auto promise =
|
||||
MakeRefPtr<PDocumentChannelParent::RedirectToRealChannelPromise::Private>(
|
||||
__func__);
|
||||
mOpenPromise->Resolve(
|
||||
OpenPromiseSucceededType({std::move(aStreamFilterEndpoints),
|
||||
aRedirectFlags, aLoadFlags, promise}),
|
||||
__func__);
|
||||
|
||||
nsTArray<EarlyHintConnectArgs> ehArgs;
|
||||
mEarlyHintsService.RegisterLinksAndGetConnectArgs(ehArgs);
|
||||
|
||||
mOpenPromise->Resolve(OpenPromiseSucceededType(
|
||||
{std::move(aStreamFilterEndpoints), aRedirectFlags,
|
||||
aLoadFlags, std::move(ehArgs), promise}),
|
||||
__func__);
|
||||
|
||||
// There is no way we could come back here if the promise had been resolved
|
||||
// previously. But for clarity and to avoid all doubt, we set this boolean to
|
||||
@ -2576,15 +2584,12 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
if (GetLoadingBrowsingContext()) {
|
||||
if (httpChannel) {
|
||||
uint32_t responseStatus;
|
||||
Unused << httpChannel->GetResponseStatus(&responseStatus);
|
||||
GetLoadingBrowsingContext()->mEarlyHintsService.FinalResponse(
|
||||
responseStatus);
|
||||
} else {
|
||||
GetLoadingBrowsingContext()->mEarlyHintsService.Cancel();
|
||||
}
|
||||
if (httpChannel) {
|
||||
uint32_t responseStatus = 0;
|
||||
Unused << httpChannel->GetResponseStatus(&responseStatus);
|
||||
mEarlyHintsService.FinalResponse(responseStatus);
|
||||
} else {
|
||||
mEarlyHintsService.Cancel();
|
||||
}
|
||||
|
||||
// If we're going to be delivering this channel to a remote content
|
||||
@ -2804,20 +2809,22 @@ DocumentLoadListener::AsyncOnChannelRedirect(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (GetDocumentBrowsingContext()) {
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
||||
if (!net::ChannelIsPost(aOldChannel)) {
|
||||
AddURIVisit(aOldChannel, 0);
|
||||
nsDocShell::SaveLastVisit(aNewChannel, oldURI, aFlags);
|
||||
}
|
||||
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
nsresult rv = ssm->CheckSameOriginURI(oldURI, uri, false, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
GetLoadingBrowsingContext()->mEarlyHintsService.Cancel();
|
||||
}
|
||||
// Cancel cross origin redirects as described by whatwg:
|
||||
// > Note: [The early hint reponse] is discarded if it is succeeded by a
|
||||
// > cross-origin redirect.
|
||||
// https://html.spec.whatwg.org/multipage/semantics.html#early-hints
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
||||
if (!net::ChannelIsPost(aOldChannel)) {
|
||||
AddURIVisit(aOldChannel, 0);
|
||||
nsDocShell::SaveLastVisit(aNewChannel, oldURI, aFlags);
|
||||
}
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
nsresult rv = ssm->CheckSameOriginURI(oldURI, uri, false, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
mEarlyHintsService.Cancel();
|
||||
}
|
||||
|
||||
mHaveVisibleRedirect |= true;
|
||||
|
||||
LOG(
|
||||
@ -2949,10 +2956,7 @@ NS_IMETHODIMP DocumentLoadListener::OnStatus(nsIRequest* aRequest,
|
||||
|
||||
NS_IMETHODIMP DocumentLoadListener::EarlyHint(const nsACString& linkHeader) {
|
||||
LOG(("DocumentLoadListener::EarlyHint.\n"));
|
||||
if (GetLoadingBrowsingContext()) {
|
||||
GetLoadingBrowsingContext()->mEarlyHintsService.EarlyHint(
|
||||
linkHeader, GetChannelCreationURI(), mChannel);
|
||||
}
|
||||
mEarlyHintsService.EarlyHint(linkHeader, GetChannelCreationURI(), mChannel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
||||
mStreamFilterEndpoints;
|
||||
uint32_t mRedirectFlags;
|
||||
uint32_t mLoadFlags;
|
||||
nsTArray<EarlyHintConnectArgs> mEarlyHints;
|
||||
RefPtr<PDocumentChannelParent::RedirectToRealChannelPromise::Private>
|
||||
mPromise;
|
||||
};
|
||||
@ -278,10 +279,10 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
||||
|
||||
// Serializes all data needed to setup the new replacement channel
|
||||
// in the content process into the RedirectToRealChannelArgs struct.
|
||||
void SerializeRedirectData(RedirectToRealChannelArgs& aArgs,
|
||||
bool aIsCrossProcess, uint32_t aRedirectFlags,
|
||||
uint32_t aLoadFlags,
|
||||
dom::ContentParent* aParent) const;
|
||||
void SerializeRedirectData(
|
||||
RedirectToRealChannelArgs& aArgs, bool aIsCrossProcess,
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags, dom::ContentParent* aParent,
|
||||
nsTArray<EarlyHintConnectArgs>&& aEarlyHints) const;
|
||||
|
||||
uint64_t GetLoadIdentifier() const { return mLoadIdentifier; }
|
||||
uint32_t GetLoadType() const { return mLoadStateLoadType; }
|
||||
@ -513,6 +514,8 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
||||
// switch occurs.
|
||||
RefPtr<nsDOMNavigationTiming> mTiming;
|
||||
|
||||
net::EarlyHintsService mEarlyHintsService;
|
||||
|
||||
// An optional ObjectUpgradeHandler which can be used to upgrade an <object>
|
||||
// or <embed> element to contain a nsFrameLoader, allowing us to switch them
|
||||
// into a different process.
|
||||
|
@ -48,7 +48,8 @@ RefPtr<RedirectToRealChannelPromise>
|
||||
ParentProcessDocumentChannel::RedirectToRealChannel(
|
||||
nsTArray<ipc::Endpoint<extensions::PStreamFilterParent>>&&
|
||||
aStreamFilterEndpoints,
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags) {
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags,
|
||||
const nsTArray<EarlyHintConnectArgs>& aEarlyHints) {
|
||||
LOG(("ParentProcessDocumentChannel RedirectToRealChannel [this=%p]", this));
|
||||
nsCOMPtr<nsIChannel> channel = mDocumentLoadListener->GetChannel();
|
||||
channel->SetLoadFlags(aLoadFlags);
|
||||
@ -207,7 +208,8 @@ NS_IMETHODIMP ParentProcessDocumentChannel::AsyncOpen(
|
||||
RefPtr<RedirectToRealChannelPromise> p =
|
||||
self->RedirectToRealChannel(
|
||||
std::move(aResolveValue.mStreamFilterEndpoints),
|
||||
aResolveValue.mRedirectFlags, aResolveValue.mLoadFlags)
|
||||
aResolveValue.mRedirectFlags, aResolveValue.mLoadFlags,
|
||||
aResolveValue.mEarlyHints)
|
||||
->Then(
|
||||
GetCurrentSerialEventTarget(), __func__,
|
||||
[self](RedirectToRealChannelPromise::ResolveOrRejectValue&&
|
||||
|
@ -16,6 +16,8 @@
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class EarlyHintConnectArgs;
|
||||
|
||||
class ParentProcessDocumentChannel : public DocumentChannel,
|
||||
public nsIAsyncVerifyRedirectCallback,
|
||||
public nsIObserver {
|
||||
@ -38,7 +40,8 @@ class ParentProcessDocumentChannel : public DocumentChannel,
|
||||
RedirectToRealChannel(
|
||||
nsTArray<ipc::Endpoint<extensions::PStreamFilterParent>>&&
|
||||
aStreamFilterEndpoints,
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags);
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags,
|
||||
const nsTArray<EarlyHintConnectArgs>& aEarlyHints);
|
||||
|
||||
private:
|
||||
virtual ~ParentProcessDocumentChannel();
|
||||
|
@ -66,6 +66,11 @@ bool OngoingEarlyHints::Add(const PreloadHashKey& aKey,
|
||||
return mOngoingPreloads.InsertOrUpdate(aKey, aPreloader);
|
||||
}
|
||||
|
||||
void OngoingEarlyHints::RegisterLinksAndGetConnectArgs(
|
||||
nsTArray<EarlyHintConnectArgs>& aOutLinks) {
|
||||
// register all channels before returning
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// EarlyHintPreloader
|
||||
//=============================================================================
|
||||
|
@ -22,6 +22,7 @@ class nsIReferrerInfo;
|
||||
namespace mozilla::net {
|
||||
|
||||
class EarlyHintPreloader;
|
||||
class EarlyHintConnectArgs;
|
||||
struct LinkHeader;
|
||||
|
||||
// class keeping track of all ongoing early hints
|
||||
@ -38,9 +39,17 @@ class OngoingEarlyHints final {
|
||||
|
||||
void CancelAllOngoingPreloads();
|
||||
|
||||
// registers all channels and returns the ids
|
||||
void RegisterLinksAndGetConnectArgs(
|
||||
nsTArray<EarlyHintConnectArgs>& aOutLinks);
|
||||
|
||||
private:
|
||||
~OngoingEarlyHints() = default;
|
||||
nsRefPtrHashtable<PreloadHashKey, EarlyHintPreloader> mOngoingPreloads;
|
||||
|
||||
// keep track of all preloads in the order they were specified in the early
|
||||
// hint header
|
||||
nsTArray<EarlyHintConnectArgs> mLinks;
|
||||
};
|
||||
|
||||
class EarlyHintPreloader final : public nsIStreamListener,
|
||||
|
@ -100,6 +100,11 @@ void EarlyHintsService::Cancel() {
|
||||
}
|
||||
}
|
||||
|
||||
void EarlyHintsService::RegisterLinksAndGetConnectArgs(
|
||||
nsTArray<EarlyHintConnectArgs>& aOutLinks) {
|
||||
mOngoingEarlyHints->RegisterLinksAndGetConnectArgs(aOutLinks);
|
||||
}
|
||||
|
||||
void EarlyHintsService::CollectTelemetry(Maybe<uint32_t> aResponseStatus) {
|
||||
// EH_NUM_OF_HINTS_PER_PAGE is only collected for the 2xx responses,
|
||||
// regardless of the number of received mEarlyHintsCount.
|
||||
|
@ -9,15 +9,17 @@
|
||||
#define mozilla_net_EarlyHintsService_h
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsStringFwd.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIChannel;
|
||||
class nsIURI;
|
||||
|
||||
namespace mozilla::net {
|
||||
|
||||
class EarlyHintConnectArgs;
|
||||
class OngoingEarlyHints;
|
||||
|
||||
class EarlyHintsService {
|
||||
@ -29,6 +31,9 @@ class EarlyHintsService {
|
||||
void FinalResponse(uint32_t aResponseStatus);
|
||||
void Cancel();
|
||||
|
||||
void RegisterLinksAndGetConnectArgs(
|
||||
nsTArray<EarlyHintConnectArgs>& aOutLinks);
|
||||
|
||||
private:
|
||||
void CollectTelemetry(Maybe<uint32_t> aResponseStatus);
|
||||
void CollectLinkTypeTelemetry(const nsAString& aRel);
|
||||
|
Loading…
Reference in New Issue
Block a user