Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/ipc/NeckoChild.cpp
Line
Count
Source (jump to first uncovered line)
1
2
/* vim: set sw=2 ts=8 et tw=80 : */
3
4
/* This Source Code Form is subject to the terms of the Mozilla Public
5
 * License, v. 2.0. If a copy of the MPL was not distributed with this
6
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8
#include "necko-config.h"
9
#include "nsHttp.h"
10
#include "mozilla/net/NeckoChild.h"
11
#include "mozilla/dom/ContentChild.h"
12
#include "mozilla/dom/TabChild.h"
13
#include "mozilla/net/HttpChannelChild.h"
14
#include "mozilla/net/CookieServiceChild.h"
15
#include "mozilla/net/WyciwygChannelChild.h"
16
#include "mozilla/net/FTPChannelChild.h"
17
#include "mozilla/net/WebSocketChannelChild.h"
18
#include "mozilla/net/WebSocketEventListenerChild.h"
19
#include "mozilla/net/DNSRequestChild.h"
20
#include "mozilla/net/ChannelDiverterChild.h"
21
#include "mozilla/net/IPCTransportProvider.h"
22
#include "mozilla/dom/network/TCPSocketChild.h"
23
#include "mozilla/dom/network/TCPServerSocketChild.h"
24
#include "mozilla/dom/network/UDPSocketChild.h"
25
#include "mozilla/net/AltDataOutputStreamChild.h"
26
#ifdef MOZ_WEBRTC
27
#include "mozilla/net/StunAddrsRequestChild.h"
28
#endif
29
30
#include "SerializedLoadContext.h"
31
#include "nsGlobalWindow.h"
32
#include "nsIOService.h"
33
#include "nsINetworkPredictor.h"
34
#include "nsINetworkPredictorVerifier.h"
35
#include "nsINetworkLinkService.h"
36
#include "nsIRedirectProcessChooser.h"
37
#include "nsQueryObject.h"
38
#include "mozilla/ipc/URIUtils.h"
39
#include "nsNetUtil.h"
40
41
using mozilla::dom::TCPSocketChild;
42
using mozilla::dom::TCPServerSocketChild;
43
using mozilla::dom::UDPSocketChild;
44
45
namespace mozilla {
46
namespace net {
47
48
PNeckoChild *gNeckoChild = nullptr;
49
50
// C++ file contents
51
52
NeckoChild::~NeckoChild()
53
0
{
54
0
  //Send__delete__(gNeckoChild);
55
0
  gNeckoChild = nullptr;
56
0
}
57
58
void NeckoChild::InitNeckoChild()
59
0
{
60
0
  MOZ_ASSERT(IsNeckoChild(), "InitNeckoChild called by non-child!");
61
0
62
0
  if (!gNeckoChild) {
63
0
    mozilla::dom::ContentChild * cpc =
64
0
      mozilla::dom::ContentChild::GetSingleton();
65
0
    NS_ASSERTION(cpc, "Content Protocol is NULL!");
66
0
    if (NS_WARN_IF(cpc->IsShuttingDown())) {
67
0
      return;
68
0
    }
69
0
    gNeckoChild = cpc->SendPNeckoConstructor();
70
0
    NS_ASSERTION(gNeckoChild, "PNecko Protocol init failed!");
71
0
  }
72
0
}
73
74
PHttpChannelChild*
75
NeckoChild::AllocPHttpChannelChild(const PBrowserOrId& browser,
76
                                   const SerializedLoadContext& loadContext,
77
                                   const HttpChannelCreationArgs& aOpenArgs)
78
0
{
79
0
  // We don't allocate here: instead we always use IPDL constructor that takes
80
0
  // an existing HttpChildChannel
81
0
  MOZ_ASSERT_UNREACHABLE("AllocPHttpChannelChild should not be called on "
82
0
                         "child");
83
0
  return nullptr;
84
0
}
85
86
bool
87
NeckoChild::DeallocPHttpChannelChild(PHttpChannelChild* channel)
88
0
{
89
0
  MOZ_ASSERT(IsNeckoChild(), "DeallocPHttpChannelChild called by non-child!");
90
0
91
0
  HttpChannelChild* child = static_cast<HttpChannelChild*>(channel);
92
0
  child->ReleaseIPDLReference();
93
0
  return true;
94
0
}
95
96
PStunAddrsRequestChild*
97
NeckoChild::AllocPStunAddrsRequestChild()
98
0
{
99
0
  // We don't allocate here: instead we always use IPDL constructor that takes
100
0
  // an existing object
101
0
  MOZ_ASSERT_UNREACHABLE("AllocPStunAddrsRequestChild should not be called "
102
0
                         "on child");
103
0
  return nullptr;
104
0
}
105
106
bool
107
NeckoChild::DeallocPStunAddrsRequestChild(PStunAddrsRequestChild* aActor)
108
0
{
109
0
#ifdef MOZ_WEBRTC
110
0
  StunAddrsRequestChild* p = static_cast<StunAddrsRequestChild*>(aActor);
111
0
  p->ReleaseIPDLReference();
112
0
#endif
113
0
  return true;
114
0
}
115
116
PAltDataOutputStreamChild*
117
NeckoChild::AllocPAltDataOutputStreamChild(
118
        const nsCString& type,
119
        const int64_t& predictedSize,
120
        PHttpChannelChild* channel)
121
0
{
122
0
  // We don't allocate here: see HttpChannelChild::OpenAlternativeOutputStream()
123
0
  MOZ_ASSERT_UNREACHABLE("AllocPAltDataOutputStreamChild should not be called");
124
0
  return nullptr;
125
0
}
126
127
bool
128
NeckoChild::DeallocPAltDataOutputStreamChild(PAltDataOutputStreamChild* aActor)
129
0
{
130
0
  AltDataOutputStreamChild* child = static_cast<AltDataOutputStreamChild*>(aActor);
131
0
  child->ReleaseIPDLReference();
132
0
  return true;
133
0
}
134
135
PFTPChannelChild*
136
NeckoChild::AllocPFTPChannelChild(const PBrowserOrId& aBrowser,
137
                                  const SerializedLoadContext& aSerialized,
138
                                  const FTPChannelCreationArgs& aOpenArgs)
139
0
{
140
0
  // We don't allocate here: see FTPChannelChild::AsyncOpen()
141
0
  MOZ_CRASH("AllocPFTPChannelChild should not be called");
142
0
  return nullptr;
143
0
}
144
145
bool
146
NeckoChild::DeallocPFTPChannelChild(PFTPChannelChild* channel)
147
0
{
148
0
  MOZ_ASSERT(IsNeckoChild(), "DeallocPFTPChannelChild called by non-child!");
149
0
150
0
  FTPChannelChild* child = static_cast<FTPChannelChild*>(channel);
151
0
  child->ReleaseIPDLReference();
152
0
  return true;
153
0
}
154
155
PCookieServiceChild*
156
NeckoChild::AllocPCookieServiceChild()
157
0
{
158
0
  // We don't allocate here: see nsCookieService::GetSingleton()
159
0
  MOZ_ASSERT_UNREACHABLE("AllocPCookieServiceChild should not be called");
160
0
  return nullptr;
161
0
}
162
163
bool
164
NeckoChild::DeallocPCookieServiceChild(PCookieServiceChild* cs)
165
0
{
166
0
  NS_ASSERTION(IsNeckoChild(), "DeallocPCookieServiceChild called by non-child!");
167
0
168
0
  CookieServiceChild *p = static_cast<CookieServiceChild*>(cs);
169
0
  p->Release();
170
0
  return true;
171
0
}
172
173
PWyciwygChannelChild*
174
NeckoChild::AllocPWyciwygChannelChild()
175
0
{
176
0
  // We don't allocate here: see nsWyciwygProtocolHandler::NewChannel2()
177
0
  MOZ_ASSERT_UNREACHABLE("AllocPWyciwygChannelChild should not be called");
178
0
  return nullptr;
179
0
}
180
181
bool
182
NeckoChild::DeallocPWyciwygChannelChild(PWyciwygChannelChild* channel)
183
0
{
184
0
  MOZ_ASSERT(IsNeckoChild(), "DeallocPWyciwygChannelChild called by non-child!");
185
0
186
0
  WyciwygChannelChild *p = static_cast<WyciwygChannelChild*>(channel);
187
0
  p->ReleaseIPDLReference();
188
0
  return true;
189
0
}
190
191
PWebSocketChild*
192
NeckoChild::AllocPWebSocketChild(const PBrowserOrId& browser,
193
                                 const SerializedLoadContext& aSerialized,
194
                                 const uint32_t& aSerial)
195
0
{
196
0
  MOZ_ASSERT_UNREACHABLE("AllocPWebSocketChild should not be called");
197
0
  return nullptr;
198
0
}
199
200
bool
201
NeckoChild::DeallocPWebSocketChild(PWebSocketChild* child)
202
0
{
203
0
  WebSocketChannelChild* p = static_cast<WebSocketChannelChild*>(child);
204
0
  p->ReleaseIPDLReference();
205
0
  return true;
206
0
}
207
208
PWebSocketEventListenerChild*
209
NeckoChild::AllocPWebSocketEventListenerChild(const uint64_t& aInnerWindowID)
210
0
{
211
0
  nsCOMPtr<nsIEventTarget> target;
212
0
  if (nsGlobalWindowInner* win = nsGlobalWindowInner::GetInnerWindowWithId(aInnerWindowID)) {
213
0
    target = win->EventTargetFor(TaskCategory::Other);
214
0
  }
215
0
216
0
  RefPtr<WebSocketEventListenerChild> c =
217
0
    new WebSocketEventListenerChild(aInnerWindowID, target);
218
0
219
0
  if (target) {
220
0
    gNeckoChild->SetEventTargetForActor(c, target);
221
0
  }
222
0
223
0
  return c.forget().take();
224
0
}
225
226
bool
227
NeckoChild::DeallocPWebSocketEventListenerChild(PWebSocketEventListenerChild* aActor)
228
0
{
229
0
  RefPtr<WebSocketEventListenerChild> c =
230
0
    dont_AddRef(static_cast<WebSocketEventListenerChild*>(aActor));
231
0
  MOZ_ASSERT(c);
232
0
  return true;
233
0
}
234
235
PDataChannelChild*
236
NeckoChild::AllocPDataChannelChild(const uint32_t& channelId)
237
0
{
238
0
  MOZ_ASSERT_UNREACHABLE("Should never get here");
239
0
  return nullptr;
240
0
}
241
242
bool
243
NeckoChild::DeallocPDataChannelChild(PDataChannelChild* child)
244
0
{
245
0
  // NB: See DataChannelChild::ActorDestroy.
246
0
  return true;
247
0
}
248
249
PFileChannelChild*
250
NeckoChild::AllocPFileChannelChild(const uint32_t& channelId)
251
0
{
252
0
  MOZ_ASSERT_UNREACHABLE("Should never get here");
253
0
  return nullptr;
254
0
}
255
256
bool
257
NeckoChild::DeallocPFileChannelChild(PFileChannelChild* child)
258
0
{
259
0
  // NB: See FileChannelChild::ActorDestroy.
260
0
  return true;
261
0
}
262
263
PSimpleChannelChild*
264
NeckoChild::AllocPSimpleChannelChild(const uint32_t& channelId)
265
0
{
266
0
  MOZ_ASSERT_UNREACHABLE("Should never get here");
267
0
  return nullptr;
268
0
}
269
270
bool
271
NeckoChild::DeallocPSimpleChannelChild(PSimpleChannelChild* child)
272
0
{
273
0
  // NB: See SimpleChannelChild::ActorDestroy.
274
0
  return true;
275
0
}
276
277
PTCPSocketChild*
278
NeckoChild::AllocPTCPSocketChild(const nsString& host,
279
                                 const uint16_t& port)
280
0
{
281
0
  TCPSocketChild* p = new TCPSocketChild(host, port, nullptr);
282
0
  p->AddIPDLReference();
283
0
  return p;
284
0
}
285
286
bool
287
NeckoChild::DeallocPTCPSocketChild(PTCPSocketChild* child)
288
0
{
289
0
  TCPSocketChild* p = static_cast<TCPSocketChild*>(child);
290
0
  p->ReleaseIPDLReference();
291
0
  return true;
292
0
}
293
294
PTCPServerSocketChild*
295
NeckoChild::AllocPTCPServerSocketChild(const uint16_t& aLocalPort,
296
                                  const uint16_t& aBacklog,
297
                                  const bool& aUseArrayBuffers)
298
0
{
299
0
  MOZ_ASSERT_UNREACHABLE("AllocPTCPServerSocket should not be called");
300
0
  return nullptr;
301
0
}
302
303
bool
304
NeckoChild::DeallocPTCPServerSocketChild(PTCPServerSocketChild* child)
305
0
{
306
0
  TCPServerSocketChild* p = static_cast<TCPServerSocketChild*>(child);
307
0
  p->ReleaseIPDLReference();
308
0
  return true;
309
0
}
310
311
PUDPSocketChild*
312
NeckoChild::AllocPUDPSocketChild(const Principal& aPrincipal,
313
                                 const nsCString& aFilter)
314
0
{
315
0
  MOZ_ASSERT_UNREACHABLE("AllocPUDPSocket should not be called");
316
0
  return nullptr;
317
0
}
318
319
bool
320
NeckoChild::DeallocPUDPSocketChild(PUDPSocketChild* child)
321
0
{
322
0
323
0
  UDPSocketChild* p = static_cast<UDPSocketChild*>(child);
324
0
  p->ReleaseIPDLReference();
325
0
  return true;
326
0
}
327
328
PDNSRequestChild*
329
NeckoChild::AllocPDNSRequestChild(const nsCString& aHost,
330
                                  const OriginAttributes& aOriginAttributes,
331
                                  const uint32_t& aFlags)
332
0
{
333
0
  // We don't allocate here: instead we always use IPDL constructor that takes
334
0
  // an existing object
335
0
  MOZ_ASSERT_UNREACHABLE("AllocPDNSRequestChild should not be called on child");
336
0
  return nullptr;
337
0
}
338
339
bool
340
NeckoChild::DeallocPDNSRequestChild(PDNSRequestChild* aChild)
341
0
{
342
0
  DNSRequestChild *p = static_cast<DNSRequestChild*>(aChild);
343
0
  p->ReleaseIPDLReference();
344
0
  return true;
345
0
}
346
347
PChannelDiverterChild*
348
NeckoChild::AllocPChannelDiverterChild(const ChannelDiverterArgs& channel)
349
0
{
350
0
  return new ChannelDiverterChild();;
351
0
}
352
353
bool
354
NeckoChild::DeallocPChannelDiverterChild(PChannelDiverterChild* child)
355
0
{
356
0
  delete static_cast<ChannelDiverterChild*>(child);
357
0
  return true;
358
0
}
359
360
PTransportProviderChild*
361
NeckoChild::AllocPTransportProviderChild()
362
0
{
363
0
  // This refcount is transferred to the receiver of the message that
364
0
  // includes the PTransportProviderChild actor.
365
0
  RefPtr<TransportProviderChild> res = new TransportProviderChild();
366
0
367
0
  return res.forget().take();
368
0
}
369
370
bool
371
NeckoChild::DeallocPTransportProviderChild(PTransportProviderChild* aActor)
372
0
{
373
0
  return true;
374
0
}
375
376
mozilla::ipc::IPCResult
377
NeckoChild::RecvCrossProcessRedirect(
378
            const uint32_t& aRegistrarId,
379
            nsIURI* aURI,
380
            const uint32_t& aNewLoadFlags,
381
            const OptionalLoadInfoArgs& aLoadInfo,
382
            const uint64_t& aChannelId,
383
            nsIURI* aOriginalURI,
384
            const uint64_t& aIdentifier)
385
0
{
386
0
  nsCOMPtr<nsILoadInfo> loadInfo;
387
0
  nsresult rv = ipc::LoadInfoArgsToLoadInfo(aLoadInfo, getter_AddRefs(loadInfo));
388
0
  if (NS_FAILED(rv)) {
389
0
    MOZ_DIAGNOSTIC_ASSERT(false, "LoadInfoArgsToLoadInfo failed");
390
0
    return IPC_OK();
391
0
  }
392
0
393
0
  nsCOMPtr<nsIChannel> newChannel;
394
0
  rv = NS_NewChannelInternal(getter_AddRefs(newChannel),
395
0
                             aURI,
396
0
                             loadInfo,
397
0
                             nullptr, // PerformanceStorage
398
0
                             nullptr, // aLoadGroup
399
0
                             nullptr, // aCallbacks
400
0
                             aNewLoadFlags);
401
0
402
0
  // We are sure this is a HttpChannelChild because the parent
403
0
  // is always a HTTP channel.
404
0
  RefPtr<HttpChannelChild> httpChild = do_QueryObject(newChannel);
405
0
  if (NS_FAILED(rv) || !httpChild) {
406
0
    MOZ_DIAGNOSTIC_ASSERT(false, "NS_NewChannelInternal failed");
407
0
    return IPC_OK();
408
0
  }
409
0
410
0
  // This is used to report any errors back to the parent by calling
411
0
  // CrossProcessRedirectFinished.
412
0
  auto scopeExit = MakeScopeExit([&]() {
413
0
    httpChild->CrossProcessRedirectFinished(rv);
414
0
  });
415
0
416
0
  rv = httpChild->SetChannelId(aChannelId);
417
0
  if (NS_FAILED(rv)) {
418
0
    return IPC_OK();
419
0
  }
420
0
421
0
  rv = httpChild->SetOriginalURI(aOriginalURI);
422
0
  if (NS_FAILED(rv)) {
423
0
    return IPC_OK();
424
0
  }
425
0
426
0
  // connect parent.
427
0
  rv = httpChild->ConnectParent(aRegistrarId); // creates parent channel
428
0
  if (NS_FAILED(rv)) {
429
0
    return IPC_OK();
430
0
  }
431
0
432
0
  nsCOMPtr<nsIChildProcessChannelListener> processListener =
433
0
      do_GetClassObject("@mozilla.org/network/childProcessChannelListener");
434
0
  // The listener will call completeRedirectSetup on the channel.
435
0
  rv = processListener->OnChannelReady(httpChild, aIdentifier);
436
0
  if (NS_FAILED(rv)) {
437
0
    return IPC_OK();
438
0
  }
439
0
440
0
  // scopeExit will call CrossProcessRedirectFinished(rv) here
441
0
  return IPC_OK();
442
0
}
443
444
mozilla::ipc::IPCResult
445
NeckoChild::RecvAsyncAuthPromptForNestedFrame(const TabId& aNestedFrameId,
446
                                              const nsCString& aUri,
447
                                              const nsString& aRealm,
448
                                              const uint64_t& aCallbackId)
449
0
{
450
0
  RefPtr<dom::TabChild> tabChild = dom::TabChild::FindTabChild(aNestedFrameId);
451
0
  if (!tabChild) {
452
0
    MOZ_CRASH();
453
0
    return IPC_FAIL_NO_REASON(this);
454
0
  }
455
0
  tabChild->SendAsyncAuthPrompt(aUri, aRealm, aCallbackId);
456
0
  return IPC_OK();
457
0
}
458
459
/* Predictor Messages */
460
mozilla::ipc::IPCResult
461
NeckoChild::RecvPredOnPredictPrefetch(const URIParams& aURI,
462
                                      const uint32_t& aHttpStatus)
