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 #pragma once |
| 8 |
| 9 #include <queue> |
| 10 #include <string> |
| 11 |
| 12 #include "base/basictypes.h" |
| 13 #include "base/memory/ref_counted.h" |
| 14 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/synchronization/condition_variable.h" |
| 16 #include "base/synchronization/lock.h" |
| 17 #include "base/task_runner.h" |
| 18 #include "ipc/ipc_channel.h" |
| 19 |
| 20 // Adapts a Chrome IPC channel to an IPC channel that we expose to Native |
| 21 // Client. This provides a mapping in both directions, so when IPC messages |
| 22 // come in from another process, we rewrite them and allow them to be received |
| 23 // via a recvmsg-like interface in the NaCl code. When NaCl code calls sendmsg, |
| 24 // we implement that as sending IPC messages on the channel. |
| 25 // |
| 26 // This object also provides the necessary logic for rewriting IPC messages. |
| 27 // NaCl code is platform-independent and runs in a Posix-like enviroment, but |
| 28 // some formatting in the message and the way handles are transferred varies |
| 29 // by platform. This class bridges that gap to provide what looks like a |
| 30 // normal platform-specific IPC implementation to Chrome, and a Posix-like |
| 31 // version on every platform to NaCl. |
| 32 // |
| 33 // This object must be threadsafe since the nacl environment determines which |
| 34 // thread every function is called on. |
| 35 class NaClIPCAdapter : public base::RefCountedThreadSafe<NaClIPCAdapter>, |
| 36 public IPC::Channel::Listener { |
| 37 public: |
| 38 // Chrome's IPC message format varies by platform, NaCl's does not. In |
| 39 // particular, the header has some extra fields on Posix platforms. Since |
| 40 // NaCl is a Posix environment, it gets that version of the header. This |
| 41 // header is duplicated here so we have a cross-platform definition of the |
| 42 // header we're exposing to NaCl. |
| 43 #pragma pack(push, 4) |
| 44 struct NaClMessageHeader : public Pickle::Header { |
| 45 int32 routing; |
| 46 uint32 type; |
| 47 uint32 flags; |
| 48 uint16 num_fds; |
| 49 uint16 pad; |
| 50 }; |
| 51 #pragma pack(pop) |
| 52 |
| 53 // Creates an adapter, using the thread associated with the given task |
| 54 // runner for posting messages. In normal use, the task runner will post to |
| 55 // the I/O thread of the process. |
| 56 NaClIPCAdapter(const IPC::ChannelHandle& handle, base::TaskRunner* runner); |
| 57 |
| 58 // Initializes with a given channel that's already created for testing |
| 59 // purposes. This function will take ownership of the given channel. |
| 60 NaClIPCAdapter(scoped_ptr<IPC::Channel> channel, base::TaskRunner* runner); |
| 61 |
| 62 virtual ~NaClIPCAdapter(); |
| 63 |
| 64 // Implementation of sendmsg. Returns the number of bytes written or -1 on |
| 65 // failure. |
| 66 int Send(const char* input_data, size_t input_data_len); |
| 67 |
| 68 // Implementation of recvmsg. Returns the number of bytes read or -1 on |
| 69 // failure. This will block until there's an error or there is data to |
| 70 // read. |
| 71 int BlockingReceive(char* output_buffer, int output_buffer_size); |
| 72 |
| 73 // Closes the IPC channel. |
| 74 void CloseChannel(); |
| 75 |
| 76 // Listener implementation. |
| 77 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; |
| 78 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; |
| 79 virtual void OnChannelError() OVERRIDE; |
| 80 |
| 81 private: |
| 82 class RewrittenMessage; |
| 83 |
| 84 // This is the data that must only be accessed inside the lock. This struct |
| 85 // just separates it so it's easier to see. |
| 86 struct LockedData { |
| 87 LockedData(); |
| 88 ~LockedData(); |
| 89 |
| 90 // Messages that we have read off of the Chrome IPC channel that are waiting |
| 91 // to be received by the plugin. |
| 92 std::queue< scoped_refptr<RewrittenMessage> > to_be_received_; |
| 93 |
| 94 // Data that we've queued from the plugin to send, but doesn't consist of a |
| 95 // full message yet. The calling code can break apart the message into |
| 96 // smaller pieces, and we need to send the message to the other process in |
| 97 // one chunk. |
| 98 // |
| 99 // The IPC channel always starts a new send() at the beginning of each |
| 100 // message, so we don't need to worry about arbitrary message boundaries. |
| 101 std::string to_be_sent_; |
| 102 |
| 103 bool channel_closed_; |
| 104 }; |
| 105 |
| 106 // This is the data that must only be accessed on the I/O thread (as defined |
| 107 // by TaskRunner). This struct just separates it so it's easier to see. |
| 108 struct IOThreadData { |
| 109 IOThreadData(); |
| 110 ~IOThreadData(); |
| 111 |
| 112 scoped_ptr<IPC::Channel> channel_; |
| 113 }; |
| 114 |
| 115 // Reads up to the given amount of data. Returns 0 if nothing is waiting. |
| 116 int LockedReceive(char* output_buffer, int output_buffer_size); |
| 117 |
| 118 // Sends a message that we know has been completed to the Chrome process. |
| 119 bool SendCompleteMessage(const char* buffer, size_t buffer_len); |
| 120 |
| 121 // Clears the LockedData.to_be_sent_ structure in a way to make sure that |
| 122 // the memory is deleted. std::string can sometimes hold onto the buffer |
| 123 // for future use which we don't want. |
| 124 void ClearToBeSent(); |
| 125 |
| 126 void CloseChannelOnIOThread(); |
| 127 void SendMessageOnIOThread(scoped_ptr<IPC::Message> message); |
| 128 |
| 129 base::Lock lock_; |
| 130 base::ConditionVariable cond_var_; |
| 131 |
| 132 scoped_refptr<base::TaskRunner> task_runner_; |
| 133 |
| 134 // To be accessed inside of lock_ only. |
| 135 LockedData locked_data_; |
| 136 |
| 137 // To be accessed on the I/O thread (via task runner) only. |
| 138 IOThreadData io_thread_data_; |
| 139 |
| 140 DISALLOW_COPY_AND_ASSIGN(NaClIPCAdapter); |
| 141 }; |
| 142 |
| 143 #endif // CHROME_NACL_NACL_IPC_ADAPTER_H_ |
OLD | NEW |