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