OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PROCESS_HOST_H_ | 5 #ifndef CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PROCESS_HOST_H_ |
6 #define CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PROCESS_HOST_H_ | 6 #define CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PROCESS_HOST_H_ |
7 | 7 |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/memory/weak_ptr.h" | 10 #include "base/memory/weak_ptr.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
12 #include "base/process.h" | 12 #include "base/process.h" |
13 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
14 | 14 |
15 namespace extensions { | 15 namespace extensions { |
16 class NativeProcessLauncher; | 16 class NativeProcessLauncher; |
17 | 17 |
18 // Manages the native side of a connection between an extension and a native | 18 // Manages the native side of a connection between an extension and a native |
19 // process. | 19 // process. |
20 // | 20 // |
21 // This class must only be created, called, and deleted on the FILE thread. | 21 // This class must only be created, called, and deleted on the IO thread. |
22 // Public methods typically accept callbacks which will be invoked on the UI | 22 // Public methods typically accept callbacks which will be invoked on the UI |
23 // thread. | 23 // thread. |
24 class NativeMessageProcessHost | 24 class NativeMessageProcessHost |
25 #if defined(OS_WIN) | 25 #if defined(OS_WIN) |
26 : public MessageLoopForIO::IOHandler { | 26 : public MessageLoopForIO::IOHandler { |
27 #else | 27 #else |
28 : public MessageLoopForIO::Watcher { | 28 : public MessageLoopForIO::Watcher { |
29 #endif // defined(OS_WIN) | 29 #endif // defined(OS_WIN) |
30 public: | 30 public: |
31 class ScopedNativeProcessClose; | 31 class ScopedNativeProcessClose; |
(...skipping 30 matching lines...) Expand all Loading... |
62 class Client { | 62 class Client { |
63 public: | 63 public: |
64 virtual ~Client() {} | 64 virtual ~Client() {} |
65 // Called on the UI thread. | 65 // Called on the UI thread. |
66 virtual void PostMessageFromNativeProcess(int port_id, | 66 virtual void PostMessageFromNativeProcess(int port_id, |
67 const std::string& message) = 0; | 67 const std::string& message) = 0; |
68 virtual void CloseChannel(int port_id, bool error) = 0; | 68 virtual void CloseChannel(int port_id, bool error) = 0; |
69 }; | 69 }; |
70 | 70 |
71 // Desctruction functor that ensures a NativeMessageProcessHost is destroyed | 71 // Desctruction functor that ensures a NativeMessageProcessHost is destroyed |
72 // on the FILE thread. | 72 // on the IO thread. |
73 class ScopedNativeProcessClose { | 73 class ScopedNativeProcessClose { |
74 public: | 74 public: |
75 inline void operator()(extensions::NativeMessageProcessHost* x) const { | 75 inline void operator()(extensions::NativeMessageProcessHost* x) const { |
76 content::BrowserThread::DeleteSoon(content::BrowserThread::FILE, | 76 content::BrowserThread::DeleteSoon(content::BrowserThread::IO, |
77 FROM_HERE, x); | 77 FROM_HERE, x); |
78 } | 78 } |
79 }; | 79 }; |
80 | 80 |
| 81 static const int kExitTimeoutMS; |
| 82 static const uint32 kMaxMessageDataLength; |
81 | 83 |
82 virtual ~NativeMessageProcessHost(); | 84 virtual ~NativeMessageProcessHost(); |
83 | 85 |
84 // |type| must be TYPE_CONNECT or TYPE_SEND_MESSAGE_REQUEST. |callback| will | 86 // |type| must be TYPE_CONNECT or TYPE_SEND_MESSAGE_REQUEST. |callback| will |
85 // be called with an empty ScopedHost on error. | 87 // be called with an empty ScopedHost on error. |
86 static void Create(base::WeakPtr<Client> weak_client_ui, | 88 static void Create(base::WeakPtr<Client> weak_client_ui, |
87 const std::string& native_app_name, | 89 const std::string& native_app_name, |
88 const std::string& connection_message, | 90 const std::string& connection_message, |
89 int destination_port, | 91 int destination_port, |
90 MessageType type, | 92 MessageType type, |
91 CreateCallback callback); | 93 CreateCallback callback); |
92 | 94 |
93 // Create a NativeMessageProcessHost using the specified launcher. This allows | 95 // Create a NativeMessageProcessHost using the specified launcher. This allows |
94 // for easy testing. | 96 // for easy testing. |
95 static void CreateWithLauncher(base::WeakPtr<Client> weak_client_ui, | 97 static void CreateWithLauncher(base::WeakPtr<Client> weak_client_ui, |
96 const std::string& native_app_name, | 98 const std::string& native_app_name, |
97 const std::string& connection_message, | 99 const std::string& connection_message, |
98 int destination_port, | 100 int destination_port, |
99 MessageType type, | 101 MessageType type, |
100 CreateCallback callback, | 102 CreateCallback callback, |
101 const NativeProcessLauncher& launcher); | 103 scoped_ptr<NativeProcessLauncher> launcher); |
102 | 104 |
103 // TYPE_SEND_MESSAGE_REQUEST will be sent via the connection message in | 105 // TYPE_SEND_MESSAGE_REQUEST will be sent via the connection message in |
104 // NativeMessageProcessHost::Create, so only TYPE_CONNECT_MESSAGE is expected. | 106 // NativeMessageProcessHost::Create, so only TYPE_CONNECT_MESSAGE is expected. |
105 void Send(const std::string& json) { | 107 void Send(const std::string& json) { |
106 SendImpl(TYPE_CONNECT_MESSAGE, json); | 108 SendImpl(TYPE_CONNECT_MESSAGE, json); |
107 } | 109 } |
108 | 110 |
109 // Try and read a single message from |read_file_|. This should only be called | 111 // Try and read a single message from |read_file_|. This should only be called |
110 // in unittests when you know there is data in the file. | 112 // in unittests when you know there is data in the file. |
111 void ReadNowForTesting(); | 113 void ReadNowForTesting(); |
112 | 114 |
113 private: | 115 private: |
| 116 enum ReadState { |
| 117 READ_STATE_INVALID, |
| 118 READ_STATE_WAITING_FOR_META, |
| 119 READ_STATE_WAITING_FOR_MESSAGE |
| 120 }; |
| 121 |
| 122 struct NativeProcessHostCreationInformation { |
| 123 NativeProcessHostCreationInformation( |
| 124 base::WeakPtr<Client> weak_client_ui, |
| 125 std::string connection_message, |
| 126 int destination_port, |
| 127 MessageType type, |
| 128 CreateCallback callback, |
| 129 FileHandle read_handle, |
| 130 FileHandle write_handle, |
| 131 base::ProcessHandle native_process_handle) |
| 132 : weak_client_ui(weak_client_ui), |
| 133 connection_message(connection_message), |
| 134 destination_port(destination_port), |
| 135 type(type), |
| 136 callback(callback), |
| 137 read_handle(read_handle), |
| 138 write_handle(write_handle), |
| 139 native_process_handle(native_process_handle) |
| 140 {} |
| 141 |
| 142 base::WeakPtr<Client> weak_client_ui; |
| 143 std::string connection_message; |
| 144 int destination_port; |
| 145 MessageType type; |
| 146 CreateCallback callback; |
| 147 FileHandle read_handle; |
| 148 FileHandle write_handle; |
| 149 base::ProcessHandle native_process_handle; |
| 150 }; |
| 151 |
| 152 // Check that the app's path is within the proper directory on the FILE |
| 153 // thread. |
| 154 static void LaunchProcessOnFileThread( |
| 155 base::WeakPtr<Client> weak_client_ui, |
| 156 const std::string& native_app_name, |
| 157 const std::string& connection_message, |
| 158 int destination_port, |
| 159 MessageType type, |
| 160 CreateCallback callback, |
| 161 scoped_ptr<NativeProcessLauncher> launcher); |
| 162 |
| 163 // Finish the launching process. This will be run on the IO thread. |
| 164 static void FinalizeCreate( |
| 165 NativeProcessHostCreationInformation creation_info); |
| 166 |
114 NativeMessageProcessHost(base::WeakPtr<Client> weak_client_ui, | 167 NativeMessageProcessHost(base::WeakPtr<Client> weak_client_ui, |
115 int destination_port, | 168 int destination_port, |
116 base::ProcessHandle native_process_handle, | 169 base::ProcessHandle native_process_handle, |
117 FileHandle read_fd, | 170 FileHandle read_fd, |
118 FileHandle write_fd, | 171 FileHandle write_fd, |
119 bool is_send_message); | 172 bool is_send_message); |
120 | 173 |
121 // Initialize any IO watching that needs to occur between the native process. | 174 // Initialize any IO watching that needs to occur between the native process. |
122 void InitIO(); | 175 void InitIO(); |
123 | 176 |
| 177 // Stop any IO operations in progress. |
| 178 void StopIO(); |
| 179 |
124 // Send a message to the native process with the specified type and payload. | 180 // Send a message to the native process with the specified type and payload. |
125 void SendImpl(MessageType type, const std::string& json); | 181 void SendImpl(MessageType type, const std::string& json); |
126 | 182 |
127 // Write a message/data to the native process. | 183 // Write a message/data to the native process. |
128 bool WriteMessage(MessageType type, const std::string& message); | 184 bool WriteMessage(MessageType type, const std::string& message); |
129 bool WriteData(FileHandle file, const char* data, size_t bytes_to_write); | 185 bool WriteData(FileHandle file, const char* data, size_t bytes_to_write); |
130 | 186 |
131 // Read a message/data from the native process. | 187 // Parse and verify the meta data (type and length) for a message. |
132 bool ReadMessage(MessageType* type, std::string* messgae); | 188 bool VerifyMessageMetaData(const char* message_meta_data, |
133 bool ReadData(FileHandle file, char* data, size_t bytes_to_write); | 189 MessageType* type, |
| 190 uint32* message_length); |
134 | 191 |
135 #if defined(OS_POSIX) | 192 #if defined(OS_POSIX) |
| 193 // Read a message from the native process. |
| 194 bool ReadMessage(MessageType* type, std::string* message); |
| 195 |
136 // MessageLoopForIO::Watcher | 196 // MessageLoopForIO::Watcher |
137 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; | 197 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; |
138 // We don't need to watch for writes. | 198 // We don't need to watch for writes. |
139 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} | 199 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} |
140 | 200 |
141 MessageLoopForIO::FileDescriptorWatcher read_watcher_; | 201 MessageLoopForIO::FileDescriptorWatcher read_watcher_; |
142 #endif // defined(OS_POSIX) | 202 #elif defined(OS_WIN) |
143 | |
144 #if defined(OS_WIN) | |
145 // MessageLoopForIO::IOHandler | 203 // MessageLoopForIO::IOHandler |
146 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, | 204 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, |
147 DWORD bytes_transfered, | 205 DWORD bytes_transfered, |
148 DWORD error) OVERRIDE; | 206 DWORD error) OVERRIDE; |
149 | 207 |
150 MessageLoopForIO::IOContext read_context_; | 208 scoped_ptr<MessageLoopForIO::IOContext> read_context_; |
151 MessageLoopForIO::IOContext write_context_; | 209 scoped_ptr<MessageLoopForIO::IOContext> write_context_; |
152 #endif // defined(OS_WIN) | |
153 | 210 |
| 211 ReadState read_state; |
| 212 std::string pending_message_; |
| 213 char pending_message_meta_data_[8]; |
| 214 #endif // defined(OS_POSIX) |
154 | 215 |
155 // The Client messages will be posted to. Should only be accessed from the | 216 // The Client messages will be posted to. Should only be accessed from the |
156 // UI thread. | 217 // UI thread. |
157 base::WeakPtr<Client> weak_client_ui_; | 218 base::WeakPtr<Client> weak_client_ui_; |
158 | 219 |
159 // The id of the port on the other side of this connection. This is passed to | 220 // The id of the port on the other side of this connection. This is passed to |
160 // |weak_client_ui_| when posting messages. | 221 // |weak_client_ui_| when posting messages. |
161 int destination_port_; | 222 int destination_port_; |
162 | 223 |
| 224 // This may be base::kNullProcessHandle during tests. On posix, this is not a |
| 225 // problem. However, on windows this may crash certian calls like |
| 226 // base::GetTerminationStatus(). |
163 base::ProcessHandle native_process_handle_; | 227 base::ProcessHandle native_process_handle_; |
164 | 228 |
165 FileHandle read_file_; | 229 FileHandle read_file_; |
166 FileHandle write_file_; | 230 FileHandle write_file_; |
167 ScopedFileHandle scoped_read_file_; | 231 ScopedFileHandle scoped_read_file_; |
168 ScopedFileHandle scoped_write_file_; | 232 ScopedFileHandle scoped_write_file_; |
169 | 233 |
170 // Only looking for one response. | 234 // Only looking for one response. |
171 bool is_send_message_; | 235 bool is_send_message_; |
172 | 236 |
173 DISALLOW_COPY_AND_ASSIGN(NativeMessageProcessHost); | 237 DISALLOW_COPY_AND_ASSIGN(NativeMessageProcessHost); |
174 }; | 238 }; |
175 | 239 |
176 } // namespace extensions | 240 } // namespace extensions |
177 | 241 |
178 #endif // CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PROCESS_HOST_H
__ | 242 #endif // CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PROCESS_HOST_H
__ |
OLD | NEW |