Chromium Code Reviews| 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 |