463
0
{
464
0
  MOZ_ASSERT(NS_IsMainThread(), "PredictorChild::RecvOnPredictPrefetch "
465
0
                                "off main thread.");
466
0
467
0
  nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
468
0
469
0
  // Get the current predictor
470
0
  nsresult rv = NS_OK;
471
0
  nsCOMPtr<nsINetworkPredictorVerifier> predictor =
472
0
    do_GetService("@mozilla.org/network/predictor;1", &rv);
473
0
  NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
474
0
475
0
  predictor->OnPredictPrefetch(uri, aHttpStatus);
476
0
  return IPC_OK();
477
0
}
478
479
mozilla::ipc::IPCResult
480
NeckoChild::RecvPredOnPredictPreconnect(const URIParams& aURI)
481
0
{
482
0
  MOZ_ASSERT(NS_IsMainThread(), "PredictorChild::RecvOnPredictPreconnect "
483
0
                                "off main thread.");
484
0
485
0
  nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
486
0
487
0
  // Get the current predictor
488
0
  nsresult rv = NS_OK;
489
0
  nsCOMPtr<nsINetworkPredictorVerifier> predictor =
490
0
    do_GetService("@mozilla.org/network/predictor;1", &rv);
491
0
  NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
492
0
493
0
  predictor->OnPredictPreconnect(uri);
494
0
  return IPC_OK();
495
0
}
496
497
mozilla::ipc::IPCResult
498
NeckoChild::RecvPredOnPredictDNS(const URIParams& aURI)
499
0
{
500
0
  MOZ_ASSERT(NS_IsMainThread(), "PredictorChild::RecvOnPredictDNS off "
501
0
                                "main thread.");
502
0
503
0
  nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
504
0
505
0
  // Get the current predictor
506
0
  nsresult rv = NS_OK;
507
0
  nsCOMPtr<nsINetworkPredictorVerifier> predictor =
508
0
    do_GetService("@mozilla.org/network/predictor;1", &rv);
509
0
  NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
510
0
511
0
  predictor->OnPredictDNS(uri);
512
0
  return IPC_OK();
513
0
}
514
515
mozilla::ipc::IPCResult
516
NeckoChild::RecvSpeculativeConnectRequest()
517
0
{
518
0
  nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
519
0
  if (obsService) {
520
0
    obsService->NotifyObservers(nullptr, "speculative-connect-request",
521
0
                                nullptr);
522
0
  }
523
0
  return IPC_OK();
524
0
}
525
526
mozilla::ipc::IPCResult
527
NeckoChild::RecvNetworkChangeNotification(nsCString const& type)
528
0
{
529
0
  nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
530
0
  if (obsService) {
531
0
    obsService->NotifyObservers(nullptr, NS_NETWORK_LINK_TOPIC,
532
0
                                NS_ConvertUTF8toUTF16(type).get());
533
0
  }
534
0
  return IPC_OK();
535
0
}
536
537
} // namespace net
538
} // namespace mozilla