Bug 1574372 - Add parent-process version of nsDocumentOpenInfo, and use it in DocumentLoadListener. r=bzbarsky

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Matt Woodrow 2019-12-16 21:26:01 +00:00
Родитель 3f6ef264a3
Коммит 898cc13c90
15 изменённых файлов: 306 добавлений и 54 удалений

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

@ -10244,6 +10244,15 @@ nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
// Let the client channel helper know if we are using DocumentChannel,
// since redirects get handled in the parent process in that case.
RefPtr<net::DocumentChannelChild> docChannel = do_QueryObject(aChannel);
if (docChannel) {
bool pluginsAllowed = true;
GetAllowPlugins(&pluginsAllowed);
docChannel->SetDocumentOpenFlags(aOpenFlags, pluginsAllowed);
// Now that we've sent the real flags across to be run on the parent,
// tell the content process nsDocumentOpenInfo to not try to do
// any sort of targeting.
aOpenFlags |= nsIURILoader::DONT_RETARGET;
}
// Since we are loading a document we need to make sure the proper reserved
// and initial client data is stored on the nsILoadInfo. The

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

@ -26,7 +26,13 @@ class ADocumentChannelBridge {
// process).
// This should remove the nsIChannel from the loadgroup, and
// fire OnStart/StopRequest with aStatus.
virtual void DisconnectChildListeners(nsresult aStatus) = 0;
// aLoadGroupStatus is used as mStatus when we remove the child channel
// from the loadgroup (but aStatus is passed as the parameter to
// RemoveRequest).
// We do this so we can remove using NS_BINDING_RETARGETED, but still have
// the channel not be in an error state.
virtual void DisconnectChildListeners(nsresult aStatus,
nsresult aLoadGroupStatus) = 0;
// Delete the bridge, and drop any refs to the DocumentLoadListener
virtual void Delete() = 0;

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

@ -190,6 +190,8 @@ DocumentChannelChild::AsyncOpen(nsIStreamListener* aListener) {
args.hasNonEmptySandboxingFlags() = mHasNonEmptySandboxingFlags;
args.channelId() = mChannelId;
args.asyncOpenTime() = mAsyncOpenTime;
args.documentOpenFlags() = mDocumentOpenFlags;
args.pluginsAllowed() = mPluginsAllowed;
nsDocShell* docshell = GetDocShell();
if (docshell) {
@ -201,7 +203,7 @@ DocumentChannelChild::AsyncOpen(nsIStreamListener* aListener) {
NS_GET_TEMPLATE_IID(nsIBrowserChild),
getter_AddRefs(iBrowserChild));
BrowserChild* browserChild = static_cast<BrowserChild*>(iBrowserChild.get());
if (MissingRequiredBrowserChild(browserChild, "ftp")) {
if (MissingRequiredBrowserChild(browserChild, "documentchannel")) {
return NS_ERROR_ILLEGAL_VALUE;
}
@ -270,8 +272,9 @@ void DocumentChannelChild::ShutdownListeners(nsresult aStatusCode) {
}
IPCResult DocumentChannelChild::RecvDisconnectChildListeners(
const nsresult& aStatus) {
const nsresult& aStatus, const nsresult& aLoadGroupStatus) {
MOZ_ASSERT(NS_FAILED(aStatus));
mStatus = aLoadGroupStatus;
// Make sure we remove from the load group before
// setting mStatus, as existing tests expect the
// status to be successful when we disconnect.

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

@ -46,7 +46,8 @@ class DocumentChannelChild final : public nsIIdentChannel,
mozilla::ipc::IPCResult RecvFailedAsyncOpen(const nsresult& aStatusCode);
mozilla::ipc::IPCResult RecvDisconnectChildListeners(const nsresult& aStatus);
mozilla::ipc::IPCResult RecvDisconnectChildListeners(
const nsresult& aStatus, const nsresult& aLoadGroupStatus);
mozilla::ipc::IPCResult RecvDeleteSelf();
@ -70,6 +71,11 @@ class DocumentChannelChild final : public nsIIdentChannel,
*aChannelRedirectFlags = mLastVisitInfo.previousFlags();
}
void SetDocumentOpenFlags(uint32_t aFlags, bool aPluginsAllowed) {
mDocumentOpenFlags = Some(aFlags);
mPluginsAllowed = aPluginsAllowed;
}
private:
void ShutdownListeners(nsresult aStatusCode);
nsDocShell* GetDocShell();
@ -93,6 +99,7 @@ class DocumentChannelChild final : public nsIIdentChannel,
nsresult mStatus = NS_OK;
bool mCanceled = false;
Maybe<uint32_t> mDocumentOpenFlags;
bool mIsPending = false;
bool mWasOpened = false;
uint64_t mChannelId;
@ -103,6 +110,7 @@ class DocumentChannelChild final : public nsIIdentChannel,
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsISupports> mOwner;
bool mPluginsAllowed = false;
};
NS_DEFINE_STATIC_IID_ACCESSOR(DocumentChannelChild, DOCUMENT_CHANNEL_CHILD_IID)

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

@ -13,19 +13,20 @@ extern mozilla::LazyLogModule gDocumentChannelLog;
namespace mozilla {
namespace net {
DocumentChannelParent::DocumentChannelParent(
const dom::PBrowserOrId& aIframeEmbedding, nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus) {
DocumentChannelParent::DocumentChannelParent(BrowserParent* aBrowser,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus) {
LOG(("DocumentChannelParent ctor [this=%p]", this));
mParent = new DocumentLoadListener(aIframeEmbedding, aLoadContext,
aOverrideStatus, this);
mParent =
new DocumentLoadListener(aBrowser, aLoadContext, aOverrideStatus, this);
}
DocumentChannelParent::~DocumentChannelParent() {
LOG(("DocumentChannelParent dtor [this=%p]", this));
}
bool DocumentChannelParent::Init(const DocumentChannelCreationArgs& aArgs) {
bool DocumentChannelParent::Init(BrowserParent* aBrowser,
const DocumentChannelCreationArgs& aArgs) {
RefPtr<nsDocShellLoadState> loadState =
new nsDocShellLoadState(aArgs.loadState());
LOG(("DocumentChannelParent Init [this=%p, uri=%s]", this,
@ -37,13 +38,14 @@ bool DocumentChannelParent::Init(const DocumentChannelCreationArgs& aArgs) {
MOZ_ASSERT(NS_SUCCEEDED(rv));
rv = NS_ERROR_UNEXPECTED;
if (!mParent->Open(loadState, loadInfo, aArgs.initiatorType().ptrOr(nullptr),
aArgs.loadFlags(), aArgs.loadType(), aArgs.cacheKey(),
aArgs.isActive(), aArgs.isTopLevelDoc(),
aArgs.hasNonEmptySandboxingFlags(), aArgs.topWindowURI(),
aArgs.contentBlockingAllowListPrincipal(),
aArgs.customUserAgent(), aArgs.channelId(),
aArgs.asyncOpenTime(), &rv)) {
if (!mParent->Open(
aBrowser, loadState, loadInfo, aArgs.initiatorType().ptrOr(nullptr),
aArgs.loadFlags(), aArgs.loadType(), aArgs.cacheKey(),
aArgs.isActive(), aArgs.isTopLevelDoc(),
aArgs.hasNonEmptySandboxingFlags(), aArgs.topWindowURI(),
aArgs.contentBlockingAllowListPrincipal(), aArgs.customUserAgent(),
aArgs.channelId(), aArgs.asyncOpenTime(), aArgs.documentOpenFlags(),
aArgs.pluginsAllowed(), &rv)) {
return SendFailedAsyncOpen(rv);
}

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

@ -23,11 +23,12 @@ class DocumentChannelParent final : public ADocumentChannelBridge,
public:
NS_INLINE_DECL_REFCOUNTING(DocumentChannelParent, override);
explicit DocumentChannelParent(const dom::PBrowserOrId& aIframeEmbedding,
explicit DocumentChannelParent(dom::BrowserParent* aBrowser,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus);
bool Init(const DocumentChannelCreationArgs& aArgs);
bool Init(dom::BrowserParent* aBrowser,
const DocumentChannelCreationArgs& aArgs);
// PDocumentChannelParent
bool RecvCancel(const nsresult& aStatus) {
@ -41,9 +42,10 @@ class DocumentChannelParent final : public ADocumentChannelBridge,
private:
// DocumentChannelListener
void DisconnectChildListeners(nsresult aStatus) override {
void DisconnectChildListeners(nsresult aStatus,
nsresult aLoadGroupStatus) override {
if (CanSend()) {
Unused << SendDisconnectChildListeners(aStatus);
Unused << SendDisconnectChildListeners(aStatus, aLoadGroupStatus);
}
}

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

@ -10,6 +10,7 @@
#include "mozilla/LoadInfo.h"
#include "mozilla/MozPromiseInlines.h" // For MozPromise::FromDomPromise
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ClientChannelHelper.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentProcessManager.h"
@ -25,6 +26,13 @@
#include "nsSerializationHelper.h"
#include "nsIPrompt.h"
#include "nsIWindowWatcher.h"
#include "nsIURIContentListener.h"
#include "nsWebNavigationInfo.h"
#include "nsURILoader.h"
#include "nsIStreamConverterService.h"
#include "nsExternalHelperAppService.h"
#include "nsCExternalHandlerService.h"
#include "nsMimeTypes.h"
mozilla::LazyLogModule gDocumentChannelLog("DocumentChannel");
#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
@ -34,6 +42,179 @@ using namespace mozilla::dom;
namespace mozilla {
namespace net {
/**
* An extension to nsDocumentOpenInfo that we run in the parent process, so
* that we can make the decision to retarget to content handlers or the external
* helper app, before we make process switching decisions.
*
* This modifies the behaviour of nsDocumentOpenInfo so that it can do
* retargeting, but doesn't do stream conversion (but confirms that we will be
* able to do so later).
*
* We still run nsDocumentOpenInfo in the content process, but disable
* retargeting, so that it can only apply stream conversion, and then send data
* to the docshell.
*/
class ParentProcessDocumentOpenInfo final : public nsDocumentOpenInfo,
public nsIMultiPartChannelListener {
public:
ParentProcessDocumentOpenInfo(ParentChannelListener* aListener,
bool aPluginsAllowed, uint32_t aFlags,
mozilla::dom::BrowsingContext* aBrowsingContext)
: nsDocumentOpenInfo(aFlags, false),
mBrowsingContext(aBrowsingContext),
mListener(aListener),
mPluginsAllowed(aPluginsAllowed) {}
NS_DECL_ISUPPORTS_INHERITED
// The default content listener is always a docshell, so this manually
// implements the same checks, and if it succeeds, uses the parent
// channel listener so that we forward onto DocumentLoadListener.
bool TryDefaultContentListener(nsIChannel* aChannel,
const nsCString& aContentType) {
uint32_t canHandle =
nsWebNavigationInfo::IsTypeSupported(aContentType, mPluginsAllowed);
if (canHandle != nsIWebNavigationInfo::UNSUPPORTED) {
m_targetStreamListener = mListener;
nsLoadFlags loadFlags = 0;
aChannel->GetLoadFlags(&loadFlags);
aChannel->SetLoadFlags(loadFlags | nsIChannel::LOAD_TARGETED);
return true;
}
return false;
}
bool TryDefaultContentListener(nsIChannel* aChannel) override {
return TryDefaultContentListener(aChannel, mContentType);
}
// Generally we only support stream converters that can tell
// use exactly what type they'll output. If we find one, then
// we just target to our default listener directly (without
// conversion), and the content process nsDocumentOpenInfo will
// run and do the actual conversion.
bool TryStreamConversion(nsIChannel* aChannel) override {
// The one exception is nsUnknownDecoder, which works in the parent
// (and we need to know what the content type is before we can
// decide if it will be handled in the parent), so we run that here.
if (mContentType.LowerCaseEqualsASCII(UNKNOWN_CONTENT_TYPE)) {
return nsDocumentOpenInfo::TryStreamConversion(aChannel);
}
nsresult rv;
nsCOMPtr<nsIStreamConverterService> streamConvService =
do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
nsAutoCString str;
if (NS_SUCCEEDED(streamConvService->ConvertedType(mContentType, str))) {
// We only support passing data to the default content listener
// (docshell), and we don't supported chaining converters.
if (TryDefaultContentListener(aChannel, str)) {
mContentType = str;
return true;
}
}
return false;
}
bool TryExternalHelperApp(nsIExternalHelperAppService* aHelperAppService,
nsIChannel* aChannel) override {
RefPtr<nsExternalAppHandler> handler;
nsresult rv = aHelperAppService->CreateListener(
mContentType, aChannel, mBrowsingContext, false, nullptr,
getter_AddRefs(handler));
if (NS_SUCCEEDED(rv)) {
m_targetStreamListener = handler;
return true;
}
return false;
}
nsDocumentOpenInfo* Clone() override {
mCloned = true;
return new ParentProcessDocumentOpenInfo(mListener, mPluginsAllowed, mFlags,
mBrowsingContext);
}
NS_IMETHOD OnStartRequest(nsIRequest* request) override {
nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(request);
if (multiPartChannel) {
mExpectingOnAfterLastPart = true;
}
nsresult rv = nsDocumentOpenInfo::OnStartRequest(request);
// If we didn't find a content handler,
// and we don't have a listener, then just forward to our
// default listener. This happens when the channel is in
// an error state, and we want to just forward that on to be
// handled in the content process.
if (!mUsedContentHandler && !m_targetStreamListener) {
m_targetStreamListener = mListener;
return m_targetStreamListener->OnStartRequest(request);
}
return rv;
}
NS_IMETHOD OnStopRequest(nsIRequest* request, nsresult aStatus) override {
// If we're not a multipart stream (and thus not expecting OnAfterLastPart),
// then this is the final OnStopRequest we'll get. If we haven't been
// targeting our default listener, then we need to manually notify it that
// we're done, and nothing further will be arriving. If we got cloned, then
// we don't need to do this, as only the last link needs to do it.
bool needToNotifyListener = false;
if (!mExpectingOnAfterLastPart && m_targetStreamListener != mListener &&
!mCloned) {
needToNotifyListener = true;
}
nsresult rv = nsDocumentOpenInfo::OnStopRequest(request, aStatus);
if (needToNotifyListener) {
// Tell the DocumentLoadListener to notify the content process that it's
// been entirely retargeted, and to stop waiting.
// Clear mListener's pointer to the DocumentLoadListener to break the
// reference cycle.
RefPtr<DocumentLoadListener> doc = do_GetInterface(ToSupports(mListener));
MOZ_ASSERT(doc);
doc->DisconnectChildListeners(NS_BINDING_RETARGETED, NS_OK);
mListener->SetListenerAfterRedirect(nullptr);
}
return rv;
}
NS_IMETHOD OnAfterLastPart(nsresult aStatus) override {
mListener->OnAfterLastPart(aStatus);
return NS_OK;
}
private:
virtual ~ParentProcessDocumentOpenInfo() = default;
RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext;
RefPtr<ParentChannelListener> mListener;
bool mPluginsAllowed;
/**
* Set to true if we got OnStartRequest called with a multipart
* channel, and thus expect OnAfterLastPart to be called when
* the channel is complete.
*/
bool mExpectingOnAfterLastPart = false;
/**
* Set to true if we got cloned to create a chained listener.
*/
bool mCloned = false;
};
NS_IMPL_ADDREF_INHERITED(ParentProcessDocumentOpenInfo, nsDocumentOpenInfo)
NS_IMPL_RELEASE_INHERITED(ParentProcessDocumentOpenInfo, nsDocumentOpenInfo)
NS_INTERFACE_MAP_BEGIN(ParentProcessDocumentOpenInfo)
NS_INTERFACE_MAP_ENTRY(nsIMultiPartChannelListener)
NS_INTERFACE_MAP_END_INHERITING(nsDocumentOpenInfo)
NS_IMPL_ADDREF(DocumentLoadListener)
NS_IMPL_RELEASE(DocumentLoadListener)
@ -50,18 +231,13 @@ NS_INTERFACE_MAP_BEGIN(DocumentLoadListener)
NS_INTERFACE_MAP_ENTRY_CONCRETE(DocumentLoadListener)
NS_INTERFACE_MAP_END
DocumentLoadListener::DocumentLoadListener(const PBrowserOrId& aIframeEmbedding,
DocumentLoadListener::DocumentLoadListener(BrowserParent* aBrowser,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus,
ADocumentChannelBridge* aBridge)
: mLoadContext(aLoadContext), mPBOverride(aOverrideStatus) {
LOG(("DocumentLoadListener ctor [this=%p]", this));
RefPtr<dom::BrowserParent> parent;
if (aIframeEmbedding.type() == PBrowserOrId::TPBrowserParent) {
parent =
static_cast<dom::BrowserParent*>(aIframeEmbedding.get_PBrowserParent());
}
mParentChannelListener = new ParentChannelListener(this, parent);
mParentChannelListener = new ParentChannelListener(this, aBrowser);
mDocumentChannelBridge = aBridge;
}
@ -70,13 +246,15 @@ DocumentLoadListener::~DocumentLoadListener() {
}
bool DocumentLoadListener::Open(
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
const nsString* aInitiatorType, nsLoadFlags aLoadFlags, uint32_t aLoadType,
uint32_t aCacheKey, bool aIsActive, bool aIsTopLevelDoc,
bool aHasNonEmptySandboxingFlags, const Maybe<URIParams>& aTopWindowURI,
BrowserParent* aBrowser, nsDocShellLoadState* aLoadState,
class LoadInfo* aLoadInfo, const nsString* aInitiatorType,
nsLoadFlags aLoadFlags, uint32_t aLoadType, uint32_t aCacheKey,
bool aIsActive, bool aIsTopLevelDoc, bool aHasNonEmptySandboxingFlags,
const Maybe<URIParams>& aTopWindowURI,
const Maybe<PrincipalInfo>& aContentBlockingAllowListPrincipal,
const nsString& aCustomUserAgent, const uint64_t& aChannelId,
const TimeStamp& aAsyncOpenTime, nsresult* aRv) {
const TimeStamp& aAsyncOpenTime, const Maybe<uint32_t>& aDocumentOpenFlags,
bool aPluginsAllowed, nsresult* aRv) {
LOG(("DocumentLoadListener Open [this=%p, uri=%s]", this,
aLoadState->URI()->GetSpecOrDefault().get()));
if (!nsDocShell::CreateChannelForLoadState(
@ -142,7 +320,17 @@ bool DocumentLoadListener::Open(
// across any serviceworker related data between channels as needed.
AddClientChannelHelperInParent(mChannel, GetMainThreadSerialEventTarget());
*aRv = mChannel->AsyncOpen(mParentChannelListener);
if (aDocumentOpenFlags) {
RefPtr<ParentProcessDocumentOpenInfo> openInfo =
new ParentProcessDocumentOpenInfo(mParentChannelListener,
aPluginsAllowed, *aDocumentOpenFlags,
aBrowser->GetBrowsingContext());
openInfo->Prepare();
*aRv = mChannel->AsyncOpen(openInfo);
} else {
*aRv = mChannel->AsyncOpen(mParentChannelListener);
}
if (NS_FAILED(*aRv)) {
mParentChannelListener = nullptr;
return false;
@ -230,7 +418,8 @@ void DocumentLoadListener::FinishReplacementChannelSetup(bool aSucceeded) {
nsresult rv;
if (mDoingProcessSwitch && mDocumentChannelBridge) {
mDocumentChannelBridge->DisconnectChildListeners(NS_BINDING_ABORTED);
mDocumentChannelBridge->DisconnectChildListeners(NS_BINDING_ABORTED,
NS_BINDING_ABORTED);
}
nsCOMPtr<nsIParentChannel> redirectChannel;
@ -687,7 +876,7 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
nsresult status = NS_OK;
aRequest->GetStatus(&status);
if (status == NS_ERROR_NO_CONTENT) {
mDocumentChannelBridge->DisconnectChildListeners(NS_ERROR_NO_CONTENT);
mDocumentChannelBridge->DisconnectChildListeners(status, status);
return NS_OK;
}
@ -779,6 +968,15 @@ DocumentLoadListener::OnDataAvailable(nsIRequest* aRequest,
NS_IMETHODIMP
DocumentLoadListener::OnAfterLastPart(nsresult aStatus) {
LOG(("DocumentLoadListener OnAfterLastPart [this=%p]", this));
if (!mInitiatedRedirectToRealChannel) {
// if we get here, and we haven't initiated a redirect to a real
// channel, then it means we never got OnStartRequest (maybe a problem?)
// and we retargeted everything.
LOG(("DocumentLoadListener Disconnecting child"));
DisconnectChildListeners(NS_BINDING_RETARGETED, NS_OK);
return NS_OK;
}
mStreamListenerFunctions.AppendElement(StreamListenerFunction{
VariantIndex<3>{}, OnAfterLastPartParams{aStatus}});
mIsFinished = true;

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

@ -14,6 +14,7 @@
#include "mozilla/net/PDocumentChannelParent.h"
#include "mozilla/net/ParentChannelListener.h"
#include "mozilla/net/ADocumentChannelBridge.h"
#include "mozilla/dom/BrowserParent.h"
#include "nsIInterfaceRequestor.h"
#include "nsIObserver.h"
#include "nsIParentChannel.h"
@ -59,20 +60,26 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
public nsIProcessSwitchRequestor,
public nsIMultiPartChannelListener {
public:
explicit DocumentLoadListener(const dom::PBrowserOrId& aIframeEmbedding,
explicit DocumentLoadListener(dom::BrowserParent* aBrowser,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus,
ADocumentChannelBridge* aBridge);
// Creates the channel, and then calls AsyncOpen on it.
bool Open(nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
const nsString* aInitiatorType, nsLoadFlags aLoadFlags,
uint32_t aLoadType, uint32_t aCacheKey, bool aIsActive,
bool aIsTopLevelDoc, bool aHasNonEmptySandboxingFlags,
// Must be the same BrowserParent as was passed to the constructor, we
// expect Necko to pass it again so that we don't need a member var for
// it.
bool Open(dom::BrowserParent* aBrowser, nsDocShellLoadState* aLoadState,
class LoadInfo* aLoadInfo, const nsString* aInitiatorType,
nsLoadFlags aLoadFlags, uint32_t aLoadType, uint32_t aCacheKey,
bool aIsActive, bool aIsTopLevelDoc,
bool aHasNonEmptySandboxingFlags,
const Maybe<ipc::URIParams>& aTopWindowURI,
const Maybe<ipc::PrincipalInfo>& aContentBlockingAllowListPrincipal,
const nsString& aCustomUserAgent, const uint64_t& aChannelId,
const TimeStamp& aAsyncOpenTime, nsresult* aRv);
const TimeStamp& aAsyncOpenTime,
const Maybe<uint32_t>& aDocumentOpenFlags, bool aPluginsAllowed,
nsresult* aRv);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
@ -134,6 +141,13 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
// our reference to it.
void DocumentChannelBridgeDisconnected();
void DisconnectChildListeners(nsresult aStatus, nsresult aLoadGroupStatus) {
if (mDocumentChannelBridge) {
mDocumentChannelBridge->DisconnectChildListeners(aStatus,
aLoadGroupStatus);
}
}
base::ProcessId OtherPid() const {
if (mDocumentChannelBridge) {
return mDocumentChannelBridge->OtherPid();

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

@ -405,9 +405,11 @@ struct DocumentChannelCreationArgs {
uint32_t loadFlags;
uint32_t loadType;
uint32_t cacheKey;
uint32_t? documentOpenFlags;
bool isActive;
bool isTopLevelDoc;
bool hasNonEmptySandboxingFlags;
bool pluginsAllowed;
};
struct DocumentChannelRedirect {

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

@ -409,7 +409,7 @@ mozilla::ipc::IPCResult NeckoParent::RecvPFTPChannelConstructor(
already_AddRefed<PDocumentChannelParent>
NeckoParent::AllocPDocumentChannelParent(
const PBrowserOrId& aBrowser, const SerializedLoadContext& aSerialized,
PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
const DocumentChannelCreationArgs& args) {
nsCOMPtr<nsIPrincipal> requestingPrincipal =
GetRequestingPrincipal(Some(args.loadInfo()));
@ -422,17 +422,21 @@ NeckoParent::AllocPDocumentChannelParent(
}
PBOverrideStatus overrideStatus =
PBOverrideStatusFromLoadContext(aSerialized);
RefPtr<dom::BrowserParent> browser =
static_cast<dom::BrowserParent*>(aBrowser);
RefPtr<DocumentChannelParent> p =
new DocumentChannelParent(aBrowser, loadContext, overrideStatus);
new DocumentChannelParent(browser, loadContext, overrideStatus);
return p.forget();
}
mozilla::ipc::IPCResult NeckoParent::RecvPDocumentChannelConstructor(
PDocumentChannelParent* aActor, const PBrowserOrId& aBrowser,
PDocumentChannelParent* aActor, PBrowserParent* aBrowser,
const SerializedLoadContext& aSerialized,
const DocumentChannelCreationArgs& aArgs) {
DocumentChannelParent* p = static_cast<DocumentChannelParent*>(aActor);
if (!p->Init(aArgs)) {
RefPtr<dom::BrowserParent> browser =
static_cast<dom::BrowserParent*>(aBrowser);
if (!p->Init(browser, aArgs)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();

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

@ -128,10 +128,10 @@ class NeckoParent : public PNeckoParent {
const uint16_t& port);
already_AddRefed<PDocumentChannelParent> AllocPDocumentChannelParent(
const PBrowserOrId& aBrowser, const SerializedLoadContext& aSerialized,
PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
const DocumentChannelCreationArgs& args);
virtual mozilla::ipc::IPCResult RecvPDocumentChannelConstructor(
PDocumentChannelParent* aActor, const PBrowserOrId& aBrowser,
PDocumentChannelParent* aActor, PBrowserParent* aBrowser,
const SerializedLoadContext& aSerialized,
const DocumentChannelCreationArgs& aArgs) override;
bool DeallocPDocumentChannelParent(PDocumentChannelParent* channel);

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

@ -45,7 +45,11 @@ child:
// As a consequence, it should cleanup the channel listeners and remove the
// request from the loadGroup.
// aStatus must be an error result.
async DisconnectChildListeners(nsresult aStatus);
// aLoadGroupReason is used as mStatus when we remove the child channel from
// the loadgroup (but aStatus is passed as the parameter to RemoveRequest).
// We do this so we can remove using NS_BINDING_RETARGETED, but still have the
// channel not be in an error state.
async DisconnectChildListeners(nsresult aStatus, nsresult aLoadGroupReason);
// Triggers replacing this DocumentChannel with a 'real' channel (like PHttpChannel),
// and notifies the listener via a redirect to the new channel.

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

@ -88,7 +88,7 @@ parent:
async PDNSRequest(nsCString hostName, OriginAttributes originAttributes,
uint32_t flags);
async PDocumentChannel(PBrowserOrId browser,
async PDocumentChannel(PBrowser browser,
SerializedLoadContext loadContext,
DocumentChannelCreationArgs args);

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

@ -98,6 +98,10 @@ class ParentChannelListener final : public nsIInterfaceRequestor,
NS_DEFINE_STATIC_IID_ACCESSOR(ParentChannelListener, PARENT_CHANNEL_LISTENER)
inline nsISupports* ToSupports(ParentChannelListener* aDoc) {
return static_cast<nsIInterfaceRequestor*>(aDoc);
}
} // namespace net
} // namespace mozilla

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

@ -1,4 +0,0 @@
[a-download-click-404.html]
[Do not navigate to 404 for anchor with download]
expected: FAIL