1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/glue/ProtocolUtils.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,309 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: sw=4 ts=4 et : 1.6 + */ 1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#ifndef mozilla_ipc_ProtocolUtils_h 1.12 +#define mozilla_ipc_ProtocolUtils_h 1 1.13 + 1.14 +#include "base/process.h" 1.15 +#include "base/process_util.h" 1.16 +#include "chrome/common/ipc_message_utils.h" 1.17 + 1.18 +#include "prenv.h" 1.19 + 1.20 +#include "IPCMessageStart.h" 1.21 +#include "mozilla/Attributes.h" 1.22 +#include "mozilla/ipc/FileDescriptor.h" 1.23 +#include "mozilla/ipc/Shmem.h" 1.24 +#include "mozilla/ipc/Transport.h" 1.25 +#include "mozilla/ipc/MessageLink.h" 1.26 +#include "mozilla/LinkedList.h" 1.27 + 1.28 +#if defined(ANDROID) && defined(DEBUG) 1.29 +#include <android/log.h> 1.30 +#endif 1.31 + 1.32 +// WARNING: this takes into account the private, special-message-type 1.33 +// enum in ipc_channel.h. They need to be kept in sync. 1.34 +namespace { 1.35 +// XXX the max message ID is actually kuint32max now ... when this 1.36 +// changed, the assumptions of the special message IDs changed in that 1.37 +// they're not carving out messages from likely-unallocated space, but 1.38 +// rather carving out messages from the end of space allocated to 1.39 +// protocol 0. Oops! We can get away with this until protocol 0 1.40 +// starts approaching its 65,536th message. 1.41 +enum { 1.42 + CHANNEL_OPENED_MESSAGE_TYPE = kuint16max - 5, 1.43 + SHMEM_DESTROYED_MESSAGE_TYPE = kuint16max - 4, 1.44 + SHMEM_CREATED_MESSAGE_TYPE = kuint16max - 3, 1.45 + GOODBYE_MESSAGE_TYPE = kuint16max - 2 1.46 + 1.47 + // kuint16max - 1 is used by ipc_channel.h. 1.48 +}; 1.49 +} 1.50 + 1.51 +namespace mozilla { 1.52 +namespace dom { 1.53 +class ContentParent; 1.54 +} 1.55 + 1.56 +namespace net { 1.57 +class NeckoParent; 1.58 +} 1.59 + 1.60 +namespace ipc { 1.61 + 1.62 +#ifdef XP_WIN 1.63 +const base::ProcessHandle kInvalidProcessHandle = INVALID_HANDLE_VALUE; 1.64 +#else 1.65 +const base::ProcessHandle kInvalidProcessHandle = -1; 1.66 +#endif 1.67 + 1.68 +class ProtocolFdMapping; 1.69 +class ProtocolCloneContext; 1.70 + 1.71 +// Used to pass references to protocol actors across the wire. 1.72 +// Actors created on the parent-side have a positive ID, and actors 1.73 +// allocated on the child side have a negative ID. 1.74 +struct ActorHandle 1.75 +{ 1.76 + int mId; 1.77 +}; 1.78 + 1.79 +// Used internally to represent a "trigger" that might cause a state 1.80 +// transition. Triggers are normalized across parent+child to Send 1.81 +// and Recv (instead of child-in, child-out, parent-in, parent-out) so 1.82 +// that they can share the same state machine implementation. To 1.83 +// further normalize, |Send| is used for 'call', |Recv| for 'answer'. 1.84 +struct Trigger 1.85 +{ 1.86 + enum Action { Send, Recv }; 1.87 + 1.88 + Trigger(Action action, int32_t msg) : 1.89 + mAction(action), 1.90 + mMsg(msg) 1.91 + {} 1.92 + 1.93 + Action mAction; 1.94 + int32_t mMsg; 1.95 +}; 1.96 + 1.97 +class ProtocolCloneContext 1.98 +{ 1.99 + typedef mozilla::dom::ContentParent ContentParent; 1.100 + typedef mozilla::net::NeckoParent NeckoParent; 1.101 + 1.102 + ContentParent* mContentParent; 1.103 + NeckoParent* mNeckoParent; 1.104 + 1.105 +public: 1.106 + ProtocolCloneContext() 1.107 + : mContentParent(nullptr) 1.108 + , mNeckoParent(nullptr) 1.109 + {} 1.110 + 1.111 + void SetContentParent(ContentParent* aContentParent) 1.112 + { 1.113 + mContentParent = aContentParent; 1.114 + } 1.115 + 1.116 + ContentParent* GetContentParent() { return mContentParent; } 1.117 + 1.118 + void SetNeckoParent(NeckoParent* aNeckoParent) 1.119 + { 1.120 + mNeckoParent = aNeckoParent; 1.121 + } 1.122 + 1.123 + NeckoParent* GetNeckoParent() { return mNeckoParent; } 1.124 +}; 1.125 + 1.126 +template<class ListenerT> 1.127 +class /*NS_INTERFACE_CLASS*/ IProtocolManager 1.128 +{ 1.129 +public: 1.130 + enum ActorDestroyReason { 1.131 + FailedConstructor, 1.132 + Deletion, 1.133 + AncestorDeletion, 1.134 + NormalShutdown, 1.135 + AbnormalShutdown 1.136 + }; 1.137 + 1.138 + typedef base::ProcessHandle ProcessHandle; 1.139 + 1.140 + virtual int32_t Register(ListenerT*) = 0; 1.141 + virtual int32_t RegisterID(ListenerT*, int32_t) = 0; 1.142 + virtual ListenerT* Lookup(int32_t) = 0; 1.143 + virtual void Unregister(int32_t) = 0; 1.144 + virtual void RemoveManagee(int32_t, ListenerT*) = 0; 1.145 + 1.146 + virtual Shmem::SharedMemory* CreateSharedMemory( 1.147 + size_t, SharedMemory::SharedMemoryType, bool, int32_t*) = 0; 1.148 + virtual bool AdoptSharedMemory(Shmem::SharedMemory*, int32_t*) = 0; 1.149 + virtual Shmem::SharedMemory* LookupSharedMemory(int32_t) = 0; 1.150 + virtual bool IsTrackingSharedMemory(Shmem::SharedMemory*) = 0; 1.151 + virtual bool DestroySharedMemory(Shmem&) = 0; 1.152 + 1.153 + // XXX odd ducks, acknowledged 1.154 + virtual ProcessHandle OtherProcess() const = 0; 1.155 + virtual MessageChannel* GetIPCChannel() = 0; 1.156 + 1.157 + // The implementation of function is generated by code generator. 1.158 + virtual void CloneManagees(ListenerT* aSource, 1.159 + ProtocolCloneContext* aCtx) = 0; 1.160 +}; 1.161 + 1.162 +typedef IPCMessageStart ProtocolId; 1.163 + 1.164 +/** 1.165 + * All RPC protocols should implement this interface. 1.166 + */ 1.167 +class IProtocol : protected MessageListener 1.168 +{ 1.169 +public: 1.170 + /** 1.171 + * This function is used to clone this protocol actor. 1.172 + * 1.173 + * see IProtocol::CloneProtocol() 1.174 + */ 1.175 + virtual IProtocol* 1.176 + CloneProtocol(MessageChannel* aChannel, 1.177 + ProtocolCloneContext* aCtx) = 0; 1.178 +}; 1.179 + 1.180 +/** 1.181 + * All top-level protocols should inherit this class. 1.182 + * 1.183 + * IToplevelProtocol tracks all top-level protocol actors created from 1.184 + * this protocol actor. 1.185 + */ 1.186 +class IToplevelProtocol : public LinkedListElement<IToplevelProtocol> 1.187 +{ 1.188 +protected: 1.189 + IToplevelProtocol(ProtocolId aProtoId) 1.190 + : mProtocolId(aProtoId) 1.191 + , mTrans(nullptr) 1.192 + { 1.193 + } 1.194 + 1.195 + ~IToplevelProtocol(); 1.196 + 1.197 + /** 1.198 + * Add an actor to the list of actors that have been opened by this 1.199 + * protocol. 1.200 + */ 1.201 + void AddOpenedActor(IToplevelProtocol* aActor); 1.202 + 1.203 +public: 1.204 + void SetTransport(Transport* aTrans) 1.205 + { 1.206 + mTrans = aTrans; 1.207 + } 1.208 + 1.209 + Transport* GetTransport() const { return mTrans; } 1.210 + 1.211 + ProtocolId GetProtocolId() const { return mProtocolId; } 1.212 + 1.213 + /** 1.214 + * Return first of actors of top level protocols opened by this one. 1.215 + */ 1.216 + IToplevelProtocol* GetFirstOpenedActors() 1.217 + { 1.218 + return mOpenActors.getFirst(); 1.219 + } 1.220 + const IToplevelProtocol* GetFirstOpenedActors() const 1.221 + { 1.222 + return mOpenActors.getFirst(); 1.223 + } 1.224 + 1.225 + virtual IToplevelProtocol* 1.226 + CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds, 1.227 + base::ProcessHandle aPeerProcess, 1.228 + ProtocolCloneContext* aCtx); 1.229 + 1.230 + void CloneOpenedToplevels(IToplevelProtocol* aTemplate, 1.231 + const InfallibleTArray<ProtocolFdMapping>& aFds, 1.232 + base::ProcessHandle aPeerProcess, 1.233 + ProtocolCloneContext* aCtx); 1.234 + 1.235 +private: 1.236 + LinkedList<IToplevelProtocol> mOpenActors; // All protocol actors opened by this. 1.237 + 1.238 + ProtocolId mProtocolId; 1.239 + Transport* mTrans; 1.240 +}; 1.241 + 1.242 + 1.243 +inline bool 1.244 +LoggingEnabled() 1.245 +{ 1.246 +#if defined(DEBUG) 1.247 + return !!PR_GetEnv("MOZ_IPC_MESSAGE_LOG"); 1.248 +#else 1.249 + return false; 1.250 +#endif 1.251 +} 1.252 + 1.253 +MOZ_NEVER_INLINE void 1.254 +ProtocolErrorBreakpoint(const char* aMsg); 1.255 + 1.256 +MOZ_NEVER_INLINE void 1.257 +FatalError(const char* aProtocolName, const char* aMsg, 1.258 + base::ProcessHandle aHandle, bool aIsParent); 1.259 + 1.260 +struct PrivateIPDLInterface {}; 1.261 + 1.262 +bool 1.263 +Bridge(const PrivateIPDLInterface&, 1.264 + MessageChannel*, base::ProcessHandle, MessageChannel*, base::ProcessHandle, 1.265 + ProtocolId, ProtocolId); 1.266 + 1.267 +bool 1.268 +Open(const PrivateIPDLInterface&, 1.269 + MessageChannel*, base::ProcessHandle, Transport::Mode, 1.270 + ProtocolId, ProtocolId); 1.271 + 1.272 +bool 1.273 +UnpackChannelOpened(const PrivateIPDLInterface&, 1.274 + const IPC::Message&, 1.275 + TransportDescriptor*, base::ProcessId*, ProtocolId*); 1.276 + 1.277 +} // namespace ipc 1.278 +} // namespace mozilla 1.279 + 1.280 + 1.281 +namespace IPC { 1.282 + 1.283 +template <> 1.284 +struct ParamTraits<mozilla::ipc::ActorHandle> 1.285 +{ 1.286 + typedef mozilla::ipc::ActorHandle paramType; 1.287 + 1.288 + static void Write(Message* aMsg, const paramType& aParam) 1.289 + { 1.290 + IPC::WriteParam(aMsg, aParam.mId); 1.291 + } 1.292 + 1.293 + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) 1.294 + { 1.295 + int id; 1.296 + if (IPC::ReadParam(aMsg, aIter, &id)) { 1.297 + aResult->mId = id; 1.298 + return true; 1.299 + } 1.300 + return false; 1.301 + } 1.302 + 1.303 + static void Log(const paramType& aParam, std::wstring* aLog) 1.304 + { 1.305 + aLog->append(StringPrintf(L"(%d)", aParam.mId)); 1.306 + } 1.307 +}; 1.308 + 1.309 +} // namespace IPC 1.310 + 1.311 + 1.312 +#endif // mozilla_ipc_ProtocolUtils_h