diff options
author | gregoryd@google.com <gregoryd@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-29 00:33:46 +0000 |
---|---|---|
committer | gregoryd@google.com <gregoryd@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-29 00:33:46 +0000 |
commit | d032f495aa168d053b8012193ecad0a60dde2595 (patch) | |
tree | b0f2952d2f68108b37ace6eaadb5bc4dd5ad0b1c | |
parent | bc1407f95bae3d7472ee0c85ef83ee10610b3f1f (diff) | |
download | chromium_src-d032f495aa168d053b8012193ecad0a60dde2595.zip chromium_src-d032f495aa168d053b8012193ecad0a60dde2595.tar.gz chromium_src-d032f495aa168d053b8012193ecad0a60dde2595.tar.bz2 |
First step towards NaCl-Chrome integration:1. NaCl plugin becomes a built-in plugin in Chrome and runs in the renderer process.2. Most of the changes are related to launching the NaCl process (that loads and runs the NaCl module) and establishing the initial communication between that process and the NaCl plugin.3. Command line flag "--internal-nacl" is required to enable the built-in NaCl plugin. NaCl still cannot run in Chrome sandbox, the flag automatically disables the sandboxCommitted: http://src.chromium.org/viewvc/chrome?view=rev&revision=27315
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=27324
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=27397
Review URL: http://codereview.chromium.org/153002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27445 0039d316-1c4b-4281-b951-d872f2087c98
29 files changed, 516 insertions, 42 deletions
@@ -40,7 +40,7 @@ deps = { "http://v8.googlecode.com/svn/trunk@2966", "src/native_client": - "http://nativeclient.googlecode.com/svn/trunk/src/native_client@730", + "http://nativeclient.googlecode.com/svn/trunk/src/native_client@797", "src/third_party/skia": "http://skia.googlecode.com/svn/trunk@341", diff --git a/base/format_macros.h b/base/format_macros.h index 4b713ef..383579f 100644 --- a/base/format_macros.h +++ b/base/format_macros.h @@ -37,9 +37,17 @@ #else // OS_WIN +#if !defined(PRId64) #define PRId64 "I64d" +#endif + +#if !defined(PRIu64) #define PRIu64 "I64u" +#endif + +#if !defined(PRIx64) #define PRIx64 "I64x" +#endif #define WidePRId64 L"I64d" #define WidePRIu64 L"I64u" diff --git a/chrome/app/chrome_dll_main.cc b/chrome/app/chrome_dll_main.cc index ecf2640..63dcc70 100644 --- a/chrome/app/chrome_dll_main.cc +++ b/chrome/app/chrome_dll_main.cc @@ -80,6 +80,7 @@ extern int BrowserMain(const MainFunctionParams&); extern int RendererMain(const MainFunctionParams&); extern int PluginMain(const MainFunctionParams&); extern int WorkerMain(const MainFunctionParams&); +extern int NaClMain(const MainFunctionParams&); extern int UtilityMain(const MainFunctionParams&); extern int ProfileImportMain(const MainFunctionParams&); extern int ZygoteMain(const MainFunctionParams&); @@ -563,6 +564,8 @@ int ChromeMain(int argc, char** argv) { #endif } else if (process_type == switches::kWorkerProcess) { rv = WorkerMain(main_params); + } else if (process_type == switches::kNaClProcess) { + rv = NaClMain(main_params); } else if (process_type == switches::kZygoteProcess) { #if defined(OS_LINUX) if (ZygoteMain(main_params)) { diff --git a/chrome/browser/nacl_process_host.cc b/chrome/browser/nacl_process_host.cc new file mode 100644 index 0000000..72db561 --- /dev/null +++ b/chrome/browser/nacl_process_host.cc @@ -0,0 +1,187 @@ +// Copyright (c) 2009 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 "build/build_config.h" + +#include "chrome/browser/nacl_process_host.h" + +#if defined(OS_POSIX) +#include <fcntl.h> +#endif + +#if defined(OS_POSIX) +#include "base/global_descriptors_posix.h" +#endif +#include "base/path_service.h" +#include "base/process_util.h" +#include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/common/chrome_descriptors.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/logging_chrome.h" +#include "chrome/common/nacl_messages.h" +#include "ipc/ipc_switches.h" + +#if defined(OS_WIN) +#include "chrome/browser/sandbox_policy.h" +#endif + +#if defined(OS_POSIX) +#include "ipc/ipc_channel_posix.h" +#endif + +NaClProcessHost::NaClProcessHost( + ResourceDispatcherHost *resource_dispatcher_host) + : ChildProcessHost(NACL_PROCESS, resource_dispatcher_host), + resource_dispatcher_host_(resource_dispatcher_host) { +} + +bool NaClProcessHost::Launch(ResourceMessageFilter* renderer_msg_filter, + const int descriptor, + nacl::FileDescriptor* handle) { + nacl::Handle pair[2]; + bool success = false; + // Create a connected socket + if (nacl::SocketPair(pair) == -1) { + NATIVE_HANDLE(*handle) = nacl::kInvalidHandle; + return false; + } + + // Launch the process + success = LaunchSelLdr(renderer_msg_filter, descriptor, pair[1]); + + if (!success) { + nacl::Close(pair[0]); + NATIVE_HANDLE(*handle) = nacl::kInvalidHandle; + return false; + } + + nacl::Handle duplicate_handle = nacl::kInvalidHandle; +#if NACL_WINDOWS + DuplicateHandle(base::GetCurrentProcessHandle(), + reinterpret_cast<HANDLE>(pair[0]), + renderer_msg_filter->handle(), + reinterpret_cast<HANDLE*>(&duplicate_handle), + GENERIC_READ | GENERIC_WRITE, + FALSE, + DUPLICATE_CLOSE_SOURCE); + *handle = duplicate_handle; +#else + duplicate_handle = pair[0]; + int flags = fcntl(duplicate_handle, F_GETFD); + if (flags != -1) { + flags |= FD_CLOEXEC; + fcntl(duplicate_handle, F_SETFD, flags); + } + // No need to dup the handle - we don't pass it anywhere else so + // it cannot be closed. + handle->fd = duplicate_handle; + handle->auto_close = true; +#endif + + return true; +} + +bool NaClProcessHost::LaunchSelLdr(ResourceMessageFilter* renderer_msg_filter, + const int descriptor, + const nacl::Handle handle) { + if (!CreateChannel()) + return false; + + // Build command line for nacl. + const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); + std::wstring exe_path = + browser_command_line.GetSwitchValue(switches::kBrowserSubprocessPath); + if (exe_path.empty() && !PathService::Get(base::FILE_EXE, &exe_path)) + return false; + + CommandLine cmd_line(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 wchar_t* const switch_names[] = { + switches::kNoSandbox, + switches::kTestSandbox, + switches::kDisableBreakpad, + switches::kFullMemoryCrashReport, + switches::kEnableLogging, + switches::kDisableLogging, + switches::kLoggingLevel, + switches::kEnableDCHECK, + switches::kSilentDumpOnDCHECK, + switches::kMemoryProfiling, + }; + + 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.GetSwitchValue(switch_names[i])); + } + } + + cmd_line.AppendSwitchWithValue(switches::kProcessType, + switches::kNaClProcess); + + cmd_line.AppendSwitchWithValue(switches::kProcessChannelID, + ASCIIToWide(channel_id())); + + base::ProcessHandle process = 0; +#if defined(OS_WIN) + process = sandbox::StartProcess(&cmd_line); +#else + base::file_handle_mapping_vector fds_to_map; + const int ipcfd = channel().GetClientFileDescriptor(); + if (ipcfd > -1) + fds_to_map.push_back(std::pair<int, int>( + ipcfd, kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor)); + base::LaunchApp(cmd_line.argv(), fds_to_map, false, &process); +#endif + + if (!process) + return false; + SetHandle(process); + + // send a message with duplicated handle to sel_ldr + return SendStartMessage(process, descriptor, handle); +} + +bool NaClProcessHost::SendStartMessage(base::ProcessHandle process, + int descriptor, + nacl::Handle handle) { + nacl::FileDescriptor channel; +#if defined(OS_WIN) + if (!DuplicateHandle(GetCurrentProcess(), + reinterpret_cast<HANDLE>(handle), + process, + reinterpret_cast<HANDLE*>(&channel), + GENERIC_READ | GENERIC_WRITE, + FALSE, DUPLICATE_CLOSE_SOURCE)) { + return false; + } +#else + channel.fd = dup(handle); + channel.auto_close = true; +#endif + NaClProcessMsg_Start* msg = new NaClProcessMsg_Start(descriptor, + channel); + + if (!Send(msg)) { + return false; + } + return true; +} + +void NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { + NOTREACHED() << "Invalid message with type = " << msg.type(); +} + +URLRequestContext* NaClProcessHost::GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data) { + return NULL; +} + diff --git a/chrome/browser/nacl_process_host.h b/chrome/browser/nacl_process_host.h new file mode 100644 index 0000000..59de526 --- /dev/null +++ b/chrome/browser/nacl_process_host.h @@ -0,0 +1,55 @@ +// Copyright (c) 2009 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_PROCESS_HOST_H_ +#define CHROME_BROWSER_NACL_PROCESS_HOST_H_ + +#include "build/build_config.h" +#include "chrome/common/child_process_host.h" +#include "chrome/common/nacl_types.h" +#include "native_client/src/shared/imc/nacl_imc.h" + +class ResourceMessageFilter; + +// Represents the browser side of the browser <--> NaCl communication +// channel. There will be one NaClProcessHost per NaCl process +// The browser is responsible for starting the NaCl process +// when requested by the renderer. +// After that, most of the communication is directly between NaCl plugin +// running in the renderer and NaCl processes. +class NaClProcessHost : public ChildProcessHost { + public: + explicit NaClProcessHost(ResourceDispatcherHost *resource_dispatcher_host); + ~NaClProcessHost() {} + + // Initialize the new NaCl process, returning true on success. + bool Launch(ResourceMessageFilter* renderer_msg_filter, + const int descriptor, + nacl::FileDescriptor *handle); + + virtual void OnMessageReceived(const IPC::Message& msg); + + private: + bool LaunchSelLdr(ResourceMessageFilter* renderer_msg_filter, + const int descriptor, + const nacl::Handle handle); + + bool SendStartMessage(base::ProcessHandle process, + int descriptor, + nacl::Handle handle); + + // ResourceDispatcherHost::Receiver implementation: + virtual URLRequestContext* GetRequestContext( + uint32 request_id, + const ViewHostMsg_Resource_Request& request_data); + + virtual bool CanShutdown() { return true; } + + private: + ResourceDispatcherHost* resource_dispatcher_host_; + + DISALLOW_COPY_AND_ASSIGN(NaClProcessHost); +}; + +#endif // CHROME_BROWSER_NACL_PROCESS_HOST_H_ diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index 42a67e9..5c5a8bb 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -23,6 +23,7 @@ #include "chrome/common/notification_type.h" #include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" +#include "native_client/src/trusted/plugin/nacl_entry_points.h" #include "webkit/glue/plugins/plugin_constants_win.h" #include "webkit/glue/plugins/plugin_list.h" @@ -44,6 +45,8 @@ PluginService::PluginService() NPAPI::PluginList::Singleton()->AddExtraPluginPath( FilePath::FromWStringHack(path)); } + if (command_line->HasSwitch(switches::kInternalNaCl)) + RegisterInternalNaClPlugin(); #if defined(OS_WIN) hkcu_key_.Create( diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index 676f8ce..159a190 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -329,6 +329,7 @@ bool BrowserRenderProcessHost::Init() { switches::kDisableAudio, switches::kSimpleDataSource, switches::kEnableBenchmarking, + switches::kInternalNaCl, switches::kEnableDatabases, }; diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 44032b1..a7d9360 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -15,6 +15,7 @@ #include "chrome/browser/chrome_thread.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h" +#include "chrome/browser/nacl_process_host.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/plugin_service.h" @@ -295,6 +296,7 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { OnReceiveContextMenuMsg(msg)) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, OnOpenChannelToPlugin) + IPC_MESSAGE_HANDLER(ViewHostMsg_LaunchNaCl, OnLaunchNaCl) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateDedicatedWorker, OnCreateDedicatedWorker) IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, @@ -583,6 +585,12 @@ void ResourceMessageFilter::OnOpenChannelToPlugin(const GURL& url, this, url, mime_type, locale, reply_msg); } +void ResourceMessageFilter::OnLaunchNaCl(int channel_descriptor, + nacl::FileDescriptor* handle) { + NaClProcessHost* nacl_host = new NaClProcessHost(resource_dispatcher_host_); + nacl_host->Launch(this, channel_descriptor, handle); +} + void ResourceMessageFilter::OnCreateDedicatedWorker(const GURL& url, int render_view_route_id, int* route_id) { diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 2e54492..97b3eb7 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -24,6 +24,7 @@ #include "chrome/browser/net/resolve_proxy_msg_helper.h" #include "chrome/browser/renderer_host/render_widget_helper.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" +#include "chrome/common/nacl_types.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/transport_dib.h" #include "ipc/ipc_channel_proxy.h" @@ -152,6 +153,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, const std::string& mime_type, const std::wstring& locale, IPC::Message* reply_msg); + void OnLaunchNaCl(int channel_descriptor, + nacl::FileDescriptor* handle); void OnCreateDedicatedWorker(const GURL& url, int render_view_route_id, int* route_id); diff --git a/chrome/browser/sandbox_policy.cc b/chrome/browser/sandbox_policy.cc index 4be8a23..f13ef72 100644 --- a/chrome/browser/sandbox_policy.cc +++ b/chrome/browser/sandbox_policy.cc @@ -343,6 +343,8 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line, type = ChildProcessInfo::PLUGIN_PROCESS; } else if (type_str == switches::kWorkerProcess) { type = ChildProcessInfo::WORKER_PROCESS; + } else if (type_str == switches::kNaClProcess) { + type = ChildProcessInfo::NACL_PROCESS; } else if (type_str == switches::kUtilityProcess) { type = ChildProcessInfo::UTILITY_PROCESS; } else { @@ -355,8 +357,10 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line, (type != ChildProcessInfo::PLUGIN_PROCESS || browser_command_line.HasSwitch(switches::kSafePlugins)); #if !defined (GOOGLE_CHROME_BUILD) - if (browser_command_line.HasSwitch(switches::kInProcessPlugins)) { + if (browser_command_line.HasSwitch(switches::kInProcessPlugins) || + browser_command_line.HasSwitch(switches::kInternalNaCl)) { // In process plugins won't work if the sandbox is enabled. + // The internal NaCl plugin doesn't work in the sandbox for now. in_sandbox = false; } #endif @@ -378,6 +382,8 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line, sandbox::TargetPolicy* policy = broker_service->CreatePolicy(); bool on_sandbox_desktop = false; + // TODO(gregoryd): try locked-down policy for sel_ldr after we fix IMC. + // TODO(gregoryd): do we need a new desktop for sel_ldr? if (type == ChildProcessInfo::PLUGIN_PROCESS) { if (!AddPolicyForPlugin(cmd_line, policy)) return 0; diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 5d1e78d..7b09ee6 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -108,7 +108,26 @@ '../views/grid_layout_unittest.cc', ], 'conditions': [ + ['OS=="win"', { + 'nacl_defines': [ + 'NACL_WINDOWS=1', + 'NACL_LINUX=0', + 'NACL_OSX=0', + ], + },], + ['OS=="linux"', { + 'nacl_defines': [ + 'NACL_WINDOWS=0', + 'NACL_LINUX=1', + 'NACL_OSX=0', + ], + },], ['OS=="mac"', { + 'nacl_defines': [ + 'NACL_WINDOWS=0', + 'NACL_LINUX=0', + 'NACL_OSX=1', + ], 'conditions': [ ['branding=="Chrome"', { 'mac_bundle_id': 'com.google.Chrome', @@ -128,6 +147,20 @@ 'chrome_personalization%': 0, 'use_syncapi_stub%': 1, }], # OS=="win" + ['target_arch=="ia32"', { + 'nacl_defines': [ + # TODO(gregoryd): consider getting this from NaCl's common.gypi + 'NACL_TARGET_SUBARCH=32', + 'NACL_BUILD_SUBARCH=32', + ], + }], + ['target_arch=="x64"', { + 'nacl_defines': [ + # TODO(gregoryd): consider getting this from NaCl's common.gypi + 'NACL_TARGET_SUBARCH=64', + 'NACL_BUILD_SUBARCH=64', + ], + }], ], # conditions }, # variables 'target_defaults': { @@ -596,6 +629,8 @@ 'common/sandbox_init_wrapper.h', 'common/security_filter_peer.cc', 'common/security_filter_peer.h', + 'common/nacl_messages.h', + 'common/nacl_messages_internal.h', 'common/sqlite_compiled_statement.cc', 'common/sqlite_compiled_statement.h', 'common/sqlite_utils.cc', @@ -710,6 +745,9 @@ '..', '<(INTERMEDIATE_DIR)', ], + 'defines': [ + '<@(nacl_defines)', + ], 'sources': [ # All .cc, .h, .m, and .mm files under browser except for tests and # mocks. @@ -1838,6 +1876,8 @@ 'browser/search_engines/template_url_prepopulate_data.h', 'browser/search_engines/template_url_table_model.cc', 'browser/search_engines/template_url_table_model.h', + 'browser/nacl_process_host.cc', + 'browser/nacl_process_host.h', 'browser/session_startup_pref.cc', 'browser/session_startup_pref.h', 'browser/sessions/base_session_service.cc', @@ -2880,11 +2920,57 @@ ], }, { + 'target_name': 'nacl', + 'type': '<(library)', + 'msvs_guid': '83E86DAF-5763-4711-AD34-5FDAE395560C', + 'dependencies': [ + 'common', + 'chrome_resources', + 'chrome_strings', + '../third_party/npapi/npapi.gyp:npapi', + '../webkit/webkit.gyp:glue', + '../native_client/src/trusted/plugin/plugin_chrome.gyp:npGoogleNaClPluginChrome', + '../native_client/src/trusted/service_runtime/service_runtime.gyp:sel', + '../native_client/src/trusted/validator_x86/validator_x86.gyp:ncvalidate', + '../native_client/src/trusted/platform_qualify/platform_qualify.gyp:platform_qual_lib', + ], + 'include_dirs': [ + '<(INTERMEDIATE_DIR)', + ], + 'defines': [ + 'NACL_BLOCK_SHIFT=5', + 'NACL_BLOCK_SIZE=32', + '<@(nacl_defines)', + ], + 'sources': [ + # All .cc, .h, .m, and .mm files under nacl except for tests and + # mocks. + 'nacl/sel_main.cc', + 'nacl/nacl_main.cc', + 'nacl/nacl_thread.cc', + 'nacl/nacl_thread.h', + ], + # TODO(gregoryd): consider switching NaCl to use Chrome OS defines + 'conditions': [ + ['OS=="win"', { + 'defines': [ + '__STD_C', + '_CRT_SECURE_NO_DEPRECATE', + '_SCL_SECURE_NO_DEPRECATE', + ], + 'include_dirs': [ + 'third_party/wtl/include', + ], + },], + ], + }, + { 'target_name': 'renderer', 'type': '<(library)', 'msvs_guid': '9301A569-5D2B-4D11-9332-B1E30AEACB8D', 'dependencies': [ 'common', + 'nacl', 'plugin', 'chrome_resources', 'chrome_strings', @@ -2899,6 +2985,9 @@ 'include_dirs': [ '..', ], + 'defines': [ + '<@(nacl_defines)', + ], 'sources': [ # TODO(jrg): to link ipc_tests, these files need to be in renderer.a. # But app/ is the wrong directory for them. @@ -3377,6 +3466,8 @@ 'infoplist_strings_tool', # Bring in pdfsqueeze and run it on all pdfs '../build/temp_gyp/pdfsqueeze.gyp:pdfsqueeze', + # This library provides the real implementation for NaClSyscallSeg + '../native_client/src/trusted/service_runtime/arch/x86_32/service_runtime_x86_32.gyp:service_runtime_x86_32_chrome' ], 'rules': [ { diff --git a/chrome/common/child_process_info.h b/chrome/common/child_process_info.h index 250ff57..c99b2c0 100644 --- a/chrome/common/child_process_info.h +++ b/chrome/common/child_process_info.h @@ -17,6 +17,7 @@ class ChildProcessInfo { RENDER_PROCESS, PLUGIN_PROCESS, WORKER_PROCESS, + NACL_PROCESS, UTILITY_PROCESS, PROFILE_IMPORT_PROCESS, ZYGOTE_PROCESS, diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 762d524..e79f345 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -71,6 +71,9 @@ const wchar_t kPluginProcess[] = L"plugin"; // Causes the process to run as a worker subprocess. const wchar_t kWorkerProcess[] = L"worker"; +// Causes the process to run as a NativeClient's sel_ldr subprocess. +const wchar_t kNaClProcess[] = L"nacl"; + // Causes the process to run as a utility subprocess. const wchar_t kUtilityProcess[] = L"utility"; @@ -367,6 +370,9 @@ const wchar_t kEnableRemoteFonts[] = L"enable-remote-fonts"; // Use the low fragmentation heap for the CRT. const wchar_t kUseLowFragHeapCrt[] = L"use-lf-heap"; +// Runs the Native Client inside the renderer process. +const wchar_t kInternalNaCl[] = L"internal-nacl"; + #ifndef NDEBUG // Debug only switch to specify which gears plugin dll to load. const wchar_t kGearsPluginPathOverride[] = L"gears-plugin-path"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 5602c58..3696066 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -30,6 +30,7 @@ extern const wchar_t kZygoteProcess[]; extern const wchar_t kBrowserSubprocessPath[]; extern const wchar_t kPluginProcess[]; extern const wchar_t kWorkerProcess[]; +extern const wchar_t kNaClProcess[]; extern const wchar_t kUtilityProcess[]; extern const wchar_t kProfileImportProcess[]; extern const wchar_t kSingleProcess[]; @@ -133,6 +134,8 @@ extern const wchar_t kEnableRemoteFonts[]; extern const wchar_t kUseLowFragHeapCrt[]; +extern const wchar_t kInternalNaCl[]; + #ifndef NDEBUG extern const wchar_t kGearsPluginPathOverride[]; #endif diff --git a/chrome/common/nacl_messages.h b/chrome/common/nacl_messages.h new file mode 100644 index 0000000..8d360dd --- /dev/null +++ b/chrome/common/nacl_messages.h @@ -0,0 +1,19 @@ +// Copyright (c) 2009 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. + +// Defines messages between the browser and NaCl process. + +#ifndef CHROME_COMMON_NACL_MESSAGES_H_ +#define CHROME_COMMON_NACL_MESSAGES_H_ + +#include <string> + +#include "base/basictypes.h" +#include "ipc/ipc_message_utils.h" + +#define MESSAGES_INTERNAL_FILE "chrome/common/nacl_messages_internal.h" +#include "ipc/ipc_message_macros.h" + +#endif // CHROME_COMMON_NACL_MESSAGES_H_ + diff --git a/chrome/common/nacl_messages_internal.h b/chrome/common/nacl_messages_internal.h new file mode 100644 index 0000000..3794255 --- /dev/null +++ b/chrome/common/nacl_messages_internal.h @@ -0,0 +1,18 @@ +// Copyright (c) 2009 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/common/nacl_types.h" +#include "ipc/ipc_message_macros.h" + +//----------------------------------------------------------------------------- +// NaClProcess messages +// These are messages sent from the browser to the NaCl process. +IPC_BEGIN_MESSAGES(NaClProcess) + // Tells the NaCl process to start. + IPC_MESSAGE_CONTROL2(NaClProcessMsg_Start, + int /* descriptor id */, + nacl::FileDescriptor /* handle value */) + +IPC_END_MESSAGES(NaClProcess) + diff --git a/chrome/common/nacl_types.h b/chrome/common/nacl_types.h new file mode 100644 index 0000000..394edd3 --- /dev/null +++ b/chrome/common/nacl_types.h @@ -0,0 +1,21 @@ +// Copyright (c) 2009 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. + +// Handle passing definitions for NaCl +#ifndef CHROME_COMMON_NACL_TYPES_H_ +#define CHROME_COMMON_NACL_TYPES_H_ + +// TODO(gregoryd): add a Windows definition for base::FileDescriptor, +// replace the macros with inline functions. +namespace nacl { +#if defined(OS_WIN) +typedef HANDLE FileDescriptor; +#define NATIVE_HANDLE(desc) (desc) +#elif defined(OS_POSIX) +typedef base::FileDescriptor FileDescriptor; +#define NATIVE_HANDLE(desc) ((desc).fd) +#endif +} + +#endif // CHROME_COMMON_NACL_TYPES_H_ diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 28dc35b..d590294 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -22,6 +22,7 @@ #include "base/values.h" #include "chrome/common/css_colors.h" #include "chrome/common/extensions/update_manifest.h" +#include "chrome/common/nacl_types.h" #include "chrome/common/notification_type.h" #include "chrome/common/transport_dib.h" #include "chrome/common/view_types.h" @@ -1105,6 +1106,14 @@ IPC_BEGIN_MESSAGES(ViewHost) IPC::ChannelHandle /* handle to channel */, WebPluginInfo /* info */) + // A renderer sends this to the browser process when it wants to start + // a new instance of the Native Client process. The browser will launch + // the process and return a handle to an IMC channel. + IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_LaunchNaCl, + int /* channel number */, + nacl::FileDescriptor /* handle - one side + of a socket pair */) + #if defined(OS_LINUX) // A renderer sends this when it needs a browser-side widget for // hosting a windowed plugin. id is the XID of the plugin window, for which diff --git a/chrome/common/sandbox_init_wrapper.cc b/chrome/common/sandbox_init_wrapper.cc index c296ff8..14006ed 100644 --- a/chrome/common/sandbox_init_wrapper.cc +++ b/chrome/common/sandbox_init_wrapper.cc @@ -27,6 +27,7 @@ void SandboxInitWrapper::InitializeSandbox(const CommandLine& command_line, if (!command_line.HasSwitch(switches::kNoSandbox)) { if ((process_type == switches::kRendererProcess) || (process_type == switches::kWorkerProcess) || + (process_type == switches::kNaClProcess) || (process_type == switches::kUtilityProcess) || (process_type == switches::kPluginProcess && command_line.HasSwitch(switches::kSafePlugins))) { diff --git a/chrome/nacl/nacl_main.cc b/chrome/nacl/nacl_main.cc index f519748..0516495 100644 --- a/chrome/nacl/nacl_main.cc +++ b/chrome/nacl/nacl_main.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. diff --git a/chrome/nacl/nacl_thread.cc b/chrome/nacl/nacl_thread.cc index ff4f508..3ed7c93 100644 --- a/chrome/nacl/nacl_thread.cc +++ b/chrome/nacl/nacl_thread.cc @@ -1,10 +1,9 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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/nacl/nacl_thread.h" -#include "build/build_config.h" #include "chrome/common/notification_service.h" #include "chrome/common/nacl_messages.h" #include "native_client/src/trusted/service_runtime/include/sys/nacl_imc_api.h" @@ -27,7 +26,7 @@ void NaClThread::OnControlMessageReceived(const IPC::Message& msg) { IPC_END_MESSAGE_MAP() } -void NaClThread::OnStartSelLdr(const int channel_descriptor, - const nacl::FileDescriptor handle) { +void NaClThread::OnStartSelLdr(int channel_descriptor, + nacl::FileDescriptor handle) { SelMain(channel_descriptor, NATIVE_HANDLE(handle)); } diff --git a/chrome/nacl/nacl_thread.h b/chrome/nacl/nacl_thread.h index a69ce3a..fd8fe76 100644 --- a/chrome/nacl/nacl_thread.h +++ b/chrome/nacl/nacl_thread.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. @@ -23,13 +23,10 @@ class NaClThread : public ChildThread { private: virtual void OnControlMessageReceived(const IPC::Message& msg); - void OnStartSelLdr(const int channel_descriptor, - const nacl::FileDescriptor handle); - // TODO(gregoryd): do we need to override Cleanup as in PluginThread? - - scoped_ptr<NotificationService> notification_service_; + void OnStartSelLdr(int channel_descriptor, nacl::FileDescriptor handle); - DISALLOW_EVIL_CONSTRUCTORS(NaClThread); + // TODO(gregoryd): do we need to override Cleanup as in PluginThread? + DISALLOW_COPY_AND_ASSIGN(NaClThread); }; #endif // CHROME_NACL_NACL_THREAD_H_ diff --git a/chrome/nacl/sel_main.cc b/chrome/nacl/sel_main.cc index 7174706..7258205 100644 --- a/chrome/nacl/sel_main.cc +++ b/chrome/nacl/sel_main.cc @@ -1,9 +1,7 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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 "build/build_config.h" - #include "native_client/src/include/portability.h" #if NACL_OSX diff --git a/chrome/renderer/render_process.cc b/chrome/renderer/render_process.cc index 610e5d3..0c579ea 100644 --- a/chrome/renderer/render_process.cc +++ b/chrome/renderer/render_process.cc @@ -25,11 +25,13 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/render_messages.h" +#include "chrome/common/nacl_types.h" #include "chrome/common/transport_dib.h" #include "chrome/renderer/render_view.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_message_utils.h" #include "media/base/media.h" +#include "native_client/src/trusted/plugin/nacl_entry_points.h" #include "webkit/glue/webkit_glue.h" //----------------------------------------------------------------------------- @@ -80,6 +82,9 @@ RenderProcess::RenderProcess() StatisticsRecorder::set_dump_on_exit(true); } + if (command_line.HasSwitch(switches::kInternalNaCl)) + RegisterInternalNaClPlugin(RenderProcess::LaunchNaClProcess); + FilePath module_path; initialized_media_library_ = PathService::Get(base::DIR_MODULE, &module_path) && @@ -112,6 +117,19 @@ bool RenderProcess::InProcessPlugins() { #endif } +bool RenderProcess::LaunchNaClProcess(int imc_fd, + nacl::Handle* handle) { + // TODO(gregoryd): nacl::FileDescriptor will be soon merged with + // base::FileDescriptor + nacl::FileDescriptor descriptor; + if (!RenderThread::current()->Send( + new ViewHostMsg_LaunchNaCl(imc_fd, &descriptor))) { + return false; + } + *handle = NATIVE_HANDLE(descriptor); + return true; +} + // ----------------------------------------------------------------------------- // Platform specific code for dealing with bitmap transport... diff --git a/chrome/renderer/render_process.h b/chrome/renderer/render_process.h index d445fbe..0ab9996 100644 --- a/chrome/renderer/render_process.h +++ b/chrome/renderer/render_process.h @@ -8,6 +8,7 @@ #include "base/timer.h" #include "chrome/common/child_process.h" #include "chrome/renderer/render_thread.h" +#include "native_client/src/shared/imc/nacl_imc.h" #include "skia/ext/platform_canvas.h" namespace gfx { @@ -51,6 +52,10 @@ class RenderProcess : public ChildProcess { // Just like in_process_plugins(), but called before RenderProcess is created. static bool InProcessPlugins(); + // Sends a message to the browser process asking to launch a new NaCl process. + // Called from NaCl plugin code. + static bool LaunchNaClProcess(int imc_fd, nacl::Handle *handle); + private: // Look in the shared memory cache for a suitable object to reuse. // result: (output) the memory found diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index e86c27d..231cfa7 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -2338,7 +2338,13 @@ webkit_glue::WebPluginDelegate* RenderView::CreatePluginDelegate( else mime_type_to_use = &mime_type; - if (RenderProcess::current()->in_process_plugins()) { + bool in_process_plugin = RenderProcess::current()->in_process_plugins(); + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInternalNaCl)) { + if (mime_type == "application/x-nacl-srpc") { + in_process_plugin = true; + } + } + if (in_process_plugin) { #if defined(OS_WIN) // In-proc plugins aren't supported on Linux or Mac. return WebPluginDelegateImpl::Create( path, *mime_type_to_use, gfx::NativeViewFromId(host_window_)); diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h index 15d5297..fd0c064 100644 --- a/ipc/ipc_message_utils.h +++ b/ipc/ipc_message_utils.h @@ -44,6 +44,7 @@ enum IPCMessageStart { WorkerProcessHostMsgStart, WorkerMsgStart, WorkerHostMsgStart, + NaClProcessMsgStart, // NOTE: When you add a new message class, also update // IPCStatusView::IPCStatusView to ensure logging works. // NOTE: this enum is used by IPC_MESSAGE_MACRO to generate a unique message diff --git a/webkit/glue/plugins/plugin_lib.h b/webkit/glue/plugins/plugin_lib.h index ed523c12..e8bb44a 100644 --- a/webkit/glue/plugins/plugin_lib.h +++ b/webkit/glue/plugins/plugin_lib.h @@ -61,6 +61,8 @@ class PluginLib : public base::RefCounted<PluginLib> { // supports. const WebPluginInfo& plugin_info() { return web_plugin_info_; } + bool internal() { return internal_; } + // // NPAPI functions // @@ -91,7 +93,7 @@ class PluginLib : public base::RefCounted<PluginLib> { void Shutdown(); private: - bool internal_; // Whether this an internal plugin. + bool internal_; // True for plugins that are built-in into chrome binaries. WebPluginInfo web_plugin_info_; // supported mime types, description base::NativeLibrary library_; // the opened library reference NPPluginFuncs plugin_funcs_; // the struct of plugin side functions diff --git a/webkit/glue/plugins/webplugin_delegate_impl_win.cc b/webkit/glue/plugins/webplugin_delegate_impl_win.cc index 1f13cf8..9d8ed45 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_win.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_win.cc @@ -326,35 +326,40 @@ void WebPluginDelegateImpl::PluginDestroyed() { void WebPluginDelegateImpl::PlatformInitialize() { plugin_->SetWindow(windowed_handle_); - if (windowless_) { + + if (windowless_ && !instance_->plugin_lib()->internal()) { CreateDummyWindowForActivation(); handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); plugin_->SetWindowlessPumpEvent(handle_event_pump_messages_event_); } - // Windowless plugins call the WindowFromPoint API and passes the result of - // that to the TrackPopupMenu API call as the owner window. This causes the - // API to fail as the API expects the window handle to live on the same thread - // as the caller. It works in the other browsers as the plugin lives on the - // browser thread. Our workaround is to intercept the TrackPopupMenu API and - // replace the window handle with the dummy activation window. - if (windowless_ && !g_iat_patch_track_popup_menu.Pointer()->is_patched()) { - g_iat_patch_track_popup_menu.Pointer()->Patch( - GetPluginPath().value().c_str(), "user32.dll", "TrackPopupMenu", - WebPluginDelegateImpl::TrackPopupMenuPatch); - } + // We cannot patch internal plugins as they are not shared libraries. + if (!instance_->plugin_lib()->internal()) { + // Windowless plugins call the WindowFromPoint API and passes the result of + // that to the TrackPopupMenu API call as the owner window. This causes the + // API to fail as the API expects the window handle to live on the same + // thread as the caller. It works in the other browsers as the plugin lives + // on the browser thread. Our workaround is to intercept the TrackPopupMenu + // API and replace the window handle with the dummy activation window. + if (windowless_ && !g_iat_patch_track_popup_menu.Pointer()->is_patched()) { + g_iat_patch_track_popup_menu.Pointer()->Patch( + GetPluginPath().value().c_str(), "user32.dll", "TrackPopupMenu", + WebPluginDelegateImpl::TrackPopupMenuPatch); + } - // Windowless plugins can set cursors by calling the SetCursor API. This - // works because the thread inputs of the browser UI thread and the plugin - // thread are attached. We intercept the SetCursor API for windowless plugins - // and remember the cursor being set. This is shipped over to the browser - // in the HandleEvent call, which ensures that the cursor does not change - // when a windowless plugin instance changes the cursor in a background tab. - if (windowless_ && !g_iat_patch_set_cursor.Pointer()->is_patched() && - (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) { - g_iat_patch_set_cursor.Pointer()->Patch( - GetPluginPath().value().c_str(), "user32.dll", "SetCursor", - WebPluginDelegateImpl::SetCursorPatch); + // Windowless plugins can set cursors by calling the SetCursor API. This + // works because the thread inputs of the browser UI thread and the plugin + // thread are attached. We intercept the SetCursor API for windowless + // plugins and remember the cursor being set. This is shipped over to the + // browser in the HandleEvent call, which ensures that the cursor does not + // change when a windowless plugin instance changes the cursor + // in a background tab. + if (windowless_ && !g_iat_patch_set_cursor.Pointer()->is_patched() && + (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) { + g_iat_patch_set_cursor.Pointer()->Patch( + GetPluginPath().value().c_str(), "user32.dll", "SetCursor", + WebPluginDelegateImpl::SetCursorPatch); + } } // On XP, WMP will use its old UI unless a registry key under HKLM has the |