зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1644945 - Implement a wrapper nsIParentChannel for ParentProcessDocumentChannel so that we can use the same code in DocumentLoadListener. r=jya
Differential Revision: https://phabricator.services.mozilla.com/D79241
This commit is contained in:
Родитель
010f052da8
Коммит
20d25fdc03
|
@ -23,7 +23,6 @@
|
|||
#include "mozilla/net/CookieJarSettings.h"
|
||||
#include "mozilla/net/HttpChannelParent.h"
|
||||
#include "mozilla/net/RedirectChannelRegistrar.h"
|
||||
#include "mozilla/net/UrlClassifierCommon.h"
|
||||
#include "nsContentSecurityUtils.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsDocShellLoadState.h"
|
||||
|
@ -733,8 +732,7 @@ void DocumentLoadListener::RedirectToRealChannelFinished(nsresult aRv) {
|
|||
("DocumentLoadListener RedirectToRealChannelFinished [this=%p, "
|
||||
"aRv=%" PRIx32 " ]",
|
||||
this, static_cast<uint32_t>(aRv)));
|
||||
|
||||
if (NS_FAILED(aRv) || !mRedirectChannelId) {
|
||||
if (NS_FAILED(aRv)) {
|
||||
FinishReplacementChannelSetup(aRv);
|
||||
return;
|
||||
}
|
||||
|
@ -777,26 +775,8 @@ void DocumentLoadListener::FinishReplacementChannelSetup(nsresult aResult) {
|
|||
"aResult=%x]",
|
||||
this, int(aResult)));
|
||||
|
||||
bool disconnected = false;
|
||||
if (mDoingProcessSwitch) {
|
||||
DisconnectListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
|
||||
disconnected = true;
|
||||
}
|
||||
|
||||
if (!mRedirectChannelId) {
|
||||
if (NS_FAILED(aResult)) {
|
||||
mChannel->Cancel(aResult);
|
||||
mChannel->Resume();
|
||||
if (!disconnected) {
|
||||
DisconnectListeners(aResult, aResult);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ApplyPendingFunctions(mChannel);
|
||||
|
||||
// The channel has already been resumed by the ParentProcessDocumentChannel
|
||||
// so we can return early.
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
|
||||
|
@ -807,18 +787,7 @@ void DocumentLoadListener::FinishReplacementChannelSetup(nsresult aResult) {
|
|||
nsresult rv = registrar->GetParentChannel(mRedirectChannelId,
|
||||
getter_AddRefs(redirectChannel));
|
||||
if (NS_FAILED(rv) || !redirectChannel) {
|
||||
// Redirect might get canceled before we got AsyncOnChannelRedirect
|
||||
nsCOMPtr<nsIChannel> newChannel;
|
||||
rv = registrar->GetRegisteredChannel(mRedirectChannelId,
|
||||
getter_AddRefs(newChannel));
|
||||
MOZ_ASSERT(newChannel, "Already registered channel not found");
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
newChannel->Cancel(NS_ERROR_FAILURE);
|
||||
}
|
||||
if (!redirectChannel) {
|
||||
aResult = NS_ERROR_FAILURE;
|
||||
}
|
||||
aResult = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Release all previously registered channels, they are no longer needed to
|
||||
|
@ -844,72 +813,46 @@ void DocumentLoadListener::FinishReplacementChannelSetup(nsresult aResult) {
|
|||
|
||||
ApplyPendingFunctions(redirectChannel);
|
||||
|
||||
ResumeSuspendedChannel(redirectChannel);
|
||||
if (!ResumeSuspendedChannel(redirectChannel)) {
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
if (loadGroup) {
|
||||
// We added ourselves to the load group, but attempting
|
||||
// to resume has notified us that the channel is already
|
||||
// finished. Better remove ourselves from the loadgroup
|
||||
// again. The only time the channel will be in a loadgroup
|
||||
// is if we're connected to the parent process.
|
||||
nsresult status = NS_OK;
|
||||
mChannel->GetStatus(&status);
|
||||
loadGroup->RemoveRequest(mChannel, nullptr, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentLoadListener::ApplyPendingFunctions(nsISupports* aChannel) const {
|
||||
void DocumentLoadListener::ApplyPendingFunctions(
|
||||
nsIParentChannel* aChannel) const {
|
||||
// We stored the values from all nsIParentChannel functions called since we
|
||||
// couldn't handle them. Copy them across to the real channel since it
|
||||
// should know what to do.
|
||||
|
||||
nsCOMPtr<nsIParentChannel> parentChannel = do_QueryInterface(aChannel);
|
||||
if (parentChannel) {
|
||||
for (auto& variant : mIParentChannelFunctions) {
|
||||
variant.match(
|
||||
[parentChannel](const nsIHttpChannel::FlashPluginState& aState) {
|
||||
parentChannel->NotifyFlashPluginStateChanged(aState);
|
||||
},
|
||||
[parentChannel](const ClassifierMatchedInfoParams& aParams) {
|
||||
parentChannel->SetClassifierMatchedInfo(
|
||||
aParams.mList, aParams.mProvider, aParams.mFullHash);
|
||||
},
|
||||
[parentChannel](const ClassifierMatchedTrackingInfoParams& aParams) {
|
||||
parentChannel->SetClassifierMatchedTrackingInfo(
|
||||
aParams.mLists, aParams.mFullHashes);
|
||||
},
|
||||
[parentChannel](const ClassificationFlagsParams& aParams) {
|
||||
parentChannel->NotifyClassificationFlags(
|
||||
aParams.mClassificationFlags, aParams.mIsThirdParty);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for (auto& variant : mIParentChannelFunctions) {
|
||||
variant.match(
|
||||
[&](const nsIHttpChannel::FlashPluginState& aState) {
|
||||
// For now, only HttpChannel use this attribute.
|
||||
RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(aChannel);
|
||||
if (httpChannel) {
|
||||
httpChannel->SetFlashPluginState(aState);
|
||||
}
|
||||
},
|
||||
[&](const ClassifierMatchedInfoParams& aParams) {
|
||||
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
|
||||
do_QueryInterface(aChannel);
|
||||
if (classifiedChannel) {
|
||||
classifiedChannel->SetMatchedInfo(
|
||||
aParams.mList, aParams.mProvider, aParams.mFullHash);
|
||||
}
|
||||
},
|
||||
[&](const ClassifierMatchedTrackingInfoParams& aParams) {
|
||||
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
|
||||
do_QueryInterface(aChannel);
|
||||
if (classifiedChannel) {
|
||||
nsTArray<nsCString> lists, fullhashes;
|
||||
for (const nsACString& token : aParams.mLists.Split(',')) {
|
||||
lists.AppendElement(token);
|
||||
}
|
||||
for (const nsACString& token : aParams.mFullHashes.Split(',')) {
|
||||
fullhashes.AppendElement(token);
|
||||
}
|
||||
classifiedChannel->SetMatchedTrackingInfo(lists, fullhashes);
|
||||
}
|
||||
},
|
||||
[&](const ClassificationFlagsParams& aParams) {
|
||||
UrlClassifierCommon::SetClassificationFlagsHelper(
|
||||
static_cast<nsIChannel*>(aChannel),
|
||||
aParams.mClassificationFlags, aParams.mIsThirdParty);
|
||||
});
|
||||
}
|
||||
nsCOMPtr<nsIParentChannel> parentChannel = aChannel;
|
||||
for (auto& variant : mIParentChannelFunctions) {
|
||||
variant.match(
|
||||
[parentChannel](const nsIHttpChannel::FlashPluginState& aState) {
|
||||
parentChannel->NotifyFlashPluginStateChanged(aState);
|
||||
},
|
||||
[parentChannel](const ClassifierMatchedInfoParams& aParams) {
|
||||
parentChannel->SetClassifierMatchedInfo(
|
||||
aParams.mList, aParams.mProvider, aParams.mFullHash);
|
||||
},
|
||||
[parentChannel](const ClassifierMatchedTrackingInfoParams& aParams) {
|
||||
parentChannel->SetClassifierMatchedTrackingInfo(aParams.mLists,
|
||||
aParams.mFullHashes);
|
||||
},
|
||||
[parentChannel](const ClassificationFlagsParams& aParams) {
|
||||
parentChannel->NotifyClassificationFlags(aParams.mClassificationFlags,
|
||||
aParams.mIsThirdParty);
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<HttpChannelSecurityWarningReporter> reporter;
|
||||
|
@ -1391,14 +1334,12 @@ DocumentLoadListener::RedirectToRealChannel(
|
|||
AddURIVisit(mChannel, aLoadFlags);
|
||||
}
|
||||
|
||||
if (aDestinationProcess || OtherPid()) {
|
||||
// Register the new channel and obtain id for it
|
||||
nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
|
||||
RedirectChannelRegistrar::GetOrCreate();
|
||||
MOZ_ASSERT(registrar);
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
registrar->RegisterChannel(mChannel, &mRedirectChannelId));
|
||||
}
|
||||
// Register the new channel and obtain id for it
|
||||
nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
|
||||
RedirectChannelRegistrar::GetOrCreate();
|
||||
MOZ_ASSERT(registrar);
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
registrar->RegisterChannel(mChannel, &mRedirectChannelId));
|
||||
|
||||
if (aDestinationProcess) {
|
||||
dom::ContentParent* cp =
|
||||
|
|
|
@ -181,6 +181,8 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
already_AddRefed<nsIWebProgressListener> GetRemoteWebProgressListener(
|
||||
nsIWebProgress** aWebProgress, nsIRequest** aRequest);
|
||||
|
||||
uint32_t GetRedirectChannelId() const { return mRedirectChannelId; }
|
||||
|
||||
nsresult ReportSecurityMessage(const nsAString& aMessageTag,
|
||||
const nsAString& aMessageCategory) override {
|
||||
ReportSecurityMessageParams params;
|
||||
|
@ -214,9 +216,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
base::ProcessId OtherPid() const {
|
||||
return mOtherPid;
|
||||
}
|
||||
base::ProcessId OtherPid() const { return mOtherPid; }
|
||||
|
||||
[[nodiscard]] RefPtr<ChildEndpointPromise> AttachStreamFilter(
|
||||
base::ProcessId aChildProcessId);
|
||||
|
@ -282,7 +282,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
|
||||
void AddURIVisit(nsIChannel* aChannel, uint32_t aLoadFlags);
|
||||
bool HasCrossOriginOpenerPolicyMismatch() const;
|
||||
void ApplyPendingFunctions(nsISupports* aChannel) const;
|
||||
void ApplyPendingFunctions(nsIParentChannel* aChannel) const;
|
||||
|
||||
void Disconnect();
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#include "mozilla/StaticPrefs_extensions.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIClassifiedChannel.h"
|
||||
#include "nsIRedirectChannelRegistrar.h"
|
||||
#include "mozilla/net/UrlClassifierCommon.h"
|
||||
|
||||
extern mozilla::LazyLogModule gDocumentChannelLog;
|
||||
#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
|
||||
|
@ -20,6 +23,25 @@ namespace net {
|
|||
using RedirectToRealChannelPromise =
|
||||
typename PDocumentChannelParent::RedirectToRealChannelPromise;
|
||||
|
||||
class ParentChannelWrapper : public nsIParentChannel {
|
||||
public:
|
||||
ParentChannelWrapper(nsIChannel* aChannel, nsIStreamListener* aListener)
|
||||
: mChannel(aChannel), mListener(aListener) {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPARENTCHANNEL
|
||||
NS_FORWARD_NSISTREAMLISTENER(mListener->)
|
||||
NS_FORWARD_NSIREQUESTOBSERVER(mListener->)
|
||||
|
||||
private:
|
||||
virtual ~ParentChannelWrapper() = default;
|
||||
const nsCOMPtr<nsIChannel> mChannel;
|
||||
const nsCOMPtr<nsIStreamListener> mListener;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ParentChannelWrapper, nsIParentChannel, nsIStreamListener,
|
||||
nsIRequestObserver);
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(ParentProcessDocumentChannel, DocumentChannel,
|
||||
nsIAsyncVerifyRedirectCallback, nsIObserver)
|
||||
|
||||
|
@ -110,15 +132,17 @@ ParentProcessDocumentChannel::OnRedirectVerifyCallback(nsresult aResult) {
|
|||
for (auto& endpoint : mStreamFilterEndpoints) {
|
||||
extensions::StreamFilterParent::Attach(channel, std::move(endpoint));
|
||||
}
|
||||
if (!mDocumentLoadListener->ResumeSuspendedChannel(mListener)) {
|
||||
// We added ourselves to the load group, but attempting
|
||||
// to resume has notified us that the channel is already
|
||||
// finished. Better remove ourselves from the loadgroup
|
||||
// again.
|
||||
nsresult status = NS_OK;
|
||||
channel->GetStatus(&status);
|
||||
mLoadGroup->RemoveRequest(channel, nullptr, status);
|
||||
}
|
||||
|
||||
RefPtr<ParentChannelWrapper> wrapper =
|
||||
new ParentChannelWrapper(channel, mListener);
|
||||
|
||||
nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
|
||||
RedirectChannelRegistrar::GetOrCreate();
|
||||
nsCOMPtr<nsIChannel> dummy;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
NS_LinkRedirectChannels(mDocumentLoadListener->GetRedirectChannelId(),
|
||||
wrapper, getter_AddRefs(dummy)));
|
||||
MOZ_ASSERT(dummy == channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,6 +284,68 @@ ParentProcessDocumentChannel::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIParentChannel
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
ParentChannelWrapper::SetParentListener(
|
||||
mozilla::net::ParentChannelListener* listener) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ParentChannelWrapper::NotifyFlashPluginStateChanged(
|
||||
nsIHttpChannel::FlashPluginState aState) {
|
||||
// For now, only HttpChannel use this attribute.
|
||||
RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(mChannel.get());
|
||||
if (httpChannel) {
|
||||
httpChannel->SetFlashPluginState(aState);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ParentChannelWrapper::SetClassifierMatchedInfo(const nsACString& aList,
|
||||
const nsACString& aProvider,
|
||||
const nsACString& aFullHash) {
|
||||
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
|
||||
do_QueryInterface(mChannel);
|
||||
if (classifiedChannel) {
|
||||
classifiedChannel->SetMatchedInfo(aList, aProvider, aFullHash);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ParentChannelWrapper::SetClassifierMatchedTrackingInfo(
|
||||
const nsACString& aLists, const nsACString& aFullHash) {
|
||||
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
|
||||
do_QueryInterface(mChannel);
|
||||
if (classifiedChannel) {
|
||||
nsTArray<nsCString> lists, fullhashes;
|
||||
for (const nsACString& token : aLists.Split(',')) {
|
||||
lists.AppendElement(token);
|
||||
}
|
||||
for (const nsACString& token : aFullHash.Split(',')) {
|
||||
fullhashes.AppendElement(token);
|
||||
}
|
||||
classifiedChannel->SetMatchedTrackingInfo(lists, fullhashes);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ParentChannelWrapper::NotifyClassificationFlags(uint32_t aClassificationFlags,
|
||||
bool aIsThirdParty) {
|
||||
UrlClassifierCommon::SetClassificationFlagsHelper(
|
||||
mChannel, aClassificationFlags, aIsThirdParty);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ParentChannelWrapper::Delete() { return NS_OK; }
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче