diff options
Diffstat (limited to 'netwerk/base/nsSecCheckWrapChannel.cpp')
-rw-r--r-- | netwerk/base/nsSecCheckWrapChannel.cpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/netwerk/base/nsSecCheckWrapChannel.cpp b/netwerk/base/nsSecCheckWrapChannel.cpp new file mode 100644 index 000000000..330079a0f --- /dev/null +++ b/netwerk/base/nsSecCheckWrapChannel.cpp @@ -0,0 +1,196 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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 "nsContentSecurityManager.h" +#include "nsSecCheckWrapChannel.h" +#include "nsIForcePendingChannel.h" +#include "nsIStreamListener.h" +#include "mozilla/Logging.h" +#include "nsCOMPtr.h" + +namespace mozilla { +namespace net { + +static LazyLogModule gChannelWrapperLog("ChannelWrapper"); +#define CHANNELWRAPPERLOG(args) MOZ_LOG(gChannelWrapperLog, LogLevel::Debug, args) + +NS_IMPL_ADDREF(nsSecCheckWrapChannelBase) +NS_IMPL_RELEASE(nsSecCheckWrapChannelBase) + +NS_INTERFACE_MAP_BEGIN(nsSecCheckWrapChannelBase) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannel, mHttpChannel) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannelInternal, mHttpChannelInternal) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHttpChannel) + NS_INTERFACE_MAP_ENTRY(nsIRequest) + NS_INTERFACE_MAP_ENTRY(nsIChannel) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIUploadChannel, mUploadChannel) + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIUploadChannel2, mUploadChannel2) + NS_INTERFACE_MAP_ENTRY(nsISecCheckWrapChannel) +NS_INTERFACE_MAP_END + +//--------------------------------------------------------- +// nsSecCheckWrapChannelBase implementation +//--------------------------------------------------------- + +nsSecCheckWrapChannelBase::nsSecCheckWrapChannelBase(nsIChannel* aChannel) + : mChannel(aChannel) + , mHttpChannel(do_QueryInterface(aChannel)) + , mHttpChannelInternal(do_QueryInterface(aChannel)) + , mRequest(do_QueryInterface(aChannel)) + , mUploadChannel(do_QueryInterface(aChannel)) + , mUploadChannel2(do_QueryInterface(aChannel)) +{ + MOZ_ASSERT(mChannel, "can not create a channel wrapper without a channel"); +} + +nsSecCheckWrapChannelBase::~nsSecCheckWrapChannelBase() +{ +} + +//--------------------------------------------------------- +// nsISecCheckWrapChannel implementation +//--------------------------------------------------------- + +NS_IMETHODIMP +nsSecCheckWrapChannelBase::GetInnerChannel(nsIChannel **aInnerChannel) +{ + NS_IF_ADDREF(*aInnerChannel = mChannel); + return NS_OK; +} + +//--------------------------------------------------------- +// nsSecCheckWrapChannel implementation +//--------------------------------------------------------- + +nsSecCheckWrapChannel::nsSecCheckWrapChannel(nsIChannel* aChannel, + nsILoadInfo* aLoadInfo) + : nsSecCheckWrapChannelBase(aChannel) + , mLoadInfo(aLoadInfo) +{ + { + nsCOMPtr<nsIURI> uri; + mChannel->GetURI(getter_AddRefs(uri)); + CHANNELWRAPPERLOG(("nsSecCheckWrapChannel::nsSecCheckWrapChannel [%p] (%s)", + this, uri ? uri->GetSpecOrDefault().get() : "")); + } +} + +// static +already_AddRefed<nsIChannel> +nsSecCheckWrapChannel::MaybeWrap(nsIChannel* aChannel, nsILoadInfo* aLoadInfo) +{ + // Maybe a custom protocol handler actually returns a gecko + // http/ftpChannel - To check this we will check whether the channel + // implements a gecko non-scriptable interface e.g. nsIForcePendingChannel. + nsCOMPtr<nsIForcePendingChannel> isGeckoChannel = do_QueryInterface(aChannel); + + nsCOMPtr<nsIChannel> channel; + if (isGeckoChannel) { + // If it is a gecko channel (ftp or http) we do not need to wrap it. + channel = aChannel; + channel->SetLoadInfo(aLoadInfo); + } else { + channel = new nsSecCheckWrapChannel(aChannel, aLoadInfo); + } + return channel.forget(); +} + +nsSecCheckWrapChannel::~nsSecCheckWrapChannel() +{ +} + +//--------------------------------------------------------- +// SecWrapChannelStreamListener helper +//--------------------------------------------------------- + +class SecWrapChannelStreamListener final : public nsIStreamListener +{ + public: + SecWrapChannelStreamListener(nsIRequest *aRequest, + nsIStreamListener *aStreamListener) + : mRequest(aRequest) + , mListener(aStreamListener) {} + + NS_DECL_ISUPPORTS + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSIREQUESTOBSERVER + + private: + ~SecWrapChannelStreamListener() {} + + nsCOMPtr<nsIRequest> mRequest; + nsCOMPtr<nsIStreamListener> mListener; +}; + +NS_IMPL_ISUPPORTS(SecWrapChannelStreamListener, + nsIStreamListener, + nsIRequestObserver) + +NS_IMETHODIMP +SecWrapChannelStreamListener::OnStartRequest(nsIRequest *aRequest, + nsISupports *aContext) +{ + return mListener->OnStartRequest(mRequest, aContext); +} + +NS_IMETHODIMP +SecWrapChannelStreamListener::OnStopRequest(nsIRequest *aRequest, + nsISupports *aContext, + nsresult aStatus) +{ + return mListener->OnStopRequest(mRequest, aContext, aStatus); +} + +NS_IMETHODIMP +SecWrapChannelStreamListener::OnDataAvailable(nsIRequest *aRequest, + nsISupports *aContext, + nsIInputStream *aInStream, + uint64_t aOffset, + uint32_t aCount) +{ + return mListener->OnDataAvailable(mRequest, aContext, aInStream, aOffset, aCount); +} + +//--------------------------------------------------------- +// nsIChannel implementation +//--------------------------------------------------------- + +NS_IMETHODIMP +nsSecCheckWrapChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) +{ + CHANNELWRAPPERLOG(("nsSecCheckWrapChannel::GetLoadInfo() [%p]",this)); + NS_IF_ADDREF(*aLoadInfo = mLoadInfo); + return NS_OK; +} + +NS_IMETHODIMP +nsSecCheckWrapChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) +{ + CHANNELWRAPPERLOG(("nsSecCheckWrapChannel::SetLoadInfo() [%p]", this)); + mLoadInfo = aLoadInfo; + return NS_OK; +} + +NS_IMETHODIMP +nsSecCheckWrapChannel::AsyncOpen2(nsIStreamListener *aListener) +{ + nsCOMPtr<nsIStreamListener> secWrapChannelListener = + new SecWrapChannelStreamListener(this, aListener); + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, secWrapChannelListener); + NS_ENSURE_SUCCESS(rv, rv); + return AsyncOpen(secWrapChannelListener, nullptr); +} + +NS_IMETHODIMP +nsSecCheckWrapChannel::Open2(nsIInputStream** aStream) +{ + nsCOMPtr<nsIStreamListener> listener; + nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); + NS_ENSURE_SUCCESS(rv, rv); + return Open(aStream); +} + +} // namespace net +} // namespace mozilla |