diff options
Diffstat (limited to 'netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp')
-rw-r--r-- | netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp new file mode 100644 index 000000000..be00c2d86 --- /dev/null +++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp @@ -0,0 +1,373 @@ +/* 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 "nsWyciwyg.h" + +#include "mozilla/net/WyciwygChannelParent.h" +#include "nsWyciwygChannel.h" +#include "nsNetUtil.h" +#include "nsCharsetSource.h" +#include "nsISerializable.h" +#include "nsSerializationHelper.h" +#include "mozilla/ipc/URIUtils.h" +#include "mozilla/net/NeckoParent.h" +#include "SerializedLoadContext.h" +#include "nsIContentPolicy.h" +#include "mozilla/ipc/BackgroundUtils.h" + +using namespace mozilla::ipc; + +namespace mozilla { +namespace net { + +WyciwygChannelParent::WyciwygChannelParent() + : mIPCClosed(false) + , mReceivedAppData(false) +{ +} + +WyciwygChannelParent::~WyciwygChannelParent() +{ +} + +void +WyciwygChannelParent::ActorDestroy(ActorDestroyReason why) +{ + // We may still have refcount>0 if the channel hasn't called OnStopRequest + // yet, but we must not send any more msgs to child. + mIPCClosed = true; + + // We need to force the cycle to break here + if (mChannel) { + mChannel->SetNotificationCallbacks(nullptr); + } +} + +//----------------------------------------------------------------------------- +// WyciwygChannelParent::nsISupports +//----------------------------------------------------------------------------- + +NS_IMPL_ISUPPORTS(WyciwygChannelParent, + nsIStreamListener, + nsIInterfaceRequestor, + nsIRequestObserver) + +//----------------------------------------------------------------------------- +// WyciwygChannelParent::PWyciwygChannelParent +//----------------------------------------------------------------------------- + +bool +WyciwygChannelParent::RecvInit(const URIParams& aURI, + const ipc::PrincipalInfo& aRequestingPrincipalInfo, + const ipc::PrincipalInfo& aTriggeringPrincipalInfo, + const ipc::PrincipalInfo& aPrincipalToInheritInfo, + const uint32_t& aSecurityFlags, + const uint32_t& aContentPolicyType) +{ + nsresult rv; + + nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); + if (!uri) + return false; + + LOG(("WyciwygChannelParent RecvInit [this=%p uri=%s]\n", + this, uri->GetSpecOrDefault().get())); + + nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv)); + if (NS_FAILED(rv)) + return SendCancelEarly(rv); + + nsCOMPtr<nsIPrincipal> requestingPrincipal = + mozilla::ipc::PrincipalInfoToPrincipal(aRequestingPrincipalInfo, &rv); + if (NS_FAILED(rv)) { + return SendCancelEarly(rv); + } + + nsCOMPtr<nsIPrincipal> triggeringPrincipal = + mozilla::ipc::PrincipalInfoToPrincipal(aTriggeringPrincipalInfo, &rv); + if (NS_FAILED(rv)) { + return SendCancelEarly(rv); + } + + nsCOMPtr<nsIPrincipal> principalToInherit = + mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalToInheritInfo, &rv); + if (NS_FAILED(rv)) { + return SendCancelEarly(rv); + } + + nsCOMPtr<nsIChannel> chan; + rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(chan), + uri, + requestingPrincipal, + triggeringPrincipal, + aSecurityFlags, + aContentPolicyType, + nullptr, // loadGroup + nullptr, // aCallbacks + nsIRequest::LOAD_NORMAL, + ios); + + if (NS_FAILED(rv)) + return SendCancelEarly(rv); + + nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo(); + rv = loadInfo->SetPrincipalToInherit(principalToInherit); + if (NS_FAILED(rv)) { + return SendCancelEarly(rv); + } + + mChannel = do_QueryInterface(chan, &rv); + if (NS_FAILED(rv)) + return SendCancelEarly(rv); + + return true; +} + +bool +WyciwygChannelParent::RecvAppData(const IPC::SerializedLoadContext& loadContext, + const PBrowserOrId &parent) +{ + LOG(("WyciwygChannelParent RecvAppData [this=%p]\n", this)); + + if (!SetupAppData(loadContext, parent)) + return false; + + mChannel->SetNotificationCallbacks(this); + return true; +} + +bool +WyciwygChannelParent::SetupAppData(const IPC::SerializedLoadContext& loadContext, + const PBrowserOrId &aParent) +{ + if (!mChannel) + return true; + + const char* error = NeckoParent::CreateChannelLoadContext(aParent, + Manager()->Manager(), + loadContext, + nullptr, + mLoadContext); + if (error) { + printf_stderr("WyciwygChannelParent::SetupAppData: FATAL ERROR: %s\n", + error); + return false; + } + + if (!mLoadContext && loadContext.IsPrivateBitValid()) { + nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(mChannel); + if (pbChannel) + pbChannel->SetPrivate(loadContext.mOriginAttributes.mPrivateBrowsingId > 0); + } + + mReceivedAppData = true; + return true; +} + +bool +WyciwygChannelParent::RecvAsyncOpen(const URIParams& aOriginal, + const uint32_t& aLoadFlags, + const IPC::SerializedLoadContext& loadContext, + const PBrowserOrId &aParent) +{ + nsCOMPtr<nsIURI> original = DeserializeURI(aOriginal); + if (!original) + return false; + + LOG(("WyciwygChannelParent RecvAsyncOpen [this=%p]\n", this)); + + if (!mChannel) + return true; + + nsresult rv; + + rv = mChannel->SetOriginalURI(original); + if (NS_FAILED(rv)) + return SendCancelEarly(rv); + + rv = mChannel->SetLoadFlags(aLoadFlags); + if (NS_FAILED(rv)) + return SendCancelEarly(rv); + + if (!mReceivedAppData && !SetupAppData(loadContext, aParent)) { + return false; + } + + rv = mChannel->SetNotificationCallbacks(this); + if (NS_FAILED(rv)) + return SendCancelEarly(rv); + + nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo(); + if (loadInfo && loadInfo->GetEnforceSecurity()) { + rv = mChannel->AsyncOpen2(this); + } + else { + rv = mChannel->AsyncOpen(this, nullptr); + } + + if (NS_FAILED(rv)) + return SendCancelEarly(rv); + + return true; +} + +bool +WyciwygChannelParent::RecvWriteToCacheEntry(const nsString& data) +{ + if (!mReceivedAppData) { + printf_stderr("WyciwygChannelParent::RecvWriteToCacheEntry: FATAL ERROR: didn't receive app data\n"); + return false; + } + + if (mChannel) + mChannel->WriteToCacheEntry(data); + + return true; +} + +bool +WyciwygChannelParent::RecvCloseCacheEntry(const nsresult& reason) +{ + if (mChannel) { + mChannel->CloseCacheEntry(reason); + } + + return true; +} + +bool +WyciwygChannelParent::RecvSetCharsetAndSource(const int32_t& aCharsetSource, + const nsCString& aCharset) +{ + if (mChannel) + mChannel->SetCharsetAndSource(aCharsetSource, aCharset); + + return true; +} + +bool +WyciwygChannelParent::RecvSetSecurityInfo(const nsCString& aSecurityInfo) +{ + if (mChannel) { + nsCOMPtr<nsISupports> securityInfo; + NS_DeserializeObject(aSecurityInfo, getter_AddRefs(securityInfo)); + mChannel->SetSecurityInfo(securityInfo); + } + + return true; +} + +bool +WyciwygChannelParent::RecvCancel(const nsresult& aStatusCode) +{ + if (mChannel) + mChannel->Cancel(aStatusCode); + return true; +} + +//----------------------------------------------------------------------------- +// WyciwygChannelParent::nsIRequestObserver +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +WyciwygChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) +{ + LOG(("WyciwygChannelParent::OnStartRequest [this=%p]\n", this)); + + nsresult rv; + + nsCOMPtr<nsIWyciwygChannel> chan = do_QueryInterface(aRequest, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsresult status; + chan->GetStatus(&status); + + int64_t contentLength = -1; + chan->GetContentLength(&contentLength); + + int32_t charsetSource = kCharsetUninitialized; + nsAutoCString charset; + chan->GetCharsetAndSource(&charsetSource, charset); + + nsCOMPtr<nsISupports> securityInfo; + chan->GetSecurityInfo(getter_AddRefs(securityInfo)); + nsCString secInfoStr; + if (securityInfo) { + nsCOMPtr<nsISerializable> serializable = do_QueryInterface(securityInfo); + if (serializable) + NS_SerializeToString(serializable, secInfoStr); + else { + NS_ERROR("Can't serialize security info"); + return NS_ERROR_UNEXPECTED; + } + } + + if (mIPCClosed || + !SendOnStartRequest(status, contentLength, charsetSource, charset, secInfoStr)) { + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; +} + +NS_IMETHODIMP +WyciwygChannelParent::OnStopRequest(nsIRequest *aRequest, + nsISupports *aContext, + nsresult aStatusCode) +{ + LOG(("WyciwygChannelParent::OnStopRequest: [this=%p status=%ul]\n", + this, aStatusCode)); + + if (mIPCClosed || !SendOnStopRequest(aStatusCode)) { + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; +} + +//----------------------------------------------------------------------------- +// WyciwygChannelParent::nsIStreamListener +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +WyciwygChannelParent::OnDataAvailable(nsIRequest *aRequest, + nsISupports *aContext, + nsIInputStream *aInputStream, + uint64_t aOffset, + uint32_t aCount) +{ + LOG(("WyciwygChannelParent::OnDataAvailable [this=%p]\n", this)); + + nsCString data; + nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount); + if (NS_FAILED(rv)) + return rv; + + if (mIPCClosed || !SendOnDataAvailable(data, aOffset)) { + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; +} + +//----------------------------------------------------------------------------- +// WyciwygChannelParent::nsIInterfaceRequestor +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +WyciwygChannelParent::GetInterface(const nsIID& uuid, void** result) +{ + // Only support nsILoadContext if child channel's callbacks did too + if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) { + nsCOMPtr<nsILoadContext> copy = mLoadContext; + copy.forget(result); + return NS_OK; + } + + return QueryInterface(uuid, result); +} + + +} // namespace net +} // namespace mozilla |