diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/memory_details.cc | 2 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_broker_host.cc | 74 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_broker_host.h | 46 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_broker_service.cc | 69 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_broker_service.h | 57 | ||||
-rw-r--r-- | chrome/browser/nacl_process_host.cc | 110 | ||||
-rw-r--r-- | chrome/browser/nacl_process_host.h | 13 |
7 files changed, 326 insertions, 45 deletions
diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc index f212698..4c7e2fb 100644 --- a/chrome/browser/memory_details.cc +++ b/chrome/browser/memory_details.cc @@ -209,7 +209,7 @@ void MemoryDetails::UpdateHistograms() { case ChildProcessInfo::SANDBOX_HELPER_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.SandboxHelper", sample); break; - case ChildProcessInfo::NACL_PROCESS: + case ChildProcessInfo::NACL_LOADER_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClient", sample); break; default: diff --git a/chrome/browser/nacl_host/nacl_broker_host.cc b/chrome/browser/nacl_host/nacl_broker_host.cc new file mode 100644 index 0000000..8abc228 --- /dev/null +++ b/chrome/browser/nacl_host/nacl_broker_host.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/nacl_host/nacl_broker_host.h" + +#include "base/command_line.h" +#include "ipc/ipc_switches.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/nacl_host/nacl_broker_service.h" +#include "chrome/browser/nacl_process_host.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/nacl_cmd_line.h" +#include "chrome/common/nacl_messages.h" + +NaClBrokerHost::NaClBrokerHost( + ResourceDispatcherHost* resource_dispatcher_host) + : ChildProcessHost(NACL_BROKER_PROCESS, resource_dispatcher_host) { +} + +NaClBrokerHost::~NaClBrokerHost() { +} + +URLRequestContext* NaClBrokerHost::GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data) { + return NULL; +} + +bool NaClBrokerHost::Init() { + // Create the channel that will be used for communicating with the broker. + if (!CreateChannel()) + return false; + + // Create the path to the nacl broker/loader executable. + FilePath exe_path = GetChildPath(false); + if (exe_path.empty()) + return false; + + FilePath nacl_path = exe_path.DirName().Append(chrome::kNaClAppName); + CommandLine* cmd_line = new CommandLine(nacl_path); + nacl::CopyNaClCommandLineArguments(cmd_line); + + cmd_line->AppendSwitchWithValue(switches::kProcessType, + switches::kNaClBrokerProcess); + + cmd_line->AppendSwitchWithValue(switches::kProcessChannelID, + ASCIIToWide(channel_id())); + + ChildProcessHost::Launch(FilePath(), cmd_line); + return true; +} + +void NaClBrokerHost::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(NaClBrokerHost, msg) + IPC_MESSAGE_HANDLER(NaClProcessMsg_BrokerReady, OnBrokerReady) + IPC_MESSAGE_HANDLER(NaClProcessMsg_LoaderLaunched, OnLoaderLaunched) + IPC_END_MESSAGE_MAP() +} + +void NaClBrokerHost::OnBrokerReady() { + NaClBrokerService::GetInstance()->OnBrokerStarted(); +} + +bool NaClBrokerHost::LaunchLoader( + const std::wstring& loader_channel_id) { + return Send(new NaClProcessMsg_LaunchLoaderThroughBroker(loader_channel_id)); +} + +void NaClBrokerHost::OnLoaderLaunched(const std::wstring& loader_channel_id, + base::ProcessHandle handle) { + NaClBrokerService::GetInstance()->OnLoaderLaunched(loader_channel_id, handle); +} diff --git a/chrome/browser/nacl_host/nacl_broker_host.h b/chrome/browser/nacl_host/nacl_broker_host.h new file mode 100644 index 0000000..f526aa1 --- /dev/null +++ b/chrome/browser/nacl_host/nacl_broker_host.h @@ -0,0 +1,46 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_NACL_HOST_NACL_BROKER_HOST_H_ +#define CHROME_BROWSER_NACL_HOST_NACL_BROKER_HOST_H_ + +#include "base/basictypes.h" +#include "base/process.h" +#include "chrome/common/child_process_host.h" +#include "ipc/ipc_message.h" + +class NaClBrokerHost : public ChildProcessHost { + public: + explicit NaClBrokerHost(ResourceDispatcherHost* resource_dispatcher_host); + ~NaClBrokerHost(); + + // This function starts the broker process. It needs to be called + // before loaders can be launched. + bool Init(); + + // Send a message to the broker process, causing it to launch + // a Native Client loader process. + bool LaunchLoader(const std::wstring& loader_channel_id); + + private: + // ResourceDispatcherHost::Receiver implementation: + virtual URLRequestContext* GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data); + + virtual bool CanShutdown() { return true; } + + // Handler for NaClProcessMsg_BrokerReady message (sent by the broker process) + void OnBrokerReady(); + // Handler for NaClProcessMsg_LoaderLaunched message + void OnLoaderLaunched(const std::wstring& loader_channel_id, + base::ProcessHandle handle); + + // IPC::Channel::Listener + virtual void OnMessageReceived(const IPC::Message& msg); + + DISALLOW_COPY_AND_ASSIGN(NaClBrokerHost); +}; + +#endif // CHROME_BROWSER_NACL_HOST_NACL_BROKER_HOST_H_ diff --git a/chrome/browser/nacl_host/nacl_broker_service.cc b/chrome/browser/nacl_host/nacl_broker_service.cc new file mode 100644 index 0000000..ef659cd --- /dev/null +++ b/chrome/browser/nacl_host/nacl_broker_service.cc @@ -0,0 +1,69 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/nacl_host/nacl_broker_service.h" + +#include "chrome/browser/browser_process.h" +#include "chrome/browser/nacl_process_host.h" +#include "chrome/common/chrome_switches.h" + +NaClBrokerService* NaClBrokerService::GetInstance() { + return Singleton<NaClBrokerService>::get(); +} + +NaClBrokerService::NaClBrokerService() + : broker_started_(false), + broker_host_(NULL), + resource_dispatcher_host_(NULL), + initialized_(false) { +} + +void NaClBrokerService::Init(ResourceDispatcherHost* resource_dispatcher_host) { + if (initialized_) { + return; + } + resource_dispatcher_host_ = resource_dispatcher_host; + StartBroker(); + initialized_ = true; +} + +bool NaClBrokerService::StartBroker() { + broker_host_.reset(new NaClBrokerHost(resource_dispatcher_host_)); + if (!broker_host_->Init()) { + // Initialization failed, we will not retry in the future + broker_host_.reset(NULL); + } + return (broker_host_ != NULL); +} + +bool NaClBrokerService::LaunchLoader(NaClProcessHost* nacl_process_host, + const std::wstring& loader_channel_id) { + if (broker_started_) { + broker_host_->LaunchLoader(loader_channel_id); + } else { + // Add task to the list + pending_launches_[loader_channel_id] = nacl_process_host; + } + return true; +} + +void NaClBrokerService::OnBrokerStarted() { + PendingLaunchesMap::iterator it; + for (it = pending_launches_.begin(); it != pending_launches_.end(); it++) { + broker_host_->LaunchLoader(it->first); + } + broker_started_ = true; +} + +void NaClBrokerService::OnLoaderLaunched(const std::wstring& channel_id, + base::ProcessHandle handle) { + NaClProcessHost* client; + PendingLaunchesMap::iterator it = pending_launches_.find(channel_id); + if (pending_launches_.end() == it) { + NOTREACHED(); + } + client = it->second; + client->OnProcessLaunchedByBroker(handle); + pending_launches_.erase(it); +} diff --git a/chrome/browser/nacl_host/nacl_broker_service.h b/chrome/browser/nacl_host/nacl_broker_service.h new file mode 100644 index 0000000..75e089d --- /dev/null +++ b/chrome/browser/nacl_host/nacl_broker_service.h @@ -0,0 +1,57 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_NACL_HOST_NACL_BROKER_SERVICE_H_ +#define CHROME_BROWSER_NACL_HOST_NACL_BROKER_SERVICE_H_ + +#include <map> + +#include "base/basictypes.h" +#include "base/singleton.h" +#include "chrome/browser/nacl_host/nacl_broker_host.h" + +class NaClProcessHost; + +class NaClBrokerService { + public: + // Returns the NaClBrokerService singleton. + static NaClBrokerService* GetInstance(); + + void Init(ResourceDispatcherHost* resource_dispatcher_host); + + // Can be called several times, must be called before LaunchLoader. + bool StartBroker(); + + // Send a message to the broker process, causing it to launch + // a Native Client loader process. + bool LaunchLoader(NaClProcessHost* client, + const std::wstring& loader_channel_id); + + // Called by NaClBrokerHost to notify the service + // that the broker was launched. + void OnBrokerStarted(); + + // Called by NaClBrokerHost to notify the service that a loader was launched. + void OnLoaderLaunched(const std::wstring& channel_id, + base::ProcessHandle handle); + + private: + typedef std::map<std::wstring, NaClProcessHost*> + PendingLaunchesMap; + + friend struct DefaultSingletonTraits<NaClBrokerService>; + + NaClBrokerService(); + ~NaClBrokerService() {} + + bool broker_started_; + scoped_ptr<NaClBrokerHost> broker_host_; + bool initialized_; + ResourceDispatcherHost* resource_dispatcher_host_; + PendingLaunchesMap pending_launches_; + + DISALLOW_COPY_AND_ASSIGN(NaClBrokerService); +}; + +#endif // CHROME_BROWSER_NACL_HOST_NACL_BROKER_SERVICE_H_ diff --git a/chrome/browser/nacl_process_host.cc b/chrome/browser/nacl_process_host.cc index f736ab7..c82b06d 100644 --- a/chrome/browser/nacl_process_host.cc +++ b/chrome/browser/nacl_process_host.cc @@ -10,9 +10,12 @@ #include <fcntl.h> #endif +#include "base/command_line.h" +#include "chrome/browser/nacl_host/nacl_broker_service.h" #include "chrome/browser/renderer_host/resource_message_filter.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/logging_chrome.h" +#include "chrome/common/nacl_cmd_line.h" #include "chrome/common/nacl_messages.h" #include "chrome/common/render_messages.h" #include "ipc/ipc_switches.h" @@ -24,11 +27,15 @@ NaClProcessHost::NaClProcessHost( ResourceDispatcherHost *resource_dispatcher_host, const std::wstring& url) - : ChildProcessHost(NACL_PROCESS, resource_dispatcher_host), + : ChildProcessHost(NACL_LOADER_PROCESS, resource_dispatcher_host), resource_dispatcher_host_(resource_dispatcher_host), reply_msg_(NULL), - descriptor_(0) { + descriptor_(0), + running_on_wow64_(false) { set_name(url); +#if defined(OS_WIN) + CheckIsWow64(); +#endif } NaClProcessHost::~NaClProcessHost() { @@ -77,73 +84,67 @@ bool NaClProcessHost::LaunchSelLdr() { return false; CommandLine* cmd_line = new CommandLine(exe_path); - if (logging::DialogsAreSuppressed()) - cmd_line->AppendSwitch(switches::kNoErrorDialogs); - - // Propagate the following switches to the plugin command line (along with - // any associated values) if present in the browser command line. - // TODO(gregoryd): check which flags of those below can be supported. - static const char* const switch_names[] = { - switches::kNoSandbox, - switches::kTestSandbox, - switches::kDisableBreakpad, - switches::kFullMemoryCrashReport, - switches::kEnableLogging, - switches::kDisableLogging, - switches::kLoggingLevel, - switches::kEnableDCHECK, - switches::kSilentDumpOnDCHECK, - switches::kMemoryProfiling, -#if defined(OS_MACOSX) - // TODO(dspringer): remove this when NaCl x86-32 security issues are fixed - switches::kEnableNaClOnMac, -#endif - }; - - const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); + nacl::CopyNaClCommandLineArguments(cmd_line); #if defined(OS_MACOSX) -// TODO(dspringer): NaCl is temporalrily disabled on the Mac by default, but it -// can be enabled with the --enable-nacl cmd-line switch. Remove this check -// when the security issues in the Mac PIC code are resolved. - if (!browser_command_line.HasSwitch(switches::kEnableNaClOnMac)) + // TODO(dspringer): NaCl is temporalrily disabled on the Mac by default, but + // it can be enabled with the --enable-nacl cmd-line switch. Remove this check + // when the security issues in the Mac PIC code are resolved. + if (!cmd_line->HasSwitch(switches::kEnableNaClOnMac)) return false; #endif - for (size_t i = 0; i < arraysize(switch_names); ++i) { - if (browser_command_line.HasSwitch(switch_names[i])) { - cmd_line->AppendSwitchWithValue(switch_names[i], - browser_command_line.GetSwitchValueASCII(switch_names[i])); - } - } - cmd_line->AppendSwitchWithValue(switches::kProcessType, - switches::kNaClProcess); + switches::kNaClLoaderProcess); cmd_line->AppendSwitchWithValue(switches::kProcessChannelID, ASCIIToWide(channel_id())); - ChildProcessHost::Launch( + // On Windows we might need to start the broker process to launch a new loader #if defined(OS_WIN) - FilePath(), + if (running_on_wow64_) { + NaClBrokerService::GetInstance()->Init(resource_dispatcher_host_); + NaClBrokerService::GetInstance()->LaunchLoader(this, + ASCIIToWide(channel_id())); + } else +#endif + ChildProcessHost::Launch( +#if defined(OS_WIN) + FilePath(), #elif defined(OS_POSIX) - false, - base::environment_vector(), + false, + base::environment_vector(), #endif - cmd_line); + cmd_line); return true; } +void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) { + set_handle(handle); + OnProcessLaunched(); +} + +bool NaClProcessHost::DidChildCrash() { + if (running_on_wow64_) { + bool child_exited; + return base::DidProcessCrash(&child_exited, handle()); + } + return ChildProcessHost::DidChildCrash(); +} + void NaClProcessHost::OnProcessLaunched() { nacl::FileDescriptor imc_handle; base::ProcessHandle nacl_process_handle; #if NACL_WINDOWS // Duplicate the IMC handle + // We assume the size of imc_handle has the same size as HANDLE, so the cast + // below is safe. + DCHECK(sizeof(HANDLE) == sizeof(imc_handle)); DuplicateHandle(base::GetCurrentProcessHandle(), reinterpret_cast<HANDLE>(pair_[0]), resource_message_filter_->handle(), - &imc_handle, + reinterpret_cast<HANDLE*>(&imc_handle), GENERIC_READ | GENERIC_WRITE, FALSE, DUPLICATE_CLOSE_SOURCE); @@ -212,3 +213,24 @@ URLRequestContext* NaClProcessHost::GetRequestContext( const ViewHostMsg_Resource_Request& request_data) { return NULL; } + +#if defined(OS_WIN) +// TODO(gregoryd): invoke CheckIsWow64 only once, not for each NaClProcessHost +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); +void NaClProcessHost::CheckIsWow64() { + LPFN_ISWOW64PROCESS fnIsWow64Process; + + fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( + GetModuleHandle(TEXT("kernel32")), + "IsWow64Process"); + + if (fnIsWow64Process != NULL) { + BOOL bIsWow64 = FALSE; + if (fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) { + if (bIsWow64) { + running_on_wow64_ = true; + } + } + } +} +#endif diff --git a/chrome/browser/nacl_process_host.h b/chrome/browser/nacl_process_host.h index 8159836..ca416f6 100644 --- a/chrome/browser/nacl_process_host.h +++ b/chrome/browser/nacl_process_host.h @@ -33,6 +33,11 @@ class NaClProcessHost : public ChildProcessHost { virtual void OnMessageReceived(const IPC::Message& msg); + void OnProcessLaunchedByBroker(base::ProcessHandle handle); + + protected: + virtual bool DidChildCrash(); + private: bool LaunchSelLdr(); @@ -47,6 +52,11 @@ class NaClProcessHost : public ChildProcessHost { virtual bool CanShutdown() { return true; } +#if defined(OS_WIN) + // Check whether the browser process is running on WOW64 - Windows only + void CheckIsWow64(); +#endif + private: ResourceDispatcherHost* resource_dispatcher_host_; @@ -63,6 +73,9 @@ class NaClProcessHost : public ChildProcessHost { // The NaCl specific descriptor for this process. int descriptor_; + // Windows platform flag + bool running_on_wow64_; + DISALLOW_COPY_AND_ASSIGN(NaClProcessHost); }; |