NeckoParent.cpp (35751B)
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 "nsBaseParentChannel.h" 9 #include "nsHttp.h" 10 #include "mozilla/BasePrincipal.h" 11 #include "mozilla/Components.h" 12 #include "mozilla/ContentPrincipal.h" 13 #include "mozilla/NullPrincipal.h" 14 #include "mozilla/ipc/IPCStreamUtils.h" 15 #include "mozilla/net/ExtensionProtocolHandler.h" 16 #include "mozilla/net/PageThumbProtocolHandler.h" 17 #include "mozilla/net/MozNewTabWallpaperProtocolHandler.h" 18 #include "mozilla/net/NeckoParent.h" 19 #include "mozilla/net/HttpChannelParent.h" 20 #include "mozilla/net/CookieServiceParent.h" 21 #include "mozilla/net/WebSocketChannelParent.h" 22 #include "mozilla/net/WebSocketEventListenerParent.h" 23 #ifdef MOZ_WIDGET_GTK 24 # include "mozilla/net/GIOChannelParent.h" 25 #endif 26 #ifdef MOZ_WIDGET_ANDROID 27 # include "mozilla/net/GeckoViewContentChannelParent.h" 28 #endif 29 #include "mozilla/net/DocumentChannelParent.h" 30 #include "mozilla/net/CacheEntryWriteHandleParent.h" 31 #include "mozilla/net/AltDataOutputStreamParent.h" 32 #include "mozilla/net/DNSRequestParent.h" 33 #include "mozilla/net/IPCTransportProvider.h" 34 #include "mozilla/net/RemoteStreamGetter.h" 35 #include "mozilla/net/RequestContextService.h" 36 #include "mozilla/net/SocketProcessParent.h" 37 #include "mozilla/net/PSocketProcessBridgeParent.h" 38 #ifdef MOZ_WEBRTC 39 # include "mozilla/net/StunAddrsRequestParent.h" 40 # include "mozilla/net/WebrtcTCPSocketParent.h" 41 #endif 42 #include "mozilla/dom/ContentParent.h" 43 #include "mozilla/dom/BrowserParent.h" 44 #include "mozilla/dom/MaybeDiscarded.h" 45 #include "mozilla/dom/network/TCPSocketParent.h" 46 #include "mozilla/dom/network/TCPServerSocketParent.h" 47 #include "mozilla/dom/network/UDPSocketParent.h" 48 #ifdef MOZ_PLACES 49 # include "mozilla/places/PageIconProtocolHandler.h" 50 #endif 51 #include "mozilla/LoadContext.h" 52 #include "mozilla/MozPromise.h" 53 #include "nsPrintfCString.h" 54 #include "mozilla/dom/HTMLDNSPrefetch.h" 55 #include "nsEscape.h" 56 #include "SerializedLoadContext.h" 57 #include "nsAuthInformationHolder.h" 58 #include "nsISpeculativeConnect.h" 59 #include "nsFileChannel.h" 60 #include "nsHttpHandler.h" 61 #include "nsIMIMEService.h" 62 #include "nsNetUtil.h" 63 #include "nsIOService.h" 64 65 using IPC::SerializedLoadContext; 66 using mozilla::dom::BrowserParent; 67 using mozilla::dom::ContentParent; 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 #ifdef MOZ_PLACES 74 using mozilla::places::PageIconProtocolHandler; 75 #endif 76 77 namespace mozilla { 78 namespace net { 79 80 // C++ file contents 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 89 static PBOverrideStatus PBOverrideStatusFromLoadContext( 90 const SerializedLoadContext& aSerialized) { 91 if (!aSerialized.IsNotNull() && aSerialized.IsPrivateBitValid()) { 92 return aSerialized.mOriginAttributes.IsPrivateBrowsing() 93 ? kPBOverride_Private 94 : kPBOverride_NotPrivate; 95 } 96 return kPBOverride_Unset; 97 } 98 99 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal( 100 const LoadInfoArgs& aLoadInfoArgs) { 101 const Maybe<PrincipalInfo>& optionalPrincipalInfo = 102 aLoadInfoArgs.requestingPrincipalInfo(); 103 104 if (optionalPrincipalInfo.isNothing()) { 105 return nullptr; 106 } 107 108 const PrincipalInfo& principalInfo = optionalPrincipalInfo.ref(); 109 110 auto principalOrErr = PrincipalInfoToPrincipal(principalInfo); 111 return principalOrErr.isOk() ? principalOrErr.unwrap().forget() : nullptr; 112 } 113 114 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal( 115 const HttpChannelCreationArgs& aArgs) { 116 if (aArgs.type() != HttpChannelCreationArgs::THttpChannelOpenArgs) { 117 return nullptr; 118 } 119 120 const HttpChannelOpenArgs& args = aArgs.get_HttpChannelOpenArgs(); 121 return GetRequestingPrincipal(args.loadInfo()); 122 } 123 124 void NeckoParent::GetValidatedOriginAttributes( 125 const SerializedLoadContext& aSerialized, PContentParent* aContent, 126 nsIPrincipal* aRequestingPrincipal, OriginAttributes& aAttrs) { 127 if (!aSerialized.IsNotNull()) { 128 // If serialized is null, we cannot validate anything. We have to assume 129 // that this requests comes from a SystemPrincipal. 130 aAttrs = OriginAttributes(); 131 } else { 132 aAttrs = aSerialized.mOriginAttributes; 133 } 134 } 135 136 void NeckoParent::CreateChannelLoadContext( 137 PBrowserParent* aBrowser, PContentParent* aContent, 138 const SerializedLoadContext& aSerialized, 139 nsIPrincipal* aRequestingPrincipal, nsCOMPtr<nsILoadContext>& aResult) { 140 OriginAttributes attrs; 141 GetValidatedOriginAttributes(aSerialized, aContent, aRequestingPrincipal, 142 attrs); 143 144 if (aSerialized.IsNotNull()) { 145 attrs.SyncAttributesWithPrivateBrowsing( 146 aSerialized.mOriginAttributes.IsPrivateBrowsing()); 147 148 RefPtr<BrowserParent> browserParent = BrowserParent::GetFrom(aBrowser); 149 dom::Element* topFrameElement = nullptr; 150 if (browserParent) { 151 topFrameElement = browserParent->GetOwnerElement(); 152 } 153 aResult = new LoadContext(aSerialized, topFrameElement, attrs); 154 } 155 } 156 157 void NeckoParent::ActorDestroy(ActorDestroyReason aWhy) { 158 // Nothing needed here. Called right before destructor since this is a 159 // non-refcounted class. 160 } 161 162 already_AddRefed<PHttpChannelParent> NeckoParent::AllocPHttpChannelParent( 163 PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized, 164 const HttpChannelCreationArgs& aOpenArgs) { 165 nsCOMPtr<nsIPrincipal> requestingPrincipal = 166 GetRequestingPrincipal(aOpenArgs); 167 168 nsCOMPtr<nsILoadContext> loadContext; 169 CreateChannelLoadContext(aBrowser, Manager(), aSerialized, 170 requestingPrincipal, loadContext); 171 PBOverrideStatus overrideStatus = 172 PBOverrideStatusFromLoadContext(aSerialized); 173 RefPtr<HttpChannelParent> p = new HttpChannelParent( 174 BrowserParent::GetFrom(aBrowser), loadContext, overrideStatus); 175 return p.forget(); 176 } 177 178 mozilla::ipc::IPCResult NeckoParent::RecvPHttpChannelConstructor( 179 PHttpChannelParent* aActor, PBrowserParent* aBrowser, 180 const SerializedLoadContext& aSerialized, 181 const HttpChannelCreationArgs& aOpenArgs) { 182 HttpChannelParent* p = static_cast<HttpChannelParent*>(aActor); 183 if (!p->Init(aOpenArgs)) { 184 return IPC_FAIL_NO_REASON(this); 185 } 186 return IPC_OK(); 187 } 188 189 PStunAddrsRequestParent* NeckoParent::AllocPStunAddrsRequestParent() { 190 #ifdef MOZ_WEBRTC 191 StunAddrsRequestParent* p = new StunAddrsRequestParent(); 192 p->AddRef(); 193 return p; 194 #else 195 return nullptr; 196 #endif 197 } 198 199 bool NeckoParent::DeallocPStunAddrsRequestParent( 200 PStunAddrsRequestParent* aActor) { 201 #ifdef MOZ_WEBRTC 202 StunAddrsRequestParent* p = static_cast<StunAddrsRequestParent*>(aActor); 203 p->Release(); 204 #endif 205 return true; 206 } 207 208 PWebrtcTCPSocketParent* NeckoParent::AllocPWebrtcTCPSocketParent( 209 const Maybe<TabId>& aTabId) { 210 #ifdef MOZ_WEBRTC 211 WebrtcTCPSocketParent* parent = new WebrtcTCPSocketParent(aTabId); 212 parent->AddRef(); 213 return parent; 214 #else 215 return nullptr; 216 #endif 217 } 218 219 bool NeckoParent::DeallocPWebrtcTCPSocketParent( 220 PWebrtcTCPSocketParent* aActor) { 221 #ifdef MOZ_WEBRTC 222 WebrtcTCPSocketParent* parent = static_cast<WebrtcTCPSocketParent*>(aActor); 223 parent->Release(); 224 #endif 225 return true; 226 } 227 228 PCacheEntryWriteHandleParent* NeckoParent::AllocPCacheEntryWriteHandleParent( 229 PHttpChannelParent* channel) { 230 HttpChannelParent* chan = static_cast<HttpChannelParent*>(channel); 231 CacheEntryWriteHandleParent* parent = chan->AllocCacheEntryWriteHandle(); 232 parent->AddRef(); 233 return parent; 234 } 235 236 bool NeckoParent::DeallocPCacheEntryWriteHandleParent( 237 PCacheEntryWriteHandleParent* aActor) { 238 CacheEntryWriteHandleParent* parent = 239 static_cast<CacheEntryWriteHandleParent*>(aActor); 240 parent->Release(); 241 return true; 242 } 243 244 PAltDataOutputStreamParent* NeckoParent::AllocPAltDataOutputStreamParent( 245 const nsACString& type, const int64_t& predictedSize, 246 mozilla::Maybe<mozilla::NotNull<mozilla::net::PHttpChannelParent*>>& 247 channel, 248 mozilla::Maybe<mozilla::NotNull<PCacheEntryWriteHandleParent*>>& handle) { 249 MOZ_ASSERT(channel || handle); 250 251 nsresult rv; 252 nsCOMPtr<nsIAsyncOutputStream> stream; 253 if (channel) { 254 HttpChannelParent* chan = static_cast<HttpChannelParent*>(channel->get()); 255 rv = chan->OpenAlternativeOutputStream(type, predictedSize, 256 getter_AddRefs(stream)); 257 } else { 258 CacheEntryWriteHandleParent* h = 259 static_cast<CacheEntryWriteHandleParent*>(handle->get()); 260 rv = h->OpenAlternativeOutputStream(type, predictedSize, 261 getter_AddRefs(stream)); 262 } 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 271 bool NeckoParent::DeallocPAltDataOutputStreamParent( 272 PAltDataOutputStreamParent* aActor) { 273 AltDataOutputStreamParent* parent = 274 static_cast<AltDataOutputStreamParent*>(aActor); 275 parent->Release(); 276 return true; 277 } 278 279 already_AddRefed<PDocumentChannelParent> 280 NeckoParent::AllocPDocumentChannelParent( 281 const dom::MaybeDiscarded<dom::BrowsingContext>& aContext, 282 const DocumentChannelCreationArgs& args) { 283 RefPtr<DocumentChannelParent> p = new DocumentChannelParent(); 284 return p.forget(); 285 } 286 287 mozilla::ipc::IPCResult NeckoParent::RecvPDocumentChannelConstructor( 288 PDocumentChannelParent* aActor, 289 const dom::MaybeDiscarded<dom::BrowsingContext>& aContext, 290 const DocumentChannelCreationArgs& aArgs) { 291 DocumentChannelParent* p = static_cast<DocumentChannelParent*>(aActor); 292 293 if (aContext.IsNullOrDiscarded()) { 294 (void)p->SendFailedAsyncOpen(NS_ERROR_FAILURE); 295 return IPC_OK(); 296 } 297 298 if (!p->Init(aContext.get_canonical(), aArgs)) { 299 return IPC_FAIL(this, "Couldn't initialize DocumentChannel"); 300 } 301 302 return IPC_OK(); 303 } 304 305 PCookieServiceParent* NeckoParent::AllocPCookieServiceParent() { 306 return new CookieServiceParent(static_cast<ContentParent*>(Manager())); 307 } 308 309 bool NeckoParent::DeallocPCookieServiceParent(PCookieServiceParent* cs) { 310 delete cs; 311 return true; 312 } 313 314 PWebSocketParent* NeckoParent::AllocPWebSocketParent( 315 PBrowserParent* browser, const SerializedLoadContext& serialized, 316 const uint32_t& aSerial) { 317 nsCOMPtr<nsILoadContext> loadContext; 318 CreateChannelLoadContext(browser, Manager(), serialized, nullptr, 319 loadContext); 320 321 RefPtr<BrowserParent> browserParent = BrowserParent::GetFrom(browser); 322 PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized); 323 WebSocketChannelParent* p = new WebSocketChannelParent( 324 browserParent, loadContext, overrideStatus, aSerial); 325 p->AddRef(); 326 return p; 327 } 328 329 bool NeckoParent::DeallocPWebSocketParent(PWebSocketParent* actor) { 330 WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor); 331 p->Release(); 332 return true; 333 } 334 335 PWebSocketEventListenerParent* NeckoParent::AllocPWebSocketEventListenerParent( 336 const uint64_t& aInnerWindowID) { 337 RefPtr<WebSocketEventListenerParent> c = 338 new WebSocketEventListenerParent(aInnerWindowID); 339 return c.forget().take(); 340 } 341 342 bool NeckoParent::DeallocPWebSocketEventListenerParent( 343 PWebSocketEventListenerParent* aActor) { 344 RefPtr<WebSocketEventListenerParent> c = 345 dont_AddRef(static_cast<WebSocketEventListenerParent*>(aActor)); 346 MOZ_ASSERT(c); 347 return true; 348 } 349 350 mozilla::ipc::IPCResult NeckoParent::RecvConnectBaseChannel( 351 const uint32_t& channelId) { 352 RefPtr<nsBaseParentChannel> parentChannel = 353 new nsBaseParentChannel(ContentParent::Cast(Manager())->GetRemoteType()); 354 355 nsCOMPtr<nsIChannel> channel; 356 NS_LinkRedirectChannels(channelId, parentChannel, getter_AddRefs(channel)); 357 return IPC_OK(); 358 } 359 360 #ifdef MOZ_WIDGET_GTK 361 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal( 362 const GIOChannelCreationArgs& aArgs) { 363 if (aArgs.type() != GIOChannelCreationArgs::TGIOChannelOpenArgs) { 364 return nullptr; 365 } 366 367 const GIOChannelOpenArgs& args = aArgs.get_GIOChannelOpenArgs(); 368 return GetRequestingPrincipal(args.loadInfo()); 369 } 370 371 PGIOChannelParent* NeckoParent::AllocPGIOChannelParent( 372 PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized, 373 const GIOChannelCreationArgs& aOpenArgs) { 374 nsCOMPtr<nsIPrincipal> requestingPrincipal = 375 GetRequestingPrincipal(aOpenArgs); 376 377 nsCOMPtr<nsILoadContext> loadContext; 378 CreateChannelLoadContext(aBrowser, Manager(), aSerialized, 379 requestingPrincipal, loadContext); 380 PBOverrideStatus overrideStatus = 381 PBOverrideStatusFromLoadContext(aSerialized); 382 GIOChannelParent* p = new GIOChannelParent(BrowserParent::GetFrom(aBrowser), 383 loadContext, overrideStatus); 384 p->AddRef(); 385 return p; 386 } 387 388 bool NeckoParent::DeallocPGIOChannelParent(PGIOChannelParent* channel) { 389 GIOChannelParent* p = static_cast<GIOChannelParent*>(channel); 390 p->Release(); 391 return true; 392 } 393 394 mozilla::ipc::IPCResult NeckoParent::RecvPGIOChannelConstructor( 395 PGIOChannelParent* actor, PBrowserParent* aBrowser, 396 const SerializedLoadContext& aSerialized, 397 const GIOChannelCreationArgs& aOpenArgs) { 398 GIOChannelParent* p = static_cast<GIOChannelParent*>(actor); 399 DebugOnly<bool> rv = p->Init(aOpenArgs); 400 MOZ_ASSERT(rv); 401 return IPC_OK(); 402 } 403 #endif 404 405 #ifdef MOZ_WIDGET_ANDROID 406 static already_AddRefed<nsIPrincipal> GetRequestingPrincipal( 407 const GeckoViewContentChannelArgs& aArgs) { 408 if (aArgs.type() != 409 GeckoViewContentChannelArgs::TGeckoViewContentChannelOpenArgs) { 410 return nullptr; 411 } 412 413 const GeckoViewContentChannelOpenArgs& args = 414 aArgs.get_GeckoViewContentChannelOpenArgs(); 415 return GetRequestingPrincipal(args.loadInfo()); 416 } 417 418 already_AddRefed<PGeckoViewContentChannelParent> 419 NeckoParent::AllocPGeckoViewContentChannelParent( 420 PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized, 421 const GeckoViewContentChannelArgs& aOpenArgs) { 422 nsCOMPtr<nsIPrincipal> requestingPrincipal = 423 GetRequestingPrincipal(aOpenArgs); 424 425 nsCOMPtr<nsILoadContext> loadContext; 426 CreateChannelLoadContext(aBrowser, Manager(), aSerialized, 427 requestingPrincipal, loadContext); 428 return MakeAndAddRef<GeckoViewContentChannelParent>( 429 BrowserParent::GetFrom(aBrowser), loadContext); 430 } 431 432 mozilla::ipc::IPCResult NeckoParent::RecvPGeckoViewContentChannelConstructor( 433 PGeckoViewContentChannelParent* actor, PBrowserParent* aBrowser, 434 const SerializedLoadContext& aSerialized, 435 const GeckoViewContentChannelArgs& aArgs) { 436 GeckoViewContentChannelParent* p = 437 static_cast<GeckoViewContentChannelParent*>(actor); 438 if (!p->Init(aArgs)) { 439 return IPC_FAIL(this, "Init is failed"); 440 } 441 return IPC_OK(); 442 } 443 #endif 444 445 mozilla::ipc::IPCResult NeckoParent::RecvNotifyFileChannelOpened( 446 const FileChannelInfo& aInfo) { 447 nsFileChannel::DoNotifyFileChannelOpened( 448 ContentParent::Cast(Manager())->GetRemoteType(), aInfo); 449 return IPC_OK(); 450 } 451 452 PTCPSocketParent* NeckoParent::AllocPTCPSocketParent( 453 const nsAString& /* host */, const uint16_t& /* port */) { 454 // We actually don't need host/port to construct a TCPSocketParent since 455 // TCPSocketParent will maintain an internal nsIDOMTCPSocket instance which 456 // can be delegated to get the host/port. 457 TCPSocketParent* p = new TCPSocketParent(); 458 p->AddIPDLReference(); 459 return p; 460 } 461 462 bool NeckoParent::DeallocPTCPSocketParent(PTCPSocketParent* actor) { 463 TCPSocketParent* p = static_cast<TCPSocketParent*>(actor); 464 p->ReleaseIPDLReference(); 465 return true; 466 } 467 468 PTCPServerSocketParent* NeckoParent::AllocPTCPServerSocketParent( 469 const uint16_t& aLocalPort, const uint16_t& aBacklog, 470 const bool& aUseArrayBuffers) { 471 TCPServerSocketParent* p = 472 new TCPServerSocketParent(this, aLocalPort, aBacklog, aUseArrayBuffers); 473 p->AddIPDLReference(); 474 return p; 475 } 476 477 mozilla::ipc::IPCResult NeckoParent::RecvPTCPServerSocketConstructor( 478 PTCPServerSocketParent* aActor, const uint16_t& aLocalPort, 479 const uint16_t& aBacklog, const bool& aUseArrayBuffers) { 480 static_cast<TCPServerSocketParent*>(aActor)->Init(); 481 return IPC_OK(); 482 } 483 484 bool NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor) { 485 TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor); 486 p->ReleaseIPDLReference(); 487 return true; 488 } 489 490 PUDPSocketParent* NeckoParent::AllocPUDPSocketParent( 491 nsIPrincipal* /* unused */, const nsACString& /* unused */) { 492 RefPtr<UDPSocketParent> p = new UDPSocketParent(this); 493 494 return p.forget().take(); 495 } 496 497 mozilla::ipc::IPCResult NeckoParent::RecvPUDPSocketConstructor( 498 PUDPSocketParent* aActor, nsIPrincipal* aPrincipal, 499 const nsACString& aFilter) { 500 if (!static_cast<UDPSocketParent*>(aActor)->Init(aPrincipal, aFilter)) { 501 return IPC_FAIL_NO_REASON(this); 502 } 503 return IPC_OK(); 504 } 505 506 bool NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor) { 507 UDPSocketParent* p = static_cast<UDPSocketParent*>(actor); 508 p->Release(); 509 return true; 510 } 511 512 already_AddRefed<PDNSRequestParent> NeckoParent::AllocPDNSRequestParent( 513 const nsACString& aHost, const nsACString& aTrrServer, const int32_t& aPort, 514 const uint16_t& aType, const OriginAttributes& aOriginAttributes, 515 const nsIDNSService::DNSFlags& aFlags) { 516 RefPtr<DNSRequestHandler> handler = new DNSRequestHandler(); 517 RefPtr<DNSRequestParent> actor = new DNSRequestParent(handler); 518 return actor.forget(); 519 } 520 521 mozilla::ipc::IPCResult NeckoParent::RecvPDNSRequestConstructor( 522 PDNSRequestParent* aActor, const nsACString& aHost, 523 const nsACString& aTrrServer, const int32_t& aPort, const uint16_t& aType, 524 const OriginAttributes& aOriginAttributes, 525 const nsIDNSService::DNSFlags& aFlags) { 526 RefPtr<DNSRequestParent> actor = static_cast<DNSRequestParent*>(aActor); 527 RefPtr<DNSRequestHandler> handler = 528 actor->GetDNSRequest()->AsDNSRequestHandler(); 529 handler->DoAsyncResolve(aHost, aTrrServer, aPort, aType, aOriginAttributes, 530 aFlags); 531 return IPC_OK(); 532 } 533 534 mozilla::ipc::IPCResult NeckoParent::RecvSpeculativeConnect( 535 nsIURI* aURI, nsIPrincipal* aPrincipal, 536 Maybe<OriginAttributes>&& aOriginAttributes, const bool& aAnonymous) { 537 nsCOMPtr<nsISpeculativeConnect> speculator(gIOService); 538 nsCOMPtr<nsIPrincipal> principal(aPrincipal); 539 if (!aURI) { 540 return IPC_FAIL(this, "aURI must not be null"); 541 } 542 if (aURI && speculator) { 543 if (aOriginAttributes) { 544 speculator->SpeculativeConnectWithOriginAttributesNative( 545 aURI, std::move(aOriginAttributes.ref()), nullptr, aAnonymous); 546 } else { 547 speculator->SpeculativeConnect(aURI, principal, nullptr, aAnonymous); 548 } 549 } 550 return IPC_OK(); 551 } 552 553 mozilla::ipc::IPCResult NeckoParent::RecvHTMLDNSPrefetch( 554 const nsAString& hostname, const bool& isHttps, 555 const OriginAttributes& aOriginAttributes, 556 const nsIDNSService::DNSFlags& flags) { 557 dom::HTMLDNSPrefetch::Prefetch(hostname, isHttps, aOriginAttributes, flags); 558 return IPC_OK(); 559 } 560 561 mozilla::ipc::IPCResult NeckoParent::RecvCancelHTMLDNSPrefetch( 562 const nsAString& hostname, const bool& isHttps, 563 const OriginAttributes& aOriginAttributes, 564 const nsIDNSService::DNSFlags& flags, const nsresult& reason) { 565 dom::HTMLDNSPrefetch::CancelPrefetch(hostname, isHttps, aOriginAttributes, 566 flags, reason); 567 return IPC_OK(); 568 } 569 570 PTransportProviderParent* NeckoParent::AllocPTransportProviderParent() { 571 RefPtr<TransportProviderParent> res = new TransportProviderParent(); 572 return res.forget().take(); 573 } 574 575 bool NeckoParent::DeallocPTransportProviderParent( 576 PTransportProviderParent* aActor) { 577 RefPtr<TransportProviderParent> provider = 578 dont_AddRef(static_cast<TransportProviderParent*>(aActor)); 579 return true; 580 } 581 582 mozilla::ipc::IPCResult NeckoParent::RecvRequestContextLoadBegin( 583 const uint64_t& rcid) { 584 nsCOMPtr<nsIRequestContextService> rcsvc = 585 RequestContextService::GetOrCreate(); 586 if (!rcsvc) { 587 return IPC_OK(); 588 } 589 nsCOMPtr<nsIRequestContext> rc; 590 rcsvc->GetRequestContext(rcid, getter_AddRefs(rc)); 591 if (rc) { 592 rc->BeginLoad(); 593 } 594 595 return IPC_OK(); 596 } 597 598 mozilla::ipc::IPCResult NeckoParent::RecvRequestContextAfterDOMContentLoaded( 599 const uint64_t& rcid) { 600 nsCOMPtr<nsIRequestContextService> rcsvc = 601 RequestContextService::GetOrCreate(); 602 if (!rcsvc) { 603 return IPC_OK(); 604 } 605 nsCOMPtr<nsIRequestContext> rc; 606 rcsvc->GetRequestContext(rcid, getter_AddRefs(rc)); 607 if (rc) { 608 rc->DOMContentLoaded(); 609 } 610 611 return IPC_OK(); 612 } 613 614 mozilla::ipc::IPCResult NeckoParent::RecvRemoveRequestContext( 615 const uint64_t& rcid) { 616 nsCOMPtr<nsIRequestContextService> rcsvc = 617 RequestContextService::GetOrCreate(); 618 if (!rcsvc) { 619 return IPC_OK(); 620 } 621 622 rcsvc->RemoveRequestContext(rcid); 623 624 return IPC_OK(); 625 } 626 627 mozilla::ipc::IPCResult NeckoParent::RecvGetExtensionStream( 628 nsIURI* aURI, GetExtensionStreamResolver&& aResolve) { 629 if (!aURI) { 630 return IPC_FAIL(this, "aURI must not be null"); 631 } 632 633 RefPtr<ExtensionProtocolHandler> ph(ExtensionProtocolHandler::GetSingleton()); 634 MOZ_ASSERT(ph); 635 636 // Ask the ExtensionProtocolHandler to give us a new input stream for 637 // this URI. The request comes from an ExtensionProtocolHandler in the 638 // child process, but is not guaranteed to be a valid moz-extension URI, 639 // and not guaranteed to represent a resource that the child should be 640 // allowed to access. The ExtensionProtocolHandler is responsible for 641 // validating the request. Specifically, only URI's for local files that 642 // an extension is allowed to access via moz-extension URI's should be 643 // accepted. 644 nsCOMPtr<nsIInputStream> inputStream; 645 bool terminateSender = true; 646 auto inputStreamOrReason = ph->NewStream(aURI, &terminateSender); 647 if (inputStreamOrReason.isOk()) { 648 inputStream = inputStreamOrReason.unwrap(); 649 } 650 651 // If NewStream failed, we send back an invalid stream to the child so 652 // it can handle the error. MozPromise rejection is reserved for channel 653 // errors/disconnects. 654 aResolve(inputStream); 655 656 if (terminateSender) { 657 return IPC_FAIL_NO_REASON(this); 658 } 659 return IPC_OK(); 660 } 661 662 mozilla::ipc::IPCResult NeckoParent::RecvGetExtensionFD( 663 nsIURI* aURI, GetExtensionFDResolver&& aResolve) { 664 if (!aURI) { 665 return IPC_FAIL(this, "aURI must not be null"); 666 } 667 668 RefPtr<ExtensionProtocolHandler> ph(ExtensionProtocolHandler::GetSingleton()); 669 MOZ_ASSERT(ph); 670 671 // Ask the ExtensionProtocolHandler to give us a new input stream for 672 // this URI. The request comes from an ExtensionProtocolHandler in the 673 // child process, but is not guaranteed to be a valid moz-extension URI, 674 // and not guaranteed to represent a resource that the child should be 675 // allowed to access. The ExtensionProtocolHandler is responsible for 676 // validating the request. Specifically, only URI's for local files that 677 // an extension is allowed to access via moz-extension URI's should be 678 // accepted. 679 bool terminateSender = true; 680 auto result = ph->NewFD(aURI, &terminateSender, aResolve); 681 682 if (result.isErr() && terminateSender) { 683 return IPC_FAIL_NO_REASON(this); 684 } 685 686 if (result.isErr()) { 687 FileDescriptor invalidFD; 688 aResolve(invalidFD); 689 } 690 691 return IPC_OK(); 692 } 693 694 mozilla::ipc::IPCResult NeckoParent::RecvInitSocketProcessBridge( 695 InitSocketProcessBridgeResolver&& aResolver) { 696 MOZ_ASSERT(NS_IsMainThread()); 697 698 // Initing the socket process bridge must be async here in order to 699 // wait for the socket process launch before executing. 700 auto task = [self = RefPtr{this}, resolver = std::move(aResolver)]() { 701 // The content process might be already destroyed. 702 if (!self->CanSend()) { 703 return; 704 } 705 706 Endpoint<PSocketProcessBridgeChild> invalidEndpoint; 707 if (NS_WARN_IF(self->mSocketProcessBridgeInited)) { 708 resolver(std::move(invalidEndpoint)); 709 return; 710 } 711 712 RefPtr<SocketProcessParent> parent = SocketProcessParent::GetSingleton(); 713 if (NS_WARN_IF(!parent)) { 714 resolver(std::move(invalidEndpoint)); 715 return; 716 } 717 718 Endpoint<PSocketProcessBridgeParent> parentEndpoint; 719 Endpoint<PSocketProcessBridgeChild> childEndpoint; 720 if (NS_WARN_IF(NS_FAILED(PSocketProcessBridge::CreateEndpoints( 721 parent->OtherEndpointProcInfo(), 722 self->Manager()->OtherEndpointProcInfo(), &parentEndpoint, 723 &childEndpoint)))) { 724 resolver(std::move(invalidEndpoint)); 725 return; 726 } 727 728 if (NS_WARN_IF(!parent->SendInitSocketProcessBridgeParent( 729 self->Manager()->OtherPid(), std::move(parentEndpoint)))) { 730 resolver(std::move(invalidEndpoint)); 731 return; 732 } 733 734 resolver(std::move(childEndpoint)); 735 self->mSocketProcessBridgeInited = true; 736 }; 737 gIOService->CallOrWaitForSocketProcess(std::move(task)); 738 739 return IPC_OK(); 740 } 741 742 mozilla::ipc::IPCResult NeckoParent::RecvResetSocketProcessBridge() { 743 // SendResetSocketProcessBridge is called from 744 // SocketProcessBridgeChild::ActorDestroy if the socket process 745 // crashes. This is necessary in order to properly initialize the 746 // restarted socket process. 747 mSocketProcessBridgeInited = false; 748 return IPC_OK(); 749 } 750 751 mozilla::ipc::IPCResult NeckoParent::RecvEnsureHSTSData( 752 EnsureHSTSDataResolver&& aResolver) { 753 auto callback = [aResolver{std::move(aResolver)}](bool aResult) { 754 aResolver(aResult); 755 }; 756 RefPtr<HSTSDataCallbackWrapper> wrapper = 757 new HSTSDataCallbackWrapper(std::move(callback)); 758 gHttpHandler->EnsureHSTSDataReadyNative(wrapper); 759 return IPC_OK(); 760 } 761 762 mozilla::ipc::IPCResult NeckoParent::RecvGetPageThumbStream( 763 nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs, 764 GetPageThumbStreamResolver&& aResolver) { 765 // Only the privileged about content process is allowed to access 766 // things over the moz-page-thumb protocol. Any other content process 767 // that tries to send this should have been blocked via the 768 // ScriptSecurityManager, but if somehow the process has been tricked into 769 // sending this message, we send IPC_FAIL in order to crash that 770 // likely-compromised content process. 771 if (static_cast<ContentParent*>(Manager())->GetRemoteType() != 772 PRIVILEGEDABOUT_REMOTE_TYPE) { 773 return IPC_FAIL(this, "Wrong process type"); 774 } 775 776 RefPtr<PageThumbProtocolHandler> ph(PageThumbProtocolHandler::GetSingleton()); 777 MOZ_ASSERT(ph); 778 779 // Ask the PageThumbProtocolHandler to give us a new input stream for 780 // this URI. The request comes from a PageThumbProtocolHandler in the 781 // child process, but is not guaranteed to be a valid moz-page-thumb URI, 782 // and not guaranteed to represent a resource that the child should be 783 // allowed to access. The PageThumbProtocolHandler is responsible for 784 // validating the request. 785 nsCOMPtr<nsIInputStream> inputStream; 786 bool terminateSender = true; 787 auto inputStreamPromise = ph->NewStream(aURI, &terminateSender); 788 789 if (terminateSender) { 790 return IPC_FAIL(this, "Malformed moz-page-thumb request"); 791 } 792 793 inputStreamPromise->Then( 794 GetMainThreadSerialEventTarget(), __func__, 795 [aResolver](const RemoteStreamInfo& aInfo) { aResolver(Some(aInfo)); }, 796 [aResolver](nsresult aRv) { 797 // If NewStream failed, we send back an invalid stream to the child so 798 // it can handle the error. MozPromise rejection is reserved for channel 799 // errors/disconnects. 800 (void)NS_WARN_IF(NS_FAILED(aRv)); 801 aResolver(Nothing()); 802 }); 803 804 return IPC_OK(); 805 } 806 807 mozilla::ipc::IPCResult NeckoParent::RecvGetMozNewTabWallpaperStream( 808 nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs, 809 GetMozNewTabWallpaperStreamResolver&& aResolver) { 810 // Only the privileged about content process is allowed to access 811 // things over the moz-newtab-wallpaper protocol. Any other content process 812 // that tries to send this should have been blocked via the 813 // ScriptSecurityManager, but if somehow the process has been tricked into 814 // sending this message, we send IPC_FAIL in order to crash that 815 // likely-compromised content process. 816 if (static_cast<ContentParent*>(Manager())->GetRemoteType() != 817 PRIVILEGEDABOUT_REMOTE_TYPE) { 818 return IPC_FAIL(this, "Wrong process type"); 819 } 820 821 RefPtr<net::MozNewTabWallpaperProtocolHandler> ph( 822 net::MozNewTabWallpaperProtocolHandler::GetSingleton()); 823 MOZ_ASSERT(ph); 824 825 // Ask the MozNewTabWallpaperProtocolHandler to give us a new input stream for 826 // this URI. The request comes from a MozNewTabWallpaperProtocolHandler in the 827 // child process, but is not guaranteed to be a valid moz-newtab-wallpaper 828 // URI, and not guaranteed to represent a resource that the child should be 829 // allowed to access. The MozNewTabWallpaperProtocolHandler is responsible for 830 // validating the request. 831 nsCOMPtr<nsIInputStream> inputStream; 832 bool terminateSender = true; 833 auto inputStreamPromise = ph->NewStream(aURI, &terminateSender); 834 835 if (terminateSender) { 836 return IPC_FAIL(this, "Malformed moz-newtab-wallpaper request"); 837 } 838 839 inputStreamPromise->Then( 840 GetMainThreadSerialEventTarget(), __func__, 841 [aResolver](const RemoteStreamInfo& aInfo) { aResolver(Some(aInfo)); }, 842 [aResolver](nsresult aRv) { 843 // If NewStream failed, we send back an invalid stream to the child so 844 // it can handle the error. MozPromise rejection is reserved for channel 845 // errors/disconnects. 846 (void)NS_WARN_IF(NS_FAILED(aRv)); 847 aResolver(Nothing()); 848 }); 849 850 return IPC_OK(); 851 } 852 853 mozilla::ipc::IPCResult NeckoParent::RecvGetPageIconStream( 854 nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs, 855 GetPageIconStreamResolver&& aResolver) { 856 #ifdef MOZ_PLACES 857 const nsACString& remoteType = 858 ContentParent::Cast(Manager())->GetRemoteType(); 859 860 // Only the privileged about content process is allowed to access 861 // things over the page-icon protocol. Any other content process 862 // that tries to send this should have been blocked via the 863 // ScriptSecurityManager, but if somehow the process has been tricked into 864 // sending this message, we send IPC_FAIL in order to crash that 865 // likely-compromised content process. 866 if (remoteType != PRIVILEGEDABOUT_REMOTE_TYPE) { 867 return IPC_FAIL(this, "Wrong process type"); 868 } 869 870 nsCOMPtr<nsILoadInfo> loadInfo; 871 nsresult rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfoArgs, remoteType, 872 getter_AddRefs(loadInfo)); 873 if (NS_FAILED(rv)) { 874 return IPC_FAIL(this, "Page-icon request must include loadInfo"); 875 } 876 877 RefPtr<PageIconProtocolHandler> ph(PageIconProtocolHandler::GetSingleton()); 878 MOZ_ASSERT(ph); 879 880 nsCOMPtr<nsIInputStream> inputStream; 881 bool terminateSender = true; 882 auto inputStreamPromise = ph->NewStream(aURI, loadInfo, &terminateSender); 883 884 if (terminateSender) { 885 return IPC_FAIL(this, "Malformed page-icon request"); 886 } 887 888 inputStreamPromise->Then( 889 GetMainThreadSerialEventTarget(), __func__, 890 [aResolver](const RemoteStreamInfo& aInfo) { aResolver(Some(aInfo)); }, 891 [aResolver](nsresult aRv) { 892 // If NewStream failed, we send back an invalid stream to the child so 893 // it can handle the error. MozPromise rejection is reserved for channel 894 // errors/disconnects. 895 (void)NS_WARN_IF(NS_FAILED(aRv)); 896 aResolver(Nothing()); 897 }); 898 899 return IPC_OK(); 900 #else 901 return IPC_FAIL(this, "page-icon: protocol unavailable"); 902 #endif 903 } 904 905 /* static */ 906 RefPtr<RemoteStreamPromise> NeckoParent::CreateRemoteStreamForResolvedURI( 907 nsIURI* aChildURI, const nsACString& aResolvedSpec, 908 const nsACString& aDefaultMimeType) { 909 MOZ_ASSERT(NS_IsMainThread()); 910 MOZ_ASSERT(XRE_IsParentProcess()); 911 912 nsresult rv; 913 914 nsAutoCString resolvedScheme; 915 rv = net_ExtractURLScheme(aResolvedSpec, resolvedScheme); 916 if (NS_FAILED(rv) || !resolvedScheme.EqualsLiteral("file")) { 917 return RemoteStreamPromise::CreateAndReject(NS_ERROR_UNEXPECTED, __func__); 918 } 919 920 MOZ_ASSERT(resolvedScheme.EqualsLiteral("file"), 921 "CreateRemoteStreamForResolvedURI requires file:// URI"); 922 923 nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); 924 if (NS_FAILED(rv)) { 925 return RemoteStreamPromise::CreateAndReject(rv, __func__); 926 } 927 928 nsCOMPtr<nsIURI> resolvedURI; 929 rv = ioService->NewURI(aResolvedSpec, nullptr, nullptr, 930 getter_AddRefs(resolvedURI)); 931 if (NS_FAILED(rv)) { 932 return RemoteStreamPromise::CreateAndReject(rv, __func__); 933 } 934 935 // Load local file resources for internal protocol handlers (moz-page-thumb, 936 // moz-newtab-wallpaper). resolvedURI must be file:// scheme pointing to the 937 // profile directory. Callers validate the original URI scheme/host and use 938 // internal path resolution (PageThumbsStorageService, profile/wallpaper/) 939 // before calling this method. 940 nsCOMPtr<nsIChannel> channel; 941 nsCOMPtr<nsIPrincipal> nullPrincipal = 942 NullPrincipal::CreateWithoutOriginAttributes(); 943 rv = NS_NewChannel(getter_AddRefs(channel), resolvedURI, nullPrincipal, 944 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, 945 nsIContentPolicy::TYPE_IMAGE); 946 if (NS_FAILED(rv)) { 947 return RemoteStreamPromise::CreateAndReject(rv, __func__); 948 } 949 950 auto promiseHolder = MakeUnique<MozPromiseHolder<RemoteStreamPromise>>(); 951 RefPtr<RemoteStreamPromise> promise = promiseHolder->Ensure(__func__); 952 953 nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv); 954 if (NS_FAILED(rv)) { 955 return RemoteStreamPromise::CreateAndReject(rv, __func__); 956 } 957 958 nsAutoCString contentType; 959 rv = mime->GetTypeFromURI(aChildURI, contentType); 960 if (NS_FAILED(rv)) { 961 if (!aDefaultMimeType.IsEmpty()) { 962 contentType = aDefaultMimeType; 963 } else { 964 return RemoteStreamPromise::CreateAndReject(rv, __func__); 965 } 966 } 967 968 rv = NS_DispatchBackgroundTask( 969 NS_NewRunnableFunction( 970 "NeckoParent::CreateRemoteStreamForResolvedURI", 971 [contentType, channel, holder = std::move(promiseHolder)]() { 972 nsresult rv; 973 974 nsCOMPtr<nsIFileChannel> fileChannel = 975 do_QueryInterface(channel, &rv); 976 if (NS_FAILED(rv)) { 977 holder->Reject(rv, __func__); 978 return; 979 } 980 981 nsCOMPtr<nsIFile> requestedFile; 982 rv = fileChannel->GetFile(getter_AddRefs(requestedFile)); 983 if (NS_FAILED(rv)) { 984 holder->Reject(rv, __func__); 985 return; 986 } 987 988 nsCOMPtr<nsIInputStream> inputStream; 989 rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), 990 requestedFile, PR_RDONLY, -1); 991 if (NS_FAILED(rv)) { 992 holder->Reject(rv, __func__); 993 return; 994 } 995 996 RemoteStreamInfo info(inputStream, contentType, -1); 997 998 holder->Resolve(std::move(info), __func__); 999 }), 1000 NS_DISPATCH_EVENT_MAY_BLOCK); 1001 1002 if (NS_FAILED(rv)) { 1003 return RemoteStreamPromise::CreateAndReject(rv, __func__); 1004 } 1005 1006 return promise; 1007 } 1008 1009 } // namespace net 1010 } // namespace mozilla