1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=4 sw=2 sts=2 et tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "GIOChannelParent.h"
8 #include "nsGIOProtocolHandler.h"
9 #include "mozilla/Assertions.h"
10 #include "mozilla/dom/ContentParent.h"
11 #include "mozilla/dom/BrowserParent.h"
12 #include "mozilla/net/NeckoParent.h"
13 #include "nsNetUtil.h"
14 #include "nsIChannel.h"
15 #include "mozilla/net/NeckoChannelParams.h"
16 #include "nsIAuthPrompt.h"
17 #include "nsIAuthPromptProvider.h"
18 #include "nsISecureBrowserUI.h"
19 #include "nsQueryObject.h"
20 #include "mozilla/Logging.h"
21
22 using namespace mozilla::dom;
23 using namespace mozilla::ipc;
24
25 namespace mozilla {
26 #undef LOG
27 #define LOG(args) MOZ_LOG(gGIOLog, mozilla::LogLevel::Debug, args)
28 namespace net {
29
GIOChannelParent(dom::BrowserParent * aIframeEmbedding,nsILoadContext * aLoadContext,PBOverrideStatus aOverrideStatus)30 GIOChannelParent::GIOChannelParent(dom::BrowserParent* aIframeEmbedding,
31 nsILoadContext* aLoadContext,
32 PBOverrideStatus aOverrideStatus)
33 : mLoadContext(aLoadContext),
34 mPBOverride(aOverrideStatus),
35 mBrowserParent(aIframeEmbedding) {
36 mEventQ = new ChannelEventQueue(static_cast<nsIParentChannel*>(this));
37 }
38
ActorDestroy(ActorDestroyReason why)39 void GIOChannelParent::ActorDestroy(ActorDestroyReason why) {
40 // We may still have refcount>0 if the channel hasn't called OnStopRequest
41 // yet, but we must not send any more msgs to child.
42 mIPCClosed = true;
43 }
44
45 //-----------------------------------------------------------------------------
46 // GIOChannelParent::nsISupports
47 //-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(GIOChannelParent,nsIStreamListener,nsIParentChannel,nsIInterfaceRequestor,nsIRequestObserver)48 NS_IMPL_ISUPPORTS(GIOChannelParent, nsIStreamListener, nsIParentChannel,
49 nsIInterfaceRequestor, nsIRequestObserver)
50
51 //-----------------------------------------------------------------------------
52 // GIOChannelParent methods
53 //-----------------------------------------------------------------------------
54
55 bool GIOChannelParent::Init(const GIOChannelCreationArgs& aOpenArgs) {
56 switch (aOpenArgs.type()) {
57 case GIOChannelCreationArgs::TGIOChannelOpenArgs: {
58 const GIOChannelOpenArgs& a = aOpenArgs.get_GIOChannelOpenArgs();
59 return DoAsyncOpen(a.uri(), a.startPos(), a.entityID(), a.uploadStream(),
60 a.loadInfo(), a.loadFlags());
61 }
62 case GIOChannelCreationArgs::TGIOChannelConnectArgs: {
63 const GIOChannelConnectArgs& cArgs =
64 aOpenArgs.get_GIOChannelConnectArgs();
65 return ConnectChannel(cArgs.channelId());
66 }
67 default:
68 MOZ_ASSERT_UNREACHABLE("unknown open type");
69 return false;
70 }
71 }
72
DoAsyncOpen(const URIParams & aURI,const uint64_t & aStartPos,const nsCString & aEntityID,const Maybe<IPCStream> & aUploadStream,const Maybe<LoadInfoArgs> & aLoadInfoArgs,const uint32_t & aLoadFlags)73 bool GIOChannelParent::DoAsyncOpen(const URIParams& aURI,
74 const uint64_t& aStartPos,
75 const nsCString& aEntityID,
76 const Maybe<IPCStream>& aUploadStream,
77 const Maybe<LoadInfoArgs>& aLoadInfoArgs,
78 const uint32_t& aLoadFlags) {
79 nsresult rv;
80
81 nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
82 if (!uri) {
83 return false;
84 }
85
86 #ifdef DEBUG
87 LOG(("GIOChannelParent DoAsyncOpen [this=%p uri=%s]\n", this,
88 uri->GetSpecOrDefault().get()));
89 #endif
90
91 nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
92 if (NS_FAILED(rv)) {
93 return SendFailedAsyncOpen(rv);
94 }
95
96 nsCOMPtr<nsILoadInfo> loadInfo;
97 rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfoArgs,
98 getter_AddRefs(loadInfo));
99 if (NS_FAILED(rv)) {
100 return SendFailedAsyncOpen(rv);
101 }
102
103 OriginAttributes attrs;
104 rv = loadInfo->GetOriginAttributes(&attrs);
105 if (NS_FAILED(rv)) {
106 return SendFailedAsyncOpen(rv);
107 }
108
109 nsCOMPtr<nsIChannel> chan;
110 rv = NS_NewChannelInternal(getter_AddRefs(chan), uri, loadInfo, nullptr,
111 nullptr, nullptr, aLoadFlags, ios);
112
113 if (NS_FAILED(rv)) {
114 return SendFailedAsyncOpen(rv);
115 }
116
117 mChannel = chan;
118
119 nsIChannel* gioChan = static_cast<nsIChannel*>(mChannel.get());
120
121 rv = gioChan->AsyncOpen(this);
122 if (NS_FAILED(rv)) {
123 return SendFailedAsyncOpen(rv);
124 }
125
126 return true;
127 }
128
ConnectChannel(const uint64_t & channelId)129 bool GIOChannelParent::ConnectChannel(const uint64_t& channelId) {
130 nsresult rv;
131
132 LOG(("Looking for a registered channel [this=%p, id=%" PRIx64 "]", this,
133 channelId));
134
135 nsCOMPtr<nsIChannel> channel;
136 rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel));
137 if (NS_SUCCEEDED(rv)) {
138 mChannel = channel;
139 }
140
141 LOG((" found channel %p, rv=%08" PRIx32, mChannel.get(),
142 static_cast<uint32_t>(rv)));
143
144 return true;
145 }
146
RecvCancel(const nsresult & status)147 mozilla::ipc::IPCResult GIOChannelParent::RecvCancel(const nsresult& status) {
148 if (mChannel) {
149 mChannel->Cancel(status);
150 }
151
152 return IPC_OK();
153 }
154
RecvSuspend()155 mozilla::ipc::IPCResult GIOChannelParent::RecvSuspend() {
156 if (mChannel) {
157 mChannel->Suspend();
158 }
159 return IPC_OK();
160 }
161
RecvResume()162 mozilla::ipc::IPCResult GIOChannelParent::RecvResume() {
163 if (mChannel) {
164 mChannel->Resume();
165 }
166 return IPC_OK();
167 }
168
169 //-----------------------------------------------------------------------------
170 // GIOChannelParent::nsIRequestObserver
171 //-----------------------------------------------------------------------------
172
173 NS_IMETHODIMP
OnStartRequest(nsIRequest * aRequest)174 GIOChannelParent::OnStartRequest(nsIRequest* aRequest) {
175 LOG(("GIOChannelParent::OnStartRequest [this=%p]\n", this));
176 nsCOMPtr<nsIChannel> chan = do_QueryInterface(aRequest);
177 MOZ_ASSERT(chan);
178 NS_ENSURE_TRUE(chan, NS_ERROR_UNEXPECTED);
179
180 int64_t contentLength;
181 chan->GetContentLength(&contentLength);
182 nsCString contentType;
183 chan->GetContentType(contentType);
184 nsresult channelStatus = NS_OK;
185 chan->GetStatus(&channelStatus);
186
187 nsCString entityID;
188 URIParams uriparam;
189 nsCOMPtr<nsIURI> uri;
190 chan->GetURI(getter_AddRefs(uri));
191 SerializeURI(uri, uriparam);
192
193 if (mIPCClosed || !SendOnStartRequest(channelStatus, contentLength,
194 contentType, entityID, uriparam)) {
195 return NS_ERROR_UNEXPECTED;
196 }
197
198 return NS_OK;
199 }
200
201 NS_IMETHODIMP
OnStopRequest(nsIRequest * aRequest,nsresult aStatusCode)202 GIOChannelParent::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
203 LOG(("GIOChannelParent::OnStopRequest: [this=%p status=%" PRIu32 "]\n", this,
204 static_cast<uint32_t>(aStatusCode)));
205
206 if (mIPCClosed || !SendOnStopRequest(aStatusCode)) {
207 return NS_ERROR_UNEXPECTED;
208 }
209
210 return NS_OK;
211 }
212
213 //-----------------------------------------------------------------------------
214 // GIOChannelParent::nsIStreamListener
215 //-----------------------------------------------------------------------------
216
217 NS_IMETHODIMP
OnDataAvailable(nsIRequest * aRequest,nsIInputStream * aInputStream,uint64_t aOffset,uint32_t aCount)218 GIOChannelParent::OnDataAvailable(nsIRequest* aRequest,
219 nsIInputStream* aInputStream,
220 uint64_t aOffset, uint32_t aCount) {
221 LOG(("GIOChannelParent::OnDataAvailable [this=%p]\n", this));
222
223 nsCString data;
224 nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
225 if (NS_FAILED(rv)) {
226 return rv;
227 }
228
229 nsresult channelStatus = NS_OK;
230 mChannel->GetStatus(&channelStatus);
231
232 if (mIPCClosed ||
233 !SendOnDataAvailable(channelStatus, data, aOffset, aCount)) {
234 return NS_ERROR_UNEXPECTED;
235 }
236 return NS_OK;
237 }
238
239 //-----------------------------------------------------------------------------
240 // GIOChannelParent::nsIParentChannel
241 //-----------------------------------------------------------------------------
242
243 NS_IMETHODIMP
SetParentListener(ParentChannelListener * aListener)244 GIOChannelParent::SetParentListener(ParentChannelListener* aListener) {
245 // Do not need ptr to ParentChannelListener.
246 return NS_OK;
247 }
248
249 NS_IMETHODIMP
NotifyClassificationFlags(uint32_t aClassificationFlags,bool aIsThirdParty)250 GIOChannelParent::NotifyClassificationFlags(uint32_t aClassificationFlags,
251 bool aIsThirdParty) {
252 // Nothing to do.
253 return NS_OK;
254 }
255
256 NS_IMETHODIMP
NotifyFlashPluginStateChanged(nsIHttpChannel::FlashPluginState aState)257 GIOChannelParent::NotifyFlashPluginStateChanged(
258 nsIHttpChannel::FlashPluginState aState) {
259 // Nothing to do.
260 return NS_OK;
261 }
262
263 NS_IMETHODIMP
SetClassifierMatchedInfo(const nsACString & aList,const nsACString & aProvider,const nsACString & aFullHash)264 GIOChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
265 const nsACString& aProvider,
266 const nsACString& aFullHash) {
267 // nothing to do
268 return NS_OK;
269 }
270
271 NS_IMETHODIMP
SetClassifierMatchedTrackingInfo(const nsACString & aLists,const nsACString & aFullHashes)272 GIOChannelParent::SetClassifierMatchedTrackingInfo(
273 const nsACString& aLists, const nsACString& aFullHashes) {
274 // nothing to do
275 return NS_OK;
276 }
277
278 NS_IMETHODIMP
Delete()279 GIOChannelParent::Delete() {
280 if (mIPCClosed || !SendDeleteSelf()) {
281 return NS_ERROR_UNEXPECTED;
282 }
283
284 return NS_OK;
285 }
286
287 NS_IMETHODIMP
GetRemoteType(nsACString & aRemoteType)288 GIOChannelParent::GetRemoteType(nsACString& aRemoteType) {
289 if (!CanSend()) {
290 return NS_ERROR_UNEXPECTED;
291 }
292
293 dom::PContentParent* pcp = Manager()->Manager();
294 aRemoteType = static_cast<dom::ContentParent*>(pcp)->GetRemoteType();
295 return NS_OK;
296 }
297
298 //-----------------------------------------------------------------------------
299 // GIOChannelParent::nsIInterfaceRequestor
300 //-----------------------------------------------------------------------------
301
302 NS_IMETHODIMP
GetInterface(const nsIID & uuid,void ** result)303 GIOChannelParent::GetInterface(const nsIID& uuid, void** result) {
304 if (uuid.Equals(NS_GET_IID(nsIAuthPromptProvider)) ||
305 uuid.Equals(NS_GET_IID(nsISecureBrowserUI))) {
306 if (mBrowserParent) {
307 return mBrowserParent->QueryInterface(uuid, result);
308 }
309 }
310
311 // Only support nsILoadContext if child channel's callbacks did too
312 if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
313 nsCOMPtr<nsILoadContext> copy = mLoadContext;
314 copy.forget(result);
315 return NS_OK;
316 }
317
318 return QueryInterface(uuid, result);
319 }
320
321 //---------------------
322 } // namespace net
323 } // namespace mozilla
324