Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "nsWyciwyg.h"
6
7
#include "mozilla/net/WyciwygChannelParent.h"
8
#include "nsWyciwygChannel.h"
9
#include "nsNetUtil.h"
10
#include "nsCharsetSource.h"
11
#include "nsISerializable.h"
12
#include "nsSerializationHelper.h"
13
#include "mozilla/ipc/URIUtils.h"
14
#include "mozilla/net/NeckoParent.h"
15
#include "SerializedLoadContext.h"
16
#include "nsIContentPolicy.h"
17
#include "mozilla/ipc/BackgroundUtils.h"
18
#include "mozilla/dom/ContentParent.h"
19
20
using namespace mozilla::ipc;
21
22
namespace mozilla {
23
namespace net {
24
25
WyciwygChannelParent::WyciwygChannelParent()
26
 : mIPCClosed(false)
27
 , mReceivedAppData(false)
28
0
{
29
0
}
30
31
void
32
WyciwygChannelParent::ActorDestroy(ActorDestroyReason why)
33
0
{
34
0
  // We may still have refcount>0 if the channel hasn't called OnStopRequest
35
0
  // yet, but we must not send any more msgs to child.
36
0
  mIPCClosed = true;
37
0
38
0
  // We need to force the cycle to break here
39
0
  if (mChannel) {
40
0
    mChannel->SetNotificationCallbacks(nullptr);
41
0
  }
42
0
}
43
44
//-----------------------------------------------------------------------------
45
// WyciwygChannelParent::nsISupports
46
//-----------------------------------------------------------------------------
47
48
NS_IMPL_ISUPPORTS(WyciwygChannelParent,
49
                  nsIStreamListener,
50
                  nsIInterfaceRequestor,
51
                  nsIRequestObserver)
52
53
//-----------------------------------------------------------------------------
54
// WyciwygChannelParent::PWyciwygChannelParent
55
//-----------------------------------------------------------------------------
56
57
mozilla::ipc::IPCResult
58
WyciwygChannelParent::RecvInit(const URIParams&          aURI,
59
                               const ipc::PrincipalInfo& aRequestingPrincipalInfo,
60
                               const ipc::PrincipalInfo& aTriggeringPrincipalInfo,
61
                               const ipc::PrincipalInfo& aPrincipalToInheritInfo,
62
                               const uint32_t&           aSecurityFlags,
63
                               const uint32_t&           aContentPolicyType)
64
0
{
65
0
  nsresult rv;
66
0
67
0
  nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
68
0
  if (!uri)
69
0
    return IPC_FAIL_NO_REASON(this);
70
0
71
0
  LOG(("WyciwygChannelParent RecvInit [this=%p uri=%s]\n",
72
0
       this, uri->GetSpecOrDefault().get()));
73
0
74
0
  nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
75
0
  if (NS_FAILED(rv)) {
76
0
    if (!SendCancelEarly(rv)) {
77
0
      return IPC_FAIL_NO_REASON(this);
78
0
    }
79
0
    return IPC_OK();
80
0
  }
81
0
82
0
  nsCOMPtr<nsIPrincipal> requestingPrincipal =
83
0
    mozilla::ipc::PrincipalInfoToPrincipal(aRequestingPrincipalInfo, &rv);
84
0
  if (NS_FAILED(rv)) {
85
0
    if (!SendCancelEarly(rv)) {
86
0
      return IPC_FAIL_NO_REASON(this);
87
0
    }
88
0
    return IPC_OK();
89
0
  }
90
0
91
0
  nsCOMPtr<nsIPrincipal> triggeringPrincipal =
92
0
    mozilla::ipc::PrincipalInfoToPrincipal(aTriggeringPrincipalInfo, &rv);
93
0
  if (NS_FAILED(rv)) {
94
0
    if (!SendCancelEarly(rv)) {
95
0
      return IPC_FAIL_NO_REASON(this);
96
0
    }
97
0
    return IPC_OK();
98
0
  }
99
0
100
0
  nsCOMPtr<nsIPrincipal> principalToInherit =
101
0
    mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalToInheritInfo, &rv);
102
0
  if (NS_FAILED(rv)) {
103
0
    if (!SendCancelEarly(rv)) {
104
0
      return IPC_FAIL_NO_REASON(this);
105
0
    }
106
0
    return IPC_OK();
107
0
  }
108
0
109
0
  nsCOMPtr<nsIChannel> chan;
110
0
  rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(chan),
111
0
                                           uri,
112
0
                                           requestingPrincipal,
113
0
                                           triggeringPrincipal,
114
0
                                           aSecurityFlags,
115
0
                                           aContentPolicyType,
116
0
                                           nullptr,   // PerformanceStorage
117
0
                                           nullptr,   // loadGroup
118
0
                                           nullptr,   // aCallbacks
119
0
                                           nsIRequest::LOAD_NORMAL,
120
0
                                           ios);
121
0
122
0
  if (NS_FAILED(rv)) {
123
0
    if (!SendCancelEarly(rv)) {
124
0
      return IPC_FAIL_NO_REASON(this);
125
0
    }
126
0
    return IPC_OK();
127
0
  }
128
0
129
0
  nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo();
130
0
  if (loadInfo) {
131
0
    rv = loadInfo->SetPrincipalToInherit(principalToInherit);
132
0
  }
133
0
  if (NS_FAILED(rv)) {
134
0
    if (!SendCancelEarly(rv)) {
135
0
      return IPC_FAIL_NO_REASON(this);
136
0
    }
137
0
    return IPC_OK();
138
0
  }
139
0
140
0
  mChannel = do_QueryInterface(chan, &rv);
141
0
  if (NS_FAILED(rv)) {
142
0
    if (!SendCancelEarly(rv)) {
143
0
      return IPC_FAIL_NO_REASON(this);
144
0
    }
145
0
    return IPC_OK();
146
0
  }
147
0
148
0
  return IPC_OK();
149
0
}
150
151
mozilla::ipc::IPCResult
152
WyciwygChannelParent::RecvAppData(const IPC::SerializedLoadContext& loadContext,
153
                                  const PBrowserOrId &parent)
