summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgregoryd@google.com <gregoryd@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-18 01:46:27 +0000
committergregoryd@google.com <gregoryd@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-18 01:46:27 +0000
commitea5ac0e47d18753dbe971a35cce7f657ba64bae8 (patch)
tree54713ad26e136bbb9b0bf0062229092c537df533
parenteb4035b0048a7c9e3eeae7e189161f0cfbf3db22 (diff)
downloadchromium_src-ea5ac0e47d18753dbe971a35cce7f657ba64bae8.zip
chromium_src-ea5ac0e47d18753dbe971a35cce7f657ba64bae8.tar.gz
chromium_src-ea5ac0e47d18753dbe971a35cce7f657ba64bae8.tar.bz2
This is a copy of http://codereview.chromium.org/153002/show
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. This CL relies on another CL that contains the changes on the Native Client side: http://codereview.chromium.org/1501904. Command line flag "--internal-nacl" is required to enable the built-in NaCl plugin.5. NaCl still cannot run in Chrome sandbox, so the "--no-sandbox" flag is also required TBR=bradnelson Review URL: http://codereview.chromium.org/207025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26540 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--DEPS2
-rw-r--r--base/format_macros.h8
-rw-r--r--chrome/app/chrome_dll_main.cc3
-rw-r--r--chrome/browser/nacl_process_host.cc187
-rw-r--r--chrome/browser/nacl_process_host.h55
-rw-r--r--chrome/browser/plugin_service.cc10
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc1
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc8
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h3
-rw-r--r--chrome/browser/sandbox_policy.cc4
-rw-r--r--chrome/chrome.gyp77
-rw-r--r--chrome/common/child_process_info.h1
-rw-r--r--chrome/common/chrome_switches.cc6
-rw-r--r--chrome/common/chrome_switches.h3
-rw-r--r--chrome/common/nacl_messages.h19
-rw-r--r--chrome/common/nacl_messages_internal.h18
-rw-r--r--chrome/common/nacl_types.h19
-rw-r--r--chrome/common/render_messages_internal.h9
-rw-r--r--chrome/common/sandbox_init_wrapper.cc1
-rw-r--r--chrome/nacl/nacl_main.cc75
-rw-r--r--chrome/nacl/nacl_thread.cc33
-rw-r--r--chrome/nacl/nacl_thread.h35
-rw-r--r--chrome/nacl/sel_main.cc210
-rw-r--r--chrome/renderer/render_process.cc12
-rw-r--r--chrome/renderer/render_view.cc8
-rw-r--r--ipc/ipc_message_utils.h1
-rw-r--r--webkit/glue/plugins/plugin_lib.h2
-rw-r--r--webkit/glue/plugins/plugin_list.cc43
-rw-r--r--webkit/glue/plugins/plugin_list.h16
-rw-r--r--webkit/glue/plugins/plugin_list_linux.cc4
-rw-r--r--webkit/glue/plugins/plugin_list_mac.mm4
-rw-r--r--webkit/glue/plugins/plugin_list_win.cc4
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h3
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_win.cc54
34 files changed, 905 insertions, 33 deletions
diff --git a/DEPS b/DEPS
index fa8bb5a..ddabc8e 100644
--- a/DEPS
+++ b/DEPS
@@ -39,7 +39,7 @@ deps = {
"http://v8.googlecode.com/svn/trunk@2901",
"src/native_client":
- "http://nativeclient.googlecode.com/svn/trunk/src/native_client@385",
+ "http://nativeclient.googlecode.com/svn/trunk/src/native_client@730",
"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 805565d..c2a0e0f 100644
--- a/chrome/app/chrome_dll_main.cc
+++ b/chrome/app/chrome_dll_main.cc
@@ -81,6 +81,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&);
@@ -579,6 +580,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..f466f6a
--- /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_StartSelLdr* msg = new NaClProcessMsg_StartSelLdr(
+ 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 1d767bd..ab5ece1 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,15 @@ PluginService::PluginService()
NPAPI::PluginList::Singleton()->AddExtraPluginPath(
FilePath::FromWStringHack(path));
}
+ if (command_line->HasSwitch(switches::kInternalNaCl)) {
+ NPAPI::PluginEntryPoints entry_points = {
+#if !defined(OS_LINUX)
+ NaCl_NP_GetEntryPoints,
+#endif
+ NaCl_NP_Initialize,
+ NaCl_NP_Shutdown};
+ NPAPI::PluginList::UseInternalNaCl(&entry_points);
+ }
#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 b757e46..e9fbe92 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -342,6 +342,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 781543e..7aa1d50 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/renderer_host/database_dispatcher_host.h"
#include "chrome/browser/renderer_host/file_system_accessor.h"
#include "chrome/browser/renderer_host/render_widget_helper.h"
+#include "chrome/browser/nacl_process_host.h"
#include "chrome/browser/spellchecker.h"
#include "chrome/browser/spellchecker_platform_engine.h"
#include "chrome/browser/worker_host/message_port_dispatcher.h"
@@ -290,6 +291,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,
@@ -580,6 +582,12 @@ void ResourceMessageFilter::OnOpenChannelToPlugin(const GURL& url,
this, url, mime_type, locale, reply_msg);
}
+void ResourceMessageFilter::OnLaunchNaCl(const 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 00c3b13..933a153 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -25,6 +25,7 @@
#include "chrome/browser/renderer_host/render_widget_helper.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/common/modal_dialog_event.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"
@@ -154,6 +155,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
const std::string& mime_type,
const std::wstring& locale,
IPC::Message* reply_msg);
+ void OnLaunchNaCl(const 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 13f4ee2..59688b4 100644
--- a/chrome/browser/sandbox_policy.cc
+++ b/chrome/browser/sandbox_policy.cc
@@ -359,6 +359,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 {
@@ -394,6 +396,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 99dbc97..3b5003f 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -104,7 +104,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',
@@ -561,6 +580,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',
@@ -673,6 +694,9 @@
'..',
'<(INTERMEDIATE_DIR)',
],
+ 'defines': [
+ '<@(nacl_defines)',
+ ],
'sources': [
# All .cc, .h, .m, and .mm files under browser except for tests and
# mocks.
@@ -1781,6 +1805,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',
@@ -2819,11 +2845,60 @@
],
},
{
+ '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',
+ # TODO(gregoryd): consider getting this from NaCl's common.gypi
+ 'NACL_TARGET_SUBARCH=32',
+ 'NACL_BUILD_SUBARCH=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',
@@ -3312,6 +3387,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 fa03c0f..9d2d610 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,
ZYGOTE_PROCESS,
SANDBOX_HELPER_PROCESS,
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 978c7c6..7ab37eb 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 733d706..6812b7f 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..1e43493
--- /dev/null
+++ b/chrome/common/nacl_messages_internal.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2006-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 "ipc/ipc_message_macros.h"
+#include "chrome/common/nacl_types.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_StartSelLdr,
+ 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..5c6072a
--- /dev/null
+++ b/chrome/common/nacl_types.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.
+
+// Handle passing definitions for NaCl
+#ifndef CHROME_COMMON_NACL_TYPES_H_
+#define CHROME_COMMON_NACL_TYPES_H_
+
+namespace nacl {
+#if defined(OS_WIN)
+typedef HANDLE FileDescriptor;
+#define NATIVE_HANDLE(desc) (static_cast<HANDLE>(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 2916c17..50bdf85 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -21,6 +21,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/transport_dib.h"
#include "chrome/common/view_types.h"
#include "ipc/ipc_channel_handle.h"
@@ -1065,6 +1066,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, usually 5 */,
+ 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
new file mode 100644
index 0000000..2d583b1
--- /dev/null
+++ b/chrome/nacl/nacl_main.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2006-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"
+
+#if defined(OS_WIN)
+#include "app/win_util.h"
+#endif
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "base/system_monitor.h"
+#include "chrome/common/child_process.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/logging_chrome.h"
+#include "chrome/common/main_function_params.h"
+#include "chrome/nacl/nacl_thread.h"
+
+#if defined(OS_WIN)
+#include "chrome/test/injection_test_dll.h"
+#include "sandbox/src/sandbox.h"
+#endif
+
+// main() routine for running as the sel_ldr process.
+int NaClMain(const MainFunctionParams& parameters) {
+ // The main thread of the plugin services IO.
+ MessageLoopForIO main_message_loop;
+ std::wstring app_name = chrome::kBrowserAppName;
+ PlatformThread::SetName(WideToASCII(app_name + L"_NaClMain").c_str());
+
+ // Initialize the SystemMonitor
+ base::SystemMonitor::Start();
+
+#if defined(OS_WIN)
+ const CommandLine& parsed_command_line = parameters.command_line_;
+
+ sandbox::TargetServices* target_services =
+ parameters.sandbox_info_.TargetServices();
+
+ DLOG(INFO) << "Started plugin with " <<
+ parsed_command_line.command_line_string();
+
+ HMODULE sandbox_test_module = NULL;
+ bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
+ if (target_services && !no_sandbox) {
+ // The command line might specify a test plugin to load.
+ if (parsed_command_line.HasSwitch(switches::kTestSandbox)) {
+ std::wstring test_plugin_name =
+ parsed_command_line.GetSwitchValue(switches::kTestSandbox);
+ sandbox_test_module = LoadLibrary(test_plugin_name.c_str());
+ DCHECK(sandbox_test_module);
+ }
+ }
+
+#else
+ NOTIMPLEMENTED() << " non-windows startup, plugin startup dialog etc.";
+#endif
+
+ {
+ ChildProcess nacl_process;
+ nacl_process.set_main_thread(new NaClThread());
+#if defined(OS_WIN)
+ if (!no_sandbox && target_services)
+ target_services->LowerToken();
+#endif
+
+ MessageLoop::current()->Run();
+ }
+
+ return 0;
+}
+
+
diff --git a/chrome/nacl/nacl_thread.cc b/chrome/nacl/nacl_thread.cc
new file mode 100644
index 0000000..0b669f0
--- /dev/null
+++ b/chrome/nacl/nacl_thread.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2006-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"
+
+int SelMain(const int desc, const NaClHandle handle);
+
+NaClThread::NaClThread() {
+}
+
+NaClThread::~NaClThread() {
+}
+
+NaClThread* NaClThread::current() {
+ return static_cast<NaClThread*>(ChildThread::current());
+}
+
+void NaClThread::OnControlMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(NaClThread, msg)
+ IPC_MESSAGE_HANDLER(NaClProcessMsg_StartSelLdr, OnStartSelLdr)
+ IPC_END_MESSAGE_MAP()
+}
+
+void NaClThread::OnStartSelLdr(const int channel_descriptor,
+ const nacl::FileDescriptor handle) {
+ SelMain(channel_descriptor, NATIVE_HANDLE(handle));
+}
diff --git a/chrome/nacl/nacl_thread.h b/chrome/nacl/nacl_thread.h
new file mode 100644
index 0000000..a69ce3a
--- /dev/null
+++ b/chrome/nacl/nacl_thread.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-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_NACL_NACL_THREAD_H_
+#define CHROME_NACL_NACL_THREAD_H_
+
+#include "base/file_path.h"
+#include "base/native_library.h"
+#include "chrome/common/child_thread.h"
+#include "chrome/common/nacl_types.h"
+
+class NotificationService;
+
+// The NaClThread class represents a background thread where NaCl app gets
+// started.
+class NaClThread : public ChildThread {
+ public:
+ NaClThread();
+ ~NaClThread();
+ // Returns the one NaCl thread.
+ static NaClThread* current();
+
+ 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_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(NaClThread);
+};
+
+#endif // CHROME_NACL_NACL_THREAD_H_
diff --git a/chrome/nacl/sel_main.cc b/chrome/nacl/sel_main.cc
new file mode 100644
index 0000000..7174706
--- /dev/null
+++ b/chrome/nacl/sel_main.cc
@@ -0,0 +1,210 @@
+// Copyright (c) 2006-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
+#include <crt_externs.h>
+#endif
+
+EXTERN_C_BEGIN
+#include "native_client/src/shared/platform/nacl_sync.h"
+#include "native_client/src/shared/platform/nacl_sync_checked.h"
+#include "native_client/src/trusted/service_runtime/nacl_globals.h"
+#include "native_client/src/trusted/service_runtime/expiration.h"
+#include "native_client/src/trusted/service_runtime/nacl_app.h"
+#include "native_client/src/trusted/service_runtime/nacl_all_modules.h"
+#include "native_client/src/trusted/service_runtime/sel_ldr.h"
+#include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h"
+EXTERN_C_END
+
+int verbosity = 0;
+
+#ifdef __GNUC__
+
+/*
+ * GDB's canonical overlay managment routine.
+ * We need its symbol in the symbol table so don't inline it.
+ * TODO(dje): add some explanation for the non-GDB person.
+ */
+
+static void __attribute__ ((noinline)) _ovly_debug_event (void) {
+ /*
+ * The asm volatile is here as instructed by the GCC docs.
+ * It's not enough to declare a function noinline.
+ * GCC will still look inside the function to see if it's worth calling.
+ */
+ asm volatile ("");
+}
+
+#endif
+
+static void StopForDebuggerInit (const struct NaClApp *state) {
+ /* Put xlate_base in a place where gdb can find it. */
+ nacl_global_xlate_base = state->xlate_base;
+
+#ifdef __GNUC__
+ _ovly_debug_event ();
+#endif
+}
+
+int SelMain(const int desc, const NaClHandle handle) {
+ char *av[1];
+ int ac = 1;
+
+ char **envp;
+ struct NaClApp state;
+ char *nacl_file = 0;
+ int main_thread_only = 1;
+ int export_addr_to = -2;
+
+ struct NaClApp *nap;
+
+ NaClErrorCode errcode;
+
+ int ret_code = 1;
+#if NACL_OSX
+ // Mac dynamic libraries cannot access the environ variable directly.
+ envp = *_NSGetEnviron();
+#else
+ extern char **environ;
+ envp = environ;
+#endif
+
+
+ if (NaClHasExpired()) {
+ // TODO(gregoryd): report error to browser?
+ fprintf(stderr, "This version of Native Client has expired.\n");
+ fprintf(stderr, "Please visit: http://code.google.com/p/nativeclient/\n");
+ exit(-1);
+ }
+
+ NaClAllModulesInit();
+
+ /* used to be -P */
+ NaClSrpcFileDescriptor = desc;
+ /* used to be -X */
+ export_addr_to = desc;
+
+ /* to be passed to NaClMain, eventually... */
+ av[0] = const_cast<char*>("NaClMain");
+
+ if (!NaClAppCtor(&state)) {
+ fprintf(stderr, "Error while constructing app state\n");
+ goto done_file_dtor;
+ }
+
+ state.restrict_to_main_thread = main_thread_only;
+
+ nap = &state;
+ errcode = LOAD_OK;
+
+ /* import IMC handle - used to be "-i" */
+ NaClAddImcHandle(nap, handle, desc);
+
+ /*
+ * in order to report load error to the browser plugin through the
+ * secure command channel, we do not immediate jump to cleanup code
+ * on error. rather, we continue processing (assuming earlier
+ * errors do not make it inappropriate) until the secure command
+ * channel is set up, and then bail out.
+ */
+
+ /*
+ * Ensure this operating system platform is supported.
+ */
+ if (!NaClOsIsSupported()) {
+ errcode = LOAD_UNSUPPORTED_OS_PLATFORM;
+ nap->module_load_status = errcode;
+ fprintf(stderr, "Error while loading \"%s\": %s\n",
+ nacl_file,
+ NaClErrorString(errcode));
+ }
+
+ /* Give debuggers a well known point at which xlate_base is known. */
+ StopForDebuggerInit(&state);
+
+ /*
+ * If export_addr_to is set to a non-negative integer, we create a
+ * bound socket and socket address pair and bind the former to
+ * descriptor 3 and the latter to descriptor 4. The socket address
+ * is written out to the export_addr_to descriptor.
+ *
+ * The service runtime also accepts a connection on the bound socket
+ * and spawns a secure command channel thread to service it.
+ *
+ * If export_addr_to is -1, we only create the bound socket and
+ * socket address pair, and we do not export to an IMC socket. This
+ * use case is typically only used in testing, where we only "dump"
+ * the socket address to stdout or similar channel.
+ */
+ if (-2 < export_addr_to) {
+ NaClCreateServiceSocket(nap);
+ if (0 <= export_addr_to) {
+ NaClSendServiceAddressTo(nap, export_addr_to);
+ /*
+ * NB: spawns a thread that uses the command channel. we do
+ * this after NaClAppLoadFile so that NaClApp object is more
+ * fully populated. Hereafter any changes to nap should be done
+ * while holding locks.
+ */
+ NaClSecureCommandChannel(nap);
+ }
+ }
+
+ NaClXMutexLock(&nap->mu);
+ nap->module_load_status = LOAD_OK;
+ NaClXCondVarBroadcast(&nap->cv);
+ NaClXMutexUnlock(&nap->mu);
+
+ if (NULL != nap->secure_channel) {
+ /*
+ * wait for start_module RPC call on secure channel thread.
+ */
+ NaClWaitForModuleStartStatusCall(nap);
+ }
+
+ /*
+ * error reporting done; can quit now if there was an error earlier.
+ */
+ if (LOAD_OK != errcode) {
+ goto done;
+ }
+
+ /*
+ * only nap->ehdrs.e_entry is usable, no symbol table is
+ * available.
+ */
+ if (!NaClCreateMainThread(nap,
+ ac,
+ av,
+ envp)) {
+ fprintf(stderr, "creating main thread failed\n");
+ goto done;
+ }
+
+ ret_code = NaClWaitForMainThreadToExit(nap);
+
+ /*
+ * exit_group or equiv kills any still running threads while module
+ * addr space is still valid. otherwise we'd have to kill threads
+ * before we clean up the address space.
+ */
+ return ret_code;
+
+ done:
+ fflush(stdout);
+
+ NaClAppDtor(&state);
+
+ done_file_dtor:
+ fflush(stdout);
+
+ NaClAllModulesFini();
+
+ return ret_code;
+}
+
diff --git a/chrome/renderer/render_process.cc b/chrome/renderer/render_process.cc
index 610e5d3..6968d93 100644
--- a/chrome/renderer/render_process.cc
+++ b/chrome/renderer/render_process.cc
@@ -30,7 +30,9 @@
#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"
+#include "webkit/glue/plugins/plugin_list.h"
//-----------------------------------------------------------------------------
@@ -80,6 +82,16 @@ RenderProcess::RenderProcess()
StatisticsRecorder::set_dump_on_exit(true);
}
+ if (command_line.HasSwitch(switches::kInternalNaCl)) {
+ NPAPI::PluginEntryPoints entry_points = {
+#if !defined(OS_LINUX)
+ NaCl_NP_GetEntryPoints,
+#endif
+ NaCl_NP_Initialize,
+ NaCl_NP_Shutdown};
+ NPAPI::PluginList::UseInternalNaCl(&entry_points);
+ }
+
FilePath module_path;
initialized_media_library_ =
PathService::Get(base::DIR_MODULE, &module_path) &&
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 4a2335c..bf59158 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -2281,7 +2281,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..a5de7fe 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
//
diff --git a/webkit/glue/plugins/plugin_list.cc b/webkit/glue/plugins/plugin_list.cc
index 69315b2..3adb0eb 100644
--- a/webkit/glue/plugins/plugin_list.cc
+++ b/webkit/glue/plugins/plugin_list.cc
@@ -15,6 +15,8 @@
#include "webkit/glue/webkit_glue.h"
#include "googleurl/src/gurl.h"
+#define kNpGoogleNaClPlugin (FILE_PATH_LITERAL("npgooglenaclplugin"))
+
namespace NPAPI {
base::LazyInstance<PluginList> g_singleton(base::LINKER_INITIALIZED);
@@ -113,7 +115,8 @@ bool PluginList::CreateWebPluginInfo(const PluginVersionInfo& pvi,
return true;
}
-PluginList::PluginList() : plugins_loaded_(false) {
+PluginList::PluginList() : plugins_loaded_(false),
+ use_internal_nacl_(false) {
PlatformInit();
#if defined(OS_WIN)
@@ -168,6 +171,10 @@ void PluginList::LoadPlugins(bool refresh) {
LoadPluginsFromDir(directories_to_scan[i], &new_plugins);
}
+ if (use_internal_nacl_) {
+ LoadPlugin(FilePath(kNaClPluginLibraryName), &new_plugins);
+ }
+
if (webkit_glue::IsDefaultPluginEnabled())
LoadPlugin(FilePath(kDefaultPluginLibraryName), &new_plugins);
@@ -209,6 +216,20 @@ void PluginList::LoadPlugin(const FilePath &path,
plugins->push_back(plugin_info);
}
+bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
+ std::vector<WebPluginInfo>* plugins) {
+ FilePath::StringType filename =
+ StringToLowerASCII(info.path.BaseName().value());
+
+ // Don't load the external version of NaCl when we need to use
+ // the internal one.
+ if (use_internal_nacl_) {
+ if (std::wstring::npos != filename.find(kNpGoogleNaClPlugin))
+ return false;
+ }
+ return PlatformShouldLoadPlugin(info, plugins);
+}
+
bool PluginList::FindPlugin(const std::string& mime_type,
bool allow_wildcard,
WebPluginInfo* info) {
@@ -327,4 +348,24 @@ void PluginList::Shutdown() {
// TODO
}
+// static
+void PluginList::UseInternalNaCl(PluginEntryPoints* entry_points) {
+ // We access the singleton directly, and not through Singleton(), since
+ // we don't want LoadPlugins() to be called.
+ g_singleton.Pointer()->use_internal_nacl_ = true;
+
+ const NPAPI::PluginVersionInfo nacl_plugin_info = {
+ FilePath(kNaClPluginLibraryName),
+ L"Native Client",
+ L"Statically linked NaCl",
+ L"1, 0, 0, 1",
+ L"application/x-nacl-srpc",
+ L"",
+ L"",
+ *entry_points
+ };
+
+ Singleton()->RegisterInternalPlugin(nacl_plugin_info);
+}
+
} // namespace NPAPI
diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h
index 7fc2b58..3840682 100644
--- a/webkit/glue/plugins/plugin_list.h
+++ b/webkit/glue/plugins/plugin_list.h
@@ -29,6 +29,7 @@ namespace NPAPI
#define kDefaultPluginLibraryName FILE_PATH_LITERAL("default_plugin")
#define kGearsPluginLibraryName FILE_PATH_LITERAL("gears")
+#define kNaClPluginLibraryName FILE_PATH_LITERAL("internal_nacl")
class PluginInstance;
@@ -105,6 +106,13 @@ class PluginList {
static bool CreateWebPluginInfo(const PluginVersionInfo& pvi,
WebPluginInfo* info);
+ // Set NativeClient plugin mode (avoid loading both the built-in and
+ // the external version of the plugin). The arguments provide pointers
+ // to NaCl plugin entry points - the functions are not referenced directly
+ // from this class to avoid introducing dependency between Webkit glue
+ // library and NaCl code.
+ static void UseInternalNaCl(PluginEntryPoints* entry_points);
+
// Shutdown all plugins. Should be called at process teardown.
void Shutdown();
@@ -148,6 +156,11 @@ class PluginList {
bool ShouldLoadPlugin(const WebPluginInfo& info,
std::vector<WebPluginInfo>* plugins);
+ // Returns true if we should load the given plugin, or false otherwise.
+ // This function is platform-specific and is called from ShouldLoadPlugin.
+ bool PlatformShouldLoadPlugin(const WebPluginInfo& info,
+ std::vector<WebPluginInfo>* plugins);
+
// Find a plugin by mime type.
// The allow_wildcard parameter controls whether this function returns
// plugins which support wildcard mime types (* as the mime type)
@@ -212,6 +225,9 @@ class PluginList {
// Holds information about internal plugins.
std::vector<PluginVersionInfo> internal_plugins_;
+ // true if we should use our internal Native Client plugin
+ bool use_internal_nacl_;
+
// Need synchronization for the above members since this object can be
// accessed on multiple threads.
Lock lock_;
diff --git a/webkit/glue/plugins/plugin_list_linux.cc b/webkit/glue/plugins/plugin_list_linux.cc
index 4f72ab1..cdfa628 100644
--- a/webkit/glue/plugins/plugin_list_linux.cc
+++ b/webkit/glue/plugins/plugin_list_linux.cc
@@ -165,8 +165,8 @@ void PluginList::LoadPluginsFromDir(const FilePath& path,
}
-bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
- std::vector<WebPluginInfo>* plugins) {
+bool PluginList::PlatformShouldLoadPlugin(const WebPluginInfo& info,
+ std::vector<WebPluginInfo>* plugins) {
if (DebugPluginLoading()) {
LOG(ERROR) << "Considering " << info.path.value()
<< " (" << info.name << ")";
diff --git a/webkit/glue/plugins/plugin_list_mac.mm b/webkit/glue/plugins/plugin_list_mac.mm
index c470c5a..ce4f2a1 100644
--- a/webkit/glue/plugins/plugin_list_mac.mm
+++ b/webkit/glue/plugins/plugin_list_mac.mm
@@ -67,8 +67,8 @@ void PluginList::LoadPluginsFromDir(const FilePath &path,
}
}
-bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
- std::vector<WebPluginInfo>* plugins) {
+bool PluginList::PlatformShouldLoadPlugin(const WebPluginInfo& info,
+ std::vector<WebPluginInfo>* plugins) {
// The Gears plugin is Safari-specific, and causes crashes, so don't load it.
for (std::vector<WebPluginMimeType>::const_iterator i =
info.mime_types.begin(); i != info.mime_types.end(); ++i) {
diff --git a/webkit/glue/plugins/plugin_list_win.cc b/webkit/glue/plugins/plugin_list_win.cc
index 9873691..4360ab6 100644
--- a/webkit/glue/plugins/plugin_list_win.cc
+++ b/webkit/glue/plugins/plugin_list_win.cc
@@ -262,8 +262,8 @@ bool IsNewerVersion(const std::wstring& a, const std::wstring& b) {
return false;
}
-bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
- std::vector<WebPluginInfo>* plugins) {
+bool PluginList::PlatformShouldLoadPlugin(const WebPluginInfo& info,
+ std::vector<WebPluginInfo>* plugins) {
// Version check
for (size_t i = 0; i < plugins->size(); ++i) {
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index 6d53339..0641093 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -43,7 +43,8 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
PLUGIN_QUIRK_WINDOWLESS_OFFSET_WINDOW_TO_DRAW = 256, // Linux
PLUGIN_QUIRK_WINDOWLESS_INVALIDATE_AFTER_SET_WINDOW = 512, // Linux
PLUGIN_QUIRK_NO_WINDOWLESS = 1024, // Windows
- PLUGIN_QUIRK_PATCH_REGENUMKEYEXW = 2048, // Windows
+ PLUGIN_QUIRK_DONT_CREATE_DUMMY_WINDOW = 2048, // Native Client
+ PLUGIN_QUIRK_PATCH_REGENUMKEYEXW = 4096, // Windows
};
static WebPluginDelegateImpl* Create(const FilePath& filename,
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_win.cc b/webkit/glue/plugins/webplugin_delegate_impl_win.cc
index 1f13cf8..25f9fa0 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_win.cc
+++ b/webkit/glue/plugins/webplugin_delegate_impl_win.cc
@@ -298,6 +298,9 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
// Explanation for this quirk can be found in
// WebPluginDelegateImpl::Initialize.
quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
+ } else if (instance_->mime_type() == "application/x-nacl-srpc") {
+ // NaCl plugin runs in the sandbox - it cannot use the hwnd
+ quirks_ |= PLUGIN_QUIRK_DONT_CREATE_DUMMY_WINDOW;
}
}
@@ -326,35 +329,40 @@ void WebPluginDelegateImpl::PluginDestroyed() {
void WebPluginDelegateImpl::PlatformInitialize() {
plugin_->SetWindow(windowed_handle_);
- if (windowless_) {
+
+ if (windowless_ && !(quirks_ & PLUGIN_QUIRK_DONT_CREATE_DUMMY_WINDOW)) {
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