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 "components/nacl/browser/nacl_process_host.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/base_switches.h" | 11 #include "base/base_switches.h" |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
17 #include "base/path_service.h" | 17 #include "base/path_service.h" |
18 #include "base/process/launch.h" | 18 #include "base/process/launch.h" |
19 #include "base/process/process_iterator.h" | 19 #include "base/process/process_iterator.h" |
20 #include "base/rand_util.h" | 20 #include "base/rand_util.h" |
21 #include "base/strings/string_number_conversions.h" | 21 #include "base/strings/string_number_conversions.h" |
22 #include "base/strings/string_split.h" | 22 #include "base/strings/string_split.h" |
23 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
24 #include "base/strings/stringprintf.h" | 24 #include "base/strings/stringprintf.h" |
25 #include "base/strings/utf_string_conversions.h" | 25 #include "base/strings/utf_string_conversions.h" |
26 #include "base/win/windows_version.h" | 26 #include "base/win/windows_version.h" |
27 #include "build/build_config.h" | 27 #include "build/build_config.h" |
28 #include "chrome/browser/nacl_host/nacl_host_message_filter.h" | |
29 #include "chrome/common/chrome_switches.h" | |
30 #include "components/nacl/browser/nacl_browser.h" | 28 #include "components/nacl/browser/nacl_browser.h" |
29 #include "components/nacl/browser/nacl_host_message_filter.h" | |
31 #include "components/nacl/common/nacl_cmd_line.h" | 30 #include "components/nacl/common/nacl_cmd_line.h" |
32 #include "components/nacl/common/nacl_host_messages.h" | 31 #include "components/nacl/common/nacl_host_messages.h" |
33 #include "components/nacl/common/nacl_messages.h" | 32 #include "components/nacl/common/nacl_messages.h" |
34 #include "components/nacl/common/nacl_process_type.h" | 33 #include "components/nacl/common/nacl_process_type.h" |
35 #include "components/nacl/common/nacl_switches.h" | 34 #include "components/nacl/common/nacl_switches.h" |
36 #include "content/public/browser/browser_child_process_host.h" | 35 #include "content/public/browser/browser_child_process_host.h" |
37 #include "content/public/browser/browser_ppapi_host.h" | 36 #include "content/public/browser/browser_ppapi_host.h" |
38 #include "content/public/browser/child_process_data.h" | 37 #include "content/public/browser/child_process_data.h" |
39 #include "content/public/common/child_process_host.h" | 38 #include "content/public/common/child_process_host.h" |
40 #include "content/public/common/content_switches.h" | 39 #include "content/public/common/content_switches.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
51 | 50 |
52 #if defined(OS_POSIX) | 51 #if defined(OS_POSIX) |
53 #include <fcntl.h> | 52 #include <fcntl.h> |
54 | 53 |
55 #include "ipc/ipc_channel_posix.h" | 54 #include "ipc/ipc_channel_posix.h" |
56 #elif defined(OS_WIN) | 55 #elif defined(OS_WIN) |
57 #include <windows.h> | 56 #include <windows.h> |
58 | 57 |
59 #include "base/threading/thread.h" | 58 #include "base/threading/thread.h" |
60 #include "base/win/scoped_handle.h" | 59 #include "base/win/scoped_handle.h" |
61 #include "chrome/browser/nacl_host/nacl_broker_service_win.h" | 60 #include "components/nacl/browser/nacl_broker_service_win.h" |
62 #include "components/nacl/common/nacl_debug_exception_handler_win.h" | 61 #include "components/nacl/common/nacl_debug_exception_handler_win.h" |
63 #include "content/public/common/sandbox_init.h" | 62 #include "content/public/common/sandbox_init.h" |
64 #include "content/public/common/sandboxed_process_launcher_delegate.h" | 63 #include "content/public/common/sandboxed_process_launcher_delegate.h" |
65 #endif | 64 #endif |
66 | 65 |
67 using content::BrowserThread; | 66 using content::BrowserThread; |
68 using content::ChildProcessData; | 67 using content::ChildProcessData; |
69 using content::ChildProcessHost; | 68 using content::ChildProcessHost; |
70 using ppapi::proxy::SerializedHandle; | 69 using ppapi::proxy::SerializedHandle; |
71 | 70 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 ppapi::PpapiPermissions GetNaClPermissions(uint32 permission_bits) { | 192 ppapi::PpapiPermissions GetNaClPermissions(uint32 permission_bits) { |
194 // Only allow NaCl plugins to request certain permissions. We don't want | 193 // Only allow NaCl plugins to request certain permissions. We don't want |
195 // a compromised renderer to be able to start a nacl plugin with e.g. Flash | 194 // a compromised renderer to be able to start a nacl plugin with e.g. Flash |
196 // permissions which may expand the surface area of the sandbox. | 195 // permissions which may expand the surface area of the sandbox. |
197 uint32 masked_bits = permission_bits & ppapi::PERMISSION_DEV; | 196 uint32 masked_bits = permission_bits & ppapi::PERMISSION_DEV; |
198 return ppapi::PpapiPermissions::GetForCommandLine(masked_bits); | 197 return ppapi::PpapiPermissions::GetForCommandLine(masked_bits); |
199 } | 198 } |
200 | 199 |
201 } // namespace | 200 } // namespace |
202 | 201 |
202 namespace nacl { | |
203 | |
203 struct NaClProcessHost::NaClInternal { | 204 struct NaClProcessHost::NaClInternal { |
204 NaClHandle socket_for_renderer; | 205 NaClHandle socket_for_renderer; |
205 NaClHandle socket_for_sel_ldr; | 206 NaClHandle socket_for_sel_ldr; |
206 | 207 |
207 NaClInternal() | 208 NaClInternal() |
208 : socket_for_renderer(NACL_INVALID_HANDLE), | 209 : socket_for_renderer(NACL_INVALID_HANDLE), |
209 socket_for_sel_ldr(NACL_INVALID_HANDLE) { } | 210 socket_for_sel_ldr(NACL_INVALID_HANDLE) { } |
210 }; | 211 }; |
211 | 212 |
212 // ----------------------------------------------------------------------------- | 213 // ----------------------------------------------------------------------------- |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
264 | 265 |
265 NaClProcessHost::~NaClProcessHost() { | 266 NaClProcessHost::~NaClProcessHost() { |
266 // Report exit status only if the process was successfully started. | 267 // Report exit status only if the process was successfully started. |
267 if (process_->GetData().handle != base::kNullProcessHandle) { | 268 if (process_->GetData().handle != base::kNullProcessHandle) { |
268 int exit_code = 0; | 269 int exit_code = 0; |
269 process_->GetTerminationStatus(false /* known_dead */, &exit_code); | 270 process_->GetTerminationStatus(false /* known_dead */, &exit_code); |
270 std::string message = | 271 std::string message = |
271 base::StringPrintf("NaCl process exited with status %i (0x%x)", | 272 base::StringPrintf("NaCl process exited with status %i (0x%x)", |
272 exit_code, exit_code); | 273 exit_code, exit_code); |
273 if (exit_code == 0) { | 274 if (exit_code == 0) { |
274 LOG(INFO) << message; | 275 VLOG(1) << message; |
Mark Seaborn
2013/11/22 20:41:48
Why are you changing this? Please undo this chang
| |
275 } else { | 276 } else { |
276 LOG(ERROR) << message; | 277 LOG(ERROR) << message; |
277 } | 278 } |
278 } | 279 } |
279 | 280 |
280 if (internal_->socket_for_renderer != NACL_INVALID_HANDLE) { | 281 if (internal_->socket_for_renderer != NACL_INVALID_HANDLE) { |
281 if (NaClClose(internal_->socket_for_renderer) != 0) { | 282 if (NaClClose(internal_->socket_for_renderer) != 0) { |
282 NOTREACHED() << "NaClClose() failed"; | 283 NOTREACHED() << "NaClClose() failed"; |
283 } | 284 } |
284 } | 285 } |
(...skipping 14 matching lines...) Expand all Loading... | |
299 if (process_launched_by_broker_) { | 300 if (process_launched_by_broker_) { |
300 NaClBrokerService::GetInstance()->OnLoaderDied(); | 301 NaClBrokerService::GetInstance()->OnLoaderDied(); |
301 } | 302 } |
302 #endif | 303 #endif |
303 } | 304 } |
304 | 305 |
305 void NaClProcessHost::OnProcessCrashed(int exit_status) { | 306 void NaClProcessHost::OnProcessCrashed(int exit_status) { |
306 if (enable_crash_throttling_ && | 307 if (enable_crash_throttling_ && |
307 !CommandLine::ForCurrentProcess()->HasSwitch( | 308 !CommandLine::ForCurrentProcess()->HasSwitch( |
308 switches::kDisablePnaclCrashThrottling)) { | 309 switches::kDisablePnaclCrashThrottling)) { |
309 nacl::NaClBrowser::GetInstance()->OnProcessCrashed(); | 310 NaClBrowser::GetInstance()->OnProcessCrashed(); |
310 } | 311 } |
311 } | 312 } |
312 | 313 |
313 // This is called at browser startup. | 314 // This is called at browser startup. |
314 // static | 315 // static |
315 void NaClProcessHost::EarlyStartup() { | 316 void NaClProcessHost::EarlyStartup() { |
316 nacl::NaClBrowser::GetInstance()->EarlyStartup(); | 317 NaClBrowser::GetInstance()->EarlyStartup(); |
317 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 318 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
318 // Open the IRT file early to make sure that it isn't replaced out from | 319 // Open the IRT file early to make sure that it isn't replaced out from |
319 // under us by autoupdate. | 320 // under us by autoupdate. |
320 nacl::NaClBrowser::GetInstance()->EnsureIrtAvailable(); | 321 NaClBrowser::GetInstance()->EnsureIrtAvailable(); |
321 #endif | 322 #endif |
322 CommandLine* cmd = CommandLine::ForCurrentProcess(); | 323 CommandLine* cmd = CommandLine::ForCurrentProcess(); |
323 UMA_HISTOGRAM_BOOLEAN( | 324 UMA_HISTOGRAM_BOOLEAN( |
324 "NaCl.nacl-gdb", | 325 "NaCl.nacl-gdb", |
325 !cmd->GetSwitchValuePath(switches::kNaClGdb).empty()); | 326 !cmd->GetSwitchValuePath(switches::kNaClGdb).empty()); |
326 UMA_HISTOGRAM_BOOLEAN( | 327 UMA_HISTOGRAM_BOOLEAN( |
327 "NaCl.nacl-gdb-script", | 328 "NaCl.nacl-gdb-script", |
328 !cmd->GetSwitchValuePath(switches::kNaClGdbScript).empty()); | 329 !cmd->GetSwitchValuePath(switches::kNaClGdbScript).empty()); |
329 UMA_HISTOGRAM_BOOLEAN( | 330 UMA_HISTOGRAM_BOOLEAN( |
330 "NaCl.enable-nacl-debug", | 331 "NaCl.enable-nacl-debug", |
331 cmd->HasSwitch(switches::kEnableNaClDebug)); | 332 cmd->HasSwitch(switches::kEnableNaClDebug)); |
332 nacl::NaClBrowser::GetDelegate()->SetDebugPatterns( | 333 NaClBrowser::GetDelegate()->SetDebugPatterns( |
333 cmd->GetSwitchValueASCII(switches::kNaClDebugMask)); | 334 cmd->GetSwitchValueASCII(switches::kNaClDebugMask)); |
334 } | 335 } |
335 | 336 |
336 void NaClProcessHost::Launch( | 337 void NaClProcessHost::Launch( |
337 NaClHostMessageFilter* nacl_host_message_filter, | 338 NaClHostMessageFilter* nacl_host_message_filter, |
338 IPC::Message* reply_msg, | 339 IPC::Message* reply_msg, |
339 const base::FilePath& manifest_path) { | 340 const base::FilePath& manifest_path) { |
340 nacl_host_message_filter_ = nacl_host_message_filter; | 341 nacl_host_message_filter_ = nacl_host_message_filter; |
341 reply_msg_ = reply_msg; | 342 reply_msg_ = reply_msg; |
342 manifest_path_ = manifest_path; | 343 manifest_path_ = manifest_path; |
343 | 344 |
344 // Do not launch the requested NaCl module if NaCl is marked "unstable" due | 345 // Do not launch the requested NaCl module if NaCl is marked "unstable" due |
345 // to too many crashes within a given time period. | 346 // to too many crashes within a given time period. |
346 if (enable_crash_throttling_ && | 347 if (enable_crash_throttling_ && |
347 !CommandLine::ForCurrentProcess()->HasSwitch( | 348 !CommandLine::ForCurrentProcess()->HasSwitch( |
348 switches::kDisablePnaclCrashThrottling) && | 349 switches::kDisablePnaclCrashThrottling) && |
349 nacl::NaClBrowser::GetInstance()->IsThrottled()) { | 350 NaClBrowser::GetInstance()->IsThrottled()) { |
350 SendErrorToRenderer("Process creation was throttled due to excessive" | 351 SendErrorToRenderer("Process creation was throttled due to excessive" |
351 " crashes"); | 352 " crashes"); |
352 delete this; | 353 delete this; |
353 return; | 354 return; |
354 } | 355 } |
355 | 356 |
356 const CommandLine* cmd = CommandLine::ForCurrentProcess(); | 357 const CommandLine* cmd = CommandLine::ForCurrentProcess(); |
357 #if defined(OS_WIN) | 358 #if defined(OS_WIN) |
358 if (cmd->HasSwitch(switches::kEnableNaClDebug) && | 359 if (cmd->HasSwitch(switches::kEnableNaClDebug) && |
359 !cmd->HasSwitch(switches::kNoSandbox)) { | 360 !cmd->HasSwitch(switches::kNoSandbox)) { |
360 // We don't switch off sandbox automatically for security reasons. | 361 // We don't switch off sandbox automatically for security reasons. |
361 SendErrorToRenderer("NaCl's GDB debug stub requires --no-sandbox flag" | 362 SendErrorToRenderer("NaCl's GDB debug stub requires --no-sandbox flag" |
362 " on Windows. See crbug.com/265624."); | 363 " on Windows. See crbug.com/265624."); |
363 delete this; | 364 delete this; |
364 return; | 365 return; |
365 } | 366 } |
366 #endif | 367 #endif |
367 if (cmd->HasSwitch(switches::kNaClGdb) && | 368 if (cmd->HasSwitch(switches::kNaClGdb) && |
368 !cmd->HasSwitch(switches::kEnableNaClDebug)) { | 369 !cmd->HasSwitch(switches::kEnableNaClDebug)) { |
369 LOG(WARNING) << "--nacl-gdb flag requires --enable-nacl-debug flag"; | 370 LOG(WARNING) << "--nacl-gdb flag requires --enable-nacl-debug flag"; |
370 } | 371 } |
371 | 372 |
372 // Start getting the IRT open asynchronously while we launch the NaCl process. | 373 // Start getting the IRT open asynchronously while we launch the NaCl process. |
373 // We'll make sure this actually finished in StartWithLaunchedProcess, below. | 374 // We'll make sure this actually finished in StartWithLaunchedProcess, below. |
374 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); | 375 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
375 nacl_browser->EnsureAllResourcesAvailable(); | 376 nacl_browser->EnsureAllResourcesAvailable(); |
376 if (!nacl_browser->IsOk()) { | 377 if (!nacl_browser->IsOk()) { |
377 SendErrorToRenderer("could not find all the resources needed" | 378 SendErrorToRenderer("could not find all the resources needed" |
378 " to launch the process"); | 379 " to launch the process"); |
379 delete this; | 380 delete this; |
380 return; | 381 return; |
381 } | 382 } |
382 | 383 |
383 // Rather than creating a socket pair in the renderer, and passing | 384 // Rather than creating a socket pair in the renderer, and passing |
384 // one side through the browser to sel_ldr, socket pairs are created | 385 // one side through the browser to sel_ldr, socket pairs are created |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 CommandLine::StringType nacl_gdb = | 444 CommandLine::StringType nacl_gdb = |
444 CommandLine::ForCurrentProcess()->GetSwitchValueNative( | 445 CommandLine::ForCurrentProcess()->GetSwitchValueNative( |
445 switches::kNaClGdb); | 446 switches::kNaClGdb); |
446 CommandLine::StringVector argv; | 447 CommandLine::StringVector argv; |
447 // We don't support spaces inside arguments in --nacl-gdb switch. | 448 // We don't support spaces inside arguments in --nacl-gdb switch. |
448 base::SplitString(nacl_gdb, static_cast<CommandLine::CharType>(' '), &argv); | 449 base::SplitString(nacl_gdb, static_cast<CommandLine::CharType>(' '), &argv); |
449 CommandLine cmd_line(argv); | 450 CommandLine cmd_line(argv); |
450 #endif | 451 #endif |
451 cmd_line.AppendArg("--eval-command"); | 452 cmd_line.AppendArg("--eval-command"); |
452 base::FilePath::StringType irt_path( | 453 base::FilePath::StringType irt_path( |
453 nacl::NaClBrowser::GetInstance()->GetIrtFilePath().value()); | 454 NaClBrowser::GetInstance()->GetIrtFilePath().value()); |
454 // Avoid back slashes because nacl-gdb uses posix escaping rules on Windows. | 455 // Avoid back slashes because nacl-gdb uses posix escaping rules on Windows. |
455 // See issue https://code.google.com/p/nativeclient/issues/detail?id=3482. | 456 // See issue https://code.google.com/p/nativeclient/issues/detail?id=3482. |
456 std::replace(irt_path.begin(), irt_path.end(), '\\', '/'); | 457 std::replace(irt_path.begin(), irt_path.end(), '\\', '/'); |
457 cmd_line.AppendArgNative(FILE_PATH_LITERAL("nacl-irt \"") + irt_path + | 458 cmd_line.AppendArgNative(FILE_PATH_LITERAL("nacl-irt \"") + irt_path + |
458 FILE_PATH_LITERAL("\"")); | 459 FILE_PATH_LITERAL("\"")); |
459 if (!manifest_path_.empty()) { | 460 if (!manifest_path_.empty()) { |
460 cmd_line.AppendArg("--eval-command"); | 461 cmd_line.AppendArg("--eval-command"); |
461 base::FilePath::StringType manifest_path_value(manifest_path_.value()); | 462 base::FilePath::StringType manifest_path_value(manifest_path_.value()); |
462 std::replace(manifest_path_value.begin(), manifest_path_value.end(), | 463 std::replace(manifest_path_value.begin(), manifest_path_value.end(), |
463 '\\', '/'); | 464 '\\', '/'); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
505 int flags = ChildProcessHost::CHILD_NORMAL; | 506 int flags = ChildProcessHost::CHILD_NORMAL; |
506 #endif | 507 #endif |
507 | 508 |
508 base::FilePath exe_path = ChildProcessHost::GetChildPath(flags); | 509 base::FilePath exe_path = ChildProcessHost::GetChildPath(flags); |
509 if (exe_path.empty()) | 510 if (exe_path.empty()) |
510 return false; | 511 return false; |
511 | 512 |
512 #if defined(OS_WIN) | 513 #if defined(OS_WIN) |
513 // On Windows 64-bit NaCl loader is called nacl64.exe instead of chrome.exe | 514 // On Windows 64-bit NaCl loader is called nacl64.exe instead of chrome.exe |
514 if (RunningOnWOW64()) { | 515 if (RunningOnWOW64()) { |
515 if (!nacl::NaClBrowser::GetInstance()->GetNaCl64ExePath(&exe_path)) { | 516 if (!NaClBrowser::GetInstance()->GetNaCl64ExePath(&exe_path)) { |
516 SendErrorToRenderer("could not get path to nacl64.exe"); | 517 SendErrorToRenderer("could not get path to nacl64.exe"); |
517 return false; | 518 return false; |
518 } | 519 } |
519 } | 520 } |
520 #endif | 521 #endif |
521 | 522 |
522 scoped_ptr<CommandLine> cmd_line(new CommandLine(exe_path)); | 523 scoped_ptr<CommandLine> cmd_line(new CommandLine(exe_path)); |
523 nacl::CopyNaClCommandLineArguments(cmd_line.get()); | 524 CopyNaClCommandLineArguments(cmd_line.get()); |
524 | 525 |
525 cmd_line->AppendSwitchASCII(switches::kProcessType, | 526 cmd_line->AppendSwitchASCII(switches::kProcessType, |
526 switches::kNaClLoaderProcess); | 527 switches::kNaClLoaderProcess); |
527 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); | 528 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); |
528 if (nacl::NaClBrowser::GetDelegate()->DialogsAreSuppressed()) | 529 if (NaClBrowser::GetDelegate()->DialogsAreSuppressed()) |
529 cmd_line->AppendSwitch(switches::kNoErrorDialogs); | 530 cmd_line->AppendSwitch(switches::kNoErrorDialogs); |
530 | 531 |
531 if (!nacl_loader_prefix.empty()) | 532 if (!nacl_loader_prefix.empty()) |
532 cmd_line->PrependWrapper(nacl_loader_prefix); | 533 cmd_line->PrependWrapper(nacl_loader_prefix); |
533 | 534 |
534 // On Windows we might need to start the broker process to launch a new loader | 535 // On Windows we might need to start the broker process to launch a new loader |
535 #if defined(OS_WIN) | 536 #if defined(OS_WIN) |
536 if (RunningOnWOW64()) { | 537 if (RunningOnWOW64()) { |
537 if (!NaClBrokerService::GetInstance()->LaunchLoader( | 538 if (!NaClBrokerService::GetInstance()->LaunchLoader( |
538 weak_factory_.GetWeakPtr(), channel_id)) { | 539 weak_factory_.GetWeakPtr(), channel_id)) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
572 return handled; | 573 return handled; |
573 } | 574 } |
574 | 575 |
575 void NaClProcessHost::OnProcessLaunched() { | 576 void NaClProcessHost::OnProcessLaunched() { |
576 if (!StartWithLaunchedProcess()) | 577 if (!StartWithLaunchedProcess()) |
577 delete this; | 578 delete this; |
578 } | 579 } |
579 | 580 |
580 // Called when the NaClBrowser singleton has been fully initialized. | 581 // Called when the NaClBrowser singleton has been fully initialized. |
581 void NaClProcessHost::OnResourcesReady() { | 582 void NaClProcessHost::OnResourcesReady() { |
582 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); | 583 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
583 if (!nacl_browser->IsReady()) { | 584 if (!nacl_browser->IsReady()) { |
584 SendErrorToRenderer("could not acquire shared resources needed by NaCl"); | 585 SendErrorToRenderer("could not acquire shared resources needed by NaCl"); |
585 delete this; | 586 delete this; |
586 } else if (!SendStart()) { | 587 } else if (!SendStart()) { |
587 delete this; | 588 delete this; |
588 } | 589 } |
589 } | 590 } |
590 | 591 |
591 bool NaClProcessHost::ReplyToRenderer( | 592 bool NaClProcessHost::ReplyToRenderer( |
592 const IPC::ChannelHandle& channel_handle) { | 593 const IPC::ChannelHandle& channel_handle) { |
593 #if defined(OS_WIN) | 594 #if defined(OS_WIN) |
594 // If we are on 64-bit Windows, the NaCl process's sandbox is | 595 // If we are on 64-bit Windows, the NaCl process's sandbox is |
595 // managed by a different process from the renderer's sandbox. We | 596 // managed by a different process from the renderer's sandbox. We |
596 // need to inform the renderer's sandbox about the NaCl process so | 597 // need to inform the renderer's sandbox about the NaCl process so |
597 // that the renderer can send handles to the NaCl process using | 598 // that the renderer can send handles to the NaCl process using |
598 // BrokerDuplicateHandle(). | 599 // BrokerDuplicateHandle(). |
599 if (RunningOnWOW64()) { | 600 if (RunningOnWOW64()) { |
600 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { | 601 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { |
601 SendErrorToRenderer("BrokerAddTargetPeer() failed"); | 602 SendErrorToRenderer("BrokerAddTargetPeer() failed"); |
602 return false; | 603 return false; |
603 } | 604 } |
604 } | 605 } |
605 #endif | 606 #endif |
606 | 607 |
607 nacl::FileDescriptor handle_for_renderer; | 608 FileDescriptor handle_for_renderer; |
608 #if defined(OS_WIN) | 609 #if defined(OS_WIN) |
609 // Copy the handle into the renderer process. | 610 // Copy the handle into the renderer process. |
610 HANDLE handle_in_renderer; | 611 HANDLE handle_in_renderer; |
611 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | 612 if (!DuplicateHandle(base::GetCurrentProcessHandle(), |
612 reinterpret_cast<HANDLE>( | 613 reinterpret_cast<HANDLE>( |
613 internal_->socket_for_renderer), | 614 internal_->socket_for_renderer), |
614 nacl_host_message_filter_->PeerHandle(), | 615 nacl_host_message_filter_->PeerHandle(), |
615 &handle_in_renderer, | 616 &handle_in_renderer, |
616 0, // Unused given DUPLICATE_SAME_ACCESS. | 617 0, // Unused given DUPLICATE_SAME_ACCESS. |
617 FALSE, | 618 FALSE, |
618 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | 619 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
619 SendErrorToRenderer("DuplicateHandle() failed"); | 620 SendErrorToRenderer("DuplicateHandle() failed"); |
620 return false; | 621 return false; |
621 } | 622 } |
622 handle_for_renderer = reinterpret_cast<nacl::FileDescriptor>( | 623 handle_for_renderer = reinterpret_cast<FileDescriptor>( |
623 handle_in_renderer); | 624 handle_in_renderer); |
624 #else | 625 #else |
625 // No need to dup the imc_handle - we don't pass it anywhere else so | 626 // No need to dup the imc_handle - we don't pass it anywhere else so |
626 // it cannot be closed. | 627 // it cannot be closed. |
627 nacl::FileDescriptor imc_handle; | 628 FileDescriptor imc_handle; |
628 imc_handle.fd = internal_->socket_for_renderer; | 629 imc_handle.fd = internal_->socket_for_renderer; |
629 imc_handle.auto_close = true; | 630 imc_handle.auto_close = true; |
630 handle_for_renderer = imc_handle; | 631 handle_for_renderer = imc_handle; |
631 #endif | 632 #endif |
632 | 633 |
633 const ChildProcessData& data = process_->GetData(); | 634 const ChildProcessData& data = process_->GetData(); |
634 SendMessageToRenderer( | 635 SendMessageToRenderer( |
635 nacl::NaClLaunchResult(handle_for_renderer, | 636 NaClLaunchResult(handle_for_renderer, |
636 channel_handle, | 637 channel_handle, |
637 base::GetProcId(data.handle), | 638 base::GetProcId(data.handle), |
638 data.id), | 639 data.id), |
639 std::string() /* error_message */); | 640 std::string() /* error_message */); |
640 internal_->socket_for_renderer = NACL_INVALID_HANDLE; | 641 internal_->socket_for_renderer = NACL_INVALID_HANDLE; |
641 return true; | 642 return true; |
642 } | 643 } |
643 | 644 |
644 void NaClProcessHost::SendErrorToRenderer(const std::string& error_message) { | 645 void NaClProcessHost::SendErrorToRenderer(const std::string& error_message) { |
645 LOG(ERROR) << "NaCl process launch failed: " << error_message; | 646 LOG(ERROR) << "NaCl process launch failed: " << error_message; |
646 SendMessageToRenderer(nacl::NaClLaunchResult(), error_message); | 647 SendMessageToRenderer(NaClLaunchResult(), error_message); |
647 } | 648 } |
648 | 649 |
649 void NaClProcessHost::SendMessageToRenderer( | 650 void NaClProcessHost::SendMessageToRenderer( |
650 const nacl::NaClLaunchResult& result, | 651 const NaClLaunchResult& result, |
651 const std::string& error_message) { | 652 const std::string& error_message) { |
652 DCHECK(nacl_host_message_filter_); | 653 DCHECK(nacl_host_message_filter_); |
653 DCHECK(reply_msg_); | 654 DCHECK(reply_msg_); |
654 if (nacl_host_message_filter_ != NULL && reply_msg_ != NULL) { | 655 if (nacl_host_message_filter_ != NULL && reply_msg_ != NULL) { |
655 NaClHostMsg_LaunchNaCl::WriteReplyParams( | 656 NaClHostMsg_LaunchNaCl::WriteReplyParams( |
656 reply_msg_, result, error_message); | 657 reply_msg_, result, error_message); |
657 nacl_host_message_filter_->Send(reply_msg_); | 658 nacl_host_message_filter_->Send(reply_msg_); |
658 nacl_host_message_filter_ = NULL; | 659 nacl_host_message_filter_ = NULL; |
659 reply_msg_ = NULL; | 660 reply_msg_ = NULL; |
660 } | 661 } |
661 } | 662 } |
662 | 663 |
663 // TCP port we chose for NaCl debug stub. It can be any other number. | 664 // TCP port we chose for NaCl debug stub. It can be any other number. |
664 static const int kDebugStubPort = 4014; | 665 static const int kDebugStubPort = 4014; |
665 | 666 |
666 #if defined(OS_POSIX) | 667 #if defined(OS_POSIX) |
667 net::SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { | 668 net::SocketDescriptor NaClProcessHost::GetDebugStubSocketHandle() { |
668 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); | 669 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
669 net::SocketDescriptor s = net::kInvalidSocket; | 670 net::SocketDescriptor s = net::kInvalidSocket; |
670 // We allocate currently unused TCP port for debug stub tests. The port | 671 // We allocate currently unused TCP port for debug stub tests. The port |
671 // number is passed to the test via debug stub port listener. | 672 // number is passed to the test via debug stub port listener. |
672 if (nacl_browser->HasGdbDebugStubPortListener()) { | 673 if (nacl_browser->HasGdbDebugStubPortListener()) { |
673 int port; | 674 int port; |
674 s = net::TCPListenSocket::CreateAndBindAnyPort("127.0.0.1", &port); | 675 s = net::TCPListenSocket::CreateAndBindAnyPort("127.0.0.1", &port); |
675 if (s != net::kInvalidSocket) { | 676 if (s != net::kInvalidSocket) { |
676 nacl_browser->FireGdbDebugStubPortOpened(port); | 677 nacl_browser->FireGdbDebugStubPortOpened(port); |
677 } | 678 } |
678 } else { | 679 } else { |
679 s = net::TCPListenSocket::CreateAndBind("127.0.0.1", kDebugStubPort); | 680 s = net::TCPListenSocket::CreateAndBind("127.0.0.1", kDebugStubPort); |
680 } | 681 } |
681 if (s == net::kInvalidSocket) { | 682 if (s == net::kInvalidSocket) { |
682 LOG(ERROR) << "failed to open socket for debug stub"; | 683 LOG(ERROR) << "failed to open socket for debug stub"; |
683 return net::kInvalidSocket; | 684 return net::kInvalidSocket; |
684 } | 685 } |
685 if (listen(s, 1)) { | 686 if (listen(s, 1)) { |
686 LOG(ERROR) << "listen() failed on debug stub socket"; | 687 LOG(ERROR) << "listen() failed on debug stub socket"; |
687 if (HANDLE_EINTR(close(s)) < 0) | 688 if (HANDLE_EINTR(close(s)) < 0) |
688 PLOG(ERROR) << "failed to close debug stub socket"; | 689 PLOG(ERROR) << "failed to close debug stub socket"; |
689 return net::kInvalidSocket; | 690 return net::kInvalidSocket; |
690 } | 691 } |
691 return s; | 692 return s; |
692 } | 693 } |
693 #endif | 694 #endif |
694 | 695 |
695 bool NaClProcessHost::StartNaClExecution() { | 696 bool NaClProcessHost::StartNaClExecution() { |
696 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); | 697 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
697 | 698 |
698 nacl::NaClStartParams params; | 699 NaClStartParams params; |
699 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); | 700 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); |
700 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); | 701 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); |
701 params.version = nacl::NaClBrowser::GetDelegate()->GetVersionString(); | 702 params.version = NaClBrowser::GetDelegate()->GetVersionString(); |
702 params.enable_exception_handling = enable_exception_handling_; | 703 params.enable_exception_handling = enable_exception_handling_; |
703 params.enable_debug_stub = enable_debug_stub_ && | 704 params.enable_debug_stub = enable_debug_stub_ && |
704 nacl::NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_); | 705 NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_); |
705 // Enable PPAPI proxy channel creation only for renderer processes. | 706 // Enable PPAPI proxy channel creation only for renderer processes. |
706 params.enable_ipc_proxy = enable_ppapi_proxy(); | 707 params.enable_ipc_proxy = enable_ppapi_proxy(); |
707 params.uses_irt = uses_irt_; | 708 params.uses_irt = uses_irt_; |
708 params.enable_dyncode_syscalls = enable_dyncode_syscalls_; | 709 params.enable_dyncode_syscalls = enable_dyncode_syscalls_; |
709 | 710 |
710 const ChildProcessData& data = process_->GetData(); | 711 const ChildProcessData& data = process_->GetData(); |
711 if (!ShareHandleToSelLdr(data.handle, | 712 if (!ShareHandleToSelLdr(data.handle, |
712 internal_->socket_for_sel_ldr, true, | 713 internal_->socket_for_sel_ldr, true, |
713 ¶ms.handles)) { | 714 ¶ms.handles)) { |
714 return false; | 715 return false; |
(...skipping 13 matching lines...) Expand all Loading... | |
728 // mappable with PROT_EXEC. Rather than requiring an extra IPC | 729 // mappable with PROT_EXEC. Rather than requiring an extra IPC |
729 // round trip out of the sandbox, we create an FD here. | 730 // round trip out of the sandbox, we create an FD here. |
730 base::SharedMemory memory_buffer; | 731 base::SharedMemory memory_buffer; |
731 base::SharedMemoryCreateOptions options; | 732 base::SharedMemoryCreateOptions options; |
732 options.size = 1; | 733 options.size = 1; |
733 options.executable = true; | 734 options.executable = true; |
734 if (!memory_buffer.Create(options)) { | 735 if (!memory_buffer.Create(options)) { |
735 DLOG(ERROR) << "Failed to allocate memory buffer"; | 736 DLOG(ERROR) << "Failed to allocate memory buffer"; |
736 return false; | 737 return false; |
737 } | 738 } |
738 nacl::FileDescriptor memory_fd; | 739 FileDescriptor memory_fd; |
739 memory_fd.fd = dup(memory_buffer.handle().fd); | 740 memory_fd.fd = dup(memory_buffer.handle().fd); |
740 if (memory_fd.fd < 0) { | 741 if (memory_fd.fd < 0) { |
741 DLOG(ERROR) << "Failed to dup() a file descriptor"; | 742 DLOG(ERROR) << "Failed to dup() a file descriptor"; |
742 return false; | 743 return false; |
743 } | 744 } |
744 memory_fd.auto_close = true; | 745 memory_fd.auto_close = true; |
745 params.handles.push_back(memory_fd); | 746 params.handles.push_back(memory_fd); |
746 #endif | 747 #endif |
747 | 748 |
748 #if defined(OS_POSIX) | 749 #if defined(OS_POSIX) |
749 if (params.enable_debug_stub) { | 750 if (params.enable_debug_stub) { |
750 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); | 751 net::SocketDescriptor server_bound_socket = GetDebugStubSocketHandle(); |
751 if (server_bound_socket != net::kInvalidSocket) { | 752 if (server_bound_socket != net::kInvalidSocket) { |
752 params.debug_stub_server_bound_socket = | 753 params.debug_stub_server_bound_socket = |
753 nacl::FileDescriptor(server_bound_socket, true); | 754 FileDescriptor(server_bound_socket, true); |
754 } | 755 } |
755 } | 756 } |
756 #endif | 757 #endif |
757 | 758 |
758 process_->Send(new NaClProcessMsg_Start(params)); | 759 process_->Send(new NaClProcessMsg_Start(params)); |
759 | 760 |
760 internal_->socket_for_sel_ldr = NACL_INVALID_HANDLE; | 761 internal_->socket_for_sel_ldr = NACL_INVALID_HANDLE; |
761 return true; | 762 return true; |
762 } | 763 } |
763 | 764 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
806 for (size_t i = 0; i < arraysize(flag_whitelist); ++i) { | 807 for (size_t i = 0; i < arraysize(flag_whitelist); ++i) { |
807 std::string value = cmdline->GetSwitchValueASCII(flag_whitelist[i]); | 808 std::string value = cmdline->GetSwitchValueASCII(flag_whitelist[i]); |
808 if (!value.empty()) { | 809 if (!value.empty()) { |
809 args.switch_names.push_back(flag_whitelist[i]); | 810 args.switch_names.push_back(flag_whitelist[i]); |
810 args.switch_values.push_back(value); | 811 args.switch_values.push_back(value); |
811 } | 812 } |
812 } | 813 } |
813 | 814 |
814 ppapi_host_->GetPpapiHost()->AddHostFactoryFilter( | 815 ppapi_host_->GetPpapiHost()->AddHostFactoryFilter( |
815 scoped_ptr<ppapi::host::HostFactory>( | 816 scoped_ptr<ppapi::host::HostFactory>( |
816 nacl::NaClBrowser::GetDelegate()->CreatePpapiHostFactory( | 817 NaClBrowser::GetDelegate()->CreatePpapiHostFactory( |
817 ppapi_host_.get()))); | 818 ppapi_host_.get()))); |
818 | 819 |
819 // Send a message to create the NaCl-Renderer channel. The handle is just | 820 // Send a message to create the NaCl-Renderer channel. The handle is just |
820 // a place holder. | 821 // a place holder. |
821 ipc_proxy_channel_->Send( | 822 ipc_proxy_channel_->Send( |
822 new PpapiMsg_CreateNaClChannel( | 823 new PpapiMsg_CreateNaClChannel( |
823 nacl_host_message_filter_->render_process_id(), | 824 nacl_host_message_filter_->render_process_id(), |
824 args, | 825 args, |
825 SerializedHandle(SerializedHandle::CHANNEL_HANDLE, | 826 SerializedHandle(SerializedHandle::CHANNEL_HANDLE, |
826 IPC::InvalidPlatformFileForTransit()))); | 827 IPC::InvalidPlatformFileForTransit()))); |
(...skipping 13 matching lines...) Expand all Loading... | |
840 bool handled = true; | 841 bool handled = true; |
841 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) | 842 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) |
842 IPC_MESSAGE_HANDLER(PpapiHostMsg_ChannelCreated, | 843 IPC_MESSAGE_HANDLER(PpapiHostMsg_ChannelCreated, |
843 OnPpapiChannelCreated) | 844 OnPpapiChannelCreated) |
844 IPC_MESSAGE_UNHANDLED(handled = false) | 845 IPC_MESSAGE_UNHANDLED(handled = false) |
845 IPC_END_MESSAGE_MAP() | 846 IPC_END_MESSAGE_MAP() |
846 return handled; | 847 return handled; |
847 } | 848 } |
848 | 849 |
849 bool NaClProcessHost::StartWithLaunchedProcess() { | 850 bool NaClProcessHost::StartWithLaunchedProcess() { |
850 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); | 851 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
851 | 852 |
852 if (nacl_browser->IsReady()) { | 853 if (nacl_browser->IsReady()) { |
853 return SendStart(); | 854 return SendStart(); |
854 } else if (nacl_browser->IsOk()) { | 855 } else if (nacl_browser->IsOk()) { |
855 nacl_browser->WaitForResources( | 856 nacl_browser->WaitForResources( |
856 base::Bind(&NaClProcessHost::OnResourcesReady, | 857 base::Bind(&NaClProcessHost::OnResourcesReady, |
857 weak_factory_.GetWeakPtr())); | 858 weak_factory_.GetWeakPtr())); |
858 return true; | 859 return true; |
859 } else { | 860 } else { |
860 SendErrorToRenderer("previously failed to acquire shared resources"); | 861 SendErrorToRenderer("previously failed to acquire shared resources"); |
861 return false; | 862 return false; |
862 } | 863 } |
863 } | 864 } |
864 | 865 |
865 void NaClProcessHost::OnQueryKnownToValidate(const std::string& signature, | 866 void NaClProcessHost::OnQueryKnownToValidate(const std::string& signature, |
866 bool* result) { | 867 bool* result) { |
867 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); | 868 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
868 *result = nacl_browser->QueryKnownToValidate(signature, off_the_record_); | 869 *result = nacl_browser->QueryKnownToValidate(signature, off_the_record_); |
869 } | 870 } |
870 | 871 |
871 void NaClProcessHost::OnSetKnownToValidate(const std::string& signature) { | 872 void NaClProcessHost::OnSetKnownToValidate(const std::string& signature) { |
872 nacl::NaClBrowser::GetInstance()->SetKnownToValidate( | 873 NaClBrowser::GetInstance()->SetKnownToValidate( |
873 signature, off_the_record_); | 874 signature, off_the_record_); |
874 } | 875 } |
875 | 876 |
876 void NaClProcessHost::FileResolved( | 877 void NaClProcessHost::FileResolved( |
877 base::PlatformFile* file, | 878 base::PlatformFile* file, |
878 const base::FilePath& file_path, | 879 const base::FilePath& file_path, |
879 IPC::Message* reply_msg) { | 880 IPC::Message* reply_msg) { |
880 if (*file != base::kInvalidPlatformFileValue) { | 881 if (*file != base::kInvalidPlatformFileValue) { |
881 IPC::PlatformFileForTransit handle = IPC::GetFileHandleForProcess( | 882 IPC::PlatformFileForTransit handle = IPC::GetFileHandleForProcess( |
882 *file, | 883 *file, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
915 // not be a problem, if needed. | 916 // not be a problem, if needed. |
916 // | 917 // |
917 // Each NaCl process will consume 2-3 entries because the manifest and main | 918 // Each NaCl process will consume 2-3 entries because the manifest and main |
918 // nexe are currently not resolved. Shared libraries will be resolved. They | 919 // nexe are currently not resolved. Shared libraries will be resolved. They |
919 // will be loaded sequentially, so they will only consume a single entry | 920 // will be loaded sequentially, so they will only consume a single entry |
920 // while the load is in flight. | 921 // while the load is in flight. |
921 // | 922 // |
922 // TODO(ncbray): track behavior with UMA. If entries are getting evicted or | 923 // TODO(ncbray): track behavior with UMA. If entries are getting evicted or |
923 // bogus keys are getting queried, this would be good to know. | 924 // bogus keys are getting queried, this would be good to know. |
924 base::FilePath file_path; | 925 base::FilePath file_path; |
925 if (!nacl::NaClBrowser::GetInstance()->GetFilePath( | 926 if (!NaClBrowser::GetInstance()->GetFilePath( |
926 file_token_lo, file_token_hi, &file_path)) { | 927 file_token_lo, file_token_hi, &file_path)) { |
927 NaClProcessMsg_ResolveFileToken::WriteReplyParams( | 928 NaClProcessMsg_ResolveFileToken::WriteReplyParams( |
928 reply_msg, | 929 reply_msg, |
929 IPC::InvalidPlatformFileForTransit(), | 930 IPC::InvalidPlatformFileForTransit(), |
930 base::FilePath(FILE_PATH_LITERAL(""))); | 931 base::FilePath(FILE_PATH_LITERAL(""))); |
931 Send(reply_msg); | 932 Send(reply_msg); |
932 return; | 933 return; |
933 } | 934 } |
934 | 935 |
935 // Scratch space to share between the callbacks. | 936 // Scratch space to share between the callbacks. |
936 base::PlatformFile* data = new base::PlatformFile(); | 937 base::PlatformFile* data = new base::PlatformFile(); |
937 | 938 |
938 // Open the file. | 939 // Open the file. |
939 if (!content::BrowserThread::PostBlockingPoolTaskAndReply( | 940 if (!content::BrowserThread::PostBlockingPoolTaskAndReply( |
940 FROM_HERE, | 941 FROM_HERE, |
941 base::Bind(nacl::OpenNaClExecutableImpl, | 942 base::Bind(OpenNaClExecutableImpl, |
942 file_path, data), | 943 file_path, data), |
943 base::Bind(&NaClProcessHost::FileResolved, | 944 base::Bind(&NaClProcessHost::FileResolved, |
944 weak_factory_.GetWeakPtr(), | 945 weak_factory_.GetWeakPtr(), |
945 base::Owned(data), | 946 base::Owned(data), |
946 file_path, | 947 file_path, |
947 reply_msg))) { | 948 reply_msg))) { |
948 NaClProcessMsg_ResolveFileToken::WriteReplyParams( | 949 NaClProcessMsg_ResolveFileToken::WriteReplyParams( |
949 reply_msg, | 950 reply_msg, |
950 IPC::InvalidPlatformFileForTransit(), | 951 IPC::InvalidPlatformFileForTransit(), |
951 base::FilePath(FILE_PATH_LITERAL(""))); | 952 base::FilePath(FILE_PATH_LITERAL(""))); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1014 } else { | 1015 } else { |
1015 NaClStartDebugExceptionHandlerThread( | 1016 NaClStartDebugExceptionHandlerThread( |
1016 process_handle.Take(), info, | 1017 process_handle.Take(), info, |
1017 base::MessageLoopProxy::current(), | 1018 base::MessageLoopProxy::current(), |
1018 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1019 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
1019 weak_factory_.GetWeakPtr())); | 1020 weak_factory_.GetWeakPtr())); |
1020 return true; | 1021 return true; |
1021 } | 1022 } |
1022 } | 1023 } |
1023 #endif | 1024 #endif |
1025 | |
1026 } // namespace nacl | |
OLD | NEW |