1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 "nsHttp.h"
9 #include "mozilla/BasePrincipal.h"
10 #include "mozilla/ContentPrincipal.h"
11 #include "mozilla/ipc/IPCStreamUtils.h"
12 #include "mozilla/net/ExtensionProtocolHandler.h"
13 #include "mozilla/net/PageThumbProtocolHandler.h"
14 #include "mozilla/net/NeckoParent.h"
15 #include "mozilla/net/HttpChannelParent.h"
16 #include "mozilla/net/CookieServiceParent.h"
17 #include "mozilla/net/WebSocketChannelParent.h"
18 #include "mozilla/net/WebSocketEventListenerParent.h"
19 #include "mozilla/net/DataChannelParent.h"
20 #ifdef MOZ_WIDGET_GTK
21 #  include "mozilla/net/GIOChannelParent.h"
22 #endif
23 #include "mozilla/net/DocumentChannelParent.h"
24 #include "mozilla/net/SimpleChannelParent.h"
25 #include "mozilla/net/AltDataOutputStreamParent.h"
26 #include "mozilla/Unused.h"
27 #include "mozilla/net/FileChannelParent.h"
28 #include "mozilla/net/DNSRequestParent.h"
29 #include "mozilla/net/ClassifierDummyChannelParent.h"
30 #include "mozilla/net/IPCTransportProvider.h"
31 #include "mozilla/net/RequestContextService.h"
32 #include "mozilla/net/SocketProcessParent.h"
33 #include "mozilla/net/PSocketProcessBridgeParent.h"
34 #ifdef MOZ_WEBRTC
35 #  include "mozilla/net/StunAddrsRequestParent.h"
36 #  include "mozilla/net/WebrtcTCPSocketParent.h"
37 #endif
38 #include "mozilla/dom/ChromeUtils.h"
39 #include "mozilla/dom/ContentParent.h"
40 #include "mozilla/dom/TabContext.h"
41 #include "mozilla/dom/BrowserParent.h"
42 #include "mozilla/dom/network/TCPSocketParent.h"
43 #include "mozilla/dom/network/TCPServerSocketParent.h"
44 #include "mozilla/dom/network/UDPSocketParent.h"
45 #include "mozilla/dom/ServiceWorkerManager.h"
46 #include "mozilla/LoadContext.h"
47 #include "mozilla/MozPromise.h"
48 #include "nsPrintfCString.h"
49 #include "mozilla/dom/HTMLDNSPrefetch.h"
50 #include "nsEscape.h"
51 #include "SerializedLoadContext.h"
52 #include "nsAuthInformationHolder.h"
53 #include "nsINetworkPredictor.h"
54 #include "nsINetworkPredictorVerifier.h"
55 #include "nsISpeculativeConnect.h"
56 #include "nsHttpHandler.h"
57 #include "nsNetUtil.h"
58 
59 using IPC::SerializedLoadContext;
60 using mozilla::OriginAttributes;
61 using mozilla::dom::BrowserParent;
62 using mozilla::dom::ChromeUtils;
63 using mozilla::dom::ContentParent;
64 using mozilla::dom::ServiceWorkerManager;
65 using mozilla::dom::TabContext;
66 using mozilla::dom::TCPServerSocketParent;
67 using mozilla::dom::TCPSocketParent;
68 using mozilla::dom::UDPSocketParent;
69 using mozilla::ipc::LoadInfoArgsToLoadInfo;
70 using mozilla::ipc::PrincipalInfo;
71 using mozilla::net::PTCPServerSocketParent;
72 using mozilla::net::PTCPSocketParent;
73 using mozilla::net::PUDPSocketParent;
74 
75 namespace mozilla {
76 namespace net {
77 
78 // C++ file contents
NeckoParent()79 NeckoParent::NeckoParent() : mSocketProcessBridgeInited(false) {
80   // Init HTTP protocol handler now since we need atomTable up and running very
81   // early (IPDL argument handling for PHttpChannel constructor needs it) so
82   // normal init (during 1st Http channel request) isn't early enough.
83   nsCOMPtr<nsIProtocolHandler> proto =
84       do_GetService("@mozilla.org/network/protocol;1?name=http");
85 }
86 
PBOverrideStatusFromLoadContext(const SerializedLoadContext & aSerialized)87 static PBOverrideStatus PBOverrideStatusFromLoadContext(
88     const SerializedLoadContext& aSerialized) {
89   if (!aSerialized.IsNotNull() && aSerialized.IsPrivateBitValid()) {
90     return (aSerialized.mOriginAttributes.mPrivateBrowsingId > 0)
91                ? kPBOverride_Private
92                : kPBOverride_NotPrivate;
93   }
94   return kPBOverride_Unset;
95 }
96 
GetRequestingPrincipal(const Maybe<LoadInfoArgs> & aOptionalLoadInfoArgs)97 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
98     const Maybe<LoadInfoArgs>& aOptionalLoadInfoArgs) {
99   if (aOptionalLoadInfoArgs.isNothing()) {
100     return nullptr;
101   }
102 
103   const LoadInfoArgs& loadInfoArgs = aOptionalLoadInfoArgs.ref();
104   const Maybe<PrincipalInfo>& optionalPrincipalInfo =
105       loadInfoArgs.requestingPrincipalInfo();
106 
107   if (optionalPrincipalInfo.isNothing()) {
108     return nullptr;
109   }
110 
111   const PrincipalInfo& principalInfo = optionalPrincipalInfo.ref();
112 
113   auto principalOrErr = PrincipalInfoToPrincipal(principalInfo);
114   return principalOrErr.isOk() ? principalOrErr.unwrap().forget() : nullptr;
115 }
116 
GetRequestingPrincipal(const HttpChannelCreationArgs & aArgs)117 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
118     const HttpChannelCreationArgs& aArgs) {
119   if (aArgs.type() != HttpChannelCreationArgs::THttpChannelOpenArgs) {
120     return nullptr;
121   }
122 
123   const HttpChannelOpenArgs& args = aArgs.get_HttpChannelOpenArgs();
124   return GetRequestingPrincipal(args.loadInfo());
125 }
126 
GetValidatedOriginAttributes(const SerializedLoadContext & aSerialized,PContentParent * aContent,nsIPrincipal * aRequestingPrincipal,OriginAttributes & aAttrs)127 const char* NeckoParent::GetValidatedOriginAttributes(
128     const SerializedLoadContext& aSerialized, PContentParent* aContent,
129     nsIPrincipal* aRequestingPrincipal, OriginAttributes& aAttrs) {
130   if (!aSerialized.IsNotNull()) {
131     // If serialized is null, we cannot validate anything. We have to assume
132     // that this requests comes from a SystemPrincipal.
133     aAttrs = OriginAttributes(false);
134   } else {
135     aAttrs = aSerialized.mOriginAttributes;
136   }
137   return nullptr;
138 }
139 
CreateChannelLoadContext(PBrowserParent * aBrowser,PContentParent * aContent,const SerializedLoadContext & aSerialized,nsIPrincipal * aRequestingPrincipal,nsCOMPtr<nsILoadContext> & aResult)140 const char* NeckoParent::CreateChannelLoadContext(
141     PBrowserParent* aBrowser, PContentParent* aContent,
142     const SerializedLoadContext& aSerialized,
143     nsIPrincipal* aRequestingPrincipal, nsCOMPtr<nsILoadContext>& aResult) {
144   OriginAttributes attrs;
145   const char* error = GetValidatedOriginAttributes(aSerialized, aContent,
146                                                    aRequestingPrincipal, attrs);
147   if (error) {
148     return error;
149   }
150 
151   // if !UsingNeckoIPCSecurity(), we may not have a LoadContext to set. This is
152   // the common case for most xpcshell tests.
153   if (aSerialized.IsNotNull()) {
154     attrs.SyncAttributesWithPrivateBrowsing(
155         aSerialized.mOriginAttributes.mPrivateBrowsingId > 0);
156 
157     RefPtr<BrowserParent> browserParent = BrowserParent::GetFrom(aBrowser);
158     dom::Element* topFrameElement = nullptr;
159     if (browserParent) {
160       topFrameElement = browserParent->GetOwnerElement();
161     }
162     aResult = new LoadContext(aSerialized, topFrameElement, attrs);
163   }
164 
165   return nullptr;
166 }
167 
ActorDestroy(ActorDestroyReason aWhy)168 void NeckoParent::ActorDestroy(ActorDestroyReason aWhy) {
169   // Nothing needed here. Called right before destructor since this is a
170   // non-refcounted class.
171 }
172 
AllocPHttpChannelParent(PBrowserParent * aBrowser,const SerializedLoadContext & aSerialized,const HttpChannelCreationArgs & aOpenArgs)173 already_AddRefed<PHttpChannelParent> NeckoParent::AllocPHttpChannelParent(
174     PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
175     const HttpChannelCreationArgs& aOpenArgs) {
176   nsCOMPtr<nsIPrincipal> requestingPrincipal =
177       GetRequestingPrincipal(aOpenArgs);
178 
179   nsCOMPtr<nsILoadContext> loadContext;
180   const char* error = CreateChannelLoadContext(
181       aBrowser, Manager(), aSerialized, requestingPrincipal, loadContext);
182   if (error) {
183     printf_stderr(
184         "NeckoParent::AllocPHttpChannelParent: "
185         "FATAL error: %s: KILLING CHILD PROCESS\n",
186         error);
187     return nullptr;
188   }
189   PBOverrideStatus overrideStatus =
190       PBOverrideStatusFromLoadContext(aSerialized);
191   RefPtr<HttpChannelParent> p = new HttpChannelParent(
192       BrowserParent::GetFrom(aBrowser), loadContext, overrideStatus);
193   return p.forget();
194 }
195 
RecvPHttpChannelConstructor(PHttpChannelParent * aActor,PBrowserParent * aBrowser,const SerializedLoadContext & aSerialized,const HttpChannelCreationArgs & aOpenArgs)196 mozilla::ipc::IPCResult NeckoParent::RecvPHttpChannelConstructor(
197     PHttpChannelParent* aActor, PBrowserParent* aBrowser,
198     const SerializedLoadContext& aSerialized,
199     const HttpChannelCreationArgs& aOpenArgs) {
200   HttpChannelParent* p = static_cast<HttpChannelParent*>(aActor);
201   if (!p->Init(aOpenArgs)) {
202     return IPC_FAIL_NO_REASON(this);
203   }
204   return IPC_OK();
205 }
206 
AllocPStunAddrsRequestParent()207 PStunAddrsRequestParent* NeckoParent::AllocPStunAddrsRequestParent() {
208 #ifdef MOZ_WEBRTC
209   StunAddrsRequestParent* p = new StunAddrsRequestParent();
210   p->AddRef();
211   return p;
212 #else
213   return nullptr;
214 #endif
215 }
216 
DeallocPStunAddrsRequestParent(PStunAddrsRequestParent * aActor)217 bool NeckoParent::DeallocPStunAddrsRequestParent(
218     PStunAddrsRequestParent* aActor) {
219 #ifdef MOZ_WEBRTC
220   StunAddrsRequestParent* p = static_cast<StunAddrsRequestParent*>(aActor);
221   p->Release();
222 #endif
223   return true;
224 }
225 
AllocPWebrtcTCPSocketParent(const Maybe<TabId> & aTabId)226 PWebrtcTCPSocketParent* NeckoParent::AllocPWebrtcTCPSocketParent(
227     const Maybe<TabId>& aTabId) {
228 #ifdef MOZ_WEBRTC
229   WebrtcTCPSocketParent* parent = new WebrtcTCPSocketParent(aTabId);
230   parent->AddRef();
231   return parent;
232 #else
233   return nullptr;
234 #endif
235 }
236 
DeallocPWebrtcTCPSocketParent(PWebrtcTCPSocketParent * aActor)237 bool NeckoParent::DeallocPWebrtcTCPSocketParent(
238     PWebrtcTCPSocketParent* aActor) {
239 #ifdef MOZ_WEBRTC
240   WebrtcTCPSocketParent* parent = static_cast<WebrtcTCPSocketParent*>(aActor);
241   parent->Release();
242 #endif
243   return true;
244 }
245 
AllocPAltDataOutputStreamParent(const nsCString & type,const int64_t & predictedSize,PHttpChannelParent * channel)246 PAltDataOutputStreamParent* NeckoParent::AllocPAltDataOutputStreamParent(
247     const nsCString& type, const int64_t& predictedSize,
248     PHttpChannelParent* channel) {
249   HttpChannelParent* chan = static_cast<HttpChannelParent*>(channel);
250   nsCOMPtr<nsIAsyncOutputStream> stream;
251   nsresult rv = chan->OpenAlternativeOutputStream(type, predictedSize,
252                                                   getter_AddRefs(stream));
253   AltDataOutputStreamParent* parent = new AltDataOutputStreamParent(stream);
254   parent->AddRef();
255   // If the return value was not NS_OK, the error code will be sent
256   // asynchronously to the child, after receiving the first message.
257   parent->SetError(rv);
258   return parent;
259 }
260 
DeallocPAltDataOutputStreamParent(PAltDataOutputStreamParent * aActor)261 bool NeckoParent::DeallocPAltDataOutputStreamParent(
262     PAltDataOutputStreamParent* aActor) {
263   AltDataOutputStreamParent* parent =
264       static_cast<AltDataOutputStreamParent*>(aActor);
265   parent->Release();
266   return true;
267 }
268 
269 already_AddRefed<PDocumentChannelParent>
AllocPDocumentChannelParent(const MaybeDiscarded<BrowsingContext> & aContext,const DocumentChannelCreationArgs & args)270 NeckoParent::AllocPDocumentChannelParent(
271     const MaybeDiscarded<BrowsingContext>& aContext,
272     const DocumentChannelCreationArgs& args) {
273   RefPtr<DocumentChannelParent> p = new DocumentChannelParent();
274   return p.forget();
275 }
276 
RecvPDocumentChannelConstructor(PDocumentChannelParent * aActor,const MaybeDiscarded<BrowsingContext> & aContext,const DocumentChannelCreationArgs & aArgs)277 mozilla::ipc::IPCResult NeckoParent::RecvPDocumentChannelConstructor(
278     PDocumentChannelParent* aActor,
279     const MaybeDiscarded<BrowsingContext>& aContext,
280     const DocumentChannelCreationArgs& aArgs) {
281   DocumentChannelParent* p = static_cast<DocumentChannelParent*>(aActor);
282 
283   if (aContext.IsNullOrDiscarded()) {
284     Unused << p->SendFailedAsyncOpen(NS_ERROR_FAILURE);
285     return IPC_OK();
286   }
287 
288   if (!p->Init(aContext.get_canonical(), aArgs)) {
289     return IPC_FAIL(this, "Couldn't initialize DocumentChannel");
290   }
291 
292   return IPC_OK();
293 }
294 
AllocPCookieServiceParent()295 PCookieServiceParent* NeckoParent::AllocPCookieServiceParent() {
296   return new CookieServiceParent();
297 }
298 
DeallocPCookieServiceParent(PCookieServiceParent * cs)299 bool NeckoParent::DeallocPCookieServiceParent(PCookieServiceParent* cs) {
300   delete cs;
301   return true;
302 }
303 
AllocPWebSocketParent(PBrowserParent * browser,const SerializedLoadContext & serialized,const uint32_t & aSerial)304 PWebSocketParent* NeckoParent::AllocPWebSocketParent(
305     PBrowserParent* browser, const SerializedLoadContext& serialized,
306     const uint32_t& aSerial) {
307   nsCOMPtr<nsILoadContext> loadContext;
308   const char* error = CreateChannelLoadContext(browser, Manager(), serialized,
309                                                nullptr, loadContext);
310   if (error) {
311     printf_stderr(
312         "NeckoParent::AllocPWebSocketParent: "
313         "FATAL error: %s: KILLING CHILD PROCESS\n",
314         error);
315     return nullptr;
316   }
317 
318   RefPtr<BrowserParent> browserParent = BrowserParent::GetFrom(browser);
319   PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized);
320   WebSocketChannelParent* p = new WebSocketChannelParent(
321       browserParent, loadContext, overrideStatus, aSerial);
322   p->AddRef();
323   return p;
324 }
325 
DeallocPWebSocketParent(PWebSocketParent * actor)326 bool NeckoParent::DeallocPWebSocketParent(PWebSocketParent* actor) {
327   WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor);
328   p->Release();
329   return true;
330 }
331 
AllocPWebSocketEventListenerParent(const uint64_t & aInnerWindowID)332 PWebSocketEventListenerParent* NeckoParent::AllocPWebSocketEventListenerParent(
333     const uint64_t& aInnerWindowID) {
334   RefPtr<WebSocketEventListenerParent> c =
335       new WebSocketEventListenerParent(aInnerWindowID);
336   return c.forget().take();
337 }
338 
DeallocPWebSocketEventListenerParent(PWebSocketEventListenerParent * aActor)339 bool NeckoParent::DeallocPWebSocketEventListenerParent(
340     PWebSocketEventListenerParent* aActor) {
341   RefPtr<WebSocketEventListenerParent> c =
342       dont_AddRef(static_cast<WebSocketEventListenerParent*>(aActor));
343   MOZ_ASSERT(c);
344   return true;
345 }
346 
AllocPDataChannelParent(const uint32_t & channelId)347 already_AddRefed<PDataChannelParent> NeckoParent::AllocPDataChannelParent(
348     const uint32_t& channelId) {
349   RefPtr<DataChannelParent> p = new DataChannelParent();
350   return p.forget();
351 }
352 
RecvPDataChannelConstructor(PDataChannelParent * actor,const uint32_t & channelId)353 mozilla::ipc::IPCResult NeckoParent::RecvPDataChannelConstructor(
354     PDataChannelParent* actor, const uint32_t& channelId) {
355   DataChannelParent* p = static_cast<DataChannelParent*>(actor);
356   DebugOnly<bool> rv = p->Init(channelId);
357   MOZ_ASSERT(rv);
358   return IPC_OK();
359 }
360 
361 #ifdef MOZ_WIDGET_GTK
GetRequestingPrincipal(const GIOChannelCreationArgs & aArgs)362 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal(
363     const GIOChannelCreationArgs& aArgs) {
364   if (aArgs.type() != GIOChannelCreationArgs::TGIOChannelOpenArgs) {
365     return nullptr;
366   }
367 
368   const GIOChannelOpenArgs& args = aArgs.get_GIOChannelOpenArgs();
369   return GetRequestingPrincipal(args.loadInfo());
370 }
371 
AllocPGIOChannelParent(PBrowserParent * aBrowser,const SerializedLoadContext & aSerialized,const GIOChannelCreationArgs & aOpenArgs)372 PGIOChannelParent* NeckoParent::AllocPGIOChannelParent(
373     PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
374     const GIOChannelCreationArgs& aOpenArgs) {
375   nsCOMPtr<nsIPrincipal> requestingPrincipal =
376       GetRequestingPrincipal(aOpenArgs);
377 
378   nsCOMPtr<nsILoadContext> loadContext;
379   const char* error = CreateChannelLoadContext(
380       aBrowser, Manager(), aSerialized, requestingPrincipal, loadContext);
381   if (error) {
382     printf_stderr(
383         "NeckoParent::AllocPGIOChannelParent: "
384         "FATAL error: %s: KILLING CHILD PROCESS\n",
385         error);
386     return nullptr;
387   }
388   PBOverrideStatus overrideStatus =
389       PBOverrideStatusFromLoadContext(aSerialized);
390   GIOChannelParent* p = new GIOChannelParent(BrowserParent::GetFrom(aBrowser),
391                                              loadContext, overrideStatus);
392   p->AddRef();
393   return p;
394 }
395 
DeallocPGIOChannelParent(PGIOChannelParent * channel)396 bool NeckoParent::DeallocPGIOChannelParent(PGIOChannelParent* channel) {
397   GIOChannelParent* p = static_cast<GIOChannelParent*>(channel);
398   p->Release();
399   return true;
400 }
401 
RecvPGIOChannelConstructor(PGIOChannelParent * actor,PBrowserParent * aBrowser,const SerializedLoadContext & aSerialized,const GIOChannelCreationArgs & aOpenArgs)402 mozilla::ipc::IPCResult NeckoParent::RecvPGIOChannelConstructor(
403     PGIOChannelParent* actor, PBrowserParent* aBrowser,
404     const SerializedLoadContext& aSerialized,
405     const GIOChannelCreationArgs& aOpenArgs) {
406   GIOChannelParent* p = static_cast<GIOChannelParent*>(actor);
407   DebugOnly<bool> rv = p->Init(aOpenArgs);
408   MOZ_ASSERT(rv);
409   return IPC_OK();
410 }
411 #endif
412 
AllocPSimpleChannelParent(const uint32_t & channelId)413 PSimpleChannelParent* NeckoParent::AllocPSimpleChannelParent(
414     const uint32_t& channelId) {
415   RefPtr<SimpleChannelParent> p = new SimpleChannelParent();
416   return p.forget().take();
417 }
418 
DeallocPSimpleChannelParent(PSimpleChannelParent * actor)419 bool NeckoParent::DeallocPSimpleChannelParent(PSimpleChannelParent* actor) {
420   RefPtr<SimpleChannelParent> p =
421       dont_AddRef(actor).downcast<SimpleChannelParent>();
422   return true;
423 }
424 
RecvPSimpleChannelConstructor(PSimpleChannelParent * actor,const uint32_t & channelId)425 mozilla::ipc::IPCResult NeckoParent::RecvPSimpleChannelConstructor(
426     PSimpleChannelParent* actor, const uint32_t& channelId) {
427   SimpleChannelParent* p = static_cast<SimpleChannelParent*>(actor);
428   MOZ_ALWAYS_TRUE(p->Init(channelId));
429   return IPC_OK();
430 }
431 
AllocPFileChannelParent(const uint32_t & channelId)432 already_AddRefed<PFileChannelParent> NeckoParent::AllocPFileChannelParent(
433     const uint32_t& channelId) {
434   RefPtr<FileChannelParent> p = new FileChannelParent();
435   return p.forget();
436 }
437 
RecvPFileChannelConstructor(PFileChannelParent * actor,const uint32_t & channelId)438 mozilla::ipc::IPCResult NeckoParent::RecvPFileChannelConstructor(
439     PFileChannelParent* actor, const uint32_t& channelId) {
440   FileChannelParent* p = static_cast<FileChannelParent*>(actor);
441   DebugOnly<bool> rv = p->Init(channelId);
442   MOZ_ASSERT(rv);
443   return IPC_OK();
444 }
445 
AllocPTCPSocketParent(const nsString &,const uint16_t &)446 PTCPSocketParent* NeckoParent::AllocPTCPSocketParent(
447     const nsString& /* host */, const uint16_t& /* port */) {
448   // We actually don't need host/port to construct a TCPSocketParent since
449   // TCPSocketParent will maintain an internal nsIDOMTCPSocket instance which
450   // can be delegated to get the host/port.
451   TCPSocketParent* p = new TCPSocketParent();
452   p->AddIPDLReference();
453   return p;
454 }
455 
DeallocPTCPSocketParent(PTCPSocketParent * actor)456 bool NeckoParent::DeallocPTCPSocketParent(PTCPSocketParent* actor) {
457   TCPSocketParent* p = static_cast<TCPSocketParent*>(actor);
458   p->ReleaseIPDLReference();
459   return true;
460 }
461 
AllocPTCPServerSocketParent(const uint16_t & aLocalPort,const uint16_t & aBacklog,const bool & aUseArrayBuffers)462 PTCPServerSocketParent* NeckoParent::AllocPTCPServerSocketParent(
463     const uint16_t& aLocalPort, const uint16_t& aBacklog,
464     const bool& aUseArrayBuffers) {
465   TCPServerSocketParent* p =
466       new TCPServerSocketParent(this, aLocalPort, aBacklog, aUseArrayBuffers);
467   p->AddIPDLReference();
468   return p;
469 }
470 
RecvPTCPServerSocketConstructor(PTCPServerSocketParent * aActor,const uint16_t & aLocalPort,const uint16_t & aBacklog,const bool & aUseArrayBuffers)471 mozilla::ipc::IPCResult NeckoParent::RecvPTCPServerSocketConstructor(
472     PTCPServerSocketParent* aActor, const uint16_t& aLocalPort,
473     const uint16_t& aBacklog, const bool& aUseArrayBuffers) {
474   static_cast<TCPServerSocketParent*>(aActor)->Init();
475   return IPC_OK();
476 }
477 
DeallocPTCPServerSocketParent(PTCPServerSocketParent * actor)478 bool NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor) {
479   TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor);
480   p->ReleaseIPDLReference();
481   return true;
482 }
483 
AllocPUDPSocketParent(nsIPrincipal *,const nsCString &)484 PUDPSocketParent* NeckoParent::AllocPUDPSocketParent(
485     nsIPrincipal* /* unused */, const nsCString& /* unused */) {
486   RefPtr<UDPSocketParent> p = new UDPSocketParent(this);
487 
488   return p.forget().take();
489 }
490 
RecvPUDPSocketConstructor(PUDPSocketParent * aActor,nsIPrincipal * aPrincipal,const nsCString & aFilter)491 mozilla::ipc::IPCResult NeckoParent::RecvPUDPSocketConstructor(
492     PUDPSocketParent* aActor, nsIPrincipal* aPrincipal,
493     const nsCString& aFilter) {
494   if (!static_cast<UDPSocketParent*>(aActor)->Init(aPrincipal, aFilter)) {
495     return IPC_FAIL_NO_REASON(this);
496   }
497   return IPC_OK();
498 }
499 
DeallocPUDPSocketParent(PUDPSocketParent * actor)500 bool NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor) {
501   UDPSocketParent* p = static_cast<UDPSocketParent*>(actor);
502   p->Release();
503   return true;
504 }
505 
AllocPDNSRequestParent(const nsCString & aHost,const nsCString & aTrrServer,const uint16_t & aType,const OriginAttributes & aOriginAttributes,const uint32_t & aFlags)506 already_AddRefed<PDNSRequestParent> NeckoParent::AllocPDNSRequestParent(
507     const nsCString& aHost, const nsCString& aTrrServer, const uint16_t& aType,
508     const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
509   RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
510   RefPtr<DNSRequestParent> actor = new DNSRequestParent(handler);
511   return actor.forget();
512 }
513 
RecvPDNSRequestConstructor(PDNSRequestParent * aActor,const nsCString & aHost,const nsCString & aTrrServer,const uint16_t & aType,const OriginAttributes & aOriginAttributes,const uint32_t & aFlags)514 mozilla::ipc::IPCResult NeckoParent::RecvPDNSRequestConstructor(
515     PDNSRequestParent* aActor, const nsCString& aHost,
516     const nsCString& aTrrServer, const uint16_t& aType,
517     const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
518   RefPtr<DNSRequestParent> actor = static_cast<DNSRequestParent*>(aActor);
519   RefPtr<DNSRequestHandler> handler =
520       actor->GetDNSRequest()->AsDNSRequestHandler();
521   handler->DoAsyncResolve(aHost, aTrrServer, aType, aOriginAttributes, aFlags);
522   return IPC_OK();
523 }
524 
RecvSpeculativeConnect(nsIURI * aURI,nsIPrincipal * aPrincipal,const bool & aAnonymous)525 mozilla::ipc::IPCResult NeckoParent::RecvSpeculativeConnect(
526     nsIURI* aURI, nsIPrincipal* aPrincipal, const bool& aAnonymous) {
527   nsCOMPtr<nsISpeculativeConnect> speculator(gIOService);
528   nsCOMPtr<nsIPrincipal> principal(aPrincipal);
529   if (!aURI) {
530     return IPC_FAIL(this, "aURI must not be null");
531   }
532   if (aURI && speculator) {
533     if (aAnonymous) {
534       speculator->SpeculativeAnonymousConnect(aURI, principal, nullptr);
535     } else {
536       speculator->SpeculativeConnect(aURI, principal, nullptr);
537     }
538   }
539   return IPC_OK();
540 }
541 
RecvHTMLDNSPrefetch(const nsString & hostname,const bool & isHttps,const OriginAttributes & aOriginAttributes,const uint32_t & flags)542 mozilla::ipc::IPCResult NeckoParent::RecvHTMLDNSPrefetch(
543     const nsString& hostname, const bool& isHttps,
544     const OriginAttributes& aOriginAttributes, const uint32_t& flags) {
545   HTMLDNSPrefetch::Prefetch(hostname, isHttps, aOriginAttributes, flags);
546   return IPC_OK();
547 }
548 
RecvCancelHTMLDNSPrefetch(const nsString & hostname,const bool & isHttps,const OriginAttributes & aOriginAttributes,const uint32_t & flags,const nsresult & reason)549 mozilla::ipc::IPCResult NeckoParent::RecvCancelHTMLDNSPrefetch(
550     const nsString& hostname, const bool& isHttps,
551     const OriginAttributes& aOriginAttributes, const uint32_t& flags,
552     const nsresult& reason) {
553   HTMLDNSPrefetch::CancelPrefetch(hostname, isHttps, aOriginAttributes, flags,
554                                   reason);
555   return IPC_OK();
556 }
557 
AllocPTransportProviderParent()558 PTransportProviderParent* NeckoParent::AllocPTransportProviderParent() {
559   RefPtr<TransportProviderParent> res = new TransportProviderParent();
560   return res.forget().take();
561 }
562 
DeallocPTransportProviderParent(PTransportProviderParent * aActor)563 bool NeckoParent::DeallocPTransportProviderParent(
564     PTransportProviderParent* aActor) {
565   RefPtr<TransportProviderParent> provider =
566       dont_AddRef(static_cast<TransportProviderParent*>(aActor));
567   return true;
568 }
569 
570 /* Predictor Messages */
RecvPredPredict(nsIURI * aTargetURI,nsIURI * aSourceURI,const uint32_t & aReason,const OriginAttributes & aOriginAttributes,const bool & hasVerifier)571 mozilla::ipc::IPCResult NeckoParent::RecvPredPredict(
572     nsIURI* aTargetURI, nsIURI* aSourceURI, const uint32_t& aReason,
573     const OriginAttributes& aOriginAttributes, const bool& hasVerifier) {
574   // Get the current predictor
575   nsresult rv = NS_OK;
576   nsCOMPtr<nsINetworkPredictor> predictor =
577       do_GetService("@mozilla.org/network/predictor;1", &rv);
578   NS_ENSURE_SUCCESS(rv, IPC_OK());
579 
580   nsCOMPtr<nsINetworkPredictorVerifier> verifier;
581   if (hasVerifier) {
582     verifier = do_QueryInterface(predictor);
583   }
584   predictor->PredictNative(aTargetURI, aSourceURI, aReason, aOriginAttributes,
585                            verifier);
586   return IPC_OK();
587 }
588 
RecvPredLearn(nsIURI * aTargetURI,nsIURI * aSourceURI,const uint32_t & aReason,const OriginAttributes & aOriginAttributes)589 mozilla::ipc::IPCResult NeckoParent::RecvPredLearn(
590     nsIURI* aTargetURI, nsIURI* aSourceURI, const uint32_t& aReason,
591     const OriginAttributes& aOriginAttributes) {
592   // Get the current predictor
593   nsresult rv = NS_OK;
594   nsCOMPtr<nsINetworkPredictor> predictor =
595       do_GetService("@mozilla.org/network/predictor;1", &rv);
596   NS_ENSURE_SUCCESS(rv, IPC_OK());
597 
598   predictor->LearnNative(aTargetURI, aSourceURI, aReason, aOriginAttributes);
599   return IPC_OK();
600 }
601 
RecvPredReset()602 mozilla::ipc::IPCResult NeckoParent::RecvPredReset() {
603   // Get the current predictor
604   nsresult rv = NS_OK;
605   nsCOMPtr<nsINetworkPredictor> predictor =
606       do_GetService("@mozilla.org/network/predictor;1", &rv);
607   NS_ENSURE_SUCCESS(rv, IPC_OK());
608 
609   predictor->Reset();
610   return IPC_OK();
611 }
612 
RecvRequestContextLoadBegin(const uint64_t & rcid)613 mozilla::ipc::IPCResult NeckoParent::RecvRequestContextLoadBegin(
614     const uint64_t& rcid) {
615   nsCOMPtr<nsIRequestContextService> rcsvc =
616       RequestContextService::GetOrCreate();
617   if (!rcsvc) {
618     return IPC_OK();
619   }
620   nsCOMPtr<nsIRequestContext> rc;
621   rcsvc->GetRequestContext(rcid, getter_AddRefs(rc));
622   if (rc) {
623     rc->BeginLoad();
624   }
625 
626   return IPC_OK();
627 }
628 
RecvRequestContextAfterDOMContentLoaded(const uint64_t & rcid)629 mozilla::ipc::IPCResult NeckoParent::RecvRequestContextAfterDOMContentLoaded(
630     const uint64_t& rcid) {
631   nsCOMPtr<nsIRequestContextService> rcsvc =
632       RequestContextService::GetOrCreate();
633   if (!rcsvc) {
634     return IPC_OK();
635   }
636   nsCOMPtr<nsIRequestContext> rc;
637   rcsvc->GetRequestContext(rcid, getter_AddRefs(rc));
638   if (rc) {
639     rc->DOMContentLoaded();
640   }
641 
642   return IPC_OK();
643 }
644 
RecvRemoveRequestContext(const uint64_t & rcid)645 mozilla::ipc::IPCResult NeckoParent::RecvRemoveRequestContext(
646     const uint64_t& rcid) {
647   nsCOMPtr<nsIRequestContextService> rcsvc =
648       RequestContextService::GetOrCreate();
649   if (!rcsvc) {
650     return IPC_OK();
651   }
652 
653   rcsvc->RemoveRequestContext(rcid);
654 
655   return IPC_OK();
656 }
657 
RecvGetExtensionStream(nsIURI * aURI,GetExtensionStreamResolver && aResolve)658 mozilla::ipc::IPCResult NeckoParent::RecvGetExtensionStream(
659     nsIURI* aURI, GetExtensionStreamResolver&& aResolve) {
660   if (!aURI) {
661     return IPC_FAIL(this, "aURI must not be null");
662   }
663 
664   RefPtr<ExtensionProtocolHandler> ph(ExtensionProtocolHandler::GetSingleton());
665   MOZ_ASSERT(ph);
666 
667   // Ask the ExtensionProtocolHandler to give us a new input stream for
668   // this URI. The request comes from an ExtensionProtocolHandler in the
669   // child process, but is not guaranteed to be a valid moz-extension URI,
670   // and not guaranteed to represent a resource that the child should be
671   // allowed to access. The ExtensionProtocolHandler is responsible for
672   // validating the request. Specifically, only URI's for local files that
673   // an extension is allowed to access via moz-extension URI's should be
674   // accepted.
675   nsCOMPtr<nsIInputStream> inputStream;
676   bool terminateSender = true;
677   auto inputStreamOrReason = ph->NewStream(aURI, &terminateSender);
678   if (inputStreamOrReason.isOk()) {
679     inputStream = inputStreamOrReason.unwrap();
680   }
681 
682   // If NewStream failed, we send back an invalid stream to the child so
683   // it can handle the error. MozPromise rejection is reserved for channel
684   // errors/disconnects.
685   aResolve(inputStream);
686 
687   if (terminateSender) {
688     return IPC_FAIL_NO_REASON(this);
689   }
690   return IPC_OK();
691 }
692 
RecvGetExtensionFD(nsIURI * aURI,GetExtensionFDResolver && aResolve)693 mozilla::ipc::IPCResult NeckoParent::RecvGetExtensionFD(
694     nsIURI* aURI, GetExtensionFDResolver&& aResolve) {
695   if (!aURI) {
696     return IPC_FAIL(this, "aURI must not be null");
697   }
698 
699   RefPtr<ExtensionProtocolHandler> ph(ExtensionProtocolHandler::GetSingleton());
700   MOZ_ASSERT(ph);
701 
702   // Ask the ExtensionProtocolHandler to give us a new input stream for
703   // this URI. The request comes from an ExtensionProtocolHandler in the
704   // child process, but is not guaranteed to be a valid moz-extension URI,
705   // and not guaranteed to represent a resource that the child should be
706   // allowed to access. The ExtensionProtocolHandler is responsible for
707   // validating the request. Specifically, only URI's for local files that
708   // an extension is allowed to access via moz-extension URI's should be
709   // accepted.
710   bool terminateSender = true;
711   auto result = ph->NewFD(aURI, &terminateSender, aResolve);
712 
713   if (result.isErr() && terminateSender) {
714     return IPC_FAIL_NO_REASON(this);
715   }
716 
717   if (result.isErr()) {
718     FileDescriptor invalidFD;
719     aResolve(invalidFD);
720   }
721 
722   return IPC_OK();
723 }
724 
AllocPClassifierDummyChannelParent(nsIURI * aURI,nsIURI * aTopWindowURI,const nsresult & aTopWindowURIResult,const Maybe<LoadInfoArgs> & aLoadInfo)725 PClassifierDummyChannelParent* NeckoParent::AllocPClassifierDummyChannelParent(
726     nsIURI* aURI, nsIURI* aTopWindowURI, const nsresult& aTopWindowURIResult,
727     const Maybe<LoadInfoArgs>& aLoadInfo) {
728   RefPtr<ClassifierDummyChannelParent> c = new ClassifierDummyChannelParent();
729   return c.forget().take();
730 }
731 
RecvPClassifierDummyChannelConstructor(PClassifierDummyChannelParent * aActor,nsIURI * aURI,nsIURI * aTopWindowURI,const nsresult & aTopWindowURIResult,const Maybe<LoadInfoArgs> & aLoadInfo)732 mozilla::ipc::IPCResult NeckoParent::RecvPClassifierDummyChannelConstructor(
733     PClassifierDummyChannelParent* aActor, nsIURI* aURI, nsIURI* aTopWindowURI,
734     const nsresult& aTopWindowURIResult, const Maybe<LoadInfoArgs>& aLoadInfo) {
735   ClassifierDummyChannelParent* p =
736       static_cast<ClassifierDummyChannelParent*>(aActor);
737 
738   if (NS_WARN_IF(!aURI)) {
739     return IPC_FAIL_NO_REASON(this);
740   }
741 
742   nsCOMPtr<nsILoadInfo> loadInfo;
743   nsresult rv = LoadInfoArgsToLoadInfo(aLoadInfo, getter_AddRefs(loadInfo));
744   if (NS_WARN_IF(NS_FAILED(rv)) || !loadInfo) {
745     return IPC_FAIL_NO_REASON(this);
746   }
747 
748   p->Init(aURI, aTopWindowURI, aTopWindowURIResult, loadInfo);
749   return IPC_OK();
750 }
751 
DeallocPClassifierDummyChannelParent(PClassifierDummyChannelParent * aActor)752 bool NeckoParent::DeallocPClassifierDummyChannelParent(
753     PClassifierDummyChannelParent* aActor) {
754   RefPtr<ClassifierDummyChannelParent> c =
755       dont_AddRef(static_cast<ClassifierDummyChannelParent*>(aActor));
756   MOZ_ASSERT(c);
757   return true;
758 }
759 
RecvInitSocketProcessBridge(InitSocketProcessBridgeResolver && aResolver)760 mozilla::ipc::IPCResult NeckoParent::RecvInitSocketProcessBridge(
761     InitSocketProcessBridgeResolver&& aResolver) {
762   MOZ_ASSERT(NS_IsMainThread());
763 
764   // Initing the socket process bridge must be async here in order to
765   // wait for the socket process launch before executing.
766   auto task = [self = this, resolver = std::move(aResolver)]() {
767     Endpoint<PSocketProcessBridgeChild> invalidEndpoint;
768     if (NS_WARN_IF(self->mSocketProcessBridgeInited)) {
769       resolver(std::move(invalidEndpoint));
770       return;
771     }
772 
773     SocketProcessParent* parent = SocketProcessParent::GetSingleton();
774     if (NS_WARN_IF(!parent)) {
775       resolver(std::move(invalidEndpoint));
776       return;
777     }
778 
779     Endpoint<PSocketProcessBridgeParent> parentEndpoint;
780     Endpoint<PSocketProcessBridgeChild> childEndpoint;
781     if (NS_WARN_IF(NS_FAILED(PSocketProcessBridge::CreateEndpoints(
782             parent->OtherPid(), self->Manager()->OtherPid(), &parentEndpoint,
783             &childEndpoint)))) {
784       resolver(std::move(invalidEndpoint));
785       return;
786     }
787 
788     if (NS_WARN_IF(!parent->SendInitSocketProcessBridgeParent(
789             self->Manager()->OtherPid(), std::move(parentEndpoint)))) {
790       resolver(std::move(invalidEndpoint));
791       return;
792     }
793 
794     resolver(std::move(childEndpoint));
795     self->mSocketProcessBridgeInited = true;
796   };
797   gIOService->CallOrWaitForSocketProcess(std::move(task));
798 
799   return IPC_OK();
800 }
801 
RecvResetSocketProcessBridge()802 mozilla::ipc::IPCResult NeckoParent::RecvResetSocketProcessBridge() {
803   // SendResetSocketProcessBridge is called from
804   // SocketProcessBridgeChild::ActorDestroy if the socket process
805   // crashes.  This is necessary in order to properly initialize the
806   // restarted socket process.
807   mSocketProcessBridgeInited = false;
808   return IPC_OK();
809 }
810 
RecvEnsureHSTSData(EnsureHSTSDataResolver && aResolver)811 mozilla::ipc::IPCResult NeckoParent::RecvEnsureHSTSData(
812     EnsureHSTSDataResolver&& aResolver) {
813   auto callback = [aResolver{std::move(aResolver)}](bool aResult) {
814     aResolver(aResult);
815   };
816   RefPtr<HSTSDataCallbackWrapper> wrapper =
817       new HSTSDataCallbackWrapper(std::move(callback));
818   gHttpHandler->EnsureHSTSDataReadyNative(wrapper);
819   return IPC_OK();
820 }
821 
RecvGetPageThumbStream(nsIURI * aURI,GetPageThumbStreamResolver && aResolver)822 mozilla::ipc::IPCResult NeckoParent::RecvGetPageThumbStream(
823     nsIURI* aURI, GetPageThumbStreamResolver&& aResolver) {
824   // Only the privileged about content process is allowed to access
825   // things over the moz-page-thumb protocol. Any other content process
826   // that tries to send this should have been blocked via the
827   // ScriptSecurityManager, but if somehow the process has been tricked into
828   // sending this message, we send IPC_FAIL in order to crash that
829   // likely-compromised content process.
830   if (static_cast<ContentParent*>(Manager())->GetRemoteType() !=
831       PRIVILEGEDABOUT_REMOTE_TYPE) {
832     return IPC_FAIL(this, "Wrong process type");
833   }
834 
835   RefPtr<PageThumbProtocolHandler> ph(PageThumbProtocolHandler::GetSingleton());
836   MOZ_ASSERT(ph);
837 
838   // Ask the PageThumbProtocolHandler to give us a new input stream for
839   // this URI. The request comes from a PageThumbProtocolHandler in the
840   // child process, but is not guaranteed to be a valid moz-page-thumb URI,
841   // and not guaranteed to represent a resource that the child should be
842   // allowed to access. The PageThumbProtocolHandler is responsible for
843   // validating the request.
844   nsCOMPtr<nsIInputStream> inputStream;
845   bool terminateSender = true;
846   auto inputStreamPromise = ph->NewStream(aURI, &terminateSender);
847 
848   if (terminateSender) {
849     return IPC_FAIL(this, "Malformed moz-page-thumb request");
850   }
851 
852   inputStreamPromise->Then(
853       GetMainThreadSerialEventTarget(), __func__,
854       [aResolver](const nsCOMPtr<nsIInputStream>& aStream) {
855         aResolver(aStream);
856       },
857       [aResolver](nsresult aRv) {
858         // If NewStream failed, we send back an invalid stream to the child so
859         // it can handle the error. MozPromise rejection is reserved for channel
860         // errors/disconnects.
861         Unused << NS_WARN_IF(NS_FAILED(aRv));
862         aResolver(nullptr);
863       });
864 
865   return IPC_OK();
866 }
867 
868 }  // namespace net
869 }  // namespace mozilla
870