/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GeckoViewContentChannelParent.h" #include "GeckoViewContentChannel.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/ipc/URIUtils.h" #include "mozilla/net/NeckoParent.h" #include "mozilla/NotNull.h" #include "nsIAuthPromptProvider.h" #include "nsISecureBrowserUI.h" namespace mozilla::net { NS_IMPL_ISUPPORTS(GeckoViewContentChannelParent, nsIParentChannel, nsIStreamListener, nsIInterfaceRequestor) GeckoViewContentChannelParent::GeckoViewContentChannelParent( dom::BrowserParent* aIframeEmbedding, nsILoadContext* aLoadContext) : mLoadContext(aLoadContext), mBrowserParent(aIframeEmbedding) {} NS_IMETHODIMP GeckoViewContentChannelParent::SetParentListener( ParentChannelListener* aListener) { // Nothing to do. return NS_OK; } NS_IMETHODIMP GeckoViewContentChannelParent::NotifyClassificationFlags( uint32_t aClassificationFlags, bool aIsThirdParty) { // Nothing to do. return NS_OK; } NS_IMETHODIMP GeckoViewContentChannelParent::SetClassifierMatchedInfo( const nsACString& aList, const nsACString& aProvider, const nsACString& aFullHash) { // nothing to do return NS_OK; } NS_IMETHODIMP GeckoViewContentChannelParent::SetClassifierMatchedTrackingInfo( const nsACString& aLists, const nsACString& aFullHashes) { // nothing to do return NS_OK; } NS_IMETHODIMP GeckoViewContentChannelParent::Delete() { if (!CanSend()) { return NS_ERROR_UNEXPECTED; } (void)SendDeleteSelf(); return NS_OK; } NS_IMETHODIMP GeckoViewContentChannelParent::GetRemoteType(nsACString& aRemoteType) { if (!CanSend()) { return NS_ERROR_UNEXPECTED; } dom::PContentParent* pcp = Manager()->Manager(); aRemoteType = static_cast(pcp)->GetRemoteType(); return NS_OK; } NS_IMETHODIMP GeckoViewContentChannelParent::OnStartRequest(nsIRequest* aRequest) { if (!CanSend()) { return NS_ERROR_UNEXPECTED; } nsCOMPtr channel = do_QueryInterface(aRequest); nsCString contentType; channel->GetContentType(contentType); nsresult channelStatus = NS_OK; channel->GetStatus(&channelStatus); nsCString entityID; nsCOMPtr uri; channel->GetURI(getter_AddRefs(uri)); if (MOZ_UNLIKELY(!uri)) { return NS_ERROR_UNEXPECTED; } (void)SendOnStartRequest(channelStatus, contentType, entityID, WrapNotNull(uri)); return NS_OK; } NS_IMETHODIMP GeckoViewContentChannelParent::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { if (!CanSend() || !SendOnStopRequest(aStatusCode)) { return NS_ERROR_UNEXPECTED; } return NS_OK; } NS_IMETHODIMP GeckoViewContentChannelParent::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream, uint64_t aOffset, uint32_t aCount) { if (!CanSend()) { return NS_ERROR_UNEXPECTED; } nsCString data; nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount); if (MOZ_UNLIKELY(NS_FAILED(rv))) { return rv; } nsresult channelStatus = NS_OK; mChannel->GetStatus(&channelStatus); (void)SendOnDataAvailable(channelStatus, data, aOffset); return NS_OK; } NS_IMETHODIMP GeckoViewContentChannelParent::GetInterface(const nsIID& uuid, void** result) { if (uuid.Equals(NS_GET_IID(nsIAuthPromptProvider)) || uuid.Equals(NS_GET_IID(nsISecureBrowserUI))) { if (mBrowserParent) { return mBrowserParent->QueryInterface(uuid, result); } } // Only support nsILoadContext if child channel's callbacks did too if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) { nsCOMPtr copy = mLoadContext; copy.forget(result); return NS_OK; } return QueryInterface(uuid, result); } bool GeckoViewContentChannelParent::Init( const GeckoViewContentChannelOpenArgs& aArgs) { nsresult rv = NS_OK; auto scopeExit = MakeScopeExit([&rv, this] { if (NS_FAILED(rv)) { (void)SendOnAsyncOpenFailed(rv); } }); nsCOMPtr uri = ipc::DeserializeURI(aArgs.uri()); nsAutoCString remoteType; rv = GetRemoteType(remoteType); if (MOZ_UNLIKELY(NS_FAILED(rv))) { return false; } nsCOMPtr loadInfo; rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aArgs.loadInfo(), remoteType, getter_AddRefs(loadInfo)); if (MOZ_UNLIKELY(NS_FAILED(rv))) { return false; } nsCOMPtr ios(do_GetIOService(&rv)); if (MOZ_UNLIKELY(NS_FAILED(rv))) { return false; } nsCOMPtr channel; rv = NS_NewChannelInternal(getter_AddRefs(channel), uri, loadInfo, nullptr, nullptr, nullptr, aArgs.loadFlags(), ios); if (MOZ_UNLIKELY(NS_FAILED(rv))) { return false; } rv = channel->AsyncOpen(this); if (MOZ_UNLIKELY(NS_FAILED(rv))) { return false; } mChannel = channel; return true; } bool GeckoViewContentChannelParent::Init( const GeckoViewContentChannelConnectArgs& aArgs) { nsCOMPtr channel; nsresult rv = NS_LinkRedirectChannels(aArgs.channelId(), this, getter_AddRefs(channel)); if (NS_SUCCEEDED(rv)) { mChannel = channel; } return true; } bool GeckoViewContentChannelParent::Init( const GeckoViewContentChannelArgs& aArgs) { switch (aArgs.type()) { case GeckoViewContentChannelArgs::TGeckoViewContentChannelOpenArgs: return Init(aArgs.get_GeckoViewContentChannelOpenArgs()); case GeckoViewContentChannelArgs::TGeckoViewContentChannelConnectArgs: return Init(aArgs.get_GeckoViewContentChannelConnectArgs()); default: return false; } } mozilla::ipc::IPCResult GeckoViewContentChannelParent::RecvCancel( const nsresult& status) { if (mChannel) { mChannel->Cancel(status); } return IPC_OK(); } mozilla::ipc::IPCResult GeckoViewContentChannelParent::RecvSuspend() { if (mChannel) { mChannel->Suspend(); } return IPC_OK(); } mozilla::ipc::IPCResult GeckoViewContentChannelParent::RecvResume() { if (mChannel) { mChannel->Resume(); } return IPC_OK(); } } // namespace mozilla::net