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