gecko-dev/netwerk/ipc/NeckoChild.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

351 lines
11 KiB
C++
Raw Normal View History

2009-08-18 19:05:15 +00:00
/* vim: set sw=2 ts=8 et tw=80 : */
2012-05-21 11:12:37 +00:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
2009-08-18 19:05:15 +00:00
#include "nsHttp.h"
2009-08-18 19:05:15 +00:00
#include "mozilla/net/NeckoChild.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/BrowserChild.h"
2009-08-18 19:05:15 +00:00
#include "mozilla/net/HttpChannelChild.h"
#include "mozilla/net/CookieServiceChild.h"
#include "mozilla/net/DataChannelChild.h"
#ifdef MOZ_WIDGET_GTK
# include "mozilla/net/GIOChannelChild.h"
#endif
#include "mozilla/net/FileChannelChild.h"
#include "mozilla/net/WebSocketChannelChild.h"
#include "mozilla/net/WebSocketEventListenerChild.h"
#include "mozilla/net/DNSRequestChild.h"
#include "mozilla/net/IPCTransportProvider.h"
#include "mozilla/dom/network/TCPSocketChild.h"
#include "mozilla/dom/network/TCPServerSocketChild.h"
#include "mozilla/dom/network/UDPSocketChild.h"
#include "mozilla/net/AltDataOutputStreamChild.h"
#include "mozilla/net/ClassifierDummyChannelChild.h"
#include "mozilla/net/SocketProcessBridgeChild.h"
#ifdef MOZ_WEBRTC
# include "mozilla/net/StunAddrsRequestChild.h"
# include "mozilla/net/WebrtcTCPSocketChild.h"
#endif
#include "SerializedLoadContext.h"
#include "nsGlobalWindow.h"
#include "nsIOService.h"
#include "nsINetworkPredictor.h"
#include "nsINetworkPredictorVerifier.h"
#include "nsINetworkLinkService.h"
Bug 1476996 - Implement cross process redirection in Http on the parent process r=bagder,nika This patch builds the foundation for the ability to relocate HTTP channels from one content process to another in order to ensure that origins are properly isolated. This relocation would normally occur when the response to an HTTP request is a redirect to a different origin. The patch merely adds the mechanism for relocating the channel, rather than the logic of doing so. This will be provided in a follow-up patch by a specialized service. Right now that functionality is mocked in the test. How this works: In nsHttpChannel::OnStartRequest we will query the service that decides whether we need to direct the response to another process. If so, it will return a promise that resolves to a TabParent. When the promise resolves, in HttpChannelParentListener::TriggerCrossProcessRedirect we call NeckoParent::SendCrossProcessRedirect passing along the required information to recreate the channel in the new process. The NeckoChild in the new process will then instantiate a new channel, call ConnectParent() which creates the associated parent channel, and connects it with the existing nsHttpChannel. A listener in the new process is then notified of the existence of the new channel. It is required to call completeRedirectSetup on the channel, passing an nsIStreamListener to the call. We then finish the entire operation with a call to HttpChannelChild::SendCrossProcessRedirectDone which causes us to close the old HttpChannelChild in the previous process and to resume the nsHttpChannel in the main process. Differential Revision: https://phabricator.services.mozilla.com/D2958 --HG-- rename : netwerk/test/browser/browser_cookie_sync_across_tabs.js => netwerk/test/browser/browser_cross_process_redirect.js rename : dom/media/test/redirect.sjs => netwerk/test/browser/redirect.sjs extra : moz-landing-system : lando
2018-09-04 20:45:22 +00:00
#include "nsQueryObject.h"
#include "mozilla/ipc/URIUtils.h"
#include "nsNetUtil.h"
#include "SimpleChannel.h"
using mozilla::dom::TCPServerSocketChild;
using mozilla::dom::TCPSocketChild;
using mozilla::dom::UDPSocketChild;
2009-08-18 19:05:15 +00:00
namespace mozilla {
namespace net {
PNeckoChild* gNeckoChild = nullptr;
2009-08-18 19:05:15 +00:00
// C++ file contents
NeckoChild::~NeckoChild() {
// Send__delete__(gNeckoChild);
gNeckoChild = nullptr;
2009-08-18 19:05:15 +00:00
}
void NeckoChild::InitNeckoChild() {
if (!IsNeckoChild()) {
MOZ_ASSERT(false, "InitNeckoChild called by non-child!");
return;
}
if (!gNeckoChild) {
mozilla::dom::ContentChild* cpc =
mozilla::dom::ContentChild::GetSingleton();
2009-08-18 19:05:15 +00:00
NS_ASSERTION(cpc, "Content Protocol is NULL!");
if (NS_WARN_IF(cpc->IsShuttingDown())) {
return;
}
2009-08-18 19:05:15 +00:00
gNeckoChild = cpc->SendPNeckoConstructor();
NS_ASSERTION(gNeckoChild, "PNecko Protocol init failed!");
}
}
PStunAddrsRequestChild* NeckoChild::AllocPStunAddrsRequestChild() {
// We don't allocate here: instead we always use IPDL constructor that takes
// an existing object
MOZ_ASSERT_UNREACHABLE(
"AllocPStunAddrsRequestChild should not be called "
"on child");
return nullptr;
}
bool NeckoChild::DeallocPStunAddrsRequestChild(PStunAddrsRequestChild* aActor) {
#ifdef MOZ_WEBRTC
StunAddrsRequestChild* p = static_cast<StunAddrsRequestChild*>(aActor);
p->ReleaseIPDLReference();
#endif
return true;
}
PWebrtcTCPSocketChild* NeckoChild::AllocPWebrtcTCPSocketChild(
const Maybe<TabId>& tabId) {
// We don't allocate here: instead we always use IPDL constructor that takes
// an existing object
MOZ_ASSERT_UNREACHABLE(
"AllocPWebrtcTCPSocketChild should not be called on"
" child");
return nullptr;
}
bool NeckoChild::DeallocPWebrtcTCPSocketChild(PWebrtcTCPSocketChild* aActor) {
#ifdef MOZ_WEBRTC
WebrtcTCPSocketChild* child = static_cast<WebrtcTCPSocketChild*>(aActor);
child->ReleaseIPDLReference();
#endif
return true;
}
PAltDataOutputStreamChild* NeckoChild::AllocPAltDataOutputStreamChild(
const nsCString& type, const int64_t& predictedSize,
PHttpChannelChild* channel) {
// We don't allocate here: see HttpChannelChild::OpenAlternativeOutputStream()
MOZ_ASSERT_UNREACHABLE("AllocPAltDataOutputStreamChild should not be called");
return nullptr;
}
bool NeckoChild::DeallocPAltDataOutputStreamChild(
PAltDataOutputStreamChild* aActor) {
AltDataOutputStreamChild* child =
static_cast<AltDataOutputStreamChild*>(aActor);
child->ReleaseIPDLReference();
return true;
}
#ifdef MOZ_WIDGET_GTK
PGIOChannelChild* NeckoChild::AllocPGIOChannelChild(
PBrowserChild* aBrowser, const SerializedLoadContext& aSerialized,
const GIOChannelCreationArgs& aOpenArgs) {
// We don't allocate here: see GIOChannelChild::AsyncOpen()
MOZ_CRASH("AllocPGIOChannelChild should not be called");
return nullptr;
}
bool NeckoChild::DeallocPGIOChannelChild(PGIOChannelChild* channel) {
MOZ_ASSERT(IsNeckoChild(), "DeallocPGIOChannelChild called by non-child!");
GIOChannelChild* child = static_cast<GIOChannelChild*>(channel);
child->ReleaseIPDLReference();
return true;
}
#endif
PCookieServiceChild* NeckoChild::AllocPCookieServiceChild() {
// We don't allocate here: see CookieService::GetSingleton()
MOZ_ASSERT_UNREACHABLE("AllocPCookieServiceChild should not be called");
return nullptr;
}
bool NeckoChild::DeallocPCookieServiceChild(PCookieServiceChild* cs) {
NS_ASSERTION(IsNeckoChild(),
"DeallocPCookieServiceChild called by non-child!");
CookieServiceChild* p = static_cast<CookieServiceChild*>(cs);
p->Release();
return true;
}
PWebSocketChild* NeckoChild::AllocPWebSocketChild(
PBrowserChild* browser, const SerializedLoadContext& aSerialized,
const uint32_t& aSerial) {
MOZ_ASSERT_UNREACHABLE("AllocPWebSocketChild should not be called");
return nullptr;
}
bool NeckoChild::DeallocPWebSocketChild(PWebSocketChild* child) {
WebSocketChannelChild* p = static_cast<WebSocketChannelChild*>(child);
p->ReleaseIPDLReference();
return true;
}
PWebSocketEventListenerChild* NeckoChild::AllocPWebSocketEventListenerChild(
const uint64_t& aInnerWindowID) {
nsCOMPtr<nsISerialEventTarget> target;
if (nsGlobalWindowInner* win =
nsGlobalWindowInner::GetInnerWindowWithId(aInnerWindowID)) {
target = win->EventTargetFor(TaskCategory::Other);
}
RefPtr<WebSocketEventListenerChild> c =
new WebSocketEventListenerChild(aInnerWindowID, target);
if (target) {
gNeckoChild->SetEventTargetForActor(c, target);
}
return c.forget().take();
}
bool NeckoChild::DeallocPWebSocketEventListenerChild(
PWebSocketEventListenerChild* aActor) {
RefPtr<WebSocketEventListenerChild> c =
dont_AddRef(static_cast<WebSocketEventListenerChild*>(aActor));
MOZ_ASSERT(c);
return true;
}
PSimpleChannelChild* NeckoChild::AllocPSimpleChannelChild(
const uint32_t& channelId) {
MOZ_ASSERT_UNREACHABLE("Should never get here");
return nullptr;
}
bool NeckoChild::DeallocPSimpleChannelChild(PSimpleChannelChild* child) {
static_cast<SimpleChannelChild*>(child)->Release();
return true;
}
PTCPSocketChild* NeckoChild::AllocPTCPSocketChild(const nsString& host,
const uint16_t& port) {
TCPSocketChild* p = new TCPSocketChild(host, port, nullptr);
p->AddIPDLReference();
return p;
}
bool NeckoChild::DeallocPTCPSocketChild(PTCPSocketChild* child) {
TCPSocketChild* p = static_cast<TCPSocketChild*>(child);
p->ReleaseIPDLReference();
return true;
}
PTCPServerSocketChild* NeckoChild::AllocPTCPServerSocketChild(
const uint16_t& aLocalPort, const uint16_t& aBacklog,
const bool& aUseArrayBuffers) {
MOZ_ASSERT_UNREACHABLE("AllocPTCPServerSocket should not be called");
return nullptr;
}
bool NeckoChild::DeallocPTCPServerSocketChild(PTCPServerSocketChild* child) {
TCPServerSocketChild* p = static_cast<TCPServerSocketChild*>(child);
p->ReleaseIPDLReference();
return true;
}
PUDPSocketChild* NeckoChild::AllocPUDPSocketChild(nsIPrincipal* aPrincipal,
const nsCString& aFilter) {
MOZ_ASSERT_UNREACHABLE("AllocPUDPSocket should not be called");
return nullptr;
}
bool NeckoChild::DeallocPUDPSocketChild(PUDPSocketChild* child) {
UDPSocketChild* p = static_cast<UDPSocketChild*>(child);
p->ReleaseIPDLReference();
return true;
}
PTransportProviderChild* NeckoChild::AllocPTransportProviderChild() {
// This refcount is transferred to the receiver of the message that
// includes the PTransportProviderChild actor.
RefPtr<TransportProviderChild> res = new TransportProviderChild();
return res.forget().take();
}
bool NeckoChild::DeallocPTransportProviderChild(
PTransportProviderChild* aActor) {
return true;
}
/* Predictor Messages */
mozilla::ipc::IPCResult NeckoChild::RecvPredOnPredictPrefetch(
nsIURI* aURI, const uint32_t& aHttpStatus) {
MOZ_ASSERT(NS_IsMainThread(),
"PredictorChild::RecvOnPredictPrefetch "
"off main thread.");
if (!aURI) {
return IPC_FAIL(this, "aURI is null");
}
// Get the current predictor
nsresult rv = NS_OK;
nsCOMPtr<nsINetworkPredictorVerifier> predictor =
do_GetService("@mozilla.org/network/predictor;1", &rv);
NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
predictor->OnPredictPrefetch(aURI, aHttpStatus);
return IPC_OK();
}
mozilla::ipc::IPCResult NeckoChild::RecvPredOnPredictPreconnect(nsIURI* aURI) {
MOZ_ASSERT(NS_IsMainThread(),
"PredictorChild::RecvOnPredictPreconnect "
"off main thread.");
if (!aURI) {
return IPC_FAIL(this, "aURI is null");
}
// Get the current predictor
nsresult rv = NS_OK;
nsCOMPtr<nsINetworkPredictorVerifier> predictor =
do_GetService("@mozilla.org/network/predictor;1", &rv);
NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
predictor->OnPredictPreconnect(aURI);
return IPC_OK();
}
mozilla::ipc::IPCResult NeckoChild::RecvPredOnPredictDNS(nsIURI* aURI) {
MOZ_ASSERT(NS_IsMainThread(),
"PredictorChild::RecvOnPredictDNS off "
"main thread.");
if (!aURI) {
return IPC_FAIL(this, "aURI is null");
}
// Get the current predictor
nsresult rv = NS_OK;
nsCOMPtr<nsINetworkPredictorVerifier> predictor =
do_GetService("@mozilla.org/network/predictor;1", &rv);
NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
predictor->OnPredictDNS(aURI);
return IPC_OK();
}
mozilla::ipc::IPCResult NeckoChild::RecvSpeculativeConnectRequest() {
nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
if (obsService) {
obsService->NotifyObservers(nullptr, "speculative-connect-request",
nullptr);
}
return IPC_OK();
}
mozilla::ipc::IPCResult NeckoChild::RecvNetworkChangeNotification(
nsCString const& type) {
nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
if (obsService) {
obsService->NotifyObservers(nullptr, NS_NETWORK_LINK_TOPIC,
NS_ConvertUTF8toUTF16(type).get());
}
return IPC_OK();
}
PClassifierDummyChannelChild* NeckoChild::AllocPClassifierDummyChannelChild(
nsIURI* aURI, nsIURI* aTopWindowURI, const nsresult& aTopWindowURIResult,
const Maybe<LoadInfoArgs>& aLoadInfo) {
return new ClassifierDummyChannelChild();
}
bool NeckoChild::DeallocPClassifierDummyChannelChild(
PClassifierDummyChannelChild* aActor) {
delete static_cast<ClassifierDummyChannelChild*>(aActor);
return true;
}
} // namespace net
} // namespace mozilla