Index: chrome/browser/extensions/api/messaging/native_message_process_host.cc |
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chrome/browser/extensions/api/messaging/native_message_process_host.cc |
index c431811ab6297a1c376b12cebc198203c6a65631..b126d47080d8fd67e3b6855432ab661abfd0caea 100644 |
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc |
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc |
@@ -4,11 +4,13 @@ |
#include "chrome/browser/extensions/api/messaging/native_message_process_host.h" |
+#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/file_path.h" |
#include "base/logging.h" |
#include "base/path_service.h" |
#include "base/pickle.h" |
+#include "base/platform_file.h" |
#include "base/process_util.h" |
#include "base/values.h" |
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h" |
@@ -30,25 +32,27 @@ namespace extensions { |
NativeMessageProcessHost::NativeMessageProcessHost( |
base::WeakPtr<Client> weak_client_ui, |
+ const std::string& native_host_name, |
int destination_port, |
- base::ProcessHandle native_process_handle, |
- FileHandle read_file, |
- FileHandle write_file, |
- bool is_send_message) |
+ scoped_ptr<NativeProcessLauncher> launcher) |
: weak_client_ui_(weak_client_ui), |
+ native_host_name_(native_host_name), |
destination_port_(destination_port), |
- native_process_handle_(native_process_handle), |
- read_file_(read_file), |
- write_file_(write_file), |
- scoped_read_file_(&read_file_), |
- scoped_write_file_(&write_file_), |
- is_send_message_(is_send_message) { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
- InitIO(); |
+ native_process_handle_(base::kNullProcessHandle), |
+ read_file_(base::kInvalidPlatformFileValue), |
+ write_file_(base::kInvalidPlatformFileValue) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
+ |
+ // It's safe to use base::Unretained() here because NativeMessagePort always |
+ // deletes us on the FILE thread. |
+ content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&NativeMessageProcessHost::LaunchHostProcess, |
+ base::Unretained(this), base::Passed(&launcher))); |
} |
NativeMessageProcessHost::~NativeMessageProcessHost() { |
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ |
// Give the process some time to shutdown, then try and kill it. |
content::BrowserThread::PostDelayedTask( |
content::BrowserThread::FILE, |
@@ -61,85 +65,84 @@ NativeMessageProcessHost::~NativeMessageProcessHost() { |
} |
// static |
-void NativeMessageProcessHost::Create(base::WeakPtr<Client> weak_client_ui, |
- const std::string& native_app_name, |
- const std::string& connection_message, |
- int destination_port, |
- MessageType type, |
- CreateCallback callback) { |
- NativeProcessLauncher launcher; |
- CreateWithLauncher(weak_client_ui, native_app_name, connection_message, |
- destination_port, type, callback, launcher); |
+scoped_ptr<NativeMessageProcessHost> NativeMessageProcessHost::Create( |
+ base::WeakPtr<Client> weak_client_ui, |
+ const std::string& native_host_name, |
+ int destination_port) { |
+ scoped_ptr<NativeProcessLauncher> launcher(new NativeProcessLauncher()); |
+ return CreateWithLauncher(weak_client_ui, native_host_name, destination_port, |
+ launcher.Pass()); |
} |
// static |
-void NativeMessageProcessHost::CreateWithLauncher( |
+scoped_ptr<NativeMessageProcessHost> |
+NativeMessageProcessHost::CreateWithLauncher( |
base::WeakPtr<Client> weak_client_ui, |
- const std::string& native_app_name, |
- const std::string& connection_message, |
+ const std::string& native_host_name, |
int destination_port, |
- MessageType type, |
- CreateCallback callback, |
- const NativeProcessLauncher& launcher) { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
- DCHECK(type == TYPE_SEND_MESSAGE_REQUEST || type == TYPE_CONNECT); |
+ scoped_ptr<NativeProcessLauncher> launcher) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
- ScopedHost process; |
+ scoped_ptr<NativeMessageProcessHost> process; |
if (Feature::GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV || |
!CommandLine::ForCurrentProcess()->HasSwitch( |
switches::kEnableNativeMessaging)) { |
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
- base::Bind(callback, |
- base::Passed(&process))); |
- return; |
+ return process.Pass(); |
} |
+ process.reset(new NativeMessageProcessHost( |
+ weak_client_ui, native_host_name, destination_port, launcher.Pass())); |
+ |
+ return process.Pass(); |
+} |
+ |
+void NativeMessageProcessHost::LaunchHostProcess( |
+ scoped_ptr<NativeProcessLauncher> launcher) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ |
FilePath native_host_program; |
FilePath native_host_registry; |
CHECK(PathService::Get(chrome::DIR_USER_DATA, &native_host_registry)); |
native_host_registry = |
native_host_registry.AppendASCII(kNativeHostsDirectoryName); |
- native_host_program = native_host_registry.AppendASCII(native_app_name); |
+ native_host_program = native_host_registry.AppendASCII(native_host_name_); |
// Make sure that the client is not trying to invoke something outside of the |
// proper directory. Eg. '../../dangerous_something.exe'. |
if (!file_util::ContainsPath(native_host_registry, native_host_program)) { |
- LOG(ERROR) << "Could not find native host: " << native_app_name; |
+ LOG(ERROR) << "Could not find native host: " << native_host_name_; |
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
- base::Bind(callback, |
- base::Passed(&process))); |
+ base::Bind(&Client::CloseChannel, weak_client_ui_, |
+ destination_port_, true)); |
return; |
} |
- FileHandle read_handle; |
- FileHandle write_handle; |
- base::ProcessHandle native_process_handle; |
- |
- if (!launcher.LaunchNativeProcess(native_host_program, |
- &native_process_handle, |
- &read_handle, |
- &write_handle)) { |
+ if (!launcher->LaunchNativeProcess(native_host_program, |
+ &native_process_handle_, |
+ &read_file_, |
+ &write_file_)) { |
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
- base::Bind(callback, |
- base::Passed(&process))); |
+ base::Bind(&Client::CloseChannel, weak_client_ui_, |
+ destination_port_, true)); |
return; |
} |
- process.reset(new NativeMessageProcessHost( |
- weak_client_ui, destination_port, native_process_handle, read_handle, |
- write_handle, type == TYPE_SEND_MESSAGE_REQUEST)); |
- |
- process->SendImpl(type, connection_message); |
+#if defined(OS_POSIX) |
+ scoped_read_file_.reset(&read_file_); |
+ scoped_write_file_.reset(&write_file_); |
+#endif // defined(OS_POSIX) |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, FROM_HERE, |
- base::Bind(callback, base::Passed(&process))); |
+ InitIO(); |
} |
-void NativeMessageProcessHost::SendImpl(MessageType type, |
- const std::string& json) { |
+void NativeMessageProcessHost::Send(const std::string& json) { |
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ if (native_process_handle_ == base::kNullProcessHandle) { |
+ // Don't need to do anything if LaunchHostProcess() didn't succeed. |
+ return; |
+ } |
+ |
// Make sure that the process has not died. |
if (base::GetTerminationStatus(native_process_handle_, NULL) != |
base::TERMINATION_STATUS_STILL_RUNNING) { |
@@ -149,21 +152,17 @@ void NativeMessageProcessHost::SendImpl(MessageType type, |
destination_port_, true)); |
} |
- WriteMessage(type, json); |
+ WriteMessage(json); |
} |
-bool NativeMessageProcessHost::WriteMessage(MessageType type, |
- const std::string& message) { |
+bool NativeMessageProcessHost::WriteMessage(const std::string& message) { |
Pickle pickle; |
- // Pickles will always pad bytes to 32-bit alignment, so just use a unit32. |
- pickle.WriteUInt32(type); |
- |
// Pickles write the length of a string before it as a uint32. |
pickle.WriteString(message); |
// Make sure that the pickle doesn't do any unexpected padding. |
- CHECK(8 + message.length() == pickle.payload_size()); |
+ CHECK_EQ(4 + message.length(), pickle.payload_size()); |
if (!WriteData(write_file_, const_cast<const Pickle*>(&pickle)->payload(), |
pickle.payload_size())) { |
@@ -174,40 +173,22 @@ bool NativeMessageProcessHost::WriteMessage(MessageType type, |
return true; |
} |
-bool NativeMessageProcessHost::ReadMessage(MessageType* type, |
- std::string* message) { |
- // Read the type (uint32) and length (uint32). |
- char message_meta_data[8]; |
- if (!ReadData(read_file_, message_meta_data, 8)) { |
- LOG(ERROR) << "Error reading the message type and length."; |
+bool NativeMessageProcessHost::ReadMessage(std::string* message) { |
+ // Read the length (uint32). |
+ char message_meta_data[4]; |
+ if (!ReadData(read_file_, message_meta_data, sizeof(message_meta_data))) { |
+ LOG(ERROR) << "Error reading the message length."; |
return false; |
} |
Pickle pickle; |
pickle.WriteBytes(message_meta_data, 8); |
jln (very slow on Chromium)
2013/01/23 01:28:13
Oops ?
That's why sizeof is good ;)
|
PickleIterator pickle_it(pickle); |
- uint32 uint_type; |
uint32 data_length; |
- if (!pickle_it.ReadUInt32(&uint_type) || |
- !pickle_it.ReadUInt32(&data_length)) { |
- LOG(ERROR) << "Error getting the message type and length from the pickle."; |
- return false; |
- } |
- |
- if (uint_type >= NUM_MESSAGE_TYPES) { |
- LOG(ERROR) << type << " is not a valid message type."; |
- return false; |
- } |
- |
- if ((is_send_message_ && (uint_type != TYPE_SEND_MESSAGE_RESPONSE)) || |
- (!is_send_message_ && (uint_type != TYPE_CONNECT_MESSAGE))) { |
- LOG(ERROR) << "Recieved a message of type " << uint_type << ". " |
- << "Expecting a message of type " |
- << (is_send_message_ ? TYPE_SEND_MESSAGE_RESPONSE : |
- TYPE_CONNECT_MESSAGE); |
+ if (!pickle_it.ReadUInt32(&data_length)) { |
+ LOG(ERROR) << "Error getting the message length from the pickle."; |
return false; |
} |
- *type = static_cast<MessageType>(uint_type); |
if (data_length > kMaxMessageDataLength) { |
LOG(ERROR) << data_length << " is too large for the length of a message. " |