diff options
Diffstat (limited to 'netwerk/ipc')
-rw-r--r-- | netwerk/ipc/ChannelEventQueue.cpp | 98 | ||||
-rw-r--r-- | netwerk/ipc/ChannelEventQueue.h | 237 | ||||
-rw-r--r-- | netwerk/ipc/NeckoChannelParams.ipdlh | 196 | ||||
-rw-r--r-- | netwerk/ipc/NeckoChild.cpp | 431 | ||||
-rw-r--r-- | netwerk/ipc/NeckoChild.h | 107 | ||||
-rw-r--r-- | netwerk/ipc/NeckoCommon.cpp | 18 | ||||
-rw-r--r-- | netwerk/ipc/NeckoCommon.h | 130 | ||||
-rw-r--r-- | netwerk/ipc/NeckoMessageUtils.h | 189 | ||||
-rw-r--r-- | netwerk/ipc/NeckoParent.cpp | 907 | ||||
-rw-r--r-- | netwerk/ipc/NeckoParent.h | 227 | ||||
-rw-r--r-- | netwerk/ipc/PChannelDiverter.ipdl | 25 | ||||
-rw-r--r-- | netwerk/ipc/PDataChannel.ipdl | 25 | ||||
-rw-r--r-- | netwerk/ipc/PNecko.ipdl | 145 | ||||
-rw-r--r-- | netwerk/ipc/PRtspChannel.ipdl | 25 | ||||
-rw-r--r-- | netwerk/ipc/PRtspController.ipdl | 64 | ||||
-rw-r--r-- | netwerk/ipc/moz.build | 40 |
16 files changed, 2864 insertions, 0 deletions
diff --git a/netwerk/ipc/ChannelEventQueue.cpp b/netwerk/ipc/ChannelEventQueue.cpp new file mode 100644 index 0000000000..a4dbae7d5b --- /dev/null +++ b/netwerk/ipc/ChannelEventQueue.cpp @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set sw=2 ts=8 et tw=80 : + */ +/* 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/. */ + +#include "nsISupports.h" +#include "mozilla/net/ChannelEventQueue.h" +#include "mozilla/Unused.h" +#include "nsThreadUtils.h" +#include "mozilla/Unused.h" + +namespace mozilla { +namespace net { + +ChannelEvent* +ChannelEventQueue::TakeEvent() +{ + MutexAutoLock lock(mMutex); + MOZ_ASSERT(mFlushing); + + if (mSuspended || mEventQueue.IsEmpty()) { + return nullptr; + } + + UniquePtr<ChannelEvent> event(Move(mEventQueue[0])); + mEventQueue.RemoveElementAt(0); + + return event.release(); +} + +void +ChannelEventQueue::FlushQueue() +{ + // Events flushed could include destruction of channel (and our own + // destructor) unless we make sure its refcount doesn't drop to 0 while this + // method is running. + nsCOMPtr<nsISupports> kungFuDeathGrip(mOwner); + mozilla::Unused << kungFuDeathGrip; // Not used in this function + + // Prevent flushed events from flushing the queue recursively + { + MutexAutoLock lock(mMutex); + mFlushing = true; + } + + while (true) { + UniquePtr<ChannelEvent> event(TakeEvent()); + if (!event) { + break; + } + + event->Run(); + } + + MutexAutoLock lock(mMutex); + mFlushing = false; +} + +void +ChannelEventQueue::Resume() +{ + MutexAutoLock lock(mMutex); + + // Resuming w/o suspend: error in debug mode, ignore in build + MOZ_ASSERT(mSuspendCount > 0); + if (mSuspendCount <= 0) { + return; + } + + if (!--mSuspendCount) { + RefPtr<Runnable> event = + NewRunnableMethod(this, &ChannelEventQueue::CompleteResume); + if (mTargetThread) { + mTargetThread->Dispatch(event.forget(), NS_DISPATCH_NORMAL); + } else { + MOZ_RELEASE_ASSERT(NS_IsMainThread()); + Unused << NS_WARN_IF(NS_FAILED(NS_DispatchToCurrentThread(event.forget()))); + } + } +} + +nsresult +ChannelEventQueue::RetargetDeliveryTo(nsIEventTarget* aTargetThread) +{ + MOZ_RELEASE_ASSERT(NS_IsMainThread()); + MOZ_RELEASE_ASSERT(!mTargetThread); + MOZ_RELEASE_ASSERT(aTargetThread); + + mTargetThread = do_QueryInterface(aTargetThread); + MOZ_RELEASE_ASSERT(mTargetThread); + + return NS_OK; +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/ipc/ChannelEventQueue.h b/netwerk/ipc/ChannelEventQueue.h new file mode 100644 index 0000000000..a843decabc --- /dev/null +++ b/netwerk/ipc/ChannelEventQueue.h @@ -0,0 +1,237 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set sw=2 ts=8 et tw=80 : + */ +/* 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/. */ + +#ifndef mozilla_net_ChannelEventQueue_h +#define mozilla_net_ChannelEventQueue_h + +#include "nsTArray.h" +#include "nsAutoPtr.h" +#include "mozilla/Mutex.h" +#include "mozilla/UniquePtr.h" + +class nsISupports; +class nsIEventTarget; + +namespace mozilla { +namespace net { + +class ChannelEvent +{ + public: + ChannelEvent() { MOZ_COUNT_CTOR(ChannelEvent); } + virtual ~ChannelEvent() { MOZ_COUNT_DTOR(ChannelEvent); } + virtual void Run() = 0; +}; + +// Workaround for Necko re-entrancy dangers. We buffer IPDL messages in a +// queue if still dispatching previous one(s) to listeners/observers. +// Otherwise synchronous XMLHttpRequests and/or other code that spins the +// event loop (ex: IPDL rpc) could cause listener->OnDataAvailable (for +// instance) to be dispatched and called before mListener->OnStartRequest has +// completed. + +class ChannelEventQueue final +{ + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChannelEventQueue) + + public: + explicit ChannelEventQueue(nsISupports *owner) + : mSuspendCount(0) + , mSuspended(false) + , mForced(false) + , mFlushing(false) + , mOwner(owner) + , mMutex("ChannelEventQueue::mMutex") + {} + + // Puts IPDL-generated channel event into queue, to be run later + // automatically when EndForcedQueueing and/or Resume is called. + // + // @param aCallback - the ChannelEvent + // @param aAssertionWhenNotQueued - this optional param will be used in an + // assertion when the event is executed directly. + inline void RunOrEnqueue(ChannelEvent* aCallback, + bool aAssertionWhenNotQueued = false); + inline nsresult PrependEvents(nsTArray<UniquePtr<ChannelEvent>>& aEvents); + + // After StartForcedQueueing is called, RunOrEnqueue() will start enqueuing + // events that will be run/flushed when EndForcedQueueing is called. + // - Note: queueing may still be required after EndForcedQueueing() (if the + // queue is suspended, etc): always call RunOrEnqueue() to avoid race + // conditions. + inline void StartForcedQueueing(); + inline void EndForcedQueueing(); + + // Suspend/resume event queue. RunOrEnqueue() will start enqueuing + // events and they will be run/flushed when resume is called. These should be + // called when the channel owning the event queue is suspended/resumed. + inline void Suspend(); + // Resume flushes the queue asynchronously, i.e. items in queue will be + // dispatched in a new event on the current thread. + void Resume(); + + // Retargets delivery of events to the target thread specified. + nsresult RetargetDeliveryTo(nsIEventTarget* aTargetThread); + + private: + // Private destructor, to discourage deletion outside of Release(): + ~ChannelEventQueue() + { + } + + inline void MaybeFlushQueue(); + void FlushQueue(); + inline void CompleteResume(); + + ChannelEvent* TakeEvent(); + + nsTArray<UniquePtr<ChannelEvent>> mEventQueue; + + uint32_t mSuspendCount; + bool mSuspended; + bool mForced; + bool mFlushing; + + // Keep ptr to avoid refcount cycle: only grab ref during flushing. + nsISupports *mOwner; + + Mutex mMutex; + + // EventTarget for delivery of events to the correct thread. + nsCOMPtr<nsIEventTarget> mTargetThread; + + friend class AutoEventEnqueuer; +}; + +inline void +ChannelEventQueue::RunOrEnqueue(ChannelEvent* aCallback, + bool aAssertionWhenNotQueued) +{ + MOZ_ASSERT(aCallback); + + // To avoid leaks. + UniquePtr<ChannelEvent> event(aCallback); + + { + MutexAutoLock lock(mMutex); + + bool enqueue = mForced || mSuspended || mFlushing; + MOZ_ASSERT(enqueue == true || mEventQueue.IsEmpty(), + "Should always enqueue if ChannelEventQueue not empty"); + + if (enqueue) { + mEventQueue.AppendElement(Move(event)); + return; + } + } + + MOZ_RELEASE_ASSERT(!aAssertionWhenNotQueued); + event->Run(); +} + +inline void +ChannelEventQueue::StartForcedQueueing() +{ + MutexAutoLock lock(mMutex); + mForced = true; +} + +inline void +ChannelEventQueue::EndForcedQueueing() +{ + { + MutexAutoLock lock(mMutex); + mForced = false; + } + + MaybeFlushQueue(); +} + +inline nsresult +ChannelEventQueue::PrependEvents(nsTArray<UniquePtr<ChannelEvent>>& aEvents) +{ + MutexAutoLock lock(mMutex); + + UniquePtr<ChannelEvent>* newEvents = + mEventQueue.InsertElementsAt(0, aEvents.Length()); + if (!newEvents) { + return NS_ERROR_OUT_OF_MEMORY; + } + + for (uint32_t i = 0; i < aEvents.Length(); i++) { + newEvents[i] = Move(aEvents[i]); + } + + return NS_OK; +} + +inline void +ChannelEventQueue::Suspend() +{ + MutexAutoLock lock(mMutex); + + mSuspended = true; + mSuspendCount++; +} + +inline void +ChannelEventQueue::CompleteResume() +{ + { + MutexAutoLock lock(mMutex); + + // channel may have been suspended again since Resume fired event to call + // this. + if (!mSuspendCount) { + // we need to remain logically suspended (for purposes of queuing incoming + // messages) until this point, else new incoming messages could run before + // queued ones. + mSuspended = false; + } + } + + MaybeFlushQueue(); +} + +inline void +ChannelEventQueue::MaybeFlushQueue() +{ + // Don't flush if forced queuing on, we're already being flushed, or + // suspended, or there's nothing to flush + bool flushQueue = false; + + { + MutexAutoLock lock(mMutex); + flushQueue = !mForced && !mFlushing && !mSuspended && + !mEventQueue.IsEmpty(); + } + + if (flushQueue) { + FlushQueue(); + } +} + +// Ensures that RunOrEnqueue() will be collecting events during its lifetime +// (letting caller know incoming IPDL msgs should be queued). Flushes the queue +// when it goes out of scope. +class MOZ_STACK_CLASS AutoEventEnqueuer +{ + public: + explicit AutoEventEnqueuer(ChannelEventQueue *queue) : mEventQueue(queue) { + mEventQueue->StartForcedQueueing(); + } + ~AutoEventEnqueuer() { + mEventQueue->EndForcedQueueing(); + } + private: + RefPtr<ChannelEventQueue> mEventQueue; +}; + +} // namespace net +} // namespace mozilla + +#endif diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh new file mode 100644 index 0000000000..9365397d19 --- /dev/null +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -0,0 +1,196 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 ft=c: */ + +/* 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/. */ + +include protocol PHttpChannel; +include protocol PFTPChannel; +include protocol PRtspChannel; +include protocol PSendStream; +include BlobTypes; +include URIParams; +include IPCStream; +include InputStreamParams; +include PBackgroundSharedTypes; + +using mozilla::NeckoOriginAttributes from "mozilla/ipc/BackgroundUtils.h"; +using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; +using RequestHeaderTuples from "mozilla/net/PHttpChannelParams.h"; +using struct nsHttpAtom from "nsHttp.h"; +using class nsHttpResponseHead from "nsHttpResponseHead.h"; + +namespace mozilla { +namespace net { + +//----------------------------------------------------------------------------- +// LoadInfo IPDL structs +//----------------------------------------------------------------------------- + +struct LoadInfoArgs +{ + OptionalPrincipalInfo requestingPrincipalInfo; + PrincipalInfo triggeringPrincipalInfo; + OptionalPrincipalInfo principalToInheritInfo; + uint32_t securityFlags; + uint32_t contentPolicyType; + uint32_t tainting; + bool upgradeInsecureRequests; + bool verifySignedContent; + bool enforceSRI; + bool forceInheritPrincipalDropped; + uint64_t innerWindowID; + uint64_t outerWindowID; + uint64_t parentOuterWindowID; + uint64_t frameOuterWindowID; + bool enforceSecurity; + bool initialSecurityCheckDone; + bool isInThirdPartyContext; + NeckoOriginAttributes originAttributes; + PrincipalInfo[] redirectChainIncludingInternalRedirects; + PrincipalInfo[] redirectChain; + nsCString[] corsUnsafeHeaders; + bool forcePreflight; + bool isPreflight; + bool forceHSTSPriming; + bool mixedContentWouldBlock; +}; + +/** + * Not every channel necessarily has a loadInfo attached. + */ +union OptionalLoadInfoArgs +{ + void_t; + LoadInfoArgs; +}; + +//----------------------------------------------------------------------------- +// HTTP IPDL structs +//----------------------------------------------------------------------------- + +union OptionalHttpResponseHead +{ + void_t; + nsHttpResponseHead; +}; + +struct CorsPreflightArgs +{ + nsCString[] unsafeHeaders; +}; + +union OptionalCorsPreflightArgs +{ + void_t; + CorsPreflightArgs; +}; + +struct HttpChannelOpenArgs +{ + URIParams uri; + // - TODO: bug 571161: unclear if any HTTP channel clients ever + // set originalURI != uri (about:credits?); also not clear if + // chrome channel would ever need to know. Get rid of next arg? + OptionalURIParams original; + OptionalURIParams doc; + OptionalURIParams referrer; + uint32_t referrerPolicy; + OptionalURIParams apiRedirectTo; + OptionalURIParams topWindowURI; + uint32_t loadFlags; + RequestHeaderTuples requestHeaders; + nsCString requestMethod; + OptionalIPCStream uploadStream; + bool uploadStreamHasHeaders; + uint16_t priority; + uint32_t classOfService; + uint8_t redirectionLimit; + bool allowPipelining; + bool allowSTS; + uint32_t thirdPartyFlags; + bool resumeAt; + uint64_t startPos; + nsCString entityID; + bool chooseApplicationCache; + nsCString appCacheClientID; + bool allowSpdy; + bool allowAltSvc; + bool beConservative; + OptionalLoadInfoArgs loadInfo; + OptionalHttpResponseHead synthesizedResponseHead; + nsCString synthesizedSecurityInfoSerialization; + uint32_t cacheKey; + nsCString requestContextID; + OptionalCorsPreflightArgs preflightArgs; + uint32_t initialRwin; + bool blockAuthPrompt; + bool suspendAfterSynthesizeResponse; + bool allowStaleCacheContent; + nsCString contentTypeHint; + nsCString channelId; + uint64_t contentWindowId; + nsCString preferredAlternativeType; +}; + +struct HttpChannelConnectArgs +{ + uint32_t registrarId; + bool shouldIntercept; +}; + +union HttpChannelCreationArgs +{ + HttpChannelOpenArgs; // For AsyncOpen: the common case. + HttpChannelConnectArgs; // Used for redirected-to channels +}; + +//----------------------------------------------------------------------------- +// FTP IPDL structs +//----------------------------------------------------------------------------- + +struct FTPChannelOpenArgs +{ + URIParams uri; + uint64_t startPos; + nsCString entityID; + OptionalInputStreamParams uploadStream; + OptionalLoadInfoArgs loadInfo; +}; + +struct FTPChannelConnectArgs +{ + uint32_t channelId; +}; + +union FTPChannelCreationArgs +{ + FTPChannelOpenArgs; // For AsyncOpen: the common case. + FTPChannelConnectArgs; // Used for redirected-to channels +}; + +struct HttpChannelDiverterArgs +{ + PHttpChannel mChannel; + bool mApplyConversion; +}; + +union ChannelDiverterArgs +{ + HttpChannelDiverterArgs; + PFTPChannel; +}; + +//----------------------------------------------------------------------------- +// RTSP IPDL structs +//----------------------------------------------------------------------------- + +struct RtspChannelConnectArgs +{ + URIParams uri; + uint32_t channelId; +}; + +} // namespace ipc +} // namespace mozilla diff --git a/netwerk/ipc/NeckoChild.cpp b/netwerk/ipc/NeckoChild.cpp new file mode 100644 index 0000000000..00827b5a08 --- /dev/null +++ b/netwerk/ipc/NeckoChild.cpp @@ -0,0 +1,431 @@ + +/* vim: set sw=2 ts=8 et tw=80 : */ + +/* 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/. */ + +#include "necko-config.h" +#include "nsHttp.h" +#include "mozilla/net/NeckoChild.h" +#include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/TabChild.h" +#include "mozilla/net/HttpChannelChild.h" +#include "mozilla/net/CookieServiceChild.h" +#include "mozilla/net/WyciwygChannelChild.h" +#include "mozilla/net/FTPChannelChild.h" +#include "mozilla/net/WebSocketChannelChild.h" +#include "mozilla/net/WebSocketEventListenerChild.h" +#include "mozilla/net/DNSRequestChild.h" +#include "mozilla/net/ChannelDiverterChild.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" + +#ifdef NECKO_PROTOCOL_rtsp +#include "mozilla/net/RtspControllerChild.h" +#include "mozilla/net/RtspChannelChild.h" +#endif +#include "SerializedLoadContext.h" +#include "nsIOService.h" +#include "nsINetworkPredictor.h" +#include "nsINetworkPredictorVerifier.h" +#include "mozilla/ipc/URIUtils.h" +#include "nsNetUtil.h" + +using mozilla::dom::TCPSocketChild; +using mozilla::dom::TCPServerSocketChild; +using mozilla::dom::UDPSocketChild; + +namespace mozilla { +namespace net { + +PNeckoChild *gNeckoChild = nullptr; + +// C++ file contents +NeckoChild::NeckoChild() +{ +} + +NeckoChild::~NeckoChild() +{ + //Send__delete__(gNeckoChild); + gNeckoChild = nullptr; +} + +void NeckoChild::InitNeckoChild() +{ + MOZ_ASSERT(IsNeckoChild(), "InitNeckoChild called by non-child!"); + + if (!gNeckoChild) { + mozilla::dom::ContentChild * cpc = + mozilla::dom::ContentChild::GetSingleton(); + NS_ASSERTION(cpc, "Content Protocol is NULL!"); + gNeckoChild = cpc->SendPNeckoConstructor(); + NS_ASSERTION(gNeckoChild, "PNecko Protocol init failed!"); + } +} + +PHttpChannelChild* +NeckoChild::AllocPHttpChannelChild(const PBrowserOrId& browser, + const SerializedLoadContext& loadContext, + const HttpChannelCreationArgs& aOpenArgs) +{ + // We don't allocate here: instead we always use IPDL constructor that takes + // an existing HttpChildChannel + NS_NOTREACHED("AllocPHttpChannelChild should not be called on child"); + return nullptr; +} + +bool +NeckoChild::DeallocPHttpChannelChild(PHttpChannelChild* channel) +{ + MOZ_ASSERT(IsNeckoChild(), "DeallocPHttpChannelChild called by non-child!"); + + HttpChannelChild* child = static_cast<HttpChannelChild*>(channel); + child->ReleaseIPDLReference(); + return true; +} + +PAltDataOutputStreamChild* +NeckoChild::AllocPAltDataOutputStreamChild( + const nsCString& type, + PHttpChannelChild* channel) +{ + AltDataOutputStreamChild* stream = new AltDataOutputStreamChild(); + stream->AddIPDLReference(); + return stream; +} + +bool +NeckoChild::DeallocPAltDataOutputStreamChild(PAltDataOutputStreamChild* aActor) +{ + AltDataOutputStreamChild* child = static_cast<AltDataOutputStreamChild*>(aActor); + child->ReleaseIPDLReference(); + return true; +} + +PFTPChannelChild* +NeckoChild::AllocPFTPChannelChild(const PBrowserOrId& aBrowser, + const SerializedLoadContext& aSerialized, + const FTPChannelCreationArgs& aOpenArgs) +{ + // We don't allocate here: see FTPChannelChild::AsyncOpen() + NS_RUNTIMEABORT("AllocPFTPChannelChild should not be called"); + return nullptr; +} + +bool +NeckoChild::DeallocPFTPChannelChild(PFTPChannelChild* channel) +{ + MOZ_ASSERT(IsNeckoChild(), "DeallocPFTPChannelChild called by non-child!"); + + FTPChannelChild* child = static_cast<FTPChannelChild*>(channel); + child->ReleaseIPDLReference(); + return true; +} + +PCookieServiceChild* +NeckoChild::AllocPCookieServiceChild() +{ + // We don't allocate here: see nsCookieService::GetSingleton() + NS_NOTREACHED("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; +} + +PWyciwygChannelChild* +NeckoChild::AllocPWyciwygChannelChild() +{ + WyciwygChannelChild *p = new WyciwygChannelChild(); + p->AddIPDLReference(); + return p; +} + +bool +NeckoChild::DeallocPWyciwygChannelChild(PWyciwygChannelChild* channel) +{ + MOZ_ASSERT(IsNeckoChild(), "DeallocPWyciwygChannelChild called by non-child!"); + + WyciwygChannelChild *p = static_cast<WyciwygChannelChild*>(channel); + p->ReleaseIPDLReference(); + return true; +} + +PWebSocketChild* +NeckoChild::AllocPWebSocketChild(const PBrowserOrId& browser, + const SerializedLoadContext& aSerialized, + const uint32_t& aSerial) +{ + NS_NOTREACHED("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) +{ + RefPtr<WebSocketEventListenerChild> c = + new WebSocketEventListenerChild(aInnerWindowID); + return c.forget().take(); +} + +bool +NeckoChild::DeallocPWebSocketEventListenerChild(PWebSocketEventListenerChild* aActor) +{ + RefPtr<WebSocketEventListenerChild> c = + dont_AddRef(static_cast<WebSocketEventListenerChild*>(aActor)); + MOZ_ASSERT(c); + return true; +} + +PDataChannelChild* +NeckoChild::AllocPDataChannelChild(const uint32_t& channelId) +{ + MOZ_ASSERT_UNREACHABLE("Should never get here"); + return nullptr; +} + +bool +NeckoChild::DeallocPDataChannelChild(PDataChannelChild* child) +{ + // NB: See DataChannelChild::ActorDestroy. + return true; +} + +PRtspControllerChild* +NeckoChild::AllocPRtspControllerChild() +{ + NS_NOTREACHED("AllocPRtspController should not be called"); + return nullptr; +} + +bool +NeckoChild::DeallocPRtspControllerChild(PRtspControllerChild* child) +{ +#ifdef NECKO_PROTOCOL_rtsp + RtspControllerChild* p = static_cast<RtspControllerChild*>(child); + p->ReleaseIPDLReference(); +#endif + return true; +} + +PRtspChannelChild* +NeckoChild::AllocPRtspChannelChild(const RtspChannelConnectArgs& aArgs) +{ + NS_NOTREACHED("AllocPRtspController should not be called"); + return nullptr; +} + +bool +NeckoChild::DeallocPRtspChannelChild(PRtspChannelChild* child) +{ +#ifdef NECKO_PROTOCOL_rtsp + RtspChannelChild* p = static_cast<RtspChannelChild*>(child); + p->ReleaseIPDLReference(); +#endif + return true; +} + +PTCPSocketChild* +NeckoChild::AllocPTCPSocketChild(const nsString& host, + const uint16_t& port) +{ + TCPSocketChild* p = new TCPSocketChild(host, port); + 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) +{ + NS_NOTREACHED("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(const Principal& aPrincipal, + const nsCString& aFilter) +{ + NS_NOTREACHED("AllocPUDPSocket should not be called"); + return nullptr; +} + +bool +NeckoChild::DeallocPUDPSocketChild(PUDPSocketChild* child) +{ + + UDPSocketChild* p = static_cast<UDPSocketChild*>(child); + p->ReleaseIPDLReference(); + return true; +} + +PDNSRequestChild* +NeckoChild::AllocPDNSRequestChild(const nsCString& aHost, + const uint32_t& aFlags, + const nsCString& aNetworkInterface) +{ + // We don't allocate here: instead we always use IPDL constructor that takes + // an existing object + NS_NOTREACHED("AllocPDNSRequestChild should not be called on child"); + return nullptr; +} + +bool +NeckoChild::DeallocPDNSRequestChild(PDNSRequestChild* aChild) +{ + DNSRequestChild *p = static_cast<DNSRequestChild*>(aChild); + p->ReleaseIPDLReference(); + return true; +} + +PChannelDiverterChild* +NeckoChild::AllocPChannelDiverterChild(const ChannelDiverterArgs& channel) +{ + return new ChannelDiverterChild();; +} + +bool +NeckoChild::DeallocPChannelDiverterChild(PChannelDiverterChild* child) +{ + delete static_cast<ChannelDiverterChild*>(child); + 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; +} + +bool +NeckoChild::RecvAsyncAuthPromptForNestedFrame(const TabId& aNestedFrameId, + const nsCString& aUri, + const nsString& aRealm, + const uint64_t& aCallbackId) +{ + RefPtr<dom::TabChild> tabChild = dom::TabChild::FindTabChild(aNestedFrameId); + if (!tabChild) { + MOZ_CRASH(); + return false; + } + tabChild->SendAsyncAuthPrompt(aUri, aRealm, aCallbackId); + return true; +} + +/* Predictor Messages */ +bool +NeckoChild::RecvPredOnPredictPrefetch(const URIParams& aURI, + const uint32_t& aHttpStatus) +{ + MOZ_ASSERT(NS_IsMainThread(), "PredictorChild::RecvOnPredictPrefetch " + "off main thread."); + + nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); + + // Get the current predictor + nsresult rv = NS_OK; + nsCOMPtr<nsINetworkPredictorVerifier> predictor = + do_GetService("@mozilla.org/network/predictor;1", &rv); + NS_ENSURE_SUCCESS(rv, false); + + predictor->OnPredictPrefetch(uri, aHttpStatus); + return true; +} + +bool +NeckoChild::RecvPredOnPredictPreconnect(const URIParams& aURI) +{ + MOZ_ASSERT(NS_IsMainThread(), "PredictorChild::RecvOnPredictPreconnect " + "off main thread."); + + nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); + + // Get the current predictor + nsresult rv = NS_OK; + nsCOMPtr<nsINetworkPredictorVerifier> predictor = + do_GetService("@mozilla.org/network/predictor;1", &rv); + NS_ENSURE_SUCCESS(rv, false); + + predictor->OnPredictPreconnect(uri); + return true; +} + +bool +NeckoChild::RecvPredOnPredictDNS(const URIParams& aURI) +{ + MOZ_ASSERT(NS_IsMainThread(), "PredictorChild::RecvOnPredictDNS off " + "main thread."); + + nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); + + // Get the current predictor + nsresult rv = NS_OK; + nsCOMPtr<nsINetworkPredictorVerifier> predictor = + do_GetService("@mozilla.org/network/predictor;1", &rv); + NS_ENSURE_SUCCESS(rv, false); + + predictor->OnPredictDNS(uri); + return true; +} + +bool +NeckoChild::RecvSpeculativeConnectRequest() +{ + nsCOMPtr<nsIObserverService> obsService = services::GetObserverService(); + if (obsService) { + obsService->NotifyObservers(nullptr, "speculative-connect-request", + nullptr); + } + return true; +} + +} // namespace net +} // namespace mozilla + diff --git a/netwerk/ipc/NeckoChild.h b/netwerk/ipc/NeckoChild.h new file mode 100644 index 0000000000..d1889d897b --- /dev/null +++ b/netwerk/ipc/NeckoChild.h @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ + +/* 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/. */ + +#ifndef mozilla_net_NeckoChild_h +#define mozilla_net_NeckoChild_h + +#include "mozilla/net/PNeckoChild.h" +#include "mozilla/net/NeckoCommon.h" + +namespace mozilla { +namespace net { + +// Header file contents +class NeckoChild : + public PNeckoChild +{ +public: + NeckoChild(); + virtual ~NeckoChild(); + + static void InitNeckoChild(); + +protected: + virtual PHttpChannelChild* + AllocPHttpChannelChild(const PBrowserOrId&, const SerializedLoadContext&, + const HttpChannelCreationArgs& aOpenArgs) override; + virtual bool DeallocPHttpChannelChild(PHttpChannelChild*) override; + + virtual PAltDataOutputStreamChild* AllocPAltDataOutputStreamChild(const nsCString& type, PHttpChannelChild* channel) override; + virtual bool DeallocPAltDataOutputStreamChild(PAltDataOutputStreamChild* aActor) override; + + virtual PCookieServiceChild* AllocPCookieServiceChild() override; + virtual bool DeallocPCookieServiceChild(PCookieServiceChild*) override; + virtual PWyciwygChannelChild* AllocPWyciwygChannelChild() override; + virtual bool DeallocPWyciwygChannelChild(PWyciwygChannelChild*) override; + virtual PFTPChannelChild* + AllocPFTPChannelChild(const PBrowserOrId& aBrowser, + const SerializedLoadContext& aSerialized, + const FTPChannelCreationArgs& aOpenArgs) override; + virtual bool DeallocPFTPChannelChild(PFTPChannelChild*) override; + virtual PWebSocketChild* + AllocPWebSocketChild(const PBrowserOrId&, + const SerializedLoadContext&, + const uint32_t&) override; + virtual bool DeallocPWebSocketChild(PWebSocketChild*) override; + virtual PTCPSocketChild* AllocPTCPSocketChild(const nsString& host, + const uint16_t& port) override; + virtual bool DeallocPTCPSocketChild(PTCPSocketChild*) override; + virtual PTCPServerSocketChild* + AllocPTCPServerSocketChild(const uint16_t& aLocalPort, + const uint16_t& aBacklog, + const bool& aUseArrayBuffers) override; + virtual bool DeallocPTCPServerSocketChild(PTCPServerSocketChild*) override; + virtual PUDPSocketChild* AllocPUDPSocketChild(const Principal& aPrincipal, + const nsCString& aFilter) override; + virtual bool DeallocPUDPSocketChild(PUDPSocketChild*) override; + virtual PDNSRequestChild* AllocPDNSRequestChild(const nsCString& aHost, + const uint32_t& aFlags, + const nsCString& aNetworkInterface) override; + virtual bool DeallocPDNSRequestChild(PDNSRequestChild*) override; + virtual PDataChannelChild* AllocPDataChannelChild(const uint32_t& channelId) override; + virtual bool DeallocPDataChannelChild(PDataChannelChild* child) override; + virtual PRtspControllerChild* AllocPRtspControllerChild() override; + virtual bool DeallocPRtspControllerChild(PRtspControllerChild*) override; + virtual PRtspChannelChild* + AllocPRtspChannelChild(const RtspChannelConnectArgs& aArgs) + override; + virtual bool DeallocPRtspChannelChild(PRtspChannelChild*) override; + virtual PChannelDiverterChild* + AllocPChannelDiverterChild(const ChannelDiverterArgs& channel) override; + virtual bool + DeallocPChannelDiverterChild(PChannelDiverterChild* actor) override; + virtual PTransportProviderChild* + AllocPTransportProviderChild() override; + virtual bool + DeallocPTransportProviderChild(PTransportProviderChild* aActor) override; + virtual bool RecvAsyncAuthPromptForNestedFrame(const TabId& aNestedFrameId, + const nsCString& aUri, + const nsString& aRealm, + const uint64_t& aCallbackId) override; + virtual PWebSocketEventListenerChild* + AllocPWebSocketEventListenerChild(const uint64_t& aInnerWindowID) override; + virtual bool DeallocPWebSocketEventListenerChild(PWebSocketEventListenerChild*) override; + + /* Predictor Messsages */ + virtual bool RecvPredOnPredictPrefetch(const URIParams& aURI, + const uint32_t& aHttpStatus) override; + virtual bool RecvPredOnPredictPreconnect(const URIParams& aURI) override; + virtual bool RecvPredOnPredictDNS(const URIParams& aURI) override; + + virtual bool RecvSpeculativeConnectRequest() override; +}; + +/** + * Reference to the PNecko Child protocol. + * Null if this is not a content process. + */ +extern PNeckoChild *gNeckoChild; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_NeckoChild_h diff --git a/netwerk/ipc/NeckoCommon.cpp b/netwerk/ipc/NeckoCommon.cpp new file mode 100644 index 0000000000..ea2dce5b24 --- /dev/null +++ b/netwerk/ipc/NeckoCommon.cpp @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ + +/* 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/. */ + +#include "NeckoCommon.h" + +namespace mozilla { +namespace net { + +namespace NeckoCommonInternal { + bool gSecurityDisabled = true; +} // namespace NeckoCommonInternal + +} // namespace net +} // namespace mozilla diff --git a/netwerk/ipc/NeckoCommon.h b/netwerk/ipc/NeckoCommon.h new file mode 100644 index 0000000000..ed92ac25ea --- /dev/null +++ b/netwerk/ipc/NeckoCommon.h @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ + +/* 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/. */ + +#ifndef mozilla_net_NeckoCommon_h +#define mozilla_net_NeckoCommon_h + +#include "nsXULAppAPI.h" +#include "prenv.h" +#include "nsPrintfCString.h" +#include "mozilla/Preferences.h" + +namespace mozilla { namespace dom { +class TabChild; +} // namespace dom +} // namespace mozilla + +#if defined(DEBUG) +# define NECKO_ERRORS_ARE_FATAL_DEFAULT true +#else +# define NECKO_ERRORS_ARE_FATAL_DEFAULT false +#endif + +// TODO: Eventually remove NECKO_MAYBE_ABORT and DROP_DEAD (bug 575494). +// Still useful for catching listener interfaces we don't yet support across +// processes, etc. + +#define NECKO_MAYBE_ABORT(msg) \ + do { \ + bool abort = NECKO_ERRORS_ARE_FATAL_DEFAULT; \ + const char *e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"); \ + if (e) \ + abort = (*e == '0') ? false : true; \ + if (abort) { \ + msg.Append(" (set NECKO_ERRORS_ARE_FATAL=0 in your environment to " \ + "convert this error into a warning.)"); \ + NS_RUNTIMEABORT(msg.get()); \ + } else { \ + msg.Append(" (set NECKO_ERRORS_ARE_FATAL=1 in your environment to " \ + "convert this warning into a fatal error.)"); \ + NS_WARNING(msg.get()); \ + } \ + } while (0) + +#define DROP_DEAD() \ + do { \ + nsPrintfCString msg("NECKO ERROR: '%s' UNIMPLEMENTED", \ + __FUNCTION__); \ + NECKO_MAYBE_ABORT(msg); \ + return NS_ERROR_NOT_IMPLEMENTED; \ + } while (0) + +#define ENSURE_CALLED_BEFORE_ASYNC_OPEN() \ + do { \ + if (mIsPending || mWasOpened) { \ + nsPrintfCString msg("'%s' called after AsyncOpen: %s +%d", \ + __FUNCTION__, __FILE__, __LINE__); \ + NECKO_MAYBE_ABORT(msg); \ + } \ + NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); \ + NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED); \ + } while (0) + +// Fails call if made after request observers (on-modify-request, etc) have been +// called + +#define ENSURE_CALLED_BEFORE_CONNECT() \ + do { \ + if (mRequestObserversCalled) { \ + nsPrintfCString msg("'%s' called too late: %s +%d", \ + __FUNCTION__, __FILE__, __LINE__); \ + NECKO_MAYBE_ABORT(msg); \ + if (mIsPending) \ + return NS_ERROR_IN_PROGRESS; \ + MOZ_ASSERT(mWasOpened); \ + return NS_ERROR_ALREADY_OPENED; \ + } \ + } while (0) + +namespace mozilla { +namespace net { + +inline bool +IsNeckoChild() +{ + static bool didCheck = false; + static bool amChild = false; + + if (!didCheck) { + didCheck = true; + amChild = (XRE_GetProcessType() == GeckoProcessType_Content); + } + return amChild; +} + +namespace NeckoCommonInternal { + extern bool gSecurityDisabled; + extern bool gRegisteredBool; +} // namespace NeckoCommonInternal + +// This should always return true unless xpcshell tests are being used +inline bool +UsingNeckoIPCSecurity() +{ + return !NeckoCommonInternal::gSecurityDisabled; +} + +inline bool +MissingRequiredTabChild(mozilla::dom::TabChild* tabChild, + const char* context) +{ + if (UsingNeckoIPCSecurity()) { + if (!tabChild) { + printf_stderr("WARNING: child tried to open %s IPDL channel w/o " + "security info\n", context); + return true; + } + } + return false; +} + + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_NeckoCommon_h + diff --git a/netwerk/ipc/NeckoMessageUtils.h b/netwerk/ipc/NeckoMessageUtils.h new file mode 100644 index 0000000000..273f049a26 --- /dev/null +++ b/netwerk/ipc/NeckoMessageUtils.h @@ -0,0 +1,189 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#ifndef mozilla_net_NeckoMessageUtils_h +#define mozilla_net_NeckoMessageUtils_h + +#include "mozilla/DebugOnly.h" + +#include "ipc/IPCMessageUtils.h" +#include "nsStringGlue.h" +#include "prio.h" +#include "mozilla/net/DNS.h" +#include "TimingStruct.h" + +#ifdef MOZ_CRASHREPORTER +#include "nsExceptionHandler.h" +#include "nsPrintfCString.h" +#endif + +namespace IPC { + +// nsIPermissionManager utilities + +struct Permission +{ + nsCString origin, type; + uint32_t capability, expireType; + int64_t expireTime; + + Permission() { } + Permission(const nsCString& aOrigin, + const nsCString& aType, + const uint32_t aCapability, + const uint32_t aExpireType, + const int64_t aExpireTime) : origin(aOrigin), + type(aType), + capability(aCapability), + expireType(aExpireType), + expireTime(aExpireTime) + {} +}; + +template<> +struct ParamTraits<Permission> +{ + static void Write(Message* aMsg, const Permission& aParam) + { + WriteParam(aMsg, aParam.origin); + WriteParam(aMsg, aParam.type); + WriteParam(aMsg, aParam.capability); + WriteParam(aMsg, aParam.expireType); + WriteParam(aMsg, aParam.expireTime); + } + + static bool Read(const Message* aMsg, PickleIterator* aIter, Permission* aResult) + { + return ReadParam(aMsg, aIter, &aResult->origin) && + ReadParam(aMsg, aIter, &aResult->type) && + ReadParam(aMsg, aIter, &aResult->capability) && + ReadParam(aMsg, aIter, &aResult->expireType) && + ReadParam(aMsg, aIter, &aResult->expireTime); + } + + static void Log(const Permission& p, std::wstring* l) + { + l->append(L"("); + LogParam(p.origin, l); + l->append(L", "); + LogParam(p.capability, l); + l->append(L", "); + LogParam(p.expireTime, l); + l->append(L", "); + LogParam(p.expireType, l); + l->append(L")"); + } +}; + +template<> +struct ParamTraits<mozilla::net::NetAddr> +{ + static void Write(Message* aMsg, const mozilla::net::NetAddr &aParam) + { + WriteParam(aMsg, aParam.raw.family); + if (aParam.raw.family == AF_UNSPEC) { + aMsg->WriteBytes(aParam.raw.data, sizeof(aParam.raw.data)); + } else if (aParam.raw.family == AF_INET) { + WriteParam(aMsg, aParam.inet.port); + WriteParam(aMsg, aParam.inet.ip); + } else if (aParam.raw.family == AF_INET6) { + WriteParam(aMsg, aParam.inet6.port); + WriteParam(aMsg, aParam.inet6.flowinfo); + WriteParam(aMsg, aParam.inet6.ip.u64[0]); + WriteParam(aMsg, aParam.inet6.ip.u64[1]); + WriteParam(aMsg, aParam.inet6.scope_id); +#if defined(XP_UNIX) + } else if (aParam.raw.family == AF_LOCAL) { + // Train's already off the rails: let's get a stack trace at least... + NS_RUNTIMEABORT("Error: please post stack trace to " + "https://bugzilla.mozilla.org/show_bug.cgi?id=661158"); + aMsg->WriteBytes(aParam.local.path, sizeof(aParam.local.path)); +#endif + } else { +#ifdef MOZ_CRASHREPORTER + if (XRE_IsParentProcess()) { + nsPrintfCString msg("%d", aParam.raw.family); + CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Unknown NetAddr socket family"), msg); + } +#endif + NS_RUNTIMEABORT("Unknown socket family"); + } + } + + static bool Read(const Message* aMsg, PickleIterator* aIter, mozilla::net::NetAddr* aResult) + { + if (!ReadParam(aMsg, aIter, &aResult->raw.family)) + return false; + + if (aResult->raw.family == AF_UNSPEC) { + return aMsg->ReadBytesInto(aIter, &aResult->raw.data, sizeof(aResult->raw.data)); + } else if (aResult->raw.family == AF_INET) { + return ReadParam(aMsg, aIter, &aResult->inet.port) && + ReadParam(aMsg, aIter, &aResult->inet.ip); + } else if (aResult->raw.family == AF_INET6) { + return ReadParam(aMsg, aIter, &aResult->inet6.port) && + ReadParam(aMsg, aIter, &aResult->inet6.flowinfo) && + ReadParam(aMsg, aIter, &aResult->inet6.ip.u64[0]) && + ReadParam(aMsg, aIter, &aResult->inet6.ip.u64[1]) && + ReadParam(aMsg, aIter, &aResult->inet6.scope_id); +#if defined(XP_UNIX) + } else if (aResult->raw.family == AF_LOCAL) { + return aMsg->ReadBytesInto(aIter, &aResult->local.path, sizeof(aResult->local.path)); +#endif + } + + /* We've been tricked by some socket family we don't know about! */ + return false; + } +}; + +template<> +struct ParamTraits<mozilla::net::ResourceTimingStruct> +{ + static void Write(Message* aMsg, const mozilla::net::ResourceTimingStruct& aParam) + { + WriteParam(aMsg, aParam.domainLookupStart); + WriteParam(aMsg, aParam.domainLookupEnd); + WriteParam(aMsg, aParam.connectStart); + WriteParam(aMsg, aParam.connectEnd); + WriteParam(aMsg, aParam.requestStart); + WriteParam(aMsg, aParam.responseStart); + WriteParam(aMsg, aParam.responseEnd); + + WriteParam(aMsg, aParam.fetchStart); + WriteParam(aMsg, aParam.redirectStart); + WriteParam(aMsg, aParam.redirectEnd); + + WriteParam(aMsg, aParam.transferSize); + WriteParam(aMsg, aParam.encodedBodySize); + WriteParam(aMsg, aParam.protocolVersion); + + WriteParam(aMsg, aParam.cacheReadStart); + WriteParam(aMsg, aParam.cacheReadEnd); + } + + static bool Read(const Message* aMsg, PickleIterator* aIter, mozilla::net::ResourceTimingStruct* aResult) + { + return ReadParam(aMsg, aIter, &aResult->domainLookupStart) && + ReadParam(aMsg, aIter, &aResult->domainLookupEnd) && + ReadParam(aMsg, aIter, &aResult->connectStart) && + ReadParam(aMsg, aIter, &aResult->connectEnd) && + ReadParam(aMsg, aIter, &aResult->requestStart) && + ReadParam(aMsg, aIter, &aResult->responseStart) && + ReadParam(aMsg, aIter, &aResult->responseEnd) && + ReadParam(aMsg, aIter, &aResult->fetchStart) && + ReadParam(aMsg, aIter, &aResult->redirectStart) && + ReadParam(aMsg, aIter, &aResult->redirectEnd) && + ReadParam(aMsg, aIter, &aResult->transferSize) && + ReadParam(aMsg, aIter, &aResult->encodedBodySize) && + ReadParam(aMsg, aIter, &aResult->protocolVersion) && + ReadParam(aMsg, aIter, &aResult->cacheReadStart) && + ReadParam(aMsg, aIter, &aResult->cacheReadEnd); + } +}; + +} // namespace IPC + +#endif // mozilla_net_NeckoMessageUtils_h diff --git a/netwerk/ipc/NeckoParent.cpp b/netwerk/ipc/NeckoParent.cpp new file mode 100644 index 0000000000..5913b59d9a --- /dev/null +++ b/netwerk/ipc/NeckoParent.cpp @@ -0,0 +1,907 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ + +/* 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/. */ + +#include "necko-config.h" +#include "nsHttp.h" +#include "mozilla/net/NeckoParent.h" +#include "mozilla/net/HttpChannelParent.h" +#include "mozilla/net/CookieServiceParent.h" +#include "mozilla/net/WyciwygChannelParent.h" +#include "mozilla/net/FTPChannelParent.h" +#include "mozilla/net/WebSocketChannelParent.h" +#include "mozilla/net/WebSocketEventListenerParent.h" +#include "mozilla/net/DataChannelParent.h" +#include "mozilla/net/AltDataOutputStreamParent.h" +#include "mozilla/Unused.h" +#ifdef NECKO_PROTOCOL_rtsp +#include "mozilla/net/RtspControllerParent.h" +#include "mozilla/net/RtspChannelParent.h" +#endif +#include "mozilla/net/DNSRequestParent.h" +#include "mozilla/net/ChannelDiverterParent.h" +#include "mozilla/net/IPCTransportProvider.h" +#include "mozilla/dom/ChromeUtils.h" +#include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/TabContext.h" +#include "mozilla/dom/TabParent.h" +#include "mozilla/dom/network/TCPSocketParent.h" +#include "mozilla/dom/network/TCPServerSocketParent.h" +#include "mozilla/dom/network/UDPSocketParent.h" +#include "mozilla/dom/workers/ServiceWorkerManager.h" +#include "mozilla/LoadContext.h" +#include "mozilla/AppProcessChecker.h" +#include "nsPrintfCString.h" +#include "nsHTMLDNSPrefetch.h" +#include "nsIAppsService.h" +#include "nsEscape.h" +#include "SerializedLoadContext.h" +#include "nsAuthInformationHolder.h" +#include "nsIAuthPromptCallback.h" +#include "nsPrincipal.h" +#include "nsINetworkPredictor.h" +#include "nsINetworkPredictorVerifier.h" +#include "nsISpeculativeConnect.h" + +using mozilla::DocShellOriginAttributes; +using mozilla::NeckoOriginAttributes; +using mozilla::dom::ChromeUtils; +using mozilla::dom::ContentParent; +using mozilla::dom::TabContext; +using mozilla::dom::TabParent; +using mozilla::net::PTCPSocketParent; +using mozilla::dom::TCPSocketParent; +using mozilla::net::PTCPServerSocketParent; +using mozilla::dom::TCPServerSocketParent; +using mozilla::net::PUDPSocketParent; +using mozilla::dom::UDPSocketParent; +using mozilla::dom::workers::ServiceWorkerManager; +using mozilla::ipc::OptionalPrincipalInfo; +using mozilla::ipc::PrincipalInfo; +using IPC::SerializedLoadContext; + +namespace mozilla { +namespace net { + +// C++ file contents +NeckoParent::NeckoParent() +{ + // Init HTTP protocol handler now since we need atomTable up and running very + // early (IPDL argument handling for PHttpChannel constructor needs it) so + // normal init (during 1st Http channel request) isn't early enough. + nsCOMPtr<nsIProtocolHandler> proto = + do_GetService("@mozilla.org/network/protocol;1?name=http"); + + // only register once--we will have multiple NeckoParents if there are + // multiple child processes. + static bool registeredBool = false; + if (!registeredBool) { + Preferences::AddBoolVarCache(&NeckoCommonInternal::gSecurityDisabled, + "network.disable.ipc.security"); + registeredBool = true; + } +} + +NeckoParent::~NeckoParent() +{ +} + +static PBOverrideStatus +PBOverrideStatusFromLoadContext(const SerializedLoadContext& aSerialized) +{ + if (!aSerialized.IsNotNull() && aSerialized.IsPrivateBitValid()) { + return (aSerialized.mOriginAttributes.mPrivateBrowsingId > 0) ? + kPBOverride_Private : + kPBOverride_NotPrivate; + } + return kPBOverride_Unset; +} + +static already_AddRefed<nsIPrincipal> +GetRequestingPrincipal(const OptionalLoadInfoArgs aOptionalLoadInfoArgs) +{ + if (aOptionalLoadInfoArgs.type() != OptionalLoadInfoArgs::TLoadInfoArgs) { + return nullptr; + } + + const LoadInfoArgs& loadInfoArgs = aOptionalLoadInfoArgs.get_LoadInfoArgs(); + const OptionalPrincipalInfo& optionalPrincipalInfo = + loadInfoArgs.requestingPrincipalInfo(); + + if (optionalPrincipalInfo.type() != OptionalPrincipalInfo::TPrincipalInfo) { + return nullptr; + } + + const PrincipalInfo& principalInfo = + optionalPrincipalInfo.get_PrincipalInfo(); + + return PrincipalInfoToPrincipal(principalInfo); +} + +static already_AddRefed<nsIPrincipal> +GetRequestingPrincipal(const HttpChannelCreationArgs& aArgs) +{ + if (aArgs.type() != HttpChannelCreationArgs::THttpChannelOpenArgs) { + return nullptr; + } + + const HttpChannelOpenArgs& args = aArgs.get_HttpChannelOpenArgs(); + return GetRequestingPrincipal(args.loadInfo()); +} + +static already_AddRefed<nsIPrincipal> +GetRequestingPrincipal(const FTPChannelCreationArgs& aArgs) +{ + if (aArgs.type() != FTPChannelCreationArgs::TFTPChannelOpenArgs) { + return nullptr; + } + + const FTPChannelOpenArgs& args = aArgs.get_FTPChannelOpenArgs(); + return GetRequestingPrincipal(args.loadInfo()); +} + +// Bug 1289001 - If GetValidatedOriginAttributes returns an error string, that +// usually leads to a content crash with very little info about the cause. +// We prefer to crash on the parent, so we get the reason in the crash report. +static MOZ_COLD +void CrashWithReason(const char * reason) +{ +#ifndef RELEASE_OR_BETA + MOZ_CRASH_UNSAFE_OOL(reason); +#endif +} + +const char* +NeckoParent::GetValidatedOriginAttributes(const SerializedLoadContext& aSerialized, + PContentParent* aContent, + nsIPrincipal* aRequestingPrincipal, + DocShellOriginAttributes& aAttrs) +{ + if (!UsingNeckoIPCSecurity()) { + if (!aSerialized.IsNotNull()) { + // If serialized is null, we cannot validate anything. We have to assume + // that this requests comes from a SystemPrincipal. + aAttrs = DocShellOriginAttributes(NECKO_NO_APP_ID, false); + } else { + aAttrs = aSerialized.mOriginAttributes; + } + return nullptr; + } + + if (!aSerialized.IsNotNull()) { + CrashWithReason("GetValidatedOriginAttributes | SerializedLoadContext from child is null"); + return "SerializedLoadContext from child is null"; + } + + nsTArray<TabContext> contextArray = + static_cast<ContentParent*>(aContent)->GetManagedTabContext(); + + nsAutoCString serializedSuffix; + aSerialized.mOriginAttributes.CreateAnonymizedSuffix(serializedSuffix); + + nsAutoCString debugString; + for (uint32_t i = 0; i < contextArray.Length(); i++) { + const TabContext& tabContext = contextArray[i]; + + if (!ChromeUtils::IsOriginAttributesEqual(aSerialized.mOriginAttributes, + tabContext.OriginAttributesRef())) { + debugString.Append("("); + debugString.Append(serializedSuffix); + debugString.Append(","); + + nsAutoCString tabSuffix; + tabContext.OriginAttributesRef().CreateAnonymizedSuffix(tabSuffix); + debugString.Append(tabSuffix); + + debugString.Append(")"); + continue; + } + + aAttrs = aSerialized.mOriginAttributes; + return nullptr; + } + + // This may be a ServiceWorker: when a push notification is received, FF wakes + // up the corrisponding service worker so that it can manage the PushEvent. At + // that time we probably don't have any valid tabcontext, but still, we want + // to support http channel requests coming from that ServiceWorker. + if (aRequestingPrincipal) { + RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); + if (swm && + swm->MayHaveActiveServiceWorkerInstance(static_cast<ContentParent*>(aContent), + aRequestingPrincipal)) { + aAttrs = aSerialized.mOriginAttributes; + return nullptr; + } + } + + nsAutoCString errorString; + errorString.Append("GetValidatedOriginAttributes | App does not have permission -"); + errorString.Append(debugString); + + // Leak the buffer on the heap to make sure that it lives long enough, as + // MOZ_CRASH_ANNOTATE expects the pointer passed to it to live to the end of + // the program. + char * error = strdup(errorString.BeginReading()); + CrashWithReason(error); + return "App does not have permission"; +} + +const char * +NeckoParent::CreateChannelLoadContext(const PBrowserOrId& aBrowser, + PContentParent* aContent, + const SerializedLoadContext& aSerialized, + nsIPrincipal* aRequestingPrincipal, + nsCOMPtr<nsILoadContext> &aResult) +{ + DocShellOriginAttributes attrs; + const char* error = GetValidatedOriginAttributes(aSerialized, aContent, + aRequestingPrincipal, attrs); + if (error) { + return error; + } + + // if !UsingNeckoIPCSecurity(), we may not have a LoadContext to set. This is + // the common case for most xpcshell tests. + if (aSerialized.IsNotNull()) { + attrs.SyncAttributesWithPrivateBrowsing(aSerialized.mOriginAttributes.mPrivateBrowsingId > 0); + switch (aBrowser.type()) { + case PBrowserOrId::TPBrowserParent: + { + RefPtr<TabParent> tabParent = + TabParent::GetFrom(aBrowser.get_PBrowserParent()); + dom::Element* topFrameElement = nullptr; + if (tabParent) { + topFrameElement = tabParent->GetOwnerElement(); + } + aResult = new LoadContext(aSerialized, topFrameElement, attrs); + break; + } + case PBrowserOrId::TTabId: + { + aResult = new LoadContext(aSerialized, aBrowser.get_TabId(), attrs); + break; + } + default: + MOZ_CRASH(); + } + } + + return nullptr; +} + +void +NeckoParent::ActorDestroy(ActorDestroyReason aWhy) +{ + // Nothing needed here. Called right before destructor since this is a + // non-refcounted class. +} + +PHttpChannelParent* +NeckoParent::AllocPHttpChannelParent(const PBrowserOrId& aBrowser, + const SerializedLoadContext& aSerialized, + const HttpChannelCreationArgs& aOpenArgs) +{ + nsCOMPtr<nsIPrincipal> requestingPrincipal = + GetRequestingPrincipal(aOpenArgs); + + nsCOMPtr<nsILoadContext> loadContext; + const char *error = CreateChannelLoadContext(aBrowser, Manager(), + aSerialized, requestingPrincipal, + loadContext); + if (error) { + printf_stderr("NeckoParent::AllocPHttpChannelParent: " + "FATAL error: %s: KILLING CHILD PROCESS\n", + error); + return nullptr; + } + PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized); + HttpChannelParent *p = new HttpChannelParent(aBrowser, loadContext, overrideStatus); + p->AddRef(); + return p; +} + +bool +NeckoParent::DeallocPHttpChannelParent(PHttpChannelParent* channel) +{ + HttpChannelParent *p = static_cast<HttpChannelParent *>(channel); + p->Release(); + return true; +} + +bool +NeckoParent::RecvPHttpChannelConstructor( + PHttpChannelParent* aActor, + const PBrowserOrId& aBrowser, + const SerializedLoadContext& aSerialized, + const HttpChannelCreationArgs& aOpenArgs) +{ + HttpChannelParent* p = static_cast<HttpChannelParent*>(aActor); + return p->Init(aOpenArgs); +} + +PAltDataOutputStreamParent* +NeckoParent::AllocPAltDataOutputStreamParent( + const nsCString& type, + PHttpChannelParent* channel) +{ + HttpChannelParent* chan = static_cast<HttpChannelParent*>(channel); + nsCOMPtr<nsIOutputStream> stream; + nsresult rv = chan->OpenAlternativeOutputStream(type, getter_AddRefs(stream)); + AltDataOutputStreamParent* parent = new AltDataOutputStreamParent(stream); + parent->AddRef(); + // If the return value was not NS_OK, the error code will be sent + // asynchronously to the child, after receiving the first message. + parent->SetError(rv); + return parent; +} + +bool +NeckoParent::DeallocPAltDataOutputStreamParent(PAltDataOutputStreamParent* aActor) +{ + AltDataOutputStreamParent* parent = static_cast<AltDataOutputStreamParent*>(aActor); + parent->Release(); + return true; +} + +PFTPChannelParent* +NeckoParent::AllocPFTPChannelParent(const PBrowserOrId& aBrowser, + const SerializedLoadContext& aSerialized, + const FTPChannelCreationArgs& aOpenArgs) +{ + nsCOMPtr<nsIPrincipal> requestingPrincipal = + GetRequestingPrincipal(aOpenArgs); + + nsCOMPtr<nsILoadContext> loadContext; + const char *error = CreateChannelLoadContext(aBrowser, Manager(), + aSerialized, requestingPrincipal, + loadContext); + if (error) { + printf_stderr("NeckoParent::AllocPFTPChannelParent: " + "FATAL error: %s: KILLING CHILD PROCESS\n", + error); + return nullptr; + } + PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized); + FTPChannelParent *p = new FTPChannelParent(aBrowser, loadContext, overrideStatus); + p->AddRef(); + return p; +} + +bool +NeckoParent::DeallocPFTPChannelParent(PFTPChannelParent* channel) +{ + FTPChannelParent *p = static_cast<FTPChannelParent *>(channel); + p->Release(); + return true; +} + +bool +NeckoParent::RecvPFTPChannelConstructor( + PFTPChannelParent* aActor, + const PBrowserOrId& aBrowser, + const SerializedLoadContext& aSerialized, + const FTPChannelCreationArgs& aOpenArgs) +{ + FTPChannelParent* p = static_cast<FTPChannelParent*>(aActor); + return p->Init(aOpenArgs); +} + +PCookieServiceParent* +NeckoParent::AllocPCookieServiceParent() +{ + return new CookieServiceParent(); +} + +bool +NeckoParent::DeallocPCookieServiceParent(PCookieServiceParent* cs) +{ + delete cs; + return true; +} + +PWyciwygChannelParent* +NeckoParent::AllocPWyciwygChannelParent() +{ + WyciwygChannelParent *p = new WyciwygChannelParent(); + p->AddRef(); + return p; +} + +bool +NeckoParent::DeallocPWyciwygChannelParent(PWyciwygChannelParent* channel) +{ + WyciwygChannelParent *p = static_cast<WyciwygChannelParent *>(channel); + p->Release(); + return true; +} + +PWebSocketParent* +NeckoParent::AllocPWebSocketParent(const PBrowserOrId& browser, + const SerializedLoadContext& serialized, + const uint32_t& aSerial) +{ + nsCOMPtr<nsILoadContext> loadContext; + const char *error = CreateChannelLoadContext(browser, Manager(), + serialized, + nullptr, + loadContext); + if (error) { + printf_stderr("NeckoParent::AllocPWebSocketParent: " + "FATAL error: %s: KILLING CHILD PROCESS\n", + error); + return nullptr; + } + + RefPtr<TabParent> tabParent = TabParent::GetFrom(browser.get_PBrowserParent()); + PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized); + WebSocketChannelParent* p = new WebSocketChannelParent(tabParent, loadContext, + overrideStatus, + aSerial); + p->AddRef(); + return p; +} + +bool +NeckoParent::DeallocPWebSocketParent(PWebSocketParent* actor) +{ + WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor); + p->Release(); + return true; +} + +PWebSocketEventListenerParent* +NeckoParent::AllocPWebSocketEventListenerParent(const uint64_t& aInnerWindowID) +{ + RefPtr<WebSocketEventListenerParent> c = + new WebSocketEventListenerParent(aInnerWindowID); + return c.forget().take(); +} + +bool +NeckoParent::DeallocPWebSocketEventListenerParent(PWebSocketEventListenerParent* aActor) +{ + RefPtr<WebSocketEventListenerParent> c = + dont_AddRef(static_cast<WebSocketEventListenerParent*>(aActor)); + MOZ_ASSERT(c); + return true; +} + +PDataChannelParent* +NeckoParent::AllocPDataChannelParent(const uint32_t &channelId) +{ + RefPtr<DataChannelParent> p = new DataChannelParent(); + return p.forget().take(); +} + +bool +NeckoParent::DeallocPDataChannelParent(PDataChannelParent* actor) +{ + RefPtr<DataChannelParent> p = dont_AddRef(static_cast<DataChannelParent*>(actor)); + return true; +} + +bool +NeckoParent::RecvPDataChannelConstructor(PDataChannelParent* actor, + const uint32_t& channelId) +{ + DataChannelParent* p = static_cast<DataChannelParent*>(actor); + DebugOnly<bool> rv = p->Init(channelId); + MOZ_ASSERT(rv); + return true; +} + +PRtspControllerParent* +NeckoParent::AllocPRtspControllerParent() +{ +#ifdef NECKO_PROTOCOL_rtsp + RtspControllerParent* p = new RtspControllerParent(); + p->AddRef(); + return p; +#else + return nullptr; +#endif +} + +bool +NeckoParent::DeallocPRtspControllerParent(PRtspControllerParent* actor) +{ +#ifdef NECKO_PROTOCOL_rtsp + RtspControllerParent* p = static_cast<RtspControllerParent*>(actor); + p->Release(); +#endif + return true; +} + +PRtspChannelParent* +NeckoParent::AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs) +{ +#ifdef NECKO_PROTOCOL_rtsp + nsCOMPtr<nsIURI> uri = DeserializeURI(aArgs.uri()); + RtspChannelParent *p = new RtspChannelParent(uri); + p->AddRef(); + return p; +#else + return nullptr; +#endif +} + +bool +NeckoParent::RecvPRtspChannelConstructor( + PRtspChannelParent* aActor, + const RtspChannelConnectArgs& aConnectArgs) +{ +#ifdef NECKO_PROTOCOL_rtsp + RtspChannelParent* p = static_cast<RtspChannelParent*>(aActor); + return p->Init(aConnectArgs); +#else + return false; +#endif +} + +bool +NeckoParent::DeallocPRtspChannelParent(PRtspChannelParent* actor) +{ +#ifdef NECKO_PROTOCOL_rtsp + RtspChannelParent* p = static_cast<RtspChannelParent*>(actor); + p->Release(); +#endif + return true; +} + +PTCPSocketParent* +NeckoParent::AllocPTCPSocketParent(const nsString& /* host */, + const uint16_t& /* port */) +{ + // We actually don't need host/port to construct a TCPSocketParent since + // TCPSocketParent will maintain an internal nsIDOMTCPSocket instance which + // can be delegated to get the host/port. + TCPSocketParent* p = new TCPSocketParent(); + p->AddIPDLReference(); + return p; +} + +bool +NeckoParent::DeallocPTCPSocketParent(PTCPSocketParent* actor) +{ + TCPSocketParent* p = static_cast<TCPSocketParent*>(actor); + p->ReleaseIPDLReference(); + return true; +} + +PTCPServerSocketParent* +NeckoParent::AllocPTCPServerSocketParent(const uint16_t& aLocalPort, + const uint16_t& aBacklog, + const bool& aUseArrayBuffers) +{ + TCPServerSocketParent* p = new TCPServerSocketParent(this, aLocalPort, aBacklog, aUseArrayBuffers); + p->AddIPDLReference(); + return p; +} + +bool +NeckoParent::RecvPTCPServerSocketConstructor(PTCPServerSocketParent* aActor, + const uint16_t& aLocalPort, + const uint16_t& aBacklog, + const bool& aUseArrayBuffers) +{ + static_cast<TCPServerSocketParent*>(aActor)->Init(); + return true; +} + +bool +NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor) +{ + TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor); + p->ReleaseIPDLReference(); + return true; +} + +PUDPSocketParent* +NeckoParent::AllocPUDPSocketParent(const Principal& /* unused */, + const nsCString& /* unused */) +{ + RefPtr<UDPSocketParent> p = new UDPSocketParent(this); + + return p.forget().take(); +} + +bool +NeckoParent::RecvPUDPSocketConstructor(PUDPSocketParent* aActor, + const Principal& aPrincipal, + const nsCString& aFilter) +{ + return static_cast<UDPSocketParent*>(aActor)->Init(aPrincipal, aFilter); +} + +bool +NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor) +{ + UDPSocketParent* p = static_cast<UDPSocketParent*>(actor); + p->Release(); + return true; +} + +PDNSRequestParent* +NeckoParent::AllocPDNSRequestParent(const nsCString& aHost, + const uint32_t& aFlags, + const nsCString& aNetworkInterface) +{ + DNSRequestParent *p = new DNSRequestParent(); + p->AddRef(); + return p; +} + +bool +NeckoParent::RecvPDNSRequestConstructor(PDNSRequestParent* aActor, + const nsCString& aHost, + const uint32_t& aFlags, + const nsCString& aNetworkInterface) +{ + static_cast<DNSRequestParent*>(aActor)->DoAsyncResolve(aHost, aFlags, + aNetworkInterface); + return true; +} + +bool +NeckoParent::DeallocPDNSRequestParent(PDNSRequestParent* aParent) +{ + DNSRequestParent *p = static_cast<DNSRequestParent*>(aParent); + p->Release(); + return true; +} + +bool +NeckoParent::RecvSpeculativeConnect(const URIParams& aURI, + const Principal& aPrincipal, + const bool& aAnonymous) +{ + nsCOMPtr<nsISpeculativeConnect> speculator(gIOService); + nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); + nsCOMPtr<nsIPrincipal> principal(aPrincipal); + if (uri && speculator) { + if (aAnonymous) { + speculator->SpeculativeAnonymousConnect2(uri, principal, nullptr); + } else { + speculator->SpeculativeConnect2(uri, principal, nullptr); + } + + } + return true; +} + +bool +NeckoParent::RecvHTMLDNSPrefetch(const nsString& hostname, + const uint16_t& flags) +{ + nsHTMLDNSPrefetch::Prefetch(hostname, flags); + return true; +} + +bool +NeckoParent::RecvCancelHTMLDNSPrefetch(const nsString& hostname, + const uint16_t& flags, + const nsresult& reason) +{ + nsHTMLDNSPrefetch::CancelPrefetch(hostname, flags, reason); + return true; +} + +PChannelDiverterParent* +NeckoParent::AllocPChannelDiverterParent(const ChannelDiverterArgs& channel) +{ + return new ChannelDiverterParent(); +} + +bool +NeckoParent::RecvPChannelDiverterConstructor(PChannelDiverterParent* actor, + const ChannelDiverterArgs& channel) +{ + auto parent = static_cast<ChannelDiverterParent*>(actor); + parent->Init(channel); + return true; +} + +bool +NeckoParent::DeallocPChannelDiverterParent(PChannelDiverterParent* parent) +{ + delete static_cast<ChannelDiverterParent*>(parent); + return true; +} + +PTransportProviderParent* +NeckoParent::AllocPTransportProviderParent() +{ + RefPtr<TransportProviderParent> res = new TransportProviderParent(); + return res.forget().take(); +} + +bool +NeckoParent::DeallocPTransportProviderParent(PTransportProviderParent* aActor) +{ + RefPtr<TransportProviderParent> provider = + dont_AddRef(static_cast<TransportProviderParent*>(aActor)); + return true; +} + +namespace { +std::map<uint64_t, nsCOMPtr<nsIAuthPromptCallback> >& +CallbackMap() +{ + MOZ_ASSERT(NS_IsMainThread()); + static std::map<uint64_t, nsCOMPtr<nsIAuthPromptCallback> > sCallbackMap; + return sCallbackMap; +} +} // namespace + +NS_IMPL_ISUPPORTS(NeckoParent::NestedFrameAuthPrompt, nsIAuthPrompt2) + +NeckoParent::NestedFrameAuthPrompt::NestedFrameAuthPrompt(PNeckoParent* aParent, + TabId aNestedFrameId) + : mNeckoParent(aParent) + , mNestedFrameId(aNestedFrameId) +{} + +NS_IMETHODIMP +NeckoParent::NestedFrameAuthPrompt::AsyncPromptAuth( + nsIChannel* aChannel, nsIAuthPromptCallback* callback, + nsISupports*, uint32_t, + nsIAuthInformation* aInfo, nsICancelable**) +{ + static uint64_t callbackId = 0; + MOZ_ASSERT(XRE_IsParentProcess()); + nsCOMPtr<nsIURI> uri; + nsresult rv = aChannel->GetURI(getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + nsAutoCString spec; + if (uri) { + rv = uri->GetSpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + } + nsString realm; + rv = aInfo->GetRealm(realm); + NS_ENSURE_SUCCESS(rv, rv); + callbackId++; + if (mNeckoParent->SendAsyncAuthPromptForNestedFrame(mNestedFrameId, + spec, + realm, + callbackId)) { + CallbackMap()[callbackId] = callback; + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +bool +NeckoParent::RecvOnAuthAvailable(const uint64_t& aCallbackId, + const nsString& aUser, + const nsString& aPassword, + const nsString& aDomain) +{ + nsCOMPtr<nsIAuthPromptCallback> callback = CallbackMap()[aCallbackId]; + if (!callback) { + return true; + } + CallbackMap().erase(aCallbackId); + + RefPtr<nsAuthInformationHolder> holder = + new nsAuthInformationHolder(0, EmptyString(), EmptyCString()); + holder->SetUsername(aUser); + holder->SetPassword(aPassword); + holder->SetDomain(aDomain); + + callback->OnAuthAvailable(nullptr, holder); + return true; +} + +bool +NeckoParent::RecvOnAuthCancelled(const uint64_t& aCallbackId, + const bool& aUserCancel) +{ + nsCOMPtr<nsIAuthPromptCallback> callback = CallbackMap()[aCallbackId]; + if (!callback) { + return true; + } + CallbackMap().erase(aCallbackId); + callback->OnAuthCancelled(nullptr, aUserCancel); + return true; +} + +/* Predictor Messages */ +bool +NeckoParent::RecvPredPredict(const ipc::OptionalURIParams& aTargetURI, + const ipc::OptionalURIParams& aSourceURI, + const uint32_t& aReason, + const SerializedLoadContext& aLoadContext, + const bool& hasVerifier) +{ + nsCOMPtr<nsIURI> targetURI = DeserializeURI(aTargetURI); + nsCOMPtr<nsIURI> sourceURI = DeserializeURI(aSourceURI); + + // We only actually care about the loadContext.mPrivateBrowsing, so we'll just + // pass dummy params for nestFrameId, and originAttributes. + uint64_t nestedFrameId = 0; + DocShellOriginAttributes attrs(NECKO_UNKNOWN_APP_ID, false); + nsCOMPtr<nsILoadContext> loadContext; + if (aLoadContext.IsNotNull()) { + attrs.SyncAttributesWithPrivateBrowsing(aLoadContext.mOriginAttributes.mPrivateBrowsingId > 0); + loadContext = new LoadContext(aLoadContext, nestedFrameId, attrs); + } + + // Get the current predictor + nsresult rv = NS_OK; + nsCOMPtr<nsINetworkPredictor> predictor = + do_GetService("@mozilla.org/network/predictor;1", &rv); + NS_ENSURE_SUCCESS(rv, false); + + nsCOMPtr<nsINetworkPredictorVerifier> verifier; + if (hasVerifier) { + verifier = do_QueryInterface(predictor); + } + predictor->Predict(targetURI, sourceURI, aReason, loadContext, verifier); + return true; +} + +bool +NeckoParent::RecvPredLearn(const ipc::URIParams& aTargetURI, + const ipc::OptionalURIParams& aSourceURI, + const uint32_t& aReason, + const SerializedLoadContext& aLoadContext) +{ + nsCOMPtr<nsIURI> targetURI = DeserializeURI(aTargetURI); + nsCOMPtr<nsIURI> sourceURI = DeserializeURI(aSourceURI); + + // We only actually care about the loadContext.mPrivateBrowsing, so we'll just + // pass dummy params for nestFrameId, and originAttributes; + uint64_t nestedFrameId = 0; + DocShellOriginAttributes attrs(NECKO_UNKNOWN_APP_ID, false); + nsCOMPtr<nsILoadContext> loadContext; + if (aLoadContext.IsNotNull()) { + attrs.SyncAttributesWithPrivateBrowsing(aLoadContext.mOriginAttributes.mPrivateBrowsingId > 0); + loadContext = new LoadContext(aLoadContext, nestedFrameId, attrs); + } + + // Get the current predictor + nsresult rv = NS_OK; + nsCOMPtr<nsINetworkPredictor> predictor = + do_GetService("@mozilla.org/network/predictor;1", &rv); + NS_ENSURE_SUCCESS(rv, false); + + predictor->Learn(targetURI, sourceURI, aReason, loadContext); + return true; +} + +bool +NeckoParent::RecvPredReset() +{ + // Get the current predictor + nsresult rv = NS_OK; + nsCOMPtr<nsINetworkPredictor> predictor = + do_GetService("@mozilla.org/network/predictor;1", &rv); + NS_ENSURE_SUCCESS(rv, false); + + predictor->Reset(); + return true; +} + +bool +NeckoParent::RecvRemoveRequestContext(const nsCString& rcid) +{ + nsCOMPtr<nsIRequestContextService> rcsvc = + do_GetService("@mozilla.org/network/request-context-service;1"); + if (!rcsvc) { + return true; + } + + nsID id; + id.Parse(rcid.BeginReading()); + rcsvc->RemoveRequestContext(id); + + return true; +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/ipc/NeckoParent.h b/netwerk/ipc/NeckoParent.h new file mode 100644 index 0000000000..1264700e50 --- /dev/null +++ b/netwerk/ipc/NeckoParent.h @@ -0,0 +1,227 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ + +/* 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/. */ + +#include "mozilla/BasePrincipal.h" +#include "mozilla/net/PNeckoParent.h" +#include "mozilla/net/NeckoCommon.h" +#include "nsIAuthPrompt2.h" +#include "nsINetworkPredictor.h" +#include "nsNetUtil.h" + +#ifndef mozilla_net_NeckoParent_h +#define mozilla_net_NeckoParent_h + +namespace mozilla { +namespace net { + +// Used to override channel Private Browsing status if needed. +enum PBOverrideStatus { + kPBOverride_Unset = 0, + kPBOverride_Private, + kPBOverride_NotPrivate +}; + +// Header file contents +class NeckoParent + : public PNeckoParent +{ +public: + NeckoParent(); + virtual ~NeckoParent(); + + MOZ_MUST_USE + static const char * + GetValidatedOriginAttributes(const SerializedLoadContext& aSerialized, + PContentParent* aBrowser, + nsIPrincipal* aRequestingPrincipal, + mozilla::DocShellOriginAttributes& aAttrs); + + /* + * Creates LoadContext for parent-side of an e10s channel. + * + * PContentParent corresponds to the process that is requesting the load. + * + * Returns null if successful, or an error string if failed. + */ + MOZ_MUST_USE + static const char* + CreateChannelLoadContext(const PBrowserOrId& aBrowser, + PContentParent* aContent, + const SerializedLoadContext& aSerialized, + nsIPrincipal* aRequestingPrincipal, + nsCOMPtr<nsILoadContext> &aResult); + + virtual void ActorDestroy(ActorDestroyReason aWhy) override; + virtual PCookieServiceParent* AllocPCookieServiceParent() override; + virtual bool + RecvPCookieServiceConstructor(PCookieServiceParent* aActor) override + { + return PNeckoParent::RecvPCookieServiceConstructor(aActor); + } + + /* + * This implementation of nsIAuthPrompt2 is used for nested remote iframes that + * want an auth prompt. This class lives in the parent process and informs the + * NeckoChild that we want an auth prompt, which forwards the request to the + * TabParent in the remote iframe that contains the nested iframe + */ + class NestedFrameAuthPrompt final : public nsIAuthPrompt2 + { + ~NestedFrameAuthPrompt() {} + + public: + NS_DECL_ISUPPORTS + + NestedFrameAuthPrompt(PNeckoParent* aParent, TabId aNestedFrameId); + + NS_IMETHOD PromptAuth(nsIChannel*, uint32_t, nsIAuthInformation*, bool*) override + { + return NS_ERROR_NOT_IMPLEMENTED; + } + + NS_IMETHOD AsyncPromptAuth(nsIChannel* aChannel, nsIAuthPromptCallback* callback, + nsISupports*, uint32_t, + nsIAuthInformation* aInfo, nsICancelable**) override; + + protected: + PNeckoParent* mNeckoParent; + TabId mNestedFrameId; + }; + +protected: + virtual PHttpChannelParent* + AllocPHttpChannelParent(const PBrowserOrId&, const SerializedLoadContext&, + const HttpChannelCreationArgs& aOpenArgs) override; + virtual bool + RecvPHttpChannelConstructor( + PHttpChannelParent* aActor, + const PBrowserOrId& aBrowser, + const SerializedLoadContext& aSerialized, + const HttpChannelCreationArgs& aOpenArgs) override; + virtual bool DeallocPHttpChannelParent(PHttpChannelParent*) override; + + virtual PAltDataOutputStreamParent* AllocPAltDataOutputStreamParent( + const nsCString& type, PHttpChannelParent* channel) override; + virtual bool DeallocPAltDataOutputStreamParent( + PAltDataOutputStreamParent* aActor) override; + + virtual bool DeallocPCookieServiceParent(PCookieServiceParent*) override; + virtual PWyciwygChannelParent* AllocPWyciwygChannelParent() override; + virtual bool DeallocPWyciwygChannelParent(PWyciwygChannelParent*) override; + virtual PFTPChannelParent* + AllocPFTPChannelParent(const PBrowserOrId& aBrowser, + const SerializedLoadContext& aSerialized, + const FTPChannelCreationArgs& aOpenArgs) override; + virtual bool + RecvPFTPChannelConstructor( + PFTPChannelParent* aActor, + const PBrowserOrId& aBrowser, + const SerializedLoadContext& aSerialized, + const FTPChannelCreationArgs& aOpenArgs) override; + virtual bool DeallocPFTPChannelParent(PFTPChannelParent*) override; + virtual PWebSocketParent* + AllocPWebSocketParent(const PBrowserOrId& browser, + const SerializedLoadContext& aSerialized, + const uint32_t& aSerial) override; + virtual bool DeallocPWebSocketParent(PWebSocketParent*) override; + virtual PTCPSocketParent* AllocPTCPSocketParent(const nsString& host, + const uint16_t& port) override; + + virtual bool DeallocPTCPSocketParent(PTCPSocketParent*) override; + virtual PTCPServerSocketParent* + AllocPTCPServerSocketParent(const uint16_t& aLocalPort, + const uint16_t& aBacklog, + const bool& aUseArrayBuffers) override; + virtual bool RecvPTCPServerSocketConstructor(PTCPServerSocketParent*, + const uint16_t& aLocalPort, + const uint16_t& aBacklog, + const bool& aUseArrayBuffers) override; + virtual bool DeallocPTCPServerSocketParent(PTCPServerSocketParent*) override; + virtual PUDPSocketParent* AllocPUDPSocketParent(const Principal& aPrincipal, + const nsCString& aFilter) override; + virtual bool RecvPUDPSocketConstructor(PUDPSocketParent*, + const Principal& aPrincipal, + const nsCString& aFilter) override; + virtual bool DeallocPUDPSocketParent(PUDPSocketParent*) override; + virtual PDNSRequestParent* AllocPDNSRequestParent(const nsCString& aHost, + const uint32_t& aFlags, + const nsCString& aNetworkInterface) override; + virtual bool RecvPDNSRequestConstructor(PDNSRequestParent* actor, + const nsCString& hostName, + const uint32_t& flags, + const nsCString& aNetworkInterface) override; + virtual bool DeallocPDNSRequestParent(PDNSRequestParent*) override; + virtual bool RecvSpeculativeConnect(const URIParams& aURI, + const Principal& aPrincipal, + const bool& aAnonymous) override; + virtual bool RecvHTMLDNSPrefetch(const nsString& hostname, + const uint16_t& flags) override; + virtual bool RecvCancelHTMLDNSPrefetch(const nsString& hostname, + const uint16_t& flags, + const nsresult& reason) override; + virtual PWebSocketEventListenerParent* + AllocPWebSocketEventListenerParent(const uint64_t& aInnerWindowID) override; + virtual bool DeallocPWebSocketEventListenerParent(PWebSocketEventListenerParent*) override; + + virtual PDataChannelParent* + AllocPDataChannelParent(const uint32_t& channelId) override; + virtual bool DeallocPDataChannelParent(PDataChannelParent* parent) override; + + virtual bool RecvPDataChannelConstructor(PDataChannelParent* aActor, + const uint32_t& channelId) override; + + virtual PRtspControllerParent* AllocPRtspControllerParent() override; + virtual bool DeallocPRtspControllerParent(PRtspControllerParent*) override; + + virtual PRtspChannelParent* + AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs) + override; + virtual bool + RecvPRtspChannelConstructor(PRtspChannelParent* aActor, + const RtspChannelConnectArgs& aArgs) + override; + virtual bool DeallocPRtspChannelParent(PRtspChannelParent*) override; + + virtual PChannelDiverterParent* + AllocPChannelDiverterParent(const ChannelDiverterArgs& channel) override; + virtual bool + RecvPChannelDiverterConstructor(PChannelDiverterParent* actor, + const ChannelDiverterArgs& channel) override; + virtual bool DeallocPChannelDiverterParent(PChannelDiverterParent* actor) + override; + virtual PTransportProviderParent* + AllocPTransportProviderParent() override; + virtual bool + DeallocPTransportProviderParent(PTransportProviderParent* aActor) override; + + virtual bool RecvOnAuthAvailable(const uint64_t& aCallbackId, + const nsString& aUser, + const nsString& aPassword, + const nsString& aDomain) override; + virtual bool RecvOnAuthCancelled(const uint64_t& aCallbackId, + const bool& aUserCancel) override; + + /* Predictor Messages */ + virtual bool RecvPredPredict(const ipc::OptionalURIParams& aTargetURI, + const ipc::OptionalURIParams& aSourceURI, + const PredictorPredictReason& aReason, + const IPC::SerializedLoadContext& aLoadContext, + const bool& hasVerifier) override; + + virtual bool RecvPredLearn(const ipc::URIParams& aTargetURI, + const ipc::OptionalURIParams& aSourceURI, + const PredictorPredictReason& aReason, + const IPC::SerializedLoadContext& aLoadContext) override; + virtual bool RecvPredReset() override; + + virtual bool RecvRemoveRequestContext(const nsCString& rcid) override; +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_NeckoParent_h diff --git a/netwerk/ipc/PChannelDiverter.ipdl b/netwerk/ipc/PChannelDiverter.ipdl new file mode 100644 index 0000000000..12be1f09b4 --- /dev/null +++ b/netwerk/ipc/PChannelDiverter.ipdl @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80 ft=cpp: */ +/* 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/. */ + +include protocol PFTPChannel; +include protocol PHttpChannel; +include protocol PNecko; + +namespace mozilla { +namespace net { + +// Used when diverting necko channels from child back to the parent. +// See nsIDivertableChannel. +async protocol PChannelDiverter +{ + manager PNecko; + +child: + async __delete__(); +}; + +}// namespace net +}// namespace mozilla diff --git a/netwerk/ipc/PDataChannel.ipdl b/netwerk/ipc/PDataChannel.ipdl new file mode 100644 index 0000000000..69eef43aed --- /dev/null +++ b/netwerk/ipc/PDataChannel.ipdl @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */ + +/* 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/. */ + +include protocol PNecko; +include URIParams; + +namespace mozilla { +namespace net { + +async protocol PDataChannel +{ + manager PNecko; + +parent: + // Note: channels are opened during construction, so no open method here: + // see PNecko.ipdl + async __delete__(); +}; + +} // namespace net +} // namespace mozilla diff --git a/netwerk/ipc/PNecko.ipdl b/netwerk/ipc/PNecko.ipdl new file mode 100644 index 0000000000..d9d88352cc --- /dev/null +++ b/netwerk/ipc/PNecko.ipdl @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */ + +/* 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/. */ + +include protocol PContent; +include protocol PHttpChannel; +include protocol PCookieService; +include protocol PBrowser; +include protocol PWyciwygChannel; +include protocol PFTPChannel; +include protocol PWebSocket; +include protocol PWebSocketEventListener; +include protocol PTCPSocket; +include protocol PTCPServerSocket; +include protocol PUDPSocket; +include protocol PDNSRequest; +include protocol PChannelDiverter; +include protocol PBlob; //FIXME: bug #792908 +include protocol PFileDescriptorSet; +include protocol PDataChannel; +include protocol PTransportProvider; +include protocol PSendStream; + +include protocol PRtspController; +include protocol PRtspChannel; +include URIParams; +include InputStreamParams; +include NeckoChannelParams; +include PBrowserOrId; +include protocol PAltDataOutputStream; + +using class IPC::SerializedLoadContext from "SerializedLoadContext.h"; +using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h"; +using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h"; + +namespace mozilla { +namespace net { + +//------------------------------------------------------------------- +nested(upto inside_cpow) sync protocol PNecko +{ + manager PContent; + manages PHttpChannel; + manages PCookieService; + manages PWyciwygChannel; + manages PFTPChannel; + manages PWebSocket; + manages PWebSocketEventListener; + manages PTCPSocket; + manages PTCPServerSocket; + manages PUDPSocket; + manages PDNSRequest; + manages PDataChannel; + manages PRtspController; + manages PRtspChannel; + manages PChannelDiverter; + manages PTransportProvider; + manages PAltDataOutputStream; + +parent: + async __delete__(); + + nested(inside_cpow) async PCookieService(); + async PHttpChannel(PBrowserOrId browser, + SerializedLoadContext loadContext, + HttpChannelCreationArgs args); + async PWyciwygChannel(); + async PFTPChannel(PBrowserOrId browser, SerializedLoadContext loadContext, + FTPChannelCreationArgs args); + + async PWebSocket(PBrowserOrId browser, SerializedLoadContext loadContext, + uint32_t aSerialID); + async PTCPServerSocket(uint16_t localPort, uint16_t backlog, bool useArrayBuffers); + async PUDPSocket(Principal principal, nsCString filter); + + async PDNSRequest(nsCString hostName, uint32_t flags, nsCString networkInterface); + + async PWebSocketEventListener(uint64_t aInnerWindowID); + + /* Predictor Methods */ + async PredPredict(OptionalURIParams targetURI, OptionalURIParams sourceURI, + uint32_t reason, SerializedLoadContext loadContext, + bool hasVerifier); + async PredLearn(URIParams targetURI, OptionalURIParams sourceURI, + uint32_t reason, SerializedLoadContext loadContext); + async PredReset(); + + async SpeculativeConnect(URIParams uri, Principal principal, bool anonymous); + async HTMLDNSPrefetch(nsString hostname, uint16_t flags); + async CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason); + + /** + * channelId is used to establish a connection between redirect channels in + * the parent and the child when we're redirecting to a data: URI. + */ + async PDataChannel(uint32_t channelId); + + async PRtspController(); + async PRtspChannel(RtspChannelConnectArgs args); + async PChannelDiverter(ChannelDiverterArgs channel); + + /** + * These are called from the child with the results of the auth prompt. + * callbackId is the id that was passed in PBrowser::AsyncAuthPrompt, + * corresponding to an nsIAuthPromptCallback + */ + async OnAuthAvailable(uint64_t callbackId, nsString user, + nsString password, nsString domain); + async OnAuthCancelled(uint64_t callbackId, bool userCancel); + + async RemoveRequestContext(nsCString rcid); + + async PAltDataOutputStream(nsCString type, PHttpChannel channel); + +child: + /* + * Bring up the http auth prompt for a nested remote mozbrowser. + * NestedFrameId is the id corresponding to the PBrowser. It is the same id + * that was passed to the PBrowserOrId param in to the PHttpChannel constructor + */ + async AsyncAuthPromptForNestedFrame(TabId nestedFrameId, nsCString uri, + nsString realm, uint64_t callbackId); + + /* Predictor Methods */ + async PredOnPredictPrefetch(URIParams uri, uint32_t httpStatus); + async PredOnPredictPreconnect(URIParams uri); + async PredOnPredictDNS(URIParams uri); + + async SpeculativeConnectRequest(); + + async PTransportProvider(); + +both: + // Actually we need PTCPSocket() for parent. But ipdl disallows us having different + // signatures on parent and child. So when constructing the parent side object, we just + // leave host/port unused. + async PTCPSocket(nsString host, uint16_t port); +}; + + +} // namespace net +} // namespace mozilla diff --git a/netwerk/ipc/PRtspChannel.ipdl b/netwerk/ipc/PRtspChannel.ipdl new file mode 100644 index 0000000000..e884cae762 --- /dev/null +++ b/netwerk/ipc/PRtspChannel.ipdl @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */ + +/* 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/. */ + +include protocol PNecko; +include URIParams; + +namespace mozilla { +namespace net { + +async protocol PRtspChannel +{ + manager PNecko; + +parent: + // Note: channels are opened during construction, so no open method here: + // see PNecko.ipdl + async __delete__(); +}; + +} // namespace net +} // namespace mozilla diff --git a/netwerk/ipc/PRtspController.ipdl b/netwerk/ipc/PRtspController.ipdl new file mode 100644 index 0000000000..656dbe0b9a --- /dev/null +++ b/netwerk/ipc/PRtspController.ipdl @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */ + +/* 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/. */ + +include protocol PNecko; +include URIParams; + +namespace mozilla { +namespace net { + +/** + * Defined meta data format. + */ +union RtspMetaValue +{ + bool; + uint8_t; + uint32_t; + uint64_t; + nsCString; +}; + +/** + * Key-value pair. + */ +struct RtspMetadataParam +{ + nsCString name; + RtspMetaValue value; +}; + +async protocol PRtspController +{ + manager PNecko; + +parent: + async AsyncOpen(URIParams aURI); + async Play(); + async Pause(); + async Resume(); + async Suspend(); + async Seek(uint64_t offset); + async Stop(); + async PlaybackEnded(); + async __delete__(); + +child: + async OnMediaDataAvailable(uint8_t index, + nsCString data, + uint32_t length, + uint32_t offset, + RtspMetadataParam[] meta); + async OnConnected(uint8_t index, + RtspMetadataParam[] meta); + async OnDisconnected(uint8_t index, + nsresult reason); + async AsyncOpenFailed(nsresult reason); +}; + +} //namespace net +} //namespace mozilla diff --git a/netwerk/ipc/moz.build b/netwerk/ipc/moz.build new file mode 100644 index 0000000000..0740e6f6b7 --- /dev/null +++ b/netwerk/ipc/moz.build @@ -0,0 +1,40 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +EXPORTS.mozilla.net += [ + 'ChannelEventQueue.h', + 'NeckoChild.h', + 'NeckoCommon.h', + 'NeckoMessageUtils.h', + 'NeckoParent.h', +] + +UNIFIED_SOURCES += [ + 'ChannelEventQueue.cpp', + 'NeckoChild.cpp', + 'NeckoCommon.cpp', + 'NeckoParent.cpp', +] + +IPDL_SOURCES = [ + 'NeckoChannelParams.ipdlh', + 'PChannelDiverter.ipdl', + 'PDataChannel.ipdl', + 'PNecko.ipdl', + 'PRtspChannel.ipdl', + 'PRtspController.ipdl', +] + +include('/ipc/chromium/chromium-config.mozbuild') + +FINAL_LIBRARY = 'xul' + +LOCAL_INCLUDES += [ + '/caps', + '/modules/libjar', + '/netwerk/base', + '/netwerk/protocol/http', +] |