154
0
{
155
0
  LOG(("WyciwygChannelParent RecvAppData [this=%p]\n", this));
156
0
157
0
  if (!SetupAppData(loadContext, parent))
158
0
    return IPC_FAIL_NO_REASON(this);
159
0
160
0
  if (!mChannel) {
161
0
    return IPC_FAIL(this, "Should have a channel");
162
0
  }
163
0
164
0
  mChannel->SetNotificationCallbacks(this);
165
0
  return IPC_OK();
166
0
}
167
168
bool
169
WyciwygChannelParent::SetupAppData(const IPC::SerializedLoadContext& loadContext,
170
                                   const PBrowserOrId &aParent)
171
0
{
172
0
  if (!mChannel)
173
0
    return true;
174
0
175
0
  const char* error = NeckoParent::CreateChannelLoadContext(aParent,
176
0
                                                            Manager()->Manager(),
177
0
                                                            loadContext,
178
0
                                                            nullptr,
179
0
                                                            mLoadContext);
180
0
  if (error) {
181
0
    printf_stderr("WyciwygChannelParent::SetupAppData: FATAL ERROR: %s\n",
182
0
                  error);
183
0
    return false;
184
0
  }
185
0
186
0
  if (!mLoadContext && loadContext.IsPrivateBitValid()) {
187
0
    nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(mChannel);
188
0
    if (pbChannel)
189
0
      pbChannel->SetPrivate(loadContext.mOriginAttributes.mPrivateBrowsingId > 0);
190
0
  }
191
0
192
0
  mReceivedAppData = true;
193
0
  return true;
194
0
}
195
196
mozilla::ipc::IPCResult
197
WyciwygChannelParent::RecvAsyncOpen(const URIParams& aOriginal,
198
                                    const uint32_t& aLoadFlags,
199
                                    const IPC::SerializedLoadContext& loadContext,
200
                                    const PBrowserOrId &aParent)
