Line data Source code
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 0 : NS_IMPL_ISUPPORTS_INHERITED(ExternalHelperAppParent,
31 : nsHashPropertyBag,
32 : nsIRequest,
33 : nsIChannel,
34 : nsIMultiPartChannel,
35 : nsIPrivateBrowsingChannel,
36 : nsIResumableChannel,
37 : nsIStreamListener,
38 : nsIExternalHelperAppParent)
39 :
40 0 : ExternalHelperAppParent::ExternalHelperAppParent(
41 : const OptionalURIParams& uri,
42 : const int64_t& aContentLength,
43 0 : const bool& aWasFileChannel)
44 0 : : mURI(DeserializeURI(uri))
45 : , mPending(false)
46 : #ifdef DEBUG
47 : , mDiverted(false)
48 : #endif
49 : , mIPCClosed(false)
50 : , mLoadFlags(0)
51 : , mStatus(NS_OK)
52 0 : , mContentLength(aContentLength)
53 0 : , mWasFileChannel(aWasFileChannel)
54 : {
55 0 : }
56 :
57 : already_AddRefed<nsIInterfaceRequestor>
58 0 : GetWindowFromTabParent(PBrowserParent* aBrowser)
59 : {
60 0 : if (!aBrowser) {
61 0 : return nullptr;
62 : }
63 :
64 0 : nsCOMPtr<nsIInterfaceRequestor> window;
65 0 : TabParent* tabParent = TabParent::GetFrom(aBrowser);
66 0 : if (tabParent->GetOwnerElement()) {
67 0 : window = do_QueryInterface(tabParent->GetOwnerElement()->OwnerDoc()->GetWindow());
68 : }
69 :
70 0 : return window.forget();
71 : }
72 :
73 : void
74 0 : UpdateContentContext(nsIStreamListener* aListener, PBrowserParent* aBrowser)
75 : {
76 0 : MOZ_ASSERT(aListener);
77 0 : nsCOMPtr<nsIInterfaceRequestor> window = GetWindowFromTabParent(aBrowser);
78 0 : static_cast<nsExternalAppHandler *>(aListener)->SetContentContext(window);
79 0 : }
80 :
81 : void
82 0 : ExternalHelperAppParent::Init(ContentParent *parent,
83 : const nsCString& aMimeContentType,
84 : const nsCString& aContentDispositionHeader,
85 : const uint32_t& aContentDispositionHint,
86 : const nsString& aContentDispositionFilename,
87 : const bool& aForceSave,
88 : const OptionalURIParams& aReferrer,
89 : PBrowserParent* aBrowser)
90 : {
91 : nsCOMPtr<nsIExternalHelperAppService> helperAppService =
92 0 : do_GetService(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID);
93 0 : NS_ASSERTION(helperAppService, "No Helper App Service!");
94 :
95 0 : nsCOMPtr<nsIURI> referrer = DeserializeURI(aReferrer);
96 0 : if (referrer)
97 0 : SetPropertyAsInterface(NS_LITERAL_STRING("docshell.internalReferrer"), referrer);
98 :
99 0 : mContentDispositionHeader = aContentDispositionHeader;
100 0 : if (!mContentDispositionHeader.IsEmpty()) {
101 0 : NS_GetFilenameFromDisposition(mContentDispositionFilename,
102 : mContentDispositionHeader,
103 0 : mURI);
104 0 : mContentDisposition =
105 0 : NS_GetContentDispositionFromHeader(mContentDispositionHeader, this);
106 : }
107 : else {
108 0 : mContentDisposition = aContentDispositionHint;
109 0 : mContentDispositionFilename = aContentDispositionFilename;
110 : }
111 :
112 0 : nsCOMPtr<nsIInterfaceRequestor> window;
113 0 : if (aBrowser) {
114 0 : TabParent* tabParent = TabParent::GetFrom(aBrowser);
115 0 : if (tabParent->GetOwnerElement())
116 0 : window = do_QueryInterface(tabParent->GetOwnerElement()->OwnerDoc()->GetWindow());
117 :
118 0 : bool isPrivate = false;
119 0 : nsCOMPtr<nsILoadContext> loadContext = tabParent->GetLoadContext();
120 0 : loadContext->GetUsePrivateBrowsing(&isPrivate);
121 0 : SetPrivate(isPrivate);
122 : }
123 :
124 0 : helperAppService->DoContent(aMimeContentType, this, window,
125 0 : aForceSave, nullptr,
126 0 : getter_AddRefs(mListener));
127 0 : }
128 :
129 : void
130 0 : ExternalHelperAppParent::ActorDestroy(ActorDestroyReason why)
131 : {
132 0 : mIPCClosed = true;
133 0 : }
134 :
135 : void
136 0 : ExternalHelperAppParent::Delete()
137 : {
138 0 : if (!mIPCClosed) {
139 0 : Unused << Send__delete__(this);
140 : }
141 0 : }
142 :
143 : mozilla::ipc::IPCResult
144 0 : ExternalHelperAppParent::RecvOnStartRequest(const nsCString& entityID,
145 : PBrowserParent* contentContext)
146 : {
147 0 : MOZ_ASSERT(!mDiverted, "child forwarding callbacks after request was diverted");
148 :
149 0 : UpdateContentContext(mListener, contentContext);
150 :
151 0 : mEntityID = entityID;
152 0 : mPending = true;
153 0 : mStatus = mListener->OnStartRequest(this, nullptr);
154 0 : return IPC_OK();
155 : }
156 :
157 : mozilla::ipc::IPCResult
158 0 : ExternalHelperAppParent::RecvOnDataAvailable(const nsCString& data,
159 : const uint64_t& offset,
160 : const uint32_t& count)
161 : {
162 0 : if (NS_FAILED(mStatus))
163 0 : return IPC_OK();
164 :
165 0 : MOZ_ASSERT(!mDiverted, "child forwarding callbacks after request was diverted");
166 0 : MOZ_ASSERT(mPending, "must be pending!");
167 :
168 0 : nsCOMPtr<nsIInputStream> stringStream;
169 0 : DebugOnly<nsresult> rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(), count, NS_ASSIGNMENT_DEPEND);
170 0 : NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create dependent string!");
171 0 : mStatus = mListener->OnDataAvailable(this, nullptr, stringStream, offset, count);
172 :
173 0 : return IPC_OK();
174 : }
175 :
176 : mozilla::ipc::IPCResult
177 0 : ExternalHelperAppParent::RecvOnStopRequest(const nsresult& code)
178 : {
179 0 : MOZ_ASSERT(!mDiverted, "child forwarding callbacks after request was diverted");
180 :
181 0 : mPending = false;
182 0 : mListener->OnStopRequest(this, nullptr,
183 0 : (NS_SUCCEEDED(code) && NS_FAILED(mStatus)) ? mStatus : code);
184 0 : Delete();
185 0 : return IPC_OK();
186 : }
187 :
188 : mozilla::ipc::IPCResult
189 0 : ExternalHelperAppParent::RecvDivertToParentUsing(PChannelDiverterParent* diverter,
190 : PBrowserParent* contentContext)
191 : {
192 0 : MOZ_ASSERT(diverter);
193 0 : UpdateContentContext(mListener, contentContext);
194 0 : auto p = static_cast<mozilla::net::ChannelDiverterParent*>(diverter);
195 0 : p->DivertTo(this);
196 : #ifdef DEBUG
197 0 : mDiverted = true;
198 : #endif
199 0 : Unused << p->Send__delete__(p);
200 0 : return IPC_OK();
201 : }
202 :
203 : //
204 : // nsIStreamListener
205 : //
206 :
207 : NS_IMETHODIMP
208 0 : ExternalHelperAppParent::OnDataAvailable(nsIRequest *request,
209 : nsISupports *ctx,
210 : nsIInputStream *input,
211 : uint64_t offset,
212 : uint32_t count)
213 : {
214 0 : MOZ_ASSERT(mDiverted);
215 0 : return mListener->OnDataAvailable(request, ctx, input, offset, count);
216 : }
217 :
218 : NS_IMETHODIMP
219 0 : ExternalHelperAppParent::OnStartRequest(nsIRequest *request, nsISupports *ctx)
220 : {
221 0 : MOZ_ASSERT(mDiverted);
222 0 : return mListener->OnStartRequest(request, ctx);
223 : }
224 :
225 : NS_IMETHODIMP
226 0 : ExternalHelperAppParent::OnStopRequest(nsIRequest *request,
227 : nsISupports *ctx,
228 : nsresult status)
229 : {
230 0 : MOZ_ASSERT(mDiverted);
231 0 : nsresult rv = mListener->OnStopRequest(request, ctx, status);
232 0 : Delete();
233 0 : return rv;
234 : }
235 :
236 0 : ExternalHelperAppParent::~ExternalHelperAppParent()
237 : {
238 0 : }
239 :
240 : //
241 : // nsIRequest implementation...
242 : //
243 :
244 : NS_IMETHODIMP
245 0 : ExternalHelperAppParent::GetName(nsACString& aResult)
246 : {
247 0 : if (!mURI) {
248 0 : aResult.Truncate();
249 0 : return NS_ERROR_NOT_AVAILABLE;
250 : }
251 0 : mURI->GetAsciiSpec(aResult);
252 0 : return NS_OK;
253 : }
254 :
255 : NS_IMETHODIMP
256 0 : ExternalHelperAppParent::IsPending(bool *aResult)
257 : {
258 0 : *aResult = mPending;
259 0 : return NS_OK;
260 : }
261 :
262 : NS_IMETHODIMP
263 0 : ExternalHelperAppParent::GetStatus(nsresult *aResult)
264 : {
265 0 : *aResult = mStatus;
266 0 : return NS_OK;
267 : }
268 :
269 : NS_IMETHODIMP
270 0 : ExternalHelperAppParent::Cancel(nsresult aStatus)
271 : {
272 0 : mStatus = aStatus;
273 0 : Unused << SendCancel(aStatus);
274 0 : return NS_OK;
275 : }
276 :
277 : NS_IMETHODIMP
278 0 : ExternalHelperAppParent::Suspend()
279 : {
280 0 : return NS_ERROR_NOT_IMPLEMENTED;
281 : }
282 :
283 : NS_IMETHODIMP
284 0 : ExternalHelperAppParent::Resume()
285 : {
286 0 : return NS_ERROR_NOT_IMPLEMENTED;
287 : }
288 :
289 : //
290 : // nsIChannel implementation
291 : //
292 :
293 : NS_IMETHODIMP
294 0 : ExternalHelperAppParent::GetOriginalURI(nsIURI * *aURI)
295 : {
296 0 : NS_IF_ADDREF(*aURI = mURI);
297 0 : return NS_OK;
298 : }
299 :
300 : NS_IMETHODIMP
301 0 : ExternalHelperAppParent::SetOriginalURI(nsIURI *aURI)
302 : {
303 0 : return NS_ERROR_NOT_IMPLEMENTED;
304 : }
305 :
306 : NS_IMETHODIMP
307 0 : ExternalHelperAppParent::GetURI(nsIURI **aURI)
308 : {
309 0 : NS_IF_ADDREF(*aURI = mURI);
310 0 : return NS_OK;
311 : }
312 :
313 : NS_IMETHODIMP
314 0 : ExternalHelperAppParent::Open(nsIInputStream **aResult)
315 : {
316 0 : return NS_ERROR_NOT_IMPLEMENTED;
317 : }
318 :
319 : NS_IMETHODIMP
320 0 : ExternalHelperAppParent::Open2(nsIInputStream** aStream)
321 : {
322 0 : return NS_ERROR_NOT_IMPLEMENTED;
323 : }
324 :
325 : NS_IMETHODIMP
326 0 : ExternalHelperAppParent::AsyncOpen(nsIStreamListener *aListener,
327 : nsISupports *aContext)
328 : {
329 0 : return NS_ERROR_NOT_IMPLEMENTED;
330 : }
331 :
332 : NS_IMETHODIMP
333 0 : ExternalHelperAppParent::AsyncOpen2(nsIStreamListener *aListener)
334 : {
335 0 : return NS_ERROR_NOT_IMPLEMENTED;
336 : }
337 :
338 :
339 : NS_IMETHODIMP
340 0 : ExternalHelperAppParent::GetLoadFlags(nsLoadFlags *aLoadFlags)
341 : {
342 0 : *aLoadFlags = mLoadFlags;
343 0 : return NS_OK;
344 : }
345 :
346 : NS_IMETHODIMP
347 0 : ExternalHelperAppParent::SetLoadFlags(nsLoadFlags aLoadFlags)
348 : {
349 0 : mLoadFlags = aLoadFlags;
350 0 : return NS_OK;
351 : }
352 :
353 : NS_IMETHODIMP
354 0 : ExternalHelperAppParent::GetIsDocument(bool *aIsDocument)
355 : {
356 0 : return NS_GetIsDocumentChannel(this, aIsDocument);
357 : }
358 :
359 : NS_IMETHODIMP
360 0 : ExternalHelperAppParent::GetLoadGroup(nsILoadGroup* *aLoadGroup)
361 : {
362 0 : *aLoadGroup = nullptr;
363 0 : return NS_OK;
364 : }
365 :
366 : NS_IMETHODIMP
367 0 : ExternalHelperAppParent::SetLoadGroup(nsILoadGroup* aLoadGroup)
368 : {
369 0 : return NS_ERROR_NOT_IMPLEMENTED;
370 : }
371 :
372 : NS_IMETHODIMP
373 0 : ExternalHelperAppParent::GetOwner(nsISupports* *aOwner)
374 : {
375 0 : *aOwner = nullptr;
376 0 : return NS_OK;
377 : }
378 :
379 : NS_IMETHODIMP
380 0 : ExternalHelperAppParent::SetOwner(nsISupports* aOwner)
381 : {
382 0 : return NS_ERROR_NOT_IMPLEMENTED;
383 : }
384 :
385 : NS_IMETHODIMP
386 0 : ExternalHelperAppParent::GetLoadInfo(nsILoadInfo* *aLoadInfo)
387 : {
388 0 : *aLoadInfo = nullptr;
389 0 : return NS_OK;
390 : }
391 :
392 : NS_IMETHODIMP
393 0 : ExternalHelperAppParent::SetLoadInfo(nsILoadInfo* aLoadInfo)
394 : {
395 0 : return NS_ERROR_NOT_IMPLEMENTED;
396 : }
397 :
398 : NS_IMETHODIMP
399 0 : ExternalHelperAppParent::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
400 : {
401 0 : *aCallbacks = nullptr;
402 0 : return NS_OK;
403 : }
404 :
405 : NS_IMETHODIMP
406 0 : ExternalHelperAppParent::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
407 : {
408 0 : return NS_ERROR_NOT_IMPLEMENTED;
409 : }
410 :
411 : NS_IMETHODIMP
412 0 : ExternalHelperAppParent::GetSecurityInfo(nsISupports * *aSecurityInfo)
413 : {
414 0 : *aSecurityInfo = nullptr;
415 0 : return NS_OK;
416 : }
417 :
418 : NS_IMETHODIMP
419 0 : ExternalHelperAppParent::GetContentType(nsACString& aContentType)
420 : {
421 0 : aContentType.Truncate();
422 0 : return NS_OK;
423 : }
424 :
425 : NS_IMETHODIMP
426 0 : ExternalHelperAppParent::SetContentType(const nsACString& aContentType)
427 : {
428 0 : return NS_ERROR_NOT_IMPLEMENTED;
429 : }
430 :
431 : NS_IMETHODIMP
432 0 : ExternalHelperAppParent::GetContentCharset(nsACString& aContentCharset)
433 : {
434 0 : aContentCharset.Truncate();
435 0 : return NS_OK;
436 : }
437 :
438 : NS_IMETHODIMP
439 0 : ExternalHelperAppParent::SetContentCharset(const nsACString& aContentCharset)
440 : {
441 0 : return NS_ERROR_NOT_IMPLEMENTED;
442 : }
443 :
444 : NS_IMETHODIMP
445 0 : ExternalHelperAppParent::GetContentDisposition(uint32_t *aContentDisposition)
446 : {
447 : // NB: mContentDisposition may or may not be set to a non UINT32_MAX value in
448 : // nsExternalHelperAppService::DoContentContentProcessHelper
449 0 : if (mContentDispositionHeader.IsEmpty() && mContentDisposition == UINT32_MAX)
450 0 : return NS_ERROR_NOT_AVAILABLE;
451 :
452 0 : *aContentDisposition = mContentDisposition;
453 0 : return NS_OK;
454 : }
455 :
456 : NS_IMETHODIMP
457 0 : ExternalHelperAppParent::SetContentDisposition(uint32_t aContentDisposition)
458 : {
459 0 : mContentDisposition = aContentDisposition;
460 0 : return NS_OK;
461 : }
462 :
463 : NS_IMETHODIMP
464 0 : ExternalHelperAppParent::GetContentDispositionFilename(nsAString& aContentDispositionFilename)
465 : {
466 0 : if (mContentDispositionFilename.IsEmpty())
467 0 : return NS_ERROR_NOT_AVAILABLE;
468 :
469 0 : aContentDispositionFilename = mContentDispositionFilename;
470 0 : return NS_OK;
471 : }
472 :
473 : NS_IMETHODIMP
474 0 : ExternalHelperAppParent::SetContentDispositionFilename(const nsAString& aContentDispositionFilename)
475 : {
476 0 : mContentDispositionFilename = aContentDispositionFilename;
477 0 : return NS_OK;
478 : }
479 :
480 : NS_IMETHODIMP
481 0 : ExternalHelperAppParent::GetContentDispositionHeader(nsACString& aContentDispositionHeader)
482 : {
483 0 : if (mContentDispositionHeader.IsEmpty())
484 0 : return NS_ERROR_NOT_AVAILABLE;
485 :
486 0 : aContentDispositionHeader = mContentDispositionHeader;
487 0 : return NS_OK;
488 : }
489 :
490 : NS_IMETHODIMP
491 0 : ExternalHelperAppParent::GetContentLength(int64_t *aContentLength)
492 : {
493 0 : if (mContentLength < 0)
494 0 : *aContentLength = -1;
495 : else
496 0 : *aContentLength = mContentLength;
497 0 : return NS_OK;
498 : }
499 :
500 : NS_IMETHODIMP
501 0 : ExternalHelperAppParent::SetContentLength(int64_t aContentLength)
502 : {
503 0 : mContentLength = aContentLength;
504 0 : return NS_OK;
505 : }
506 :
507 : //
508 : // nsIResumableChannel implementation
509 : //
510 :
511 : NS_IMETHODIMP
512 0 : ExternalHelperAppParent::ResumeAt(uint64_t startPos, const nsACString& entityID)
513 : {
514 0 : return NS_ERROR_NOT_IMPLEMENTED;
515 : }
516 :
517 : NS_IMETHODIMP
518 0 : ExternalHelperAppParent::GetEntityID(nsACString& aEntityID)
519 : {
520 0 : aEntityID = mEntityID;
521 0 : return NS_OK;
522 : }
523 :
524 : //
525 : // nsIMultiPartChannel implementation
526 : //
527 :
528 : NS_IMETHODIMP
529 0 : ExternalHelperAppParent::GetBaseChannel(nsIChannel* *aChannel)
530 : {
531 0 : return NS_ERROR_NOT_IMPLEMENTED;
532 : }
533 :
534 : NS_IMETHODIMP
535 0 : ExternalHelperAppParent::GetPartID(uint32_t* aPartID)
536 : {
537 0 : return NS_ERROR_NOT_IMPLEMENTED;
538 : }
539 :
540 : NS_IMETHODIMP
541 0 : ExternalHelperAppParent::GetIsLastPart(bool* aIsLastPart)
542 : {
543 0 : return NS_ERROR_NOT_IMPLEMENTED;
544 : }
545 :
546 : } // namespace dom
547 : } // namespace mozilla
|