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 98afbc56e66c2c3f874d1f07b2879c43a8723290..b8ed087b0d9331738c8b6afdd6c2bf0a8e3f532c 100644 |
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc |
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc |
@@ -20,14 +20,16 @@ |
namespace { |
-const int kExitTimeoutMS = 5000; |
-const uint32 kMaxMessageDataLength = 10 * 1024 * 1024; |
const char kNativeHostsDirectoryName[] = "Native Hosts"; |
} // namespace |
namespace extensions { |
+// static |
+const int NativeMessageProcessHost::kExitTimeoutMS = 5000; |
+const uint32 NativeMessageProcessHost::kMaxMessageDataLength = 10 * 1024 * 1024; |
+ |
NativeMessageProcessHost::NativeMessageProcessHost( |
base::WeakPtr<Client> weak_client_ui, |
int destination_port, |
@@ -43,21 +45,28 @@ NativeMessageProcessHost::NativeMessageProcessHost( |
scoped_read_file_(&read_file_), |
scoped_write_file_(&write_file_), |
is_send_message_(is_send_message) { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
InitIO(); |
} |
NativeMessageProcessHost::~NativeMessageProcessHost() { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
+ |
+ StopIO(); |
+ |
// Give the process some time to shutdown, then try and kill it. |
- content::BrowserThread::PostDelayedTask( |
- content::BrowserThread::FILE, |
- FROM_HERE, |
- base::Bind(base::IgnoreResult(&base::KillProcess), |
- native_process_handle_, |
- content::RESULT_CODE_NORMAL_EXIT, |
- false /* don't wait for exit */), |
- base::TimeDelta::FromMilliseconds(kExitTimeoutMS)); |
+ if (native_process_handle_ != base::kNullProcessHandle && |
+ base::GetTerminationStatus(native_process_handle_, NULL) == |
+ base::TERMINATION_STATUS_STILL_RUNNING) { |
+ content::BrowserThread::PostDelayedTask( |
+ content::BrowserThread::IO, |
+ FROM_HERE, |
+ base::Bind(base::IgnoreResult(&base::KillProcess), |
+ native_process_handle_, |
+ content::RESULT_CODE_NORMAL_EXIT, |
+ true /* wait for exit */), |
+ base::TimeDelta::FromMilliseconds(kExitTimeoutMS)); |
+ } |
} |
// static |
@@ -67,9 +76,10 @@ void NativeMessageProcessHost::Create(base::WeakPtr<Client> weak_client_ui, |
int destination_port, |
MessageType type, |
CreateCallback callback) { |
- NativeProcessLauncher launcher; |
CreateWithLauncher(weak_client_ui, native_app_name, connection_message, |
- destination_port, type, callback, launcher); |
+ destination_port, type, callback, |
+ scoped_ptr<NativeProcessLauncher>( |
+ new NativeProcessLauncher())); |
} |
// static |
@@ -80,8 +90,8 @@ void NativeMessageProcessHost::CreateWithLauncher( |
int destination_port, |
MessageType type, |
CreateCallback callback, |
- const NativeProcessLauncher& launcher) { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ scoped_ptr<NativeProcessLauncher> launcher) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
DCHECK(type == TYPE_SEND_MESSAGE_REQUEST || type == TYPE_CONNECT); |
ScopedHost process; |
@@ -94,6 +104,28 @@ void NativeMessageProcessHost::CreateWithLauncher( |
return; |
} |
+ content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&NativeMessageProcessHost::LaunchProcessOnFileThread, |
+ weak_client_ui, |
+ native_app_name, |
+ connection_message, |
+ destination_port, |
+ type, |
+ callback, |
+ base::Passed(&launcher))); |
+} |
+ |
+// static |
+void NativeMessageProcessHost::LaunchProcessOnFileThread( |
+ base::WeakPtr<Client> weak_client_ui, |
+ const std::string& native_app_name, |
+ const std::string& connection_message, |
+ int destination_port, |
+ MessageType type, |
+ CreateCallback callback, |
+ scoped_ptr<NativeProcessLauncher> launcher) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ ScopedHost process; |
FilePath native_host_program; |
FilePath native_host_registry; |
CHECK(PathService::Get(chrome::DIR_USER_DATA, &native_host_registry)); |
@@ -115,34 +147,57 @@ void NativeMessageProcessHost::CreateWithLauncher( |
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_handle, |
+ &write_handle)) { |
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
base::Bind(callback, |
base::Passed(&process))); |
return; |
} |
+ NativeProcessHostCreationInformation creation_info(weak_client_ui, |
+ connection_message, |
+ destination_port, |
+ type, |
+ callback, |
+ read_handle, |
+ write_handle, |
+ native_process_handle); |
+ |
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
+ base::Bind(&NativeMessageProcessHost::FinalizeCreate, |
+ creation_info)); |
+} |
+ |
+// static |
+void NativeMessageProcessHost::FinalizeCreate( |
+ NativeProcessHostCreationInformation creation_info) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
+ ScopedHost process; |
+ |
process.reset(new NativeMessageProcessHost( |
- weak_client_ui, destination_port, native_process_handle, read_handle, |
- write_handle, type == TYPE_SEND_MESSAGE_REQUEST)); |
+ creation_info.weak_client_ui, creation_info.destination_port, |
+ creation_info.native_process_handle, creation_info.read_handle, |
+ creation_info.write_handle, |
+ creation_info.type == TYPE_SEND_MESSAGE_REQUEST)); |
- process->SendImpl(type, connection_message); |
+ process->SendImpl(creation_info.type, creation_info.connection_message); |
content::BrowserThread::PostTask( |
content::BrowserThread::UI, FROM_HERE, |
- base::Bind(callback, base::Passed(&process))); |
+ base::Bind(creation_info.callback, base::Passed(&process))); |
} |
void NativeMessageProcessHost::SendImpl(MessageType type, |
const std::string& json) { |
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
// Make sure that the process has not died. |
- if (base::GetTerminationStatus(native_process_handle_, NULL) != |
- base::TERMINATION_STATUS_STILL_RUNNING) { |
+ if (native_process_handle_ != base::kNullProcessHandle && |
+ base::GetTerminationStatus(native_process_handle_, NULL) != |
+ base::TERMINATION_STATUS_STILL_RUNNING) { |
// Notify the message service that the channel should close. |
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
base::Bind(&Client::CloseChannel, weak_client_ui_, |
@@ -174,15 +229,10 @@ 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."; |
- return false; |
- } |
- |
+bool NativeMessageProcessHost::VerifyMessageMetaData( |
+ const char* message_meta_data, |
+ MessageType* type, |
+ uint32* message_length) { |
Pickle pickle; |
pickle.WriteBytes(message_meta_data, 8); |
PickleIterator pickle_it(pickle); |
@@ -207,7 +257,6 @@ bool NativeMessageProcessHost::ReadMessage(MessageType* type, |
TYPE_CONNECT_MESSAGE); |
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. " |
@@ -215,11 +264,8 @@ bool NativeMessageProcessHost::ReadMessage(MessageType* type, |
return false; |
} |
- message->resize(data_length, '\0'); |
- if (!ReadData(read_file_, &(*message)[0], data_length)) { |
- LOG(ERROR) << "Error reading the json data."; |
- return false; |
- } |
+ *type = static_cast<MessageType>(uint_type); |
+ *message_length = data_length; |
return true; |
} |