uriloader/exthandler/ExternalHelperAppParent.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:e0c965aa2a71
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

mercurial