Bug 1602318 - Associate a current DocumentLoadListener with CanonicalBrowsingContext. r=nika,necko-reviewers,dragana

Differential Revision: https://phabricator.services.mozilla.com/D67094
This commit is contained in:
Matt Woodrow 2020-04-20 22:58:40 +00:00
Родитель 0230c3bba2
Коммит 8981f913c2
4 изменённых файлов: 72 добавлений и 15 удалений

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

@ -15,6 +15,7 @@
#include "mozilla/dom/PlaybackController.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/net/DocumentLoadListener.h"
#include "nsGlobalWindowOuter.h"
@ -543,6 +544,20 @@ MediaController* CanonicalBrowsingContext::GetMediaController() {
return mTabMediaController;
}
void CanonicalBrowsingContext::StartDocumentLoad(
net::DocumentLoadListener* aLoad) {
if (mCurrentLoad) {
mCurrentLoad->Cancel(NS_BINDING_ABORTED);
}
mCurrentLoad = aLoad;
}
void CanonicalBrowsingContext::EndDocumentLoad(
net::DocumentLoadListener* aLoad) {
if (mCurrentLoad == aLoad) {
mCurrentLoad = nullptr;
}
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(CanonicalBrowsingContext, BrowsingContext,
mSessionHistory)

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

@ -19,6 +19,10 @@
#include "nsISHEntry.h"
namespace mozilla {
namespace net {
class DocumentLoadListener;
}
namespace dom {
class WindowGlobalParent;
@ -176,6 +180,15 @@ class CanonicalBrowsingContext final : public BrowsingContext {
uint64_t mPendingSwitchId;
};
friend class net::DocumentLoadListener;
// Called when a DocumentLoadListener is created to start a load for
// this browsing context.
void StartDocumentLoad(net::DocumentLoadListener* aLoad);
// Called once DocumentLoadListener completes handling a load, and it
// is either complete, or handed off to the final channel to deliver
// data to the destination docshell.
void EndDocumentLoad(net::DocumentLoadListener* aLoad);
// XXX(farre): Store a ContentParent pointer here rather than mProcessId?
// Indicates which process owns the docshell.
uint64_t mProcessId;
@ -197,6 +210,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
// context.
RefPtr<MediaController> mTabMediaController;
RefPtr<net::DocumentLoadListener> mCurrentLoad;
// These are being mirrored from docshell
nsCOMPtr<nsISHEntry> mOSHE;
nsCOMPtr<nsISHEntry> mLSHE;

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

@ -38,6 +38,7 @@
#include "nsMimeTypes.h"
#include "nsIViewSourceChannel.h"
#include "nsIOService.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/StaticPrefs_security.h"
#include "nsICookieService.h"
@ -339,6 +340,13 @@ GetTopWindowExcludingExtensionAccessibleContentFrames(
return prev.forget();
}
CanonicalBrowsingContext* DocumentLoadListener::GetBrowsingContext() {
if (!mParentChannelListener) {
return nullptr;
}
return mParentChannelListener->GetBrowsingContext();
}
bool DocumentLoadListener::Open(
nsDocShellLoadState* aLoadState, nsLoadFlags aLoadFlags, uint32_t aCacheKey,
const uint64_t& aChannelId, const TimeStamp& aAsyncOpenTime,
@ -505,6 +513,10 @@ bool DocumentLoadListener::Open(
mTiming = aTiming;
mSrcdocData = aLoadState->SrcdocData();
mBaseURI = aLoadState->BaseURI();
if (auto* ctx = GetBrowsingContext()) {
ctx->StartDocumentLoad(this);
}
return true;
}
@ -518,6 +530,10 @@ void DocumentLoadListener::DocumentChannelBridgeDisconnected() {
httpChannelImpl->SetWarningReporter(nullptr);
}
mDocumentChannelBridge = nullptr;
if (auto* ctx = GetBrowsingContext()) {
ctx->EndDocumentLoad(this);
}
}
void DocumentLoadListener::Cancel(const nsresult& aStatusCode) {
@ -525,9 +541,18 @@ void DocumentLoadListener::Cancel(const nsresult& aStatusCode) {
("DocumentLoadListener Cancel [this=%p, "
"aStatusCode=%" PRIx32 " ]",
this, static_cast<uint32_t>(aStatusCode)));
if (mChannel && !mDoingProcessSwitch) {
if (mDoingProcessSwitch) {
// If we've already initiated process-switching
// then we can no longer be cancelled and we'll
// disconnect the old listeners when done.
return;
}
if (mChannel) {
mChannel->Cancel(aStatusCode);
}
DisconnectChildListeners(aStatusCode, aStatusCode);
}
void DocumentLoadListener::DisconnectChildListeners(nsresult aStatus,
@ -537,7 +562,10 @@ void DocumentLoadListener::DisconnectChildListeners(nsresult aStatus,
"aStatus=%" PRIx32 " aLoadGroupStatus=%" PRIx32 " ]",
this, static_cast<uint32_t>(aStatus),
static_cast<uint32_t>(aLoadGroupStatus)));
RefPtr<DocumentLoadListener> keepAlive(this);
if (mDocumentChannelBridge) {
// This will drop the bridge's reference to us, so we use keepAlive to
// make sure we don't get deleted until we exit the function.
mDocumentChannelBridge->DisconnectChildListeners(aStatus, aLoadGroupStatus);
}
DocumentChannelBridgeDisconnected();
@ -639,6 +667,9 @@ void DocumentLoadListener::FinishReplacementChannelSetup(bool aSucceeded) {
redirectChannel->Delete();
}
mChannel->Resume();
if (auto* ctx = GetBrowsingContext()) {
ctx->EndDocumentLoad(this);
}
return;
}
@ -765,6 +796,10 @@ void DocumentLoadListener::ResumeSuspendedChannel(
"Should not have added new stream listener function!");
mChannel->Resume();
if (auto* ctx = GetBrowsingContext()) {
ctx->EndDocumentLoad(this);
}
}
void DocumentLoadListener::SerializeRedirectData(
@ -1024,9 +1059,6 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
MOZ_DIAGNOSTIC_ASSERT(mChannel);
RefPtr<nsHttpChannel> httpChannel = do_QueryObject(mChannel);
// If this is a download, then redirect entirely within the parent.
// TODO, see bug 1574372.
if (!mDocumentChannelBridge) {
return NS_ERROR_UNEXPECTED;
}
@ -1035,15 +1067,6 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
// might cancel the channel.
nsContentSecurityUtils::PerformCSPFrameAncestorAndXFOCheck(mChannel);
// Once we initiate a process switch, we ask the child to notify the
// listeners that we have completed. If the switch promise then gets
// rejected we also cancel the parent, which results in this being called.
// We don't need to forward it on though, since the child side is already
// completed.
if (mDoingProcessSwitch) {
return NS_OK;
}
// Generally we want to switch to a real channel even if the request failed,
// since the listener might want to access protocol-specific data (like http
// response headers) in its error handling.
@ -1053,7 +1076,7 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
nsresult status = NS_OK;
aRequest->GetStatus(&status);
if (status == NS_ERROR_NO_CONTENT) {
mDocumentChannelBridge->DisconnectChildListeners(status, status);
DisconnectChildListeners(status, status);
return NS_OK;
}

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

@ -14,7 +14,6 @@
#include "mozilla/net/PDocumentChannelParent.h"
#include "mozilla/net/ParentChannelListener.h"
#include "mozilla/net/ADocumentChannelBridge.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "nsDOMNavigationTiming.h"
#include "nsIInterfaceRequestor.h"
#include "nsIObserver.h"
@ -32,6 +31,9 @@
}
namespace mozilla {
namespace dom {
class CanonicalBrowsingContext;
}
namespace net {
using ChildEndpointPromise =
MozPromise<ipc::Endpoint<extensions::PStreamFilterChild>, bool, true>;
@ -218,6 +220,8 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
dom::CanonicalBrowsingContext* aBrowsingContext,
nsDocShellLoadState* aLoadState, uint64_t aOuterWindowId);
dom::CanonicalBrowsingContext* GetBrowsingContext();
// This defines a variant that describes all the attribute setters (and their
// parameters) from nsIParentChannel
//