201
0
{
202
0
  nsCOMPtr<nsIURI> original = DeserializeURI(aOriginal);
203
0
  if (!original)
204
0
    return IPC_FAIL_NO_REASON(this);
205
0
206
0
  LOG(("WyciwygChannelParent RecvAsyncOpen [this=%p]\n", this));
207
0
208
0
  if (!mChannel)
209
0
    return IPC_OK();
210
0
211
0
  nsresult rv;
212
0
213
0
  rv = mChannel->SetOriginalURI(original);
214
0
  if (NS_FAILED(rv)) {
215
0
    if (!SendCancelEarly(rv)) {
216
0
      return IPC_FAIL_NO_REASON(this);
217
0
    }
218
0
    return IPC_OK();
219
0
  }
220
0
221
0
  rv = mChannel->SetLoadFlags(aLoadFlags);
222
0
  if (NS_FAILED(rv)) {
223
0
    if (!SendCancelEarly(rv)) {
224
0
      return IPC_FAIL_NO_REASON(this);
225
0
    }
226
0
    return IPC_OK();
227
0
  }
228
0
229
0
  if (!mReceivedAppData && !SetupAppData(loadContext, aParent)) {
230
0
    return IPC_FAIL_NO_REASON(this);
231
0
  }
232
0
233
0
  rv = mChannel->SetNotificationCallbacks(this);
234
0
  if (NS_FAILED(rv)) {
235
0
    if (!SendCancelEarly(rv)) {
236
0
      return IPC_FAIL_NO_REASON(this);
237
0
    }
238
0
    return IPC_OK();
239
0
  }
240
0
241
0
  nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
242
0
  if (loadInfo && loadInfo->GetEnforceSecurity()) {
243
0
    rv = mChannel->AsyncOpen2(this);
244
0
  }
245
0
  else {
246
0
    rv = mChannel->AsyncOpen(this, nullptr);
247
0
  }
248
0
249
0
  if (NS_FAILED(rv)) {
250
0
    if (!SendCancelEarly(rv)) {
251
0
      return IPC_FAIL_NO_REASON(this);
252
0
    }
253
0
    return IPC_OK();
254
0
  }
255
0
256
0
  return IPC_OK();
257
0
}
258
259
mozilla::ipc::IPCResult
260
WyciwygChannelParent::RecvWriteToCacheEntry(const nsDependentSubstring& data)
261
0
{
262
0
  if (!mReceivedAppData) {
263
0
    printf_stderr("WyciwygChannelParent::RecvWriteToCacheEntry: FATAL ERROR: didn't receive app data\n");
264
0
    return IPC_FAIL_NO_REASON(this);
265
0
  }
266
0
267
0
  if (mChannel)
268
0
    mChannel->WriteToCacheEntry(data);
269
0
270
0
  return IPC_OK();
271
0
}
272
273
mozilla::ipc::IPCResult
274
WyciwygChannelParent::RecvCloseCacheEntry(const nsresult& reason)
275
0
{
276
0
  if (mChannel) {
277
0
    mChannel->CloseCacheEntry(reason);
278
0
  }
279
0
280
0
  return IPC_OK();
281
0
}
282
283
mozilla::ipc::IPCResult
284
WyciwygChannelParent::RecvSetCharsetAndSource(const int32_t& aCharsetSource,
285
                                              const nsCString& aCharset)
