Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: sw=4 ts=4 et :
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #ifndef mozilla_ipc_ProtocolUtils_h
9 #define mozilla_ipc_ProtocolUtils_h 1
11 #include "base/process.h"
12 #include "base/process_util.h"
13 #include "chrome/common/ipc_message_utils.h"
15 #include "prenv.h"
17 #include "IPCMessageStart.h"
18 #include "mozilla/Attributes.h"
19 #include "mozilla/ipc/FileDescriptor.h"
20 #include "mozilla/ipc/Shmem.h"
21 #include "mozilla/ipc/Transport.h"
22 #include "mozilla/ipc/MessageLink.h"
23 #include "mozilla/LinkedList.h"
25 #if defined(ANDROID) && defined(DEBUG)
26 #include <android/log.h>
27 #endif
29 // WARNING: this takes into account the private, special-message-type
30 // enum in ipc_channel.h. They need to be kept in sync.
31 namespace {
32 // XXX the max message ID is actually kuint32max now ... when this
33 // changed, the assumptions of the special message IDs changed in that
34 // they're not carving out messages from likely-unallocated space, but
35 // rather carving out messages from the end of space allocated to
36 // protocol 0. Oops! We can get away with this until protocol 0
37 // starts approaching its 65,536th message.
38 enum {
39 CHANNEL_OPENED_MESSAGE_TYPE = kuint16max - 5,
40 SHMEM_DESTROYED_MESSAGE_TYPE = kuint16max - 4,
41 SHMEM_CREATED_MESSAGE_TYPE = kuint16max - 3,
42 GOODBYE_MESSAGE_TYPE = kuint16max - 2
44 // kuint16max - 1 is used by ipc_channel.h.
45 };
46 }
48 namespace mozilla {
49 namespace dom {
50 class ContentParent;
51 }
53 namespace net {
54 class NeckoParent;
55 }
57 namespace ipc {
59 #ifdef XP_WIN
60 const base::ProcessHandle kInvalidProcessHandle = INVALID_HANDLE_VALUE;
61 #else
62 const base::ProcessHandle kInvalidProcessHandle = -1;
63 #endif
65 class ProtocolFdMapping;
66 class ProtocolCloneContext;
68 // Used to pass references to protocol actors across the wire.
69 // Actors created on the parent-side have a positive ID, and actors
70 // allocated on the child side have a negative ID.
71 struct ActorHandle
72 {
73 int mId;
74 };
76 // Used internally to represent a "trigger" that might cause a state
77 // transition. Triggers are normalized across parent+child to Send
78 // and Recv (instead of child-in, child-out, parent-in, parent-out) so
79 // that they can share the same state machine implementation. To
80 // further normalize, |Send| is used for 'call', |Recv| for 'answer'.
81 struct Trigger
82 {
83 enum Action { Send, Recv };
85 Trigger(Action action, int32_t msg) :
86 mAction(action),
87 mMsg(msg)
88 {}
90 Action mAction;
91 int32_t mMsg;
92 };
94 class ProtocolCloneContext
95 {
96 typedef mozilla::dom::ContentParent ContentParent;
97 typedef mozilla::net::NeckoParent NeckoParent;
99 ContentParent* mContentParent;
100 NeckoParent* mNeckoParent;
102 public:
103 ProtocolCloneContext()
104 : mContentParent(nullptr)
105 , mNeckoParent(nullptr)
106 {}
108 void SetContentParent(ContentParent* aContentParent)
109 {
110 mContentParent = aContentParent;
111 }
113 ContentParent* GetContentParent() { return mContentParent; }
115 void SetNeckoParent(NeckoParent* aNeckoParent)
116 {
117 mNeckoParent = aNeckoParent;
118 }
120 NeckoParent* GetNeckoParent() { return mNeckoParent; }
121 };
123 template<class ListenerT>
124 class /*NS_INTERFACE_CLASS*/ IProtocolManager
125 {
126 public:
127 enum ActorDestroyReason {
128 FailedConstructor,
129 Deletion,
130 AncestorDeletion,
131 NormalShutdown,
132 AbnormalShutdown
133 };
135 typedef base::ProcessHandle ProcessHandle;
137 virtual int32_t Register(ListenerT*) = 0;
138 virtual int32_t RegisterID(ListenerT*, int32_t) = 0;
139 virtual ListenerT* Lookup(int32_t) = 0;
140 virtual void Unregister(int32_t) = 0;
141 virtual void RemoveManagee(int32_t, ListenerT*) = 0;
143 virtual Shmem::SharedMemory* CreateSharedMemory(
144 size_t, SharedMemory::SharedMemoryType, bool, int32_t*) = 0;
145 virtual bool AdoptSharedMemory(Shmem::SharedMemory*, int32_t*) = 0;
146 virtual Shmem::SharedMemory* LookupSharedMemory(int32_t) = 0;
147 virtual bool IsTrackingSharedMemory(Shmem::SharedMemory*) = 0;
148 virtual bool DestroySharedMemory(Shmem&) = 0;
150 // XXX odd ducks, acknowledged
151 virtual ProcessHandle OtherProcess() const = 0;
152 virtual MessageChannel* GetIPCChannel() = 0;
154 // The implementation of function is generated by code generator.
155 virtual void CloneManagees(ListenerT* aSource,
156 ProtocolCloneContext* aCtx) = 0;
157 };
159 typedef IPCMessageStart ProtocolId;
161 /**
162 * All RPC protocols should implement this interface.
163 */
164 class IProtocol : protected MessageListener
165 {
166 public:
167 /**
168 * This function is used to clone this protocol actor.
169 *
170 * see IProtocol::CloneProtocol()
171 */
172 virtual IProtocol*
173 CloneProtocol(MessageChannel* aChannel,
174 ProtocolCloneContext* aCtx) = 0;
175 };
177 /**
178 * All top-level protocols should inherit this class.
179 *
180 * IToplevelProtocol tracks all top-level protocol actors created from
181 * this protocol actor.
182 */
183 class IToplevelProtocol : public LinkedListElement<IToplevelProtocol>
184 {
185 protected:
186 IToplevelProtocol(ProtocolId aProtoId)
187 : mProtocolId(aProtoId)
188 , mTrans(nullptr)
189 {
190 }
192 ~IToplevelProtocol();
194 /**
195 * Add an actor to the list of actors that have been opened by this
196 * protocol.
197 */
198 void AddOpenedActor(IToplevelProtocol* aActor);
200 public:
201 void SetTransport(Transport* aTrans)
202 {
203 mTrans = aTrans;
204 }
206 Transport* GetTransport() const { return mTrans; }
208 ProtocolId GetProtocolId() const { return mProtocolId; }
210 /**
211 * Return first of actors of top level protocols opened by this one.
212 */
213 IToplevelProtocol* GetFirstOpenedActors()
214 {
215 return mOpenActors.getFirst();
216 }
217 const IToplevelProtocol* GetFirstOpenedActors() const
218 {
219 return mOpenActors.getFirst();
220 }
222 virtual IToplevelProtocol*
223 CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
224 base::ProcessHandle aPeerProcess,
225 ProtocolCloneContext* aCtx);
227 void CloneOpenedToplevels(IToplevelProtocol* aTemplate,
228 const InfallibleTArray<ProtocolFdMapping>& aFds,
229 base::ProcessHandle aPeerProcess,
230 ProtocolCloneContext* aCtx);
232 private:
233 LinkedList<IToplevelProtocol> mOpenActors; // All protocol actors opened by this.
235 ProtocolId mProtocolId;
236 Transport* mTrans;
237 };
240 inline bool
241 LoggingEnabled()
242 {
243 #if defined(DEBUG)
244 return !!PR_GetEnv("MOZ_IPC_MESSAGE_LOG");
245 #else
246 return false;
247 #endif
248 }
250 MOZ_NEVER_INLINE void
251 ProtocolErrorBreakpoint(const char* aMsg);
253 MOZ_NEVER_INLINE void
254 FatalError(const char* aProtocolName, const char* aMsg,
255 base::ProcessHandle aHandle, bool aIsParent);
257 struct PrivateIPDLInterface {};
259 bool
260 Bridge(const PrivateIPDLInterface&,
261 MessageChannel*, base::ProcessHandle, MessageChannel*, base::ProcessHandle,
262 ProtocolId, ProtocolId);
264 bool
265 Open(const PrivateIPDLInterface&,
266 MessageChannel*, base::ProcessHandle, Transport::Mode,
267 ProtocolId, ProtocolId);
269 bool
270 UnpackChannelOpened(const PrivateIPDLInterface&,
271 const IPC::Message&,
272 TransportDescriptor*, base::ProcessId*, ProtocolId*);
274 } // namespace ipc
275 } // namespace mozilla
278 namespace IPC {
280 template <>
281 struct ParamTraits<mozilla::ipc::ActorHandle>
282 {
283 typedef mozilla::ipc::ActorHandle paramType;
285 static void Write(Message* aMsg, const paramType& aParam)
286 {
287 IPC::WriteParam(aMsg, aParam.mId);
288 }
290 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
291 {
292 int id;
293 if (IPC::ReadParam(aMsg, aIter, &id)) {
294 aResult->mId = id;
295 return true;
296 }
297 return false;
298 }
300 static void Log(const paramType& aParam, std::wstring* aLog)
301 {
302 aLog->append(StringPrintf(L"(%d)", aParam.mId));
303 }
304 };
306 } // namespace IPC
309 #endif // mozilla_ipc_ProtocolUtils_h