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 #include "chrome/browser/nacl_host/nacl_process_host.h" | 5 #include "chrome/browser/nacl_host/nacl_process_host.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 28 matching lines...) Expand all Loading... | |
39 #include "base/threading/thread.h" | 39 #include "base/threading/thread.h" |
40 #include "base/process_util.h" | 40 #include "base/process_util.h" |
41 #include "chrome/browser/nacl_host/nacl_broker_service_win.h" | 41 #include "chrome/browser/nacl_host/nacl_broker_service_win.h" |
42 #include "native_client/src/trusted/service_runtime/win/debug_exception_handler. h" | 42 #include "native_client/src/trusted/service_runtime/win/debug_exception_handler. h" |
43 #endif | 43 #endif |
44 | 44 |
45 using content::BrowserThread; | 45 using content::BrowserThread; |
46 using content::ChildProcessData; | 46 using content::ChildProcessData; |
47 using content::ChildProcessHost; | 47 using content::ChildProcessHost; |
48 | 48 |
49 static const char dummy[1<<16]="1"; | |
Mark Seaborn
2012/03/21 20:41:29
Left in by mistake?
halyavin
2012/03/22 08:35:47
Sorry, I was doing an experiment in this working c
| |
50 | |
49 #if defined(OS_WIN) | 51 #if defined(OS_WIN) |
50 class NaClProcessHost::DebugContext | 52 class NaClProcessHost::DebugContext |
51 : public base::RefCountedThreadSafe<NaClProcessHost::DebugContext> { | 53 : public base::RefCountedThreadSafe<NaClProcessHost::DebugContext> { |
52 public: | 54 public: |
53 DebugContext() | 55 DebugContext() |
54 : can_send_start_msg_(false), | 56 : can_send_start_msg_(false), |
55 child_process_host_(NULL) { | 57 child_process_host_(NULL) { |
56 } | 58 } |
57 | 59 |
58 ~DebugContext() { | 60 ~DebugContext() { |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
228 }; | 230 }; |
229 | 231 |
230 #if defined(OS_WIN) | 232 #if defined(OS_WIN) |
231 static bool RunningOnWOW64() { | 233 static bool RunningOnWOW64() { |
232 return (base::win::OSInfo::GetInstance()->wow64_status() == | 234 return (base::win::OSInfo::GetInstance()->wow64_status() == |
233 base::win::OSInfo::WOW64_ENABLED); | 235 base::win::OSInfo::WOW64_ENABLED); |
234 } | 236 } |
235 #endif | 237 #endif |
236 | 238 |
237 NaClProcessHost::NaClProcessHost(const std::wstring& url) | 239 NaClProcessHost::NaClProcessHost(const std::wstring& url) |
238 : reply_msg_(NULL), | 240 : |
241 #if defined(OS_WIN) | |
242 process_launched_by_broker_(false), | |
243 #endif | |
244 reply_msg_(NULL), | |
239 internal_(new NaClInternal()), | 245 internal_(new NaClInternal()), |
240 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 246 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
241 process_.reset(content::BrowserChildProcessHost::Create( | 247 process_.reset(content::BrowserChildProcessHost::Create( |
242 content::PROCESS_TYPE_NACL_LOADER, this)); | 248 content::PROCESS_TYPE_NACL_LOADER, this)); |
243 process_->SetName(WideToUTF16Hack(url)); | 249 process_->SetName(WideToUTF16Hack(url)); |
244 #if defined(OS_WIN) | 250 #if defined(OS_WIN) |
245 if (!RunningOnWOW64()) { | 251 if (!RunningOnWOW64()) { |
246 debug_context_ = new DebugContext(); | 252 debug_context_ = new DebugContext(); |
247 } | 253 } |
248 #endif | 254 #endif |
(...skipping 16 matching lines...) Expand all Loading... | |
265 LOG(ERROR) << "nacl::Close() failed"; | 271 LOG(ERROR) << "nacl::Close() failed"; |
266 } | 272 } |
267 } | 273 } |
268 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { | 274 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { |
269 if (nacl::Close(internal_->sockets_for_sel_ldr[i]) != 0) { | 275 if (nacl::Close(internal_->sockets_for_sel_ldr[i]) != 0) { |
270 LOG(ERROR) << "nacl::Close() failed"; | 276 LOG(ERROR) << "nacl::Close() failed"; |
271 } | 277 } |
272 } | 278 } |
273 | 279 |
274 if (reply_msg_) { | 280 if (reply_msg_) { |
275 // The process failed to launch for some reason. | 281 SendNaClLaunchError(); |
276 // Don't keep the renderer hanging. | |
277 reply_msg_->set_reply_error(); | |
278 chrome_render_message_filter_->Send(reply_msg_); | |
279 } | 282 } |
280 #if defined(OS_WIN) | 283 #if defined(OS_WIN) |
281 if (RunningOnWOW64()) { | 284 if (process_launched_by_broker_) { |
282 // If the nacl-gdb switch is not empty, the NaCl loader has been launched | 285 NaClBrokerService::GetInstance()->OnLoaderDied(); |
283 // without the broker and so we shouldn't inform the broker about | 286 } |
284 // the loader termination. | 287 if (!RunningOnWOW64()) { |
Mark Seaborn
2012/03/21 20:41:29
On merging with HEAD this becomes "if (debug_conte
halyavin
2012/03/22 08:35:47
Done.
| |
285 if (CommandLine::ForCurrentProcess()->GetSwitchValuePath( | |
286 switches::kNaClGdb).empty()) { | |
287 NaClBrokerService::GetInstance()->OnLoaderDied(); | |
288 } | |
289 } else { | |
290 debug_context_->SetChildProcessHost(NULL); | 288 debug_context_->SetChildProcessHost(NULL); |
291 } | 289 } |
292 #endif | 290 #endif |
293 } | 291 } |
294 | 292 |
295 // Attempt to ensure the IRT will be available when we need it, but don't wait. | 293 // Attempt to ensure the IRT will be available when we need it, but don't wait. |
296 bool NaClBrowser::EnsureIrtAvailable() { | 294 bool NaClBrowser::EnsureIrtAvailable() { |
297 if (IrtAvailable()) | 295 if (IrtAvailable()) |
298 return true; | 296 return true; |
299 | 297 |
(...skipping 13 matching lines...) Expand all Loading... | |
313 // This is called at browser startup. | 311 // This is called at browser startup. |
314 // static | 312 // static |
315 void NaClProcessHost::EarlyStartup() { | 313 void NaClProcessHost::EarlyStartup() { |
316 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 314 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
317 // Open the IRT file early to make sure that it isn't replaced out from | 315 // Open the IRT file early to make sure that it isn't replaced out from |
318 // under us by autoupdate. | 316 // under us by autoupdate. |
319 NaClBrowser::GetInstance()->EnsureIrtAvailable(); | 317 NaClBrowser::GetInstance()->EnsureIrtAvailable(); |
320 #endif | 318 #endif |
321 } | 319 } |
322 | 320 |
323 bool NaClProcessHost::Launch( | 321 void NaClProcessHost::SendNaClLaunchError() { |
Mark Seaborn
2012/03/21 20:41:29
This method only has one call site, doesn't it? Y
halyavin
2012/03/22 08:35:47
Done.
| |
322 // The process failed to launch for some reason. | |
323 // Don't keep the renderer hanging. | |
324 reply_msg_->set_reply_error(); | |
325 chrome_render_message_filter_->Send(reply_msg_); | |
326 reply_msg_ = NULL; | |
327 chrome_render_message_filter_ = NULL; | |
328 } | |
329 | |
330 void NaClProcessHost::Launch( | |
324 ChromeRenderMessageFilter* chrome_render_message_filter, | 331 ChromeRenderMessageFilter* chrome_render_message_filter, |
325 int socket_count, | 332 int socket_count, |
326 IPC::Message* reply_msg) { | 333 IPC::Message* reply_msg) { |
334 chrome_render_message_filter_ = chrome_render_message_filter; | |
335 reply_msg_ = reply_msg; | |
336 | |
327 // Place an arbitrary limit on the number of sockets to limit | 337 // Place an arbitrary limit on the number of sockets to limit |
328 // exposure in case the renderer is compromised. We can increase | 338 // exposure in case the renderer is compromised. We can increase |
329 // this if necessary. | 339 // this if necessary. |
330 if (socket_count > 8) { | 340 if (socket_count > 8) { |
331 return false; | 341 delete this; |
342 return; | |
332 } | 343 } |
333 | 344 |
334 // Start getting the IRT open asynchronously while we launch the NaCl process. | 345 // Start getting the IRT open asynchronously while we launch the NaCl process. |
335 // We'll make sure this actually finished in OnProcessLaunched, below. | 346 // We'll make sure this actually finished in OnProcessLaunched, below. |
336 if (!NaClBrowser::GetInstance()->EnsureIrtAvailable()) { | 347 if (!NaClBrowser::GetInstance()->EnsureIrtAvailable()) { |
337 LOG(ERROR) << "Cannot launch NaCl process after IRT file open failed"; | 348 LOG(ERROR) << "Cannot launch NaCl process after IRT file open failed"; |
338 return false; | 349 delete this; |
350 return; | |
339 } | 351 } |
340 | 352 |
341 // Rather than creating a socket pair in the renderer, and passing | 353 // Rather than creating a socket pair in the renderer, and passing |
342 // one side through the browser to sel_ldr, socket pairs are created | 354 // one side through the browser to sel_ldr, socket pairs are created |
343 // in the browser and then passed to the renderer and sel_ldr. | 355 // in the browser and then passed to the renderer and sel_ldr. |
344 // | 356 // |
345 // This is mainly for the benefit of Windows, where sockets cannot | 357 // This is mainly for the benefit of Windows, where sockets cannot |
346 // be passed in messages, but are copied via DuplicateHandle(). | 358 // be passed in messages, but are copied via DuplicateHandle(). |
347 // This means the sandboxed renderer cannot send handles to the | 359 // This means the sandboxed renderer cannot send handles to the |
348 // browser process. | 360 // browser process. |
349 | 361 |
350 for (int i = 0; i < socket_count; i++) { | 362 for (int i = 0; i < socket_count; i++) { |
351 nacl::Handle pair[2]; | 363 nacl::Handle pair[2]; |
352 // Create a connected socket | 364 // Create a connected socket |
353 if (nacl::SocketPair(pair) == -1) | 365 if (nacl::SocketPair(pair) == -1) { |
354 return false; | 366 delete this; |
367 return; | |
368 } | |
355 internal_->sockets_for_renderer.push_back(pair[0]); | 369 internal_->sockets_for_renderer.push_back(pair[0]); |
356 internal_->sockets_for_sel_ldr.push_back(pair[1]); | 370 internal_->sockets_for_sel_ldr.push_back(pair[1]); |
357 SetCloseOnExec(pair[0]); | 371 SetCloseOnExec(pair[0]); |
358 SetCloseOnExec(pair[1]); | 372 SetCloseOnExec(pair[1]); |
359 } | 373 } |
360 | 374 |
361 // Launch the process | 375 // Launch the process |
362 if (!LaunchSelLdr()) { | 376 if (!LaunchSelLdr()) { |
363 return false; | 377 delete this; |
364 } | 378 } |
365 | |
366 chrome_render_message_filter_ = chrome_render_message_filter; | |
367 | |
368 // On success, we take responsibility for sending the reply. | |
369 reply_msg_ = reply_msg; | |
370 return true; | |
371 } | 379 } |
372 | 380 |
373 scoped_ptr<CommandLine> NaClProcessHost::LaunchWithNaClGdb( | 381 scoped_ptr<CommandLine> NaClProcessHost::LaunchWithNaClGdb( |
374 const FilePath& nacl_gdb, CommandLine* line) { | 382 const FilePath& nacl_gdb, CommandLine* line) { |
375 CommandLine* cmd_line = new CommandLine(nacl_gdb); | 383 CommandLine* cmd_line = new CommandLine(nacl_gdb); |
376 // We can't use PrependWrapper because our parameters contain spaces. | 384 // We can't use PrependWrapper because our parameters contain spaces. |
377 cmd_line->AppendArg("--eval-command"); | 385 cmd_line->AppendArg("--eval-command"); |
378 const FilePath::StringType& irt_path = | 386 const FilePath::StringType& irt_path = |
379 NaClBrowser::GetInstance()->GetIrtFilePath().value(); | 387 NaClBrowser::GetInstance()->GetIrtFilePath().value(); |
380 cmd_line->AppendArgNative(FILE_PATH_LITERAL("nacl-irt ") + irt_path); | 388 cmd_line->AppendArgNative(FILE_PATH_LITERAL("nacl-irt ") + irt_path); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 #elif defined(OS_POSIX) | 476 #elif defined(OS_POSIX) |
469 process_->Launch(nacl_loader_prefix.empty(), // use_zygote | 477 process_->Launch(nacl_loader_prefix.empty(), // use_zygote |
470 base::EnvironmentVector(), | 478 base::EnvironmentVector(), |
471 cmd_line.release()); | 479 cmd_line.release()); |
472 #endif | 480 #endif |
473 | 481 |
474 return true; | 482 return true; |
475 } | 483 } |
476 | 484 |
477 void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) { | 485 void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) { |
486 #if defined(OS_WIN) | |
487 process_launched_by_broker_ = true; | |
488 #endif | |
478 process_->SetHandle(handle); | 489 process_->SetHandle(handle); |
479 OnProcessLaunched(); | 490 OnProcessLaunched(); |
480 } | 491 } |
481 | 492 |
482 void NaClProcessHost::OnProcessCrashed(int exit_code) { | 493 void NaClProcessHost::OnProcessCrashed(int exit_code) { |
483 std::string message = base::StringPrintf( | 494 std::string message = base::StringPrintf( |
484 "NaCl process exited with status %i (0x%x)", exit_code, exit_code); | 495 "NaCl process exited with status %i (0x%x)", exit_code, exit_code); |
485 LOG(ERROR) << message; | 496 LOG(ERROR) << message; |
486 } | 497 } |
487 | 498 |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
802 process_->Send(new NaClProcessMsg_Start(handles_for_sel_ldr)); | 813 process_->Send(new NaClProcessMsg_Start(handles_for_sel_ldr)); |
803 #endif | 814 #endif |
804 | 815 |
805 internal_->sockets_for_sel_ldr.clear(); | 816 internal_->sockets_for_sel_ldr.clear(); |
806 } | 817 } |
807 | 818 |
808 bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { | 819 bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { |
809 NOTREACHED() << "Invalid message with type = " << msg.type(); | 820 NOTREACHED() << "Invalid message with type = " << msg.type(); |
810 return false; | 821 return false; |
811 } | 822 } |
OLD | NEW |