286
0
{
287
0
  if (mChannel)
288
0
    mChannel->SetCharsetAndSource(aCharsetSource, aCharset);
289
0
290
0
  return IPC_OK();
291
0
}
292
293
mozilla::ipc::IPCResult
294
WyciwygChannelParent::RecvSetSecurityInfo(const nsCString& aSecurityInfo)
295
0
{
296
0
  if (mChannel) {
297
0
    nsCOMPtr<nsISupports> securityInfo;
298
0
    NS_DeserializeObject(aSecurityInfo, getter_AddRefs(securityInfo));
299
0
    mChannel->SetSecurityInfo(securityInfo);
300
0
  }
301
0
302
0
  return IPC_OK();
303
0
}
304
305
mozilla::ipc::IPCResult
306
WyciwygChannelParent::RecvCancel(const nsresult& aStatusCode)
307
0
{
308
0
  if (mChannel)
309
0
    mChannel->Cancel(aStatusCode);
310
0
  return IPC_OK();
311
0
}
312
313
//-----------------------------------------------------------------------------
314
// WyciwygChannelParent::nsIRequestObserver
315
//-----------------------------------------------------------------------------
316
317
NS_IMETHODIMP
318
WyciwygChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
319
0
{
320
0
  LOG(("WyciwygChannelParent::OnStartRequest [this=%p]\n", this));
321
0
322
0
  nsresult rv;
323
0
324
0
  nsCOMPtr<nsIWyciwygChannel> chan = do_QueryInterface(aRequest, &rv);
325
0
  NS_ENSURE_SUCCESS(rv, rv);
326
0
327
0
  // Send down any permissions which are relevant to this URL if we are
328
0
  // performing a document load.
329
0
  if (!mIPCClosed) {
330
0
    PContentParent* pcp = Manager()->Manager();
331
0
    MOZ_ASSERT(pcp, "We should have a manager if our IPC isn't closed");
332
0
    rv = static_cast<ContentParent*>(pcp)->AboutToLoadHttpFtpWyciwygDocumentForChild(chan);
333
0
    MOZ_ASSERT(NS_SUCCEEDED(rv));
334
0
  }
335
0
336
0
  nsresult status;
337
0
  chan->GetStatus(&status);
338
0
339
0
  int64_t contentLength = -1;
340
0
  chan->GetContentLength(&contentLength);
341
0
342
0
  int32_t charsetSource = kCharsetUninitialized;
343
0
  nsAutoCString charset;
344
0
  chan->GetCharsetAndSource(&charsetSource, charset);
345
0
346
0
  nsCOMPtr<nsISupports> securityInfo;
347
0
  chan->GetSecurityInfo(getter_AddRefs(securityInfo));
348
0
  nsCString secInfoStr;
349
0
  if (securityInfo) {
350
0
    nsCOMPtr<nsISerializable> serializable = do_QueryInterface(securityInfo);
351
0
    if (serializable)
352
0
      NS_SerializeToString(serializable, secInfoStr);
353
0
    else {
354
0
      NS_ERROR("Can't serialize security info");
355
0
      return NS_ERROR_UNEXPECTED;
356
0
    }
357
0
  }
358
0
359
0
  if (mIPCClosed ||
360
0
      !SendOnStartRequest(status, contentLength, charsetSource, charset, secInfoStr)) {
361
0
    return NS_ERROR_UNEXPECTED;
362
0
  }
363
0
364
0
  return NS_OK;
365
0
}
366
367
NS_IMETHODIMP
368
WyciwygChannelParent::OnStopRequest(nsIRequest *aRequest,
369
                                    nsISupports *aContext,
370
                                    nsresult aStatusCode)
371
0
{
372
0
  LOG(("WyciwygChannelParent::OnStopRequest: [this=%p status=%" PRIu32 "]\n",
373
0
       this, static_cast<uint32_t>(aStatusCode)));
374
0
375
0
  if (mIPCClosed || !SendOnStopRequest(aStatusCode)) {
376
0
    return NS_ERROR_UNEXPECTED;
377
0
  }
378
0
379
0
  return NS_OK;
380
0
}
381
382
//-----------------------------------------------------------------------------
383
// WyciwygChannelParent::nsIStreamListener
384
//-----------------------------------------------------------------------------
385
386
NS_IMETHODIMP
387
WyciwygChannelParent::OnDataAvailable(nsIRequest *aRequest,
388
                                      nsISupports *aContext,
389
                                      nsIInputStream *aInputStream,
390
                                      uint64_t aOffset,
391
                                      uint32_t aCount)
392
0
{
393
0
  LOG(("WyciwygChannelParent::OnDataAvailable [this=%p]\n", this));
394
0
395
0
  nsCString data;
396
0
  nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
397
0
  if (NS_FAILED(rv))
398
0
    return rv;
399
0
400
0
  if (mIPCClosed || !SendOnDataAvailable(data, aOffset)) {
401
0
    return NS_ERROR_UNEXPECTED;
402
0
  }
403
0
404
0
  return NS_OK;
405
0
}
406
407
//-----------------------------------------------------------------------------
408
// WyciwygChannelParent::nsIInterfaceRequestor
409
//-----------------------------------------------------------------------------
410
411
NS_IMETHODIMP
412
WyciwygChannelParent::GetInterface(const nsIID& uuid, void** result)
413
0
{
414
0
  // Only support nsILoadContext if child channel's callbacks did too
415
0
  if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
416
0
    nsCOMPtr<nsILoadContext> copy = mLoadContext;
417
0
    copy.forget(result);
418
0
    return NS_OK;
419
0
  }
420
0
421
0
  return QueryInterface(uuid, result);
422
0
}
423
424
425
} // namespace net
426
} // namespace mozilla