Coverage Report

Created: 2018-09-25 14:53

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