| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef CHROME_NACL_NACL_IPC_ADAPTER_H_ | |
| 6 #define CHROME_NACL_NACL_IPC_ADAPTER_H_ | |
| 7 | |
| 8 #include <map> | |
| 9 #include <queue> | |
| 10 #include <string> | |
| 11 #include <vector> | |
| 12 | |
| 13 #include "base/basictypes.h" | |
| 14 #include "base/memory/ref_counted.h" | |
| 15 #include "base/memory/scoped_ptr.h" | |
| 16 #include "base/memory/scoped_vector.h" | |
| 17 #include "base/memory/shared_memory.h" | |
| 18 #include "base/pickle.h" | |
| 19 #include "base/synchronization/condition_variable.h" | |
| 20 #include "base/synchronization/lock.h" | |
| 21 #include "base/task_runner.h" | |
| 22 #include "ipc/ipc_listener.h" | |
| 23 #include "ppapi/c/pp_stdint.h" | |
| 24 #include "ppapi/proxy/handle_converter.h" | |
| 25 | |
| 26 struct NaClDesc; | |
| 27 struct NaClImcTypedMsgHdr; | |
| 28 struct PP_Size; | |
| 29 | |
| 30 namespace IPC { | |
| 31 class Channel; | |
| 32 struct ChannelHandle; | |
| 33 } | |
| 34 | |
| 35 namespace ppapi { | |
| 36 class HostResource; | |
| 37 } | |
| 38 | |
| 39 // Adapts a Chrome IPC channel to an IPC channel that we expose to Native | |
| 40 // Client. This provides a mapping in both directions, so when IPC messages | |
| 41 // come in from another process, we rewrite them and allow them to be received | |
| 42 // via a recvmsg-like interface in the NaCl code. When NaCl code calls sendmsg, | |
| 43 // we implement that as sending IPC messages on the channel. | |
| 44 // | |
| 45 // This object also provides the necessary logic for rewriting IPC messages. | |
| 46 // NaCl code is platform-independent and runs in a Posix-like enviroment, but | |
| 47 // some formatting in the message and the way handles are transferred varies | |
| 48 // by platform. This class bridges that gap to provide what looks like a | |
| 49 // normal platform-specific IPC implementation to Chrome, and a Posix-like | |
| 50 // version on every platform to NaCl. | |
| 51 // | |
| 52 // This object must be threadsafe since the nacl environment determines which | |
| 53 // thread every function is called on. | |
| 54 class NaClIPCAdapter : public base::RefCountedThreadSafe<NaClIPCAdapter>, | |
| 55 public IPC::Listener { | |
| 56 public: | |
| 57 // Chrome's IPC message format varies by platform, NaCl's does not. In | |
| 58 // particular, the header has some extra fields on Posix platforms. Since | |
| 59 // NaCl is a Posix environment, it gets that version of the header. This | |
| 60 // header is duplicated here so we have a cross-platform definition of the | |
| 61 // header we're exposing to NaCl. | |
| 62 #pragma pack(push, 4) | |
| 63 struct NaClMessageHeader : public Pickle::Header { | |
| 64 int32 routing; | |
| 65 uint32 type; | |
| 66 uint32 flags; | |
| 67 uint16 num_fds; | |
| 68 uint16 pad; | |
| 69 }; | |
| 70 #pragma pack(pop) | |
| 71 | |
| 72 // Creates an adapter, using the thread associated with the given task | |
| 73 // runner for posting messages. In normal use, the task runner will post to | |
| 74 // the I/O thread of the process. | |
| 75 // | |
| 76 // If you use this constructor, you MUST call ConnectChannel after the | |
| 77 // NaClIPCAdapter is constructed, or the NaClIPCAdapter's channel will not be | |
| 78 // connected. | |
| 79 NaClIPCAdapter(const IPC::ChannelHandle& handle, base::TaskRunner* runner); | |
| 80 | |
| 81 // Initializes with a given channel that's already created for testing | |
| 82 // purposes. This function will take ownership of the given channel. | |
| 83 NaClIPCAdapter(scoped_ptr<IPC::Channel> channel, base::TaskRunner* runner); | |
| 84 | |
| 85 // Connect the channel. This must be called after the constructor that accepts | |
| 86 // an IPC::ChannelHandle, and causes the Channel to be connected on the IO | |
| 87 // thread. | |
| 88 void ConnectChannel(); | |
| 89 | |
| 90 // Implementation of sendmsg. Returns the number of bytes written or -1 on | |
| 91 // failure. | |
| 92 int Send(const NaClImcTypedMsgHdr* msg); | |
| 93 | |
| 94 // Implementation of recvmsg. Returns the number of bytes read or -1 on | |
| 95 // failure. This will block until there's an error or there is data to | |
| 96 // read. | |
| 97 int BlockingReceive(NaClImcTypedMsgHdr* msg); | |
| 98 | |
| 99 // Closes the IPC channel. | |
| 100 void CloseChannel(); | |
| 101 | |
| 102 // Make a NaClDesc that refers to this NaClIPCAdapter. Note that the returned | |
| 103 // NaClDesc is reference-counted, and a reference is returned. | |
| 104 NaClDesc* MakeNaClDesc(); | |
| 105 | |
| 106 #if defined(OS_POSIX) | |
| 107 int TakeClientFileDescriptor(); | |
| 108 #endif | |
| 109 | |
| 110 // Listener implementation. | |
| 111 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; | |
| 112 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; | |
| 113 virtual void OnChannelError() OVERRIDE; | |
| 114 | |
| 115 private: | |
| 116 friend class base::RefCountedThreadSafe<NaClIPCAdapter>; | |
| 117 | |
| 118 class RewrittenMessage; | |
| 119 | |
| 120 // This is the data that must only be accessed inside the lock. This struct | |
| 121 // just separates it so it's easier to see. | |
| 122 struct LockedData { | |
| 123 LockedData(); | |
| 124 ~LockedData(); | |
| 125 | |
| 126 // Messages that we have read off of the Chrome IPC channel that are waiting | |
| 127 // to be received by the plugin. | |
| 128 std::queue< scoped_refptr<RewrittenMessage> > to_be_received_; | |
| 129 | |
| 130 ppapi::proxy::HandleConverter handle_converter_; | |
| 131 | |
| 132 // Data that we've queued from the plugin to send, but doesn't consist of a | |
| 133 // full message yet. The calling code can break apart the message into | |
| 134 // smaller pieces, and we need to send the message to the other process in | |
| 135 // one chunk. | |
| 136 // | |
| 137 // The IPC channel always starts a new send() at the beginning of each | |
| 138 // message, so we don't need to worry about arbitrary message boundaries. | |
| 139 std::string to_be_sent_; | |
| 140 | |
| 141 bool channel_closed_; | |
| 142 }; | |
| 143 | |
| 144 // This is the data that must only be accessed on the I/O thread (as defined | |
| 145 // by TaskRunner). This struct just separates it so it's easier to see. | |
| 146 struct IOThreadData { | |
| 147 IOThreadData(); | |
| 148 ~IOThreadData(); | |
| 149 | |
| 150 scoped_ptr<IPC::Channel> channel_; | |
| 151 }; | |
| 152 | |
| 153 virtual ~NaClIPCAdapter(); | |
| 154 | |
| 155 // Returns 0 if nothing is waiting. | |
| 156 int LockedReceive(NaClImcTypedMsgHdr* msg); | |
| 157 | |
| 158 // Sends a message that we know has been completed to the Chrome process. | |
| 159 bool SendCompleteMessage(const char* buffer, size_t buffer_len); | |
| 160 | |
| 161 // Clears the LockedData.to_be_sent_ structure in a way to make sure that | |
| 162 // the memory is deleted. std::string can sometimes hold onto the buffer | |
| 163 // for future use which we don't want. | |
| 164 void ClearToBeSent(); | |
| 165 | |
| 166 void ConnectChannelOnIOThread(); | |
| 167 void CloseChannelOnIOThread(); | |
| 168 void SendMessageOnIOThread(scoped_ptr<IPC::Message> message); | |
| 169 | |
| 170 // Saves the message to forward to NaCl. This method assumes that the caller | |
| 171 // holds the lock for locked_data_. | |
| 172 void SaveMessage(const IPC::Message& message, | |
| 173 RewrittenMessage* rewritten_message); | |
| 174 | |
| 175 base::Lock lock_; | |
| 176 base::ConditionVariable cond_var_; | |
| 177 | |
| 178 scoped_refptr<base::TaskRunner> task_runner_; | |
| 179 | |
| 180 // To be accessed inside of lock_ only. | |
| 181 LockedData locked_data_; | |
| 182 | |
| 183 // To be accessed on the I/O thread (via task runner) only. | |
| 184 IOThreadData io_thread_data_; | |
| 185 | |
| 186 DISALLOW_COPY_AND_ASSIGN(NaClIPCAdapter); | |
| 187 }; | |
| 188 | |
| 189 // Export TranslatePepperFileReadWriteOpenFlags for testing. | |
| 190 int TranslatePepperFileReadWriteOpenFlagsForTesting(int32_t pp_open_flags); | |
| 191 | |
| 192 #endif // CHROME_NACL_NACL_IPC_ADAPTER_H_ | |
| OLD | NEW |