1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "RemoteStreamGetter.h"
8 #include "mozilla/MozPromise.h"
9 #include "mozilla/net/NeckoChild.h"
10 #include "mozilla/RefPtr.h"
11 #include "mozilla/ResultExtensions.h"
12 #include "nsContentUtils.h"
13 #include "nsIInputStreamPump.h"
18 NS_IMPL_ISUPPORTS(RemoteStreamGetter
, nsICancelable
)
20 RemoteStreamGetter::RemoteStreamGetter(nsIURI
* aURI
, nsILoadInfo
* aLoadInfo
)
21 : mURI(aURI
), mLoadInfo(aLoadInfo
) {
23 MOZ_ASSERT(aLoadInfo
);
26 // Request an input stream from the parent.
27 RequestOrReason
RemoteStreamGetter::GetAsync(nsIStreamListener
* aListener
,
30 MOZ_ASSERT(IsNeckoChild());
33 mListener
= aListener
;
36 nsCOMPtr
<nsICancelable
> cancelableRequest(this);
38 RefPtr
<RemoteStreamGetter
> self
= this;
39 LoadInfoArgs loadInfoArgs
;
40 nsresult rv
= ipc::LoadInfoToLoadInfoArgs(mLoadInfo
, &loadInfoArgs
);
45 (gNeckoChild
->*aMethod
)(mURI
, loadInfoArgs
)
47 GetMainThreadSerialEventTarget(), __func__
,
48 [self
](const Maybe
<RemoteStreamInfo
>& info
) { self
->OnStream(info
); },
49 [self
](const mozilla::ipc::ResponseRejectReason
) {
50 self
->OnStream(Nothing());
52 return RequestOrCancelable(WrapNotNull(cancelableRequest
));
55 // Called to cancel the ongoing async request.
57 RemoteStreamGetter::Cancel(nsresult aStatus
) {
66 mPump
->Cancel(aStatus
);
74 void RemoteStreamGetter::CancelRequest(nsIStreamListener
* aListener
,
75 nsIChannel
* aChannel
, nsresult aResult
) {
76 MOZ_ASSERT(aListener
);
79 aListener
->OnStartRequest(aChannel
);
80 aListener
->OnStopRequest(aChannel
, aResult
);
81 aChannel
->CancelWithReason(NS_BINDING_ABORTED
,
82 "RemoteStreamGetter::CancelRequest"_ns
);
85 // Handle an input stream sent from the parent.
86 void RemoteStreamGetter::OnStream(const Maybe
<RemoteStreamInfo
>& aStreamInfo
) {
87 MOZ_ASSERT(IsNeckoChild());
89 MOZ_ASSERT(mListener
);
91 nsCOMPtr
<nsIChannel
> channel
= std::move(mChannel
);
93 // We must keep an owning reference to the listener until we pass it on
95 nsCOMPtr
<nsIStreamListener
> listener
= mListener
.forget();
97 if (aStreamInfo
.isNothing()) {
98 // The parent didn't send us back a stream.
99 CancelRequest(listener
, channel
, NS_ERROR_FILE_ACCESS_DENIED
);
104 // The channel that has created this stream getter has been canceled.
105 CancelRequest(listener
, channel
, mStatus
);
109 nsCOMPtr
<nsIInputStream
> stream
= std::move(aStreamInfo
.ref().inputStream());
111 // We somehow failed to get a stream, so just cancel the request.
112 CancelRequest(listener
, channel
, mStatus
);
116 nsCOMPtr
<nsIInputStreamPump
> pump
;
118 NS_NewInputStreamPump(getter_AddRefs(pump
), stream
.forget(), 0, 0, false,
119 GetMainThreadSerialEventTarget());
121 CancelRequest(listener
, channel
, rv
);
125 channel
->SetContentType(aStreamInfo
.ref().contentType());
126 channel
->SetContentLength(aStreamInfo
.ref().contentLength());
128 rv
= pump
->AsyncRead(listener
);
130 CancelRequest(listener
, channel
, rv
);
138 } // namespace mozilla