|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=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 |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "mozilla/DebugOnly.h" |
|
8 |
|
9 #include "ExternalHelperAppParent.h" |
|
10 #include "nsIContent.h" |
|
11 #include "nsCExternalHandlerService.h" |
|
12 #include "nsIExternalHelperAppService.h" |
|
13 #include "mozilla/dom/ContentParent.h" |
|
14 #include "mozilla/dom/Element.h" |
|
15 #include "mozilla/dom/TabParent.h" |
|
16 #include "nsIBrowserDOMWindow.h" |
|
17 #include "nsStringStream.h" |
|
18 #include "mozilla/ipc/URIUtils.h" |
|
19 #include "nsNetUtil.h" |
|
20 #include "nsIDocument.h" |
|
21 #include "mozilla/net/ChannelDiverterParent.h" |
|
22 |
|
23 #include "mozilla/unused.h" |
|
24 |
|
25 using namespace mozilla::ipc; |
|
26 |
|
27 namespace mozilla { |
|
28 namespace dom { |
|
29 |
|
30 NS_IMPL_ISUPPORTS_INHERITED(ExternalHelperAppParent, |
|
31 nsHashPropertyBag, |
|
32 nsIRequest, |
|
33 nsIChannel, |
|
34 nsIMultiPartChannel, |
|
35 nsIResumableChannel, |
|
36 nsIStreamListener) |
|
37 |
|
38 ExternalHelperAppParent::ExternalHelperAppParent( |
|
39 const OptionalURIParams& uri, |
|
40 const int64_t& aContentLength) |
|
41 : mURI(DeserializeURI(uri)) |
|
42 , mPending(false) |
|
43 , mDiverted(false) |
|
44 , mIPCClosed(false) |
|
45 , mLoadFlags(0) |
|
46 , mStatus(NS_OK) |
|
47 , mContentLength(aContentLength) |
|
48 { |
|
49 } |
|
50 |
|
51 void |
|
52 ExternalHelperAppParent::Init(ContentParent *parent, |
|
53 const nsCString& aMimeContentType, |
|
54 const nsCString& aContentDispositionHeader, |
|
55 const uint32_t& aContentDispositionHint, |
|
56 const nsString& aContentDispositionFilename, |
|
57 const bool& aForceSave, |
|
58 const OptionalURIParams& aReferrer, |
|
59 PBrowserParent* aBrowser) |
|
60 { |
|
61 nsCOMPtr<nsIExternalHelperAppService> helperAppService = |
|
62 do_GetService(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID); |
|
63 NS_ASSERTION(helperAppService, "No Helper App Service!"); |
|
64 |
|
65 nsCOMPtr<nsIURI> referrer = DeserializeURI(aReferrer); |
|
66 if (referrer) |
|
67 SetPropertyAsInterface(NS_LITERAL_STRING("docshell.internalReferrer"), referrer); |
|
68 |
|
69 mContentDispositionHeader = aContentDispositionHeader; |
|
70 if (!mContentDispositionHeader.IsEmpty()) { |
|
71 NS_GetFilenameFromDisposition(mContentDispositionFilename, |
|
72 mContentDispositionHeader, |
|
73 mURI); |
|
74 mContentDisposition = |
|
75 NS_GetContentDispositionFromHeader(mContentDispositionHeader, this); |
|
76 } |
|
77 else { |
|
78 mContentDisposition = aContentDispositionHint; |
|
79 mContentDispositionFilename = aContentDispositionFilename; |
|
80 } |
|
81 |
|
82 nsCOMPtr<nsIInterfaceRequestor> window; |
|
83 if (aBrowser) { |
|
84 TabParent* tabParent = static_cast<TabParent*>(aBrowser); |
|
85 if (tabParent->GetOwnerElement()) |
|
86 window = do_QueryInterface(tabParent->GetOwnerElement()->OwnerDoc()->GetWindow()); |
|
87 } |
|
88 |
|
89 helperAppService->DoContent(aMimeContentType, this, window, |
|
90 aForceSave, getter_AddRefs(mListener)); |
|
91 } |
|
92 |
|
93 void |
|
94 ExternalHelperAppParent::ActorDestroy(ActorDestroyReason why) |
|
95 { |
|
96 mIPCClosed = true; |
|
97 } |
|
98 |
|
99 void |
|
100 ExternalHelperAppParent::Delete() |
|
101 { |
|
102 if (!mIPCClosed) { |
|
103 unused << Send__delete__(this); |
|
104 } |
|
105 } |
|
106 |
|
107 bool |
|
108 ExternalHelperAppParent::RecvOnStartRequest(const nsCString& entityID) |
|
109 { |
|
110 MOZ_ASSERT(!mDiverted, "child forwarding callbacks after request was diverted"); |
|
111 |
|
112 mEntityID = entityID; |
|
113 mPending = true; |
|
114 mStatus = mListener->OnStartRequest(this, nullptr); |
|
115 return true; |
|
116 } |
|
117 |
|
118 bool |
|
119 ExternalHelperAppParent::RecvOnDataAvailable(const nsCString& data, |
|
120 const uint64_t& offset, |
|
121 const uint32_t& count) |
|
122 { |
|
123 if (NS_FAILED(mStatus)) |
|
124 return true; |
|
125 |
|
126 MOZ_ASSERT(!mDiverted, "child forwarding callbacks after request was diverted"); |
|
127 MOZ_ASSERT(mPending, "must be pending!"); |
|
128 |
|
129 nsCOMPtr<nsIInputStream> stringStream; |
|
130 DebugOnly<nsresult> rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(), count, NS_ASSIGNMENT_DEPEND); |
|
131 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create dependent string!"); |
|
132 mStatus = mListener->OnDataAvailable(this, nullptr, stringStream, offset, count); |
|
133 |
|
134 return true; |
|
135 } |
|
136 |
|
137 bool |
|
138 ExternalHelperAppParent::RecvOnStopRequest(const nsresult& code) |
|
139 { |
|
140 MOZ_ASSERT(!mDiverted, "child forwarding callbacks after request was diverted"); |
|
141 |
|
142 mPending = false; |
|
143 mListener->OnStopRequest(this, nullptr, |
|
144 (NS_SUCCEEDED(code) && NS_FAILED(mStatus)) ? mStatus : code); |
|
145 Delete(); |
|
146 return true; |
|
147 } |
|
148 |
|
149 bool |
|
150 ExternalHelperAppParent::RecvDivertToParentUsing(PChannelDiverterParent* diverter) |
|
151 { |
|
152 MOZ_ASSERT(diverter); |
|
153 auto p = static_cast<mozilla::net::ChannelDiverterParent*>(diverter); |
|
154 p->DivertTo(this); |
|
155 mDiverted = true; |
|
156 unused << p->Send__delete__(p); |
|
157 return true; |
|
158 } |
|
159 |
|
160 // |
|
161 // nsIStreamListener |
|
162 // |
|
163 |
|
164 NS_IMETHODIMP |
|
165 ExternalHelperAppParent::OnDataAvailable(nsIRequest *request, |
|
166 nsISupports *ctx, |
|
167 nsIInputStream *input, |
|
168 uint64_t offset, |
|
169 uint32_t count) |
|
170 { |
|
171 MOZ_ASSERT(mDiverted); |
|
172 return mListener->OnDataAvailable(request, ctx, input, offset, count); |
|
173 } |
|
174 |
|
175 NS_IMETHODIMP |
|
176 ExternalHelperAppParent::OnStartRequest(nsIRequest *request, nsISupports *ctx) |
|
177 { |
|
178 MOZ_ASSERT(mDiverted); |
|
179 return mListener->OnStartRequest(request, ctx); |
|
180 } |
|
181 |
|
182 NS_IMETHODIMP |
|
183 ExternalHelperAppParent::OnStopRequest(nsIRequest *request, |
|
184 nsISupports *ctx, |
|
185 nsresult status) |
|
186 { |
|
187 MOZ_ASSERT(mDiverted); |
|
188 nsresult rv = mListener->OnStopRequest(request, ctx, status); |
|
189 Delete(); |
|
190 return rv; |
|
191 } |
|
192 |
|
193 ExternalHelperAppParent::~ExternalHelperAppParent() |
|
194 { |
|
195 } |
|
196 |
|
197 // |
|
198 // nsIRequest implementation... |
|
199 // |
|
200 |
|
201 NS_IMETHODIMP |
|
202 ExternalHelperAppParent::GetName(nsACString& aResult) |
|
203 { |
|
204 if (!mURI) { |
|
205 aResult.Truncate(); |
|
206 return NS_ERROR_NOT_AVAILABLE; |
|
207 } |
|
208 mURI->GetAsciiSpec(aResult); |
|
209 return NS_OK; |
|
210 } |
|
211 |
|
212 NS_IMETHODIMP |
|
213 ExternalHelperAppParent::IsPending(bool *aResult) |
|
214 { |
|
215 *aResult = mPending; |
|
216 return NS_OK; |
|
217 } |
|
218 |
|
219 NS_IMETHODIMP |
|
220 ExternalHelperAppParent::GetStatus(nsresult *aResult) |
|
221 { |
|
222 *aResult = mStatus; |
|
223 return NS_OK; |
|
224 } |
|
225 |
|
226 NS_IMETHODIMP |
|
227 ExternalHelperAppParent::Cancel(nsresult aStatus) |
|
228 { |
|
229 mStatus = aStatus; |
|
230 unused << SendCancel(aStatus); |
|
231 return NS_OK; |
|
232 } |
|
233 |
|
234 NS_IMETHODIMP |
|
235 ExternalHelperAppParent::Suspend() |
|
236 { |
|
237 return NS_ERROR_NOT_IMPLEMENTED; |
|
238 } |
|
239 |
|
240 NS_IMETHODIMP |
|
241 ExternalHelperAppParent::Resume() |
|
242 { |
|
243 return NS_ERROR_NOT_IMPLEMENTED; |
|
244 } |
|
245 |
|
246 // |
|
247 // nsIChannel implementation |
|
248 // |
|
249 |
|
250 NS_IMETHODIMP |
|
251 ExternalHelperAppParent::GetOriginalURI(nsIURI * *aURI) |
|
252 { |
|
253 NS_IF_ADDREF(*aURI = mURI); |
|
254 return NS_OK; |
|
255 } |
|
256 |
|
257 NS_IMETHODIMP |
|
258 ExternalHelperAppParent::SetOriginalURI(nsIURI *aURI) |
|
259 { |
|
260 return NS_ERROR_NOT_IMPLEMENTED; |
|
261 } |
|
262 |
|
263 NS_IMETHODIMP |
|
264 ExternalHelperAppParent::GetURI(nsIURI **aURI) |
|
265 { |
|
266 NS_IF_ADDREF(*aURI = mURI); |
|
267 return NS_OK; |
|
268 } |
|
269 |
|
270 NS_IMETHODIMP |
|
271 ExternalHelperAppParent::Open(nsIInputStream **aResult) |
|
272 { |
|
273 return NS_ERROR_NOT_IMPLEMENTED; |
|
274 } |
|
275 |
|
276 NS_IMETHODIMP |
|
277 ExternalHelperAppParent::AsyncOpen(nsIStreamListener *aListener, |
|
278 nsISupports *aContext) |
|
279 { |
|
280 return NS_ERROR_NOT_IMPLEMENTED; |
|
281 } |
|
282 |
|
283 |
|
284 NS_IMETHODIMP |
|
285 ExternalHelperAppParent::GetLoadFlags(nsLoadFlags *aLoadFlags) |
|
286 { |
|
287 *aLoadFlags = mLoadFlags; |
|
288 return NS_OK; |
|
289 } |
|
290 |
|
291 NS_IMETHODIMP |
|
292 ExternalHelperAppParent::SetLoadFlags(nsLoadFlags aLoadFlags) |
|
293 { |
|
294 mLoadFlags = aLoadFlags; |
|
295 return NS_OK; |
|
296 } |
|
297 |
|
298 NS_IMETHODIMP |
|
299 ExternalHelperAppParent::GetLoadGroup(nsILoadGroup* *aLoadGroup) |
|
300 { |
|
301 *aLoadGroup = nullptr; |
|
302 return NS_OK; |
|
303 } |
|
304 |
|
305 NS_IMETHODIMP |
|
306 ExternalHelperAppParent::SetLoadGroup(nsILoadGroup* aLoadGroup) |
|
307 { |
|
308 return NS_ERROR_NOT_IMPLEMENTED; |
|
309 } |
|
310 |
|
311 NS_IMETHODIMP |
|
312 ExternalHelperAppParent::GetOwner(nsISupports* *aOwner) |
|
313 { |
|
314 *aOwner = nullptr; |
|
315 return NS_OK; |
|
316 } |
|
317 |
|
318 NS_IMETHODIMP |
|
319 ExternalHelperAppParent::SetOwner(nsISupports* aOwner) |
|
320 { |
|
321 return NS_ERROR_NOT_IMPLEMENTED; |
|
322 } |
|
323 |
|
324 NS_IMETHODIMP |
|
325 ExternalHelperAppParent::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks) |
|
326 { |
|
327 *aCallbacks = nullptr; |
|
328 return NS_OK; |
|
329 } |
|
330 |
|
331 NS_IMETHODIMP |
|
332 ExternalHelperAppParent::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) |
|
333 { |
|
334 return NS_ERROR_NOT_IMPLEMENTED; |
|
335 } |
|
336 |
|
337 NS_IMETHODIMP |
|
338 ExternalHelperAppParent::GetSecurityInfo(nsISupports * *aSecurityInfo) |
|
339 { |
|
340 *aSecurityInfo = nullptr; |
|
341 return NS_OK; |
|
342 } |
|
343 |
|
344 NS_IMETHODIMP |
|
345 ExternalHelperAppParent::GetContentType(nsACString& aContentType) |
|
346 { |
|
347 aContentType.Truncate(); |
|
348 return NS_OK; |
|
349 } |
|
350 |
|
351 NS_IMETHODIMP |
|
352 ExternalHelperAppParent::SetContentType(const nsACString& aContentType) |
|
353 { |
|
354 return NS_ERROR_NOT_IMPLEMENTED; |
|
355 } |
|
356 |
|
357 NS_IMETHODIMP |
|
358 ExternalHelperAppParent::GetContentCharset(nsACString& aContentCharset) |
|
359 { |
|
360 aContentCharset.Truncate(); |
|
361 return NS_OK; |
|
362 } |
|
363 |
|
364 NS_IMETHODIMP |
|
365 ExternalHelperAppParent::SetContentCharset(const nsACString& aContentCharset) |
|
366 { |
|
367 return NS_ERROR_NOT_IMPLEMENTED; |
|
368 } |
|
369 |
|
370 NS_IMETHODIMP |
|
371 ExternalHelperAppParent::GetContentDisposition(uint32_t *aContentDisposition) |
|
372 { |
|
373 if (mContentDispositionHeader.IsEmpty()) |
|
374 return NS_ERROR_NOT_AVAILABLE; |
|
375 |
|
376 *aContentDisposition = mContentDisposition; |
|
377 return NS_OK; |
|
378 } |
|
379 |
|
380 NS_IMETHODIMP |
|
381 ExternalHelperAppParent::SetContentDisposition(uint32_t aContentDisposition) |
|
382 { |
|
383 mContentDisposition = aContentDisposition; |
|
384 return NS_OK; |
|
385 } |
|
386 |
|
387 NS_IMETHODIMP |
|
388 ExternalHelperAppParent::GetContentDispositionFilename(nsAString& aContentDispositionFilename) |
|
389 { |
|
390 if (mContentDispositionFilename.IsEmpty()) |
|
391 return NS_ERROR_NOT_AVAILABLE; |
|
392 |
|
393 aContentDispositionFilename = mContentDispositionFilename; |
|
394 return NS_OK; |
|
395 } |
|
396 |
|
397 NS_IMETHODIMP |
|
398 ExternalHelperAppParent::SetContentDispositionFilename(const nsAString& aContentDispositionFilename) |
|
399 { |
|
400 mContentDispositionFilename = aContentDispositionFilename; |
|
401 return NS_OK; |
|
402 } |
|
403 |
|
404 NS_IMETHODIMP |
|
405 ExternalHelperAppParent::GetContentDispositionHeader(nsACString& aContentDispositionHeader) |
|
406 { |
|
407 if (mContentDispositionHeader.IsEmpty()) |
|
408 return NS_ERROR_NOT_AVAILABLE; |
|
409 |
|
410 aContentDispositionHeader = mContentDispositionHeader; |
|
411 return NS_OK; |
|
412 } |
|
413 |
|
414 NS_IMETHODIMP |
|
415 ExternalHelperAppParent::GetContentLength(int64_t *aContentLength) |
|
416 { |
|
417 if (mContentLength < 0) |
|
418 *aContentLength = -1; |
|
419 else |
|
420 *aContentLength = mContentLength; |
|
421 return NS_OK; |
|
422 } |
|
423 |
|
424 NS_IMETHODIMP |
|
425 ExternalHelperAppParent::SetContentLength(int64_t aContentLength) |
|
426 { |
|
427 mContentLength = aContentLength; |
|
428 return NS_OK; |
|
429 } |
|
430 |
|
431 // |
|
432 // nsIResumableChannel implementation |
|
433 // |
|
434 |
|
435 NS_IMETHODIMP |
|
436 ExternalHelperAppParent::ResumeAt(uint64_t startPos, const nsACString& entityID) |
|
437 { |
|
438 return NS_ERROR_NOT_IMPLEMENTED; |
|
439 } |
|
440 |
|
441 NS_IMETHODIMP |
|
442 ExternalHelperAppParent::GetEntityID(nsACString& aEntityID) |
|
443 { |
|
444 aEntityID = mEntityID; |
|
445 return NS_OK; |
|
446 } |
|
447 |
|
448 // |
|
449 // nsIMultiPartChannel implementation |
|
450 // |
|
451 |
|
452 NS_IMETHODIMP |
|
453 ExternalHelperAppParent::GetBaseChannel(nsIChannel* *aChannel) |
|
454 { |
|
455 return NS_ERROR_NOT_IMPLEMENTED; |
|
456 } |
|
457 |
|
458 NS_IMETHODIMP |
|
459 ExternalHelperAppParent::GetPartID(uint32_t* aPartID) |
|
460 { |
|
461 return NS_ERROR_NOT_IMPLEMENTED; |
|
462 } |
|
463 |
|
464 NS_IMETHODIMP |
|
465 ExternalHelperAppParent::GetIsLastPart(bool* aIsLastPart) |
|
466 { |
|
467 return NS_ERROR_NOT_IMPLEMENTED; |
|
468 } |
|
469 |
|
470 } // namespace dom |
|
471 } // namespace mozilla |