|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set sw=2 ts=8 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 "RtspChannelChild.h" |
|
8 #include "mozilla/ipc/URIUtils.h" |
|
9 |
|
10 using namespace mozilla::ipc; |
|
11 |
|
12 namespace mozilla { |
|
13 namespace net { |
|
14 |
|
15 //----------------------------------------------------------------------------- |
|
16 // RtspChannelChild |
|
17 //----------------------------------------------------------------------------- |
|
18 RtspChannelChild::RtspChannelChild(nsIURI *aUri) |
|
19 : mIPCOpen(false) |
|
20 , mCanceled(false) |
|
21 { |
|
22 nsBaseChannel::SetURI(aUri); |
|
23 } |
|
24 |
|
25 RtspChannelChild::~RtspChannelChild() |
|
26 { |
|
27 } |
|
28 |
|
29 nsIStreamingProtocolController* |
|
30 RtspChannelChild::GetController() |
|
31 { |
|
32 return mMediaStreamController; |
|
33 } |
|
34 |
|
35 void |
|
36 RtspChannelChild::ReleaseController() |
|
37 { |
|
38 if (mMediaStreamController) { |
|
39 mMediaStreamController = nullptr; |
|
40 } |
|
41 } |
|
42 |
|
43 //----------------------------------------------------------------------------- |
|
44 // IPDL |
|
45 //----------------------------------------------------------------------------- |
|
46 void |
|
47 RtspChannelChild::AddIPDLReference() |
|
48 { |
|
49 NS_ABORT_IF_FALSE(!mIPCOpen, |
|
50 "Attempt to retain more than one IPDL reference"); |
|
51 mIPCOpen = true; |
|
52 AddRef(); |
|
53 } |
|
54 |
|
55 void |
|
56 RtspChannelChild::ReleaseIPDLReference() |
|
57 { |
|
58 NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference"); |
|
59 mIPCOpen = false; |
|
60 Release(); |
|
61 } |
|
62 |
|
63 //----------------------------------------------------------------------------- |
|
64 // nsISupports |
|
65 //----------------------------------------------------------------------------- |
|
66 NS_IMPL_ISUPPORTS_INHERITED(RtspChannelChild, |
|
67 nsBaseChannel, |
|
68 nsIChannel, |
|
69 nsIChildChannel) |
|
70 |
|
71 //----------------------------------------------------------------------------- |
|
72 // nsBaseChannel::nsIChannel |
|
73 //----------------------------------------------------------------------------- |
|
74 NS_IMETHODIMP |
|
75 RtspChannelChild::GetContentType(nsACString& aContentType) |
|
76 { |
|
77 aContentType.AssignLiteral("RTSP"); |
|
78 return NS_OK; |
|
79 } |
|
80 |
|
81 class CallListenerOnStartRequestEvent : public nsRunnable |
|
82 { |
|
83 public: |
|
84 CallListenerOnStartRequestEvent(nsIStreamListener *aListener, |
|
85 nsIRequest *aRequest, nsISupports *aContext) |
|
86 : mListener(aListener) |
|
87 , mRequest(aRequest) |
|
88 , mContext(aContext) |
|
89 { |
|
90 MOZ_RELEASE_ASSERT(aListener); |
|
91 } |
|
92 NS_IMETHOD Run() |
|
93 { |
|
94 MOZ_ASSERT(NS_IsMainThread()); |
|
95 mListener->OnStartRequest(mRequest, mContext); |
|
96 return NS_OK; |
|
97 } |
|
98 private: |
|
99 nsRefPtr<nsIStreamListener> mListener; |
|
100 nsRefPtr<nsIRequest> mRequest; |
|
101 nsRefPtr<nsISupports> mContext; |
|
102 }; |
|
103 |
|
104 NS_IMETHODIMP |
|
105 RtspChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) |
|
106 { |
|
107 // Precondition checks. |
|
108 MOZ_ASSERT(aListener); |
|
109 nsCOMPtr<nsIURI> uri = nsBaseChannel::URI(); |
|
110 NS_ENSURE_TRUE(uri, NS_ERROR_ILLEGAL_VALUE); |
|
111 |
|
112 // Create RtspController. |
|
113 nsCOMPtr<nsIStreamingProtocolControllerService> mediaControllerService = |
|
114 do_GetService(MEDIASTREAMCONTROLLERSERVICE_CONTRACTID); |
|
115 MOZ_RELEASE_ASSERT(mediaControllerService, |
|
116 "Cannot proceed if media controller service is unavailable!"); |
|
117 mediaControllerService->Create(this, getter_AddRefs(mMediaStreamController)); |
|
118 MOZ_ASSERT(mMediaStreamController); |
|
119 |
|
120 // Add ourselves to the load group. |
|
121 if (mLoadGroup) { |
|
122 mLoadGroup->AddRequest(this, nullptr); |
|
123 } |
|
124 |
|
125 // Dispatch mListener's OnStartRequest directly. mListener is expected to |
|
126 // create an RtspMediaResource and use the RtspController we just created to |
|
127 // manage the control and data streams to and from the network. |
|
128 mListener = aListener; |
|
129 mListenerContext = aContext; |
|
130 NS_DispatchToMainThread( |
|
131 new CallListenerOnStartRequestEvent(mListener, this, mListenerContext)); |
|
132 |
|
133 return NS_OK; |
|
134 } |
|
135 |
|
136 //----------------------------------------------------------------------------- |
|
137 // nsBaseChannel::nsIStreamListener::nsIRequestObserver |
|
138 //----------------------------------------------------------------------------- |
|
139 NS_IMETHODIMP |
|
140 RtspChannelChild::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) |
|
141 { |
|
142 MOZ_CRASH("Should never be called"); |
|
143 } |
|
144 |
|
145 NS_IMETHODIMP |
|
146 RtspChannelChild::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, |
|
147 nsresult aStatusCode) |
|
148 { |
|
149 MOZ_CRASH("Should never be called"); |
|
150 } |
|
151 |
|
152 //----------------------------------------------------------------------------- |
|
153 // nsBaseChannel::nsIStreamListener |
|
154 //----------------------------------------------------------------------------- |
|
155 NS_IMETHODIMP |
|
156 RtspChannelChild::OnDataAvailable(nsIRequest *aRequest, |
|
157 nsISupports *aContext, |
|
158 nsIInputStream *aInputStream, |
|
159 uint64_t aOffset, |
|
160 uint32_t aCount) |
|
161 { |
|
162 MOZ_CRASH("Should never be called"); |
|
163 } |
|
164 |
|
165 //----------------------------------------------------------------------------- |
|
166 // nsBaseChannel::nsIChannel::nsIRequest |
|
167 //----------------------------------------------------------------------------- |
|
168 class CallListenerOnStopRequestEvent : public nsRunnable |
|
169 { |
|
170 public: |
|
171 CallListenerOnStopRequestEvent(nsIStreamListener *aListener, |
|
172 nsIRequest *aRequest, |
|
173 nsISupports *aContext, nsresult aStatus) |
|
174 : mListener(aListener) |
|
175 , mRequest(aRequest) |
|
176 , mContext(aContext) |
|
177 , mStatus(aStatus) |
|
178 { |
|
179 MOZ_RELEASE_ASSERT(aListener); |
|
180 } |
|
181 NS_IMETHOD Run() |
|
182 { |
|
183 MOZ_ASSERT(NS_IsMainThread()); |
|
184 mListener->OnStopRequest(mRequest, mContext, mStatus); |
|
185 return NS_OK; |
|
186 } |
|
187 private: |
|
188 nsRefPtr<nsIStreamListener> mListener; |
|
189 nsRefPtr<nsIRequest> mRequest; |
|
190 nsRefPtr<nsISupports> mContext; |
|
191 nsresult mStatus; |
|
192 }; |
|
193 |
|
194 NS_IMETHODIMP |
|
195 RtspChannelChild::Cancel(nsresult status) |
|
196 { |
|
197 if (mCanceled) { |
|
198 return NS_OK; |
|
199 } |
|
200 |
|
201 mCanceled = true; |
|
202 // Stop RtspController. |
|
203 if (mMediaStreamController) { |
|
204 mMediaStreamController->Stop(); |
|
205 } |
|
206 |
|
207 // Call mListener's OnStopRequest to do clean up. |
|
208 NS_DispatchToMainThread( |
|
209 new CallListenerOnStopRequestEvent(mListener, this, |
|
210 mListenerContext, status)); |
|
211 mListener = nullptr; |
|
212 mListenerContext = nullptr; |
|
213 |
|
214 // Remove ourselves from the load group. |
|
215 if (mLoadGroup) { |
|
216 mLoadGroup->RemoveRequest(this, nullptr, status); |
|
217 } |
|
218 |
|
219 return NS_OK; |
|
220 } |
|
221 |
|
222 NS_IMETHODIMP |
|
223 RtspChannelChild::Suspend() |
|
224 { |
|
225 MOZ_CRASH("Should never be called"); |
|
226 } |
|
227 |
|
228 NS_IMETHODIMP |
|
229 RtspChannelChild::Resume() |
|
230 { |
|
231 MOZ_CRASH("Should never be called"); |
|
232 } |
|
233 |
|
234 //----------------------------------------------------------------------------- |
|
235 // nsBaseChannel |
|
236 //----------------------------------------------------------------------------- |
|
237 NS_IMETHODIMP |
|
238 RtspChannelChild::OpenContentStream(bool aAsync, |
|
239 nsIInputStream **aStream, |
|
240 nsIChannel **aChannel) |
|
241 { |
|
242 MOZ_CRASH("Should never be called"); |
|
243 } |
|
244 |
|
245 //----------------------------------------------------------------------------- |
|
246 // nsIChildChannel |
|
247 //----------------------------------------------------------------------------- |
|
248 NS_IMETHODIMP |
|
249 RtspChannelChild::ConnectParent(uint32_t id) |
|
250 { |
|
251 // Create RtspChannelParent for redirection. |
|
252 AddIPDLReference(); |
|
253 RtspChannelConnectArgs connectArgs; |
|
254 SerializeURI(nsBaseChannel::URI(), connectArgs.uri()); |
|
255 connectArgs.channelId() = id; |
|
256 if (!gNeckoChild->SendPRtspChannelConstructor(this, connectArgs)) { |
|
257 return NS_ERROR_FAILURE; |
|
258 } |
|
259 |
|
260 return NS_OK; |
|
261 } |
|
262 |
|
263 NS_IMETHODIMP |
|
264 RtspChannelChild::CompleteRedirectSetup(nsIStreamListener *aListener, |
|
265 nsISupports *aContext) |
|
266 { |
|
267 return AsyncOpen(aListener, aContext); |
|
268 } |
|
269 |
|
270 } // namespace net |
|
271 } // namespace mozilla |