Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/uriloader/exthandler/ExternalHelperAppChild.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 "ExternalHelperAppChild.h"
8
#include "mozilla/net/ChannelDiverterChild.h"
9
#include "mozilla/dom/TabChild.h"
10
#include "nsIDivertableChannel.h"
11
#include "nsIInputStream.h"
12
#include "nsIFTPChannel.h"
13
#include "nsIRequest.h"
14
#include "nsIResumableChannel.h"
15
#include "nsNetUtil.h"
16
17
namespace mozilla {
18
namespace dom {
19
20
NS_IMPL_ISUPPORTS(ExternalHelperAppChild,
21
                  nsIStreamListener,
22
                  nsIRequestObserver)
23
24
ExternalHelperAppChild::ExternalHelperAppChild()
25
  : mStatus(NS_OK)
26
0
{
27
0
}
28
29
ExternalHelperAppChild::~ExternalHelperAppChild()
30
0
{
31
0
}
32
33
//-----------------------------------------------------------------------------
34
// nsIStreamListener
35
//-----------------------------------------------------------------------------
36
NS_IMETHODIMP
37
ExternalHelperAppChild::OnDataAvailable(nsIRequest *request,
38
                                        nsISupports *ctx,
39
                                        nsIInputStream *input,
40
                                        uint64_t offset,
41
                                        uint32_t count)
42
0
{
43
0
  if (NS_FAILED(mStatus))
44
0
    return mStatus;
45
0
46
0
  static uint32_t const kCopyChunkSize = 128 * 1024;
47
0
  uint32_t toRead = std::min<uint32_t>(count, kCopyChunkSize);
48
0
49
0
  nsCString data;
50
0
  if (NS_WARN_IF(!data.SetCapacity(toRead, fallible))) {
51
0
    return NS_ERROR_OUT_OF_MEMORY;
52
0
  }
53
0
54
0
  while (count) {
55
0
    nsresult rv = NS_ReadInputStreamToString(input, data, toRead);
56
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
57
0
      return rv;
58
0
    }
59
0
60
0
    if (NS_WARN_IF(!SendOnDataAvailable(data, offset, toRead))) {
61
0
      return NS_ERROR_UNEXPECTED;
62
0
    }
63
0
64
0
    count -= toRead;
65
0
    offset += toRead;
66
0
    toRead = std::min<uint32_t>(count, kCopyChunkSize);
67
0
  }
68
0
69
0
  return NS_OK;
70
0
}
71
72
//////////////////////////////////////////////////////////////////////////////
73
// nsIRequestObserver
74
//////////////////////////////////////////////////////////////////////////////
75
76
NS_IMETHODIMP
77
ExternalHelperAppChild::OnStartRequest(nsIRequest *request, nsISupports *ctx)
78
0
{
79
0
  nsresult rv = mHandler->OnStartRequest(request, ctx);
80
0
  NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
81
0
82
0
  // Calling OnStartRequest could cause mHandler to close the window it was
83
0
  // loaded for. In that case, the TabParent in the parent context might then
84
0
  // point to the wrong window. Re-send the window context along with either
85
0
  // DivertToParent or SendOnStartRequest just in case.
86
0
  nsCOMPtr<nsPIDOMWindowOuter> window =
87
0
    do_GetInterface(mHandler->GetDialogParent());
88
0
  NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
89
0
90
0
  TabChild *tabChild = mozilla::dom::TabChild::GetFrom(window);
91
0
  NS_ENSURE_TRUE(tabChild, NS_ERROR_NOT_AVAILABLE);
92
0
93
0
  nsCOMPtr<nsIDivertableChannel> divertable = do_QueryInterface(request);
94
0
  if (divertable) {
95
0
    return DivertToParent(divertable, request, tabChild);
96
0
  }
97
0
98
0
  nsCString entityID;
99
0
  nsCOMPtr<nsIResumableChannel> resumable(do_QueryInterface(request));
100
0
  if (resumable) {
101
0
    resumable->GetEntityID(entityID);
102
0
  }
103
0
  SendOnStartRequest(entityID, tabChild);
104
0
  return NS_OK;
105
0
}
106
107
NS_IMETHODIMP
108
ExternalHelperAppChild::OnStopRequest(nsIRequest *request,
109
                                      nsISupports *ctx,
110
                                      nsresult status)
111
0
{
112
0
  // mHandler can be null if we diverted the request to the parent
113
0
  if (mHandler) {
114
0
    nsresult rv = mHandler->OnStopRequest(request, ctx, status);
115
0
    SendOnStopRequest(status);
116
0
    NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
117
0
  }
118
0
119
0
  return NS_OK;
120
0
}
121
122
nsresult
123
ExternalHelperAppChild::DivertToParent(nsIDivertableChannel *divertable,
124
                                       nsIRequest *request,
125
                                       TabChild *tabChild)
126
0
{
127
0
  // nsIDivertable must know about content conversions before being diverted.
128
0
  MOZ_ASSERT(mHandler);
129
0
  mHandler->MaybeApplyDecodingForExtension(request);
130
0
131
0
  mozilla::net::ChannelDiverterChild *diverter = nullptr;
132
0
  nsresult rv = divertable->DivertToParent(&diverter);
133
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
134
0
    return rv;
135
0
  }
136
0
  MOZ_ASSERT(diverter);
137
0
138
0
  if (SendDivertToParentUsing(diverter, tabChild)) {
139
0
    mHandler->DidDivertRequest(request);
140
0
    mHandler = nullptr;
141
0
    return NS_OK;
142
0
  }
143
0
144
0
  return NS_ERROR_FAILURE;
145
0
}
146
147
mozilla::ipc::IPCResult
148
ExternalHelperAppChild::RecvCancel(const nsresult& aStatus)
149
0
{
150
0
  mStatus = aStatus;
151
0
  return IPC_OK();
152
0
}
153
154
} // namespace dom
155
} // namespace mozilla