1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsContentSecurityManager.h"
7 #include "nsSecCheckWrapChannel.h"
8 #include "nsIForcePendingChannel.h"
9 #include "nsIStreamListener.h"
10 #include "mozilla/Logging.h"
16 static LazyLogModule
gChannelWrapperLog("ChannelWrapper");
17 #define CHANNELWRAPPERLOG(args) \
18 MOZ_LOG(gChannelWrapperLog, LogLevel::Debug, args)
20 NS_IMPL_ADDREF(nsSecCheckWrapChannelBase
)
21 NS_IMPL_RELEASE(nsSecCheckWrapChannelBase
)
23 NS_INTERFACE_MAP_BEGIN(nsSecCheckWrapChannelBase
)
24 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannel
, mHttpChannel
)
25 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannelInternal
,
27 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIHttpChannel
)
28 NS_INTERFACE_MAP_ENTRY(nsIRequest
)
29 NS_INTERFACE_MAP_ENTRY(nsIChannel
)
30 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIUploadChannel
, mUploadChannel
)
31 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIUploadChannel2
, mUploadChannel2
)
32 NS_INTERFACE_MAP_ENTRY(nsISecCheckWrapChannel
)
35 //---------------------------------------------------------
36 // nsSecCheckWrapChannelBase implementation
37 //---------------------------------------------------------
39 nsSecCheckWrapChannelBase::nsSecCheckWrapChannelBase(nsIChannel
*aChannel
)
41 mHttpChannel(do_QueryInterface(aChannel
)),
42 mHttpChannelInternal(do_QueryInterface(aChannel
)),
44 mUploadChannel(do_QueryInterface(aChannel
)),
45 mUploadChannel2(do_QueryInterface(aChannel
)) {
46 MOZ_ASSERT(mChannel
, "can not create a channel wrapper without a channel");
49 //---------------------------------------------------------
50 // nsISecCheckWrapChannel implementation
51 //---------------------------------------------------------
54 nsSecCheckWrapChannelBase::GetInnerChannel(nsIChannel
**aInnerChannel
) {
55 NS_IF_ADDREF(*aInnerChannel
= mChannel
);
59 //---------------------------------------------------------
60 // nsSecCheckWrapChannel implementation
61 //---------------------------------------------------------
63 nsSecCheckWrapChannel::nsSecCheckWrapChannel(nsIChannel
*aChannel
,
64 nsILoadInfo
*aLoadInfo
)
65 : nsSecCheckWrapChannelBase(aChannel
), mLoadInfo(aLoadInfo
) {
68 mChannel
->GetURI(getter_AddRefs(uri
));
69 CHANNELWRAPPERLOG(("nsSecCheckWrapChannel::nsSecCheckWrapChannel [%p] (%s)",
70 this, uri
? uri
->GetSpecOrDefault().get() : ""));
75 already_AddRefed
<nsIChannel
> nsSecCheckWrapChannel::MaybeWrap(
76 nsIChannel
*aChannel
, nsILoadInfo
*aLoadInfo
) {
77 // Maybe a custom protocol handler actually returns a gecko
78 // http/ftpChannel - To check this we will check whether the channel
79 // implements a gecko non-scriptable interface e.g. nsIForcePendingChannel.
80 nsCOMPtr
<nsIForcePendingChannel
> isGeckoChannel
= do_QueryInterface(aChannel
);
82 nsCOMPtr
<nsIChannel
> channel
;
84 // If it is a gecko channel (ftp or http) we do not need to wrap it.
86 channel
->SetLoadInfo(aLoadInfo
);
88 channel
= new nsSecCheckWrapChannel(aChannel
, aLoadInfo
);
90 return channel
.forget();
93 //---------------------------------------------------------
94 // SecWrapChannelStreamListener helper
95 //---------------------------------------------------------
97 class SecWrapChannelStreamListener final
: public nsIStreamListener
{
99 SecWrapChannelStreamListener(nsIRequest
*aRequest
,
100 nsIStreamListener
*aStreamListener
)
101 : mRequest(aRequest
), mListener(aStreamListener
) {}
104 NS_DECL_NSISTREAMLISTENER
105 NS_DECL_NSIREQUESTOBSERVER
108 ~SecWrapChannelStreamListener() = default;
110 nsCOMPtr
<nsIRequest
> mRequest
;
111 nsCOMPtr
<nsIStreamListener
> mListener
;
114 NS_IMPL_ISUPPORTS(SecWrapChannelStreamListener
, nsIStreamListener
,
118 SecWrapChannelStreamListener::OnStartRequest(nsIRequest
*aRequest
,
119 nsISupports
*aContext
) {
120 return mListener
->OnStartRequest(mRequest
, aContext
);
124 SecWrapChannelStreamListener::OnStopRequest(nsIRequest
*aRequest
,
125 nsISupports
*aContext
,
127 return mListener
->OnStopRequest(mRequest
, aContext
, aStatus
);
131 SecWrapChannelStreamListener::OnDataAvailable(nsIRequest
*aRequest
,
132 nsISupports
*aContext
,
133 nsIInputStream
*aInStream
,
136 return mListener
->OnDataAvailable(mRequest
, aContext
, aInStream
, aOffset
,
140 //---------------------------------------------------------
141 // nsIChannel implementation
142 //---------------------------------------------------------
145 nsSecCheckWrapChannel::GetLoadInfo(nsILoadInfo
**aLoadInfo
) {
146 CHANNELWRAPPERLOG(("nsSecCheckWrapChannel::GetLoadInfo() [%p]", this));
147 NS_IF_ADDREF(*aLoadInfo
= mLoadInfo
);
152 nsSecCheckWrapChannel::SetLoadInfo(nsILoadInfo
*aLoadInfo
) {
153 CHANNELWRAPPERLOG(("nsSecCheckWrapChannel::SetLoadInfo() [%p]", this));
154 mLoadInfo
= aLoadInfo
;
159 nsSecCheckWrapChannel::AsyncOpen2(nsIStreamListener
*aListener
) {
160 nsCOMPtr
<nsIStreamListener
> secWrapChannelListener
=
161 new SecWrapChannelStreamListener(this, aListener
);
162 nsresult rv
= nsContentSecurityManager::doContentSecurityCheck(
163 this, secWrapChannelListener
);
164 NS_ENSURE_SUCCESS(rv
, rv
);
165 return AsyncOpen(secWrapChannelListener
, nullptr);
169 nsSecCheckWrapChannel::Open2(nsIInputStream
**aStream
) {
170 nsCOMPtr
<nsIStreamListener
> listener
;
172 nsContentSecurityManager::doContentSecurityCheck(this, listener
);
173 NS_ENSURE_SUCCESS(rv
, rv
);
174 return Open(aStream
);
178 } // namespace mozilla