Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: chrome/browser/extensions/api/messaging/native_message_process_host.cc

Issue 591463003: Remote Assistance on Chrome OS Part III - NativeMessageHost (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@native_messaging
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h" 5 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/process/kill.h" 10 #include "base/process/kill.h"
12 #include "base/threading/sequenced_worker_pool.h" 11 #include "base/threading/sequenced_worker_pool.h"
13 #include "base/values.h"
14 #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest .h" 12 #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest .h"
15 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" 13 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
16 #include "chrome/common/chrome_version_info.h" 14 #include "chrome/common/chrome_version_info.h"
17 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
18 #include "extensions/browser/pref_names.h"
19 #include "extensions/common/constants.h" 16 #include "extensions/common/constants.h"
20 #include "extensions/common/features/feature.h" 17 #include "extensions/common/features/feature.h"
21 #include "net/base/file_stream.h" 18 #include "net/base/file_stream.h"
22 #include "net/base/io_buffer.h" 19 #include "net/base/io_buffer.h"
23 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.h"
24 #include "net/base/net_util.h" 21 #include "net/base/net_util.h"
25 #include "url/gurl.h" 22 #include "url/gurl.h"
26 23
27 namespace { 24 namespace {
28 25
(...skipping 15 matching lines...) Expand all
44 const char kNotFoundError[] = "Specified native messaging host not found."; 41 const char kNotFoundError[] = "Specified native messaging host not found.";
45 const char kForbiddenError[] = 42 const char kForbiddenError[] =
46 "Access to the specified native messaging host is forbidden."; 43 "Access to the specified native messaging host is forbidden.";
47 const char kHostInputOuputError[] = 44 const char kHostInputOuputError[] =
48 "Error when communicating with the native messaging host."; 45 "Error when communicating with the native messaging host.";
49 46
50 } // namespace 47 } // namespace
51 48
52 namespace extensions { 49 namespace extensions {
53 50
54 // static
55 NativeMessageProcessHost::PolicyPermission
56 NativeMessageProcessHost::IsHostAllowed(const PrefService* pref_service,
57 const std::string& native_host_name) {
58 NativeMessageProcessHost::PolicyPermission allow_result = ALLOW_ALL;
59 if (pref_service->IsManagedPreference(
60 pref_names::kNativeMessagingUserLevelHosts)) {
61 if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts))
62 allow_result = ALLOW_SYSTEM_ONLY;
63 }
64
65 // All native messaging hosts are allowed if there is no blacklist.
66 if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlacklist))
67 return allow_result;
68 const base::ListValue* blacklist =
69 pref_service->GetList(pref_names::kNativeMessagingBlacklist);
70 if (!blacklist)
71 return allow_result;
72
73 // Check if the name or the wildcard is in the blacklist.
74 base::StringValue name_value(native_host_name);
75 base::StringValue wildcard_value("*");
76 if (blacklist->Find(name_value) == blacklist->end() &&
77 blacklist->Find(wildcard_value) == blacklist->end()) {
78 return allow_result;
79 }
80
81 // The native messaging host is blacklisted. Check the whitelist.
82 if (pref_service->IsManagedPreference(
83 pref_names::kNativeMessagingWhitelist)) {
84 const base::ListValue* whitelist =
85 pref_service->GetList(pref_names::kNativeMessagingWhitelist);
86 if (whitelist && whitelist->Find(name_value) != whitelist->end())
87 return allow_result;
88 }
89
90 return DISALLOW;
91 }
92
93 NativeMessageProcessHost::NativeMessageProcessHost( 51 NativeMessageProcessHost::NativeMessageProcessHost(
94 base::WeakPtr<Client> weak_client_ui,
95 const std::string& source_extension_id, 52 const std::string& source_extension_id,
96 const std::string& native_host_name, 53 const std::string& native_host_name,
97 int destination_port,
98 scoped_ptr<NativeProcessLauncher> launcher) 54 scoped_ptr<NativeProcessLauncher> launcher)
99 : weak_client_ui_(weak_client_ui), 55 : source_extension_id_(source_extension_id),
100 source_extension_id_(source_extension_id),
101 native_host_name_(native_host_name), 56 native_host_name_(native_host_name),
102 destination_port_(destination_port),
103 launcher_(launcher.Pass()), 57 launcher_(launcher.Pass()),
104 closed_(false), 58 closed_(false),
105 process_handle_(base::kNullProcessHandle), 59 process_handle_(base::kNullProcessHandle),
106 #if defined(OS_POSIX) 60 #if defined(OS_POSIX)
107 read_file_(-1), 61 read_file_(-1),
108 #endif 62 #endif
109 read_pending_(false), 63 read_pending_(false),
110 write_pending_(false) { 64 write_pending_(false) {
111 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 65 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
112 66
67 task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
68 content::BrowserThread::IO);
113 // It's safe to use base::Unretained() here because NativeMessagePort always 69 // It's safe to use base::Unretained() here because NativeMessagePort always
114 // deletes us on the IO thread. 70 // deletes us on the IO thread.
115 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, 71 task_runner_->PostTask(
72 FROM_HERE,
116 base::Bind(&NativeMessageProcessHost::LaunchHostProcess, 73 base::Bind(&NativeMessageProcessHost::LaunchHostProcess,
117 base::Unretained(this))); 74 base::Unretained(this)));
118 } 75 }
119 76
120 NativeMessageProcessHost::~NativeMessageProcessHost() { 77 NativeMessageProcessHost::~NativeMessageProcessHost() {
121 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 78 DCHECK(task_runner_->BelongsToCurrentThread());
122 Close(std::string()); 79 Close(std::string());
123 } 80 }
124 81
125 // static 82 // static
126 scoped_ptr<NativeMessageProcessHost> NativeMessageProcessHost::Create( 83 scoped_ptr<NativeMessageHost> NativeMessageHost::Create(
127 gfx::NativeView native_view, 84 gfx::NativeView native_view,
128 base::WeakPtr<Client> weak_client_ui,
129 const std::string& source_extension_id, 85 const std::string& source_extension_id,
130 const std::string& native_host_name, 86 const std::string& native_host_name,
131 int destination_port,
132 bool allow_user_level) { 87 bool allow_user_level) {
133 return CreateWithLauncher(weak_client_ui, source_extension_id, 88 return NativeMessageProcessHost::CreateWithLauncher(
134 native_host_name, destination_port, 89 source_extension_id,
135 NativeProcessLauncher::CreateDefault( 90 native_host_name,
136 allow_user_level, native_view)); 91 NativeProcessLauncher::CreateDefault(allow_user_level, native_view));
137 } 92 }
138 93
139 // static 94 // static
140 scoped_ptr<NativeMessageProcessHost> 95 scoped_ptr<NativeMessageHost> NativeMessageProcessHost::CreateWithLauncher(
141 NativeMessageProcessHost::CreateWithLauncher(
142 base::WeakPtr<Client> weak_client_ui,
143 const std::string& source_extension_id, 96 const std::string& source_extension_id,
144 const std::string& native_host_name, 97 const std::string& native_host_name,
145 int destination_port,
146 scoped_ptr<NativeProcessLauncher> launcher) { 98 scoped_ptr<NativeProcessLauncher> launcher) {
147 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 99 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
148 100
149 scoped_ptr<NativeMessageProcessHost> process(new NativeMessageProcessHost( 101 scoped_ptr<NativeMessageHost> process(
150 weak_client_ui, source_extension_id, native_host_name, 102 new NativeMessageProcessHost(source_extension_id,
151 destination_port, launcher.Pass())); 103 native_host_name,
104 launcher.Pass()));
152 105
153 return process.Pass(); 106 return process.Pass();
154 } 107 }
155 108
156 void NativeMessageProcessHost::LaunchHostProcess() { 109 void NativeMessageProcessHost::LaunchHostProcess() {
157 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 110 DCHECK(task_runner_->BelongsToCurrentThread());
158 111
159 GURL origin(std::string(kExtensionScheme) + "://" + source_extension_id_); 112 GURL origin(std::string(kExtensionScheme) + "://" + source_extension_id_);
160 launcher_->Launch(origin, native_host_name_, 113 launcher_->Launch(origin, native_host_name_,
161 base::Bind(&NativeMessageProcessHost::OnHostProcessLaunched, 114 base::Bind(&NativeMessageProcessHost::OnHostProcessLaunched,
162 base::Unretained(this))); 115 base::Unretained(this)));
163 } 116 }
164 117
165 void NativeMessageProcessHost::OnHostProcessLaunched( 118 void NativeMessageProcessHost::OnHostProcessLaunched(
166 NativeProcessLauncher::LaunchResult result, 119 NativeProcessLauncher::LaunchResult result,
167 base::ProcessHandle process_handle, 120 base::ProcessHandle process_handle,
168 base::File read_file, 121 base::File read_file,
169 base::File write_file) { 122 base::File write_file) {
170 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 123 DCHECK(task_runner_->BelongsToCurrentThread());
171 124
172 switch (result) { 125 switch (result) {
173 case NativeProcessLauncher::RESULT_INVALID_NAME: 126 case NativeProcessLauncher::RESULT_INVALID_NAME:
174 Close(kInvalidNameError); 127 Close(kInvalidNameError);
175 return; 128 return;
176 case NativeProcessLauncher::RESULT_NOT_FOUND: 129 case NativeProcessLauncher::RESULT_NOT_FOUND:
177 Close(kNotFoundError); 130 Close(kNotFoundError);
178 return; 131 return;
179 case NativeProcessLauncher::RESULT_FORBIDDEN: 132 case NativeProcessLauncher::RESULT_FORBIDDEN:
180 Close(kForbiddenError); 133 Close(kForbiddenError);
(...skipping 16 matching lines...) Expand all
197 GetTaskRunnerWithShutdownBehavior( 150 GetTaskRunnerWithShutdownBehavior(
198 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); 151 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
199 152
200 read_stream_.reset(new net::FileStream(read_file.Pass(), task_runner)); 153 read_stream_.reset(new net::FileStream(read_file.Pass(), task_runner));
201 write_stream_.reset(new net::FileStream(write_file.Pass(), task_runner)); 154 write_stream_.reset(new net::FileStream(write_file.Pass(), task_runner));
202 155
203 WaitRead(); 156 WaitRead();
204 DoWrite(); 157 DoWrite();
205 } 158 }
206 159
207 void NativeMessageProcessHost::Send(const std::string& json) { 160 void NativeMessageProcessHost::OnMessage(const std::string& json) {
208 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 161 DCHECK(task_runner_->BelongsToCurrentThread());
209 162
210 if (closed_) 163 if (closed_)
211 return; 164 return;
212 165
213 // Allocate new buffer for the message. 166 // Allocate new buffer for the message.
214 scoped_refptr<net::IOBufferWithSize> buffer = 167 scoped_refptr<net::IOBufferWithSize> buffer =
215 new net::IOBufferWithSize(json.size() + kMessageHeaderSize); 168 new net::IOBufferWithSize(json.size() + kMessageHeaderSize);
216 169
217 // Copy size and content of the message to the buffer. 170 // Copy size and content of the message to the buffer.
218 COMPILE_ASSERT(sizeof(uint32) == kMessageHeaderSize, incorrect_header_size); 171 COMPILE_ASSERT(sizeof(uint32) == kMessageHeaderSize, incorrect_header_size);
219 *reinterpret_cast<uint32*>(buffer->data()) = json.size(); 172 *reinterpret_cast<uint32*>(buffer->data()) = json.size();
220 memcpy(buffer->data() + kMessageHeaderSize, json.data(), json.size()); 173 memcpy(buffer->data() + kMessageHeaderSize, json.data(), json.size());
221 174
222 // Push new message to the write queue. 175 // Push new message to the write queue.
223 write_queue_.push(buffer); 176 write_queue_.push(buffer);
224 177
225 // Send() may be called before the host process is started. In that case the 178 // Send() may be called before the host process is started. In that case the
226 // message will be written when OnHostProcessLaunched() is called. If it's 179 // message will be written when OnHostProcessLaunched() is called. If it's
227 // already started then write the message now. 180 // already started then write the message now.
228 if (write_stream_) 181 if (write_stream_)
229 DoWrite(); 182 DoWrite();
230 } 183 }
231 184
185 void NativeMessageProcessHost::set_client(base::WeakPtr<Client> client) {
186 weak_client_ = client;
187 }
188
189 scoped_refptr<base::SingleThreadTaskRunner>
190 NativeMessageProcessHost::task_runner() const {
191 return task_runner_;
192 }
193
232 #if defined(OS_POSIX) 194 #if defined(OS_POSIX)
233 void NativeMessageProcessHost::OnFileCanReadWithoutBlocking(int fd) { 195 void NativeMessageProcessHost::OnFileCanReadWithoutBlocking(int fd) {
234 DCHECK_EQ(fd, read_file_); 196 DCHECK_EQ(fd, read_file_);
235 DoRead(); 197 DoRead();
236 } 198 }
237 199
238 void NativeMessageProcessHost::OnFileCanWriteWithoutBlocking(int fd) { 200 void NativeMessageProcessHost::OnFileCanWriteWithoutBlocking(int fd) {
239 NOTREACHED(); 201 NOTREACHED();
240 } 202 }
241 #endif // !defined(OS_POSIX) 203 #endif // !defined(OS_POSIX)
(...skipping 15 matching lines...) Expand all
257 #if defined(OS_POSIX) 219 #if defined(OS_POSIX)
258 base::MessageLoopForIO::current()->WatchFileDescriptor( 220 base::MessageLoopForIO::current()->WatchFileDescriptor(
259 read_file_, false /* persistent */, 221 read_file_, false /* persistent */,
260 base::MessageLoopForIO::WATCH_READ, &read_watcher_, this); 222 base::MessageLoopForIO::WATCH_READ, &read_watcher_, this);
261 #else // defined(OS_POSIX) 223 #else // defined(OS_POSIX)
262 DoRead(); 224 DoRead();
263 #endif // defined(!OS_POSIX) 225 #endif // defined(!OS_POSIX)
264 } 226 }
265 227
266 void NativeMessageProcessHost::DoRead() { 228 void NativeMessageProcessHost::DoRead() {
267 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 229 DCHECK(task_runner_->BelongsToCurrentThread());
268 230
269 while (!closed_ && !read_pending_) { 231 while (!closed_ && !read_pending_) {
270 read_buffer_ = new net::IOBuffer(kReadBufferSize); 232 read_buffer_ = new net::IOBuffer(kReadBufferSize);
271 int result = read_stream_->Read( 233 int result = read_stream_->Read(
272 read_buffer_.get(), 234 read_buffer_.get(),
273 kReadBufferSize, 235 kReadBufferSize,
274 base::Bind(&NativeMessageProcessHost::OnRead, base::Unretained(this))); 236 base::Bind(&NativeMessageProcessHost::OnRead, base::Unretained(this)));
275 HandleReadResult(result); 237 HandleReadResult(result);
276 } 238 }
277 } 239 }
278 240
279 void NativeMessageProcessHost::OnRead(int result) { 241 void NativeMessageProcessHost::OnRead(int result) {
280 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 242 DCHECK(task_runner_->BelongsToCurrentThread());
281 DCHECK(read_pending_); 243 DCHECK(read_pending_);
282 read_pending_ = false; 244 read_pending_ = false;
283 245
284 HandleReadResult(result); 246 HandleReadResult(result);
285 WaitRead(); 247 WaitRead();
286 } 248 }
287 249
288 void NativeMessageProcessHost::HandleReadResult(int result) { 250 void NativeMessageProcessHost::HandleReadResult(int result) {
289 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 251 DCHECK(task_runner_->BelongsToCurrentThread());
290 252
291 if (closed_) 253 if (closed_)
292 return; 254 return;
293 255
294 if (result > 0) { 256 if (result > 0) {
295 ProcessIncomingData(read_buffer_->data(), result); 257 ProcessIncomingData(read_buffer_->data(), result);
296 } else if (result == net::ERR_IO_PENDING) { 258 } else if (result == net::ERR_IO_PENDING) {
297 read_pending_ = true; 259 read_pending_ = true;
298 } else if (result == 0 || result == net::ERR_CONNECTION_RESET) { 260 } else if (result == 0 || result == net::ERR_CONNECTION_RESET) {
299 // On Windows we get net::ERR_CONNECTION_RESET for a broken pipe, while on 261 // On Windows we get net::ERR_CONNECTION_RESET for a broken pipe, while on
300 // Posix read() returns 0 in that case. 262 // Posix read() returns 0 in that case.
301 Close(kNativeHostExited); 263 Close(kNativeHostExited);
302 } else { 264 } else {
303 LOG(ERROR) << "Error when reading from Native Messaging host: " << result; 265 LOG(ERROR) << "Error when reading from Native Messaging host: " << result;
304 Close(kHostInputOuputError); 266 Close(kHostInputOuputError);
305 } 267 }
306 } 268 }
307 269
308 void NativeMessageProcessHost::ProcessIncomingData( 270 void NativeMessageProcessHost::ProcessIncomingData(
309 const char* data, int data_size) { 271 const char* data, int data_size) {
310 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 272 DCHECK(task_runner_->BelongsToCurrentThread());
311 273
312 incoming_data_.append(data, data_size); 274 incoming_data_.append(data, data_size);
313 275
314 while (true) { 276 while (true) {
315 if (incoming_data_.size() < kMessageHeaderSize) 277 if (incoming_data_.size() < kMessageHeaderSize)
316 return; 278 return;
317 279
318 size_t message_size = 280 size_t message_size =
319 *reinterpret_cast<const uint32*>(incoming_data_.data()); 281 *reinterpret_cast<const uint32*>(incoming_data_.data());
320 282
321 if (message_size > kMaximumMessageSize) { 283 if (message_size > kMaximumMessageSize) {
322 LOG(ERROR) << "Native Messaging host tried sending a message that is " 284 LOG(ERROR) << "Native Messaging host tried sending a message that is "
323 << message_size << " bytes long."; 285 << message_size << " bytes long.";
324 Close(kHostInputOuputError); 286 Close(kHostInputOuputError);
325 return; 287 return;
326 } 288 }
327 289
328 if (incoming_data_.size() < message_size + kMessageHeaderSize) 290 if (incoming_data_.size() < message_size + kMessageHeaderSize)
329 return; 291 return;
330 292
331 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 293 content::BrowserThread::PostTask(
Sergey Ulanov 2014/09/30 20:33:39 Since it's NativeMessagingHost's responsibility to
kelvinp 2014/10/01 06:08:02 Done.
332 base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_, 294 content::BrowserThread::UI,
333 destination_port_, 295 FROM_HERE,
334 incoming_data_.substr(kMessageHeaderSize, message_size))); 296 base::Bind(&Client::PostMessageFromNativeHost,
297 weak_client_,
298 incoming_data_.substr(kMessageHeaderSize, message_size)));
335 299
336 incoming_data_.erase(0, kMessageHeaderSize + message_size); 300 incoming_data_.erase(0, kMessageHeaderSize + message_size);
337 } 301 }
338 } 302 }
339 303
340 void NativeMessageProcessHost::DoWrite() { 304 void NativeMessageProcessHost::DoWrite() {
341 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 305 DCHECK(task_runner_->BelongsToCurrentThread());
342 306
343 while (!write_pending_ && !closed_) { 307 while (!write_pending_ && !closed_) {
344 if (!current_write_buffer_.get() || 308 if (!current_write_buffer_.get() ||
345 !current_write_buffer_->BytesRemaining()) { 309 !current_write_buffer_->BytesRemaining()) {
346 if (write_queue_.empty()) 310 if (write_queue_.empty())
347 return; 311 return;
348 current_write_buffer_ = new net::DrainableIOBuffer( 312 current_write_buffer_ = new net::DrainableIOBuffer(
349 write_queue_.front().get(), write_queue_.front()->size()); 313 write_queue_.front().get(), write_queue_.front()->size());
350 write_queue_.pop(); 314 write_queue_.pop();
351 } 315 }
352 316
353 int result = 317 int result =
354 write_stream_->Write(current_write_buffer_.get(), 318 write_stream_->Write(current_write_buffer_.get(),
355 current_write_buffer_->BytesRemaining(), 319 current_write_buffer_->BytesRemaining(),
356 base::Bind(&NativeMessageProcessHost::OnWritten, 320 base::Bind(&NativeMessageProcessHost::OnWritten,
357 base::Unretained(this))); 321 base::Unretained(this)));
358 HandleWriteResult(result); 322 HandleWriteResult(result);
359 } 323 }
360 } 324 }
361 325
362 void NativeMessageProcessHost::HandleWriteResult(int result) { 326 void NativeMessageProcessHost::HandleWriteResult(int result) {
363 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 327 DCHECK(task_runner_->BelongsToCurrentThread());
364 328
365 if (result <= 0) { 329 if (result <= 0) {
366 if (result == net::ERR_IO_PENDING) { 330 if (result == net::ERR_IO_PENDING) {
367 write_pending_ = true; 331 write_pending_ = true;
368 } else { 332 } else {
369 LOG(ERROR) << "Error when writing to Native Messaging host: " << result; 333 LOG(ERROR) << "Error when writing to Native Messaging host: " << result;
370 Close(kHostInputOuputError); 334 Close(kHostInputOuputError);
371 } 335 }
372 return; 336 return;
373 } 337 }
374 338
375 current_write_buffer_->DidConsume(result); 339 current_write_buffer_->DidConsume(result);
376 } 340 }
377 341
378 void NativeMessageProcessHost::OnWritten(int result) { 342 void NativeMessageProcessHost::OnWritten(int result) {
379 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 343 DCHECK(task_runner_->BelongsToCurrentThread());
380 344
381 DCHECK(write_pending_); 345 DCHECK(write_pending_);
382 write_pending_ = false; 346 write_pending_ = false;
383 347
384 HandleWriteResult(result); 348 HandleWriteResult(result);
385 DoWrite(); 349 DoWrite();
386 } 350 }
387 351
388 void NativeMessageProcessHost::Close(const std::string& error_message) { 352 void NativeMessageProcessHost::Close(const std::string& error_message) {
389 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 353 DCHECK(task_runner_->BelongsToCurrentThread());
390 354
391 if (!closed_) { 355 if (!closed_) {
392 closed_ = true; 356 closed_ = true;
393 read_stream_.reset(); 357 read_stream_.reset();
394 write_stream_.reset(); 358 write_stream_.reset();
395 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 359 content::BrowserThread::PostTask(
396 base::Bind(&Client::CloseChannel, weak_client_ui_, 360 content::BrowserThread::UI,
397 destination_port_, error_message)); 361 FROM_HERE,
362 base::Bind(&Client::CloseChannel, weak_client_, error_message));
398 } 363 }
399 364
400 if (process_handle_ != base::kNullProcessHandle) { 365 if (process_handle_ != base::kNullProcessHandle) {
401 // Kill the host process if necessary to make sure we don't leave zombies. 366 // Kill the host process if necessary to make sure we don't leave zombies.
402 // On OSX base::EnsureProcessTerminated() may block, so we have to post a 367 // On OSX base::EnsureProcessTerminated() may block, so we have to post a
403 // task on the blocking pool. 368 // task on the blocking pool.
404 #if defined(OS_MACOSX) 369 #if defined(OS_MACOSX)
405 content::BrowserThread::PostBlockingPoolTask( 370 content::BrowserThread::PostBlockingPoolTask(
406 FROM_HERE, base::Bind(&base::EnsureProcessTerminated, process_handle_)); 371 FROM_HERE, base::Bind(&base::EnsureProcessTerminated, process_handle_));
407 #else 372 #else
408 base::EnsureProcessTerminated(process_handle_); 373 base::EnsureProcessTerminated(process_handle_);
409 #endif 374 #endif
410 process_handle_ = base::kNullProcessHandle; 375 process_handle_ = base::kNullProcessHandle;
411 } 376 }
412 } 377 }
413 378
414 } // namespace extensions 379 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698