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