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 bc3808a28c848b27bc6f74ae18a0bd968840bba6..7d7e37f40dddd6523f13624e297b3bd3b5936e56 100644 |
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc |
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc |
@@ -7,12 +7,15 @@ |
#include "base/bind.h" |
#include "base/files/file_path.h" |
#include "base/logging.h" |
+#include "base/prefs/pref_service.h" |
#include "base/process/kill.h" |
#include "base/threading/sequenced_worker_pool.h" |
+#include "base/values.h" |
#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h" |
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h" |
#include "chrome/common/chrome_version_info.h" |
#include "content/public/browser/browser_thread.h" |
+#include "extensions/browser/pref_names.h" |
#include "extensions/common/constants.h" |
#include "extensions/common/features/feature.h" |
#include "net/base/file_stream.h" |
@@ -34,16 +37,69 @@ const size_t kMessageHeaderSize = 4; |
// Size of the buffer to be allocated for each read. |
const size_t kReadBufferSize = 4096; |
+const char kFailedToStartError[] = "Failed to start native messaging host."; |
+const char kInvalidNameError[] = |
+ "Invalid native messaging host name specified."; |
+const char kNativeHostExited[] = "Native host has exited."; |
+const char kNotFoundError[] = "Specified native messaging host not found."; |
+const char kForbiddenError[] = |
+ "Access to the specified native messaging host is forbidden."; |
+const char kHostInputOuputError[] = |
+ "Error when communicating with the native messaging host."; |
+ |
} // namespace |
namespace extensions { |
+// static |
+NativeMessageProcessHost::PolicyPermission |
+NativeMessageProcessHost::IsHostAllowed(const PrefService* pref_service, |
+ const std::string& native_host_name) { |
+ NativeMessageProcessHost::PolicyPermission allow_result = ALLOW_ALL; |
+ if (pref_service->IsManagedPreference( |
+ pref_names::kNativeMessagingUserLevelHosts)) { |
+ if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts)) |
+ allow_result = ALLOW_SYSTEM_ONLY; |
+ } |
+ |
+ // All native messaging hosts are allowed if there is no blacklist. |
+ if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlacklist)) |
+ return allow_result; |
+ const base::ListValue* blacklist = |
+ pref_service->GetList(pref_names::kNativeMessagingBlacklist); |
+ if (!blacklist) |
+ return allow_result; |
+ |
+ // Check if the name or the wildcard is in the blacklist. |
+ base::StringValue name_value(native_host_name); |
+ base::StringValue wildcard_value("*"); |
+ if (blacklist->Find(name_value) == blacklist->end() && |
+ blacklist->Find(wildcard_value) == blacklist->end()) { |
+ return allow_result; |
+ } |
+ |
+ // The native messaging host is blacklisted. Check the whitelist. |
+ if (pref_service->IsManagedPreference( |
+ pref_names::kNativeMessagingWhitelist)) { |
+ const base::ListValue* whitelist = |
+ pref_service->GetList(pref_names::kNativeMessagingWhitelist); |
+ if (whitelist && whitelist->Find(name_value) != whitelist->end()) |
+ return allow_result; |
+ } |
+ |
+ return DISALLOW; |
+} |
+ |
NativeMessageProcessHost::NativeMessageProcessHost( |
+ base::WeakPtr<Client> weak_client_ui, |
const std::string& source_extension_id, |
const std::string& native_host_name, |
+ int destination_port, |
scoped_ptr<NativeProcessLauncher> launcher) |
- : source_extension_id_(source_extension_id), |
+ : weak_client_ui_(weak_client_ui), |
+ source_extension_id_(source_extension_id), |
native_host_name_(native_host_name), |
+ destination_port_(destination_port), |
launcher_(launcher.Pass()), |
closed_(false), |
process_handle_(base::kNullProcessHandle), |
@@ -54,50 +110,51 @@ NativeMessageProcessHost::NativeMessageProcessHost( |
write_pending_(false) { |
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread( |
- content::BrowserThread::IO); |
// It's safe to use base::Unretained() here because NativeMessagePort always |
// deletes us on the IO thread. |
- task_runner_->PostTask( |
- FROM_HERE, |
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
base::Bind(&NativeMessageProcessHost::LaunchHostProcess, |
base::Unretained(this))); |
} |
NativeMessageProcessHost::~NativeMessageProcessHost() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
+ Close(std::string()); |
} |
// static |
-scoped_ptr<NativeMessageHost> NativeMessageHost::Create( |
+scoped_ptr<NativeMessageProcessHost> NativeMessageProcessHost::Create( |
gfx::NativeView native_view, |
+ base::WeakPtr<Client> weak_client_ui, |
const std::string& source_extension_id, |
const std::string& native_host_name, |
- bool allow_user_level, |
- std::string* error_message) { |
- return NativeMessageProcessHost::CreateWithLauncher( |
- source_extension_id, |
- native_host_name, |
- NativeProcessLauncher::CreateDefault(allow_user_level, native_view)); |
+ int destination_port, |
+ bool allow_user_level) { |
+ return CreateWithLauncher(weak_client_ui, source_extension_id, |
+ native_host_name, destination_port, |
+ NativeProcessLauncher::CreateDefault( |
+ allow_user_level, native_view)); |
} |
// static |
-scoped_ptr<NativeMessageHost> NativeMessageProcessHost::CreateWithLauncher( |
+scoped_ptr<NativeMessageProcessHost> |
+NativeMessageProcessHost::CreateWithLauncher( |
+ base::WeakPtr<Client> weak_client_ui, |
const std::string& source_extension_id, |
const std::string& native_host_name, |
+ int destination_port, |
scoped_ptr<NativeProcessLauncher> launcher) { |
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- scoped_ptr<NativeMessageHost> process( |
- new NativeMessageProcessHost(source_extension_id, |
- native_host_name, |
- launcher.Pass())); |
+ scoped_ptr<NativeMessageProcessHost> process(new NativeMessageProcessHost( |
+ weak_client_ui, source_extension_id, native_host_name, |
+ destination_port, launcher.Pass())); |
return process.Pass(); |
} |
void NativeMessageProcessHost::LaunchHostProcess() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
GURL origin(std::string(kExtensionScheme) + "://" + source_extension_id_); |
launcher_->Launch(origin, native_host_name_, |
@@ -110,7 +167,7 @@ void NativeMessageProcessHost::OnHostProcessLaunched( |
base::ProcessHandle process_handle, |
base::File read_file, |
base::File write_file) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
switch (result) { |
case NativeProcessLauncher::RESULT_INVALID_NAME: |
@@ -147,8 +204,8 @@ void NativeMessageProcessHost::OnHostProcessLaunched( |
DoWrite(); |
} |
-void NativeMessageProcessHost::OnMessage(const std::string& json) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+void NativeMessageProcessHost::Send(const std::string& json) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
if (closed_) |
return; |
@@ -172,16 +229,6 @@ void NativeMessageProcessHost::OnMessage(const std::string& json) { |
DoWrite(); |
} |
-void NativeMessageProcessHost::Start(Client* client) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
- client_ = client; |
-} |
- |
-scoped_refptr<base::SingleThreadTaskRunner> |
-NativeMessageProcessHost::task_runner() const { |
- return task_runner_; |
-} |
- |
#if defined(OS_POSIX) |
void NativeMessageProcessHost::OnFileCanReadWithoutBlocking(int fd) { |
DCHECK_EQ(fd, read_file_); |
@@ -217,7 +264,7 @@ void NativeMessageProcessHost::WaitRead() { |
} |
void NativeMessageProcessHost::DoRead() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
while (!closed_ && !read_pending_) { |
read_buffer_ = new net::IOBuffer(kReadBufferSize); |
@@ -230,7 +277,7 @@ void NativeMessageProcessHost::DoRead() { |
} |
void NativeMessageProcessHost::OnRead(int result) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
DCHECK(read_pending_); |
read_pending_ = false; |
@@ -239,7 +286,7 @@ void NativeMessageProcessHost::OnRead(int result) { |
} |
void NativeMessageProcessHost::HandleReadResult(int result) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
if (closed_) |
return; |
@@ -260,7 +307,7 @@ void NativeMessageProcessHost::HandleReadResult(int result) { |
void NativeMessageProcessHost::ProcessIncomingData( |
const char* data, int data_size) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
incoming_data_.append(data, data_size); |
@@ -281,15 +328,17 @@ void NativeMessageProcessHost::ProcessIncomingData( |
if (incoming_data_.size() < message_size + kMessageHeaderSize) |
return; |
- client_->PostMessageFromNativeHost( |
- incoming_data_.substr(kMessageHeaderSize, message_size)); |
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
+ base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_, |
+ destination_port_, |
+ incoming_data_.substr(kMessageHeaderSize, message_size))); |
incoming_data_.erase(0, kMessageHeaderSize + message_size); |
} |
} |
void NativeMessageProcessHost::DoWrite() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
while (!write_pending_ && !closed_) { |
if (!current_write_buffer_.get() || |
@@ -311,7 +360,7 @@ void NativeMessageProcessHost::DoWrite() { |
} |
void NativeMessageProcessHost::HandleWriteResult(int result) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
if (result <= 0) { |
if (result == net::ERR_IO_PENDING) { |
@@ -327,7 +376,7 @@ void NativeMessageProcessHost::HandleWriteResult(int result) { |
} |
void NativeMessageProcessHost::OnWritten(int result) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
DCHECK(write_pending_); |
write_pending_ = false; |
@@ -337,13 +386,15 @@ void NativeMessageProcessHost::OnWritten(int result) { |
} |
void NativeMessageProcessHost::Close(const std::string& error_message) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
if (!closed_) { |
closed_ = true; |
read_stream_.reset(); |
write_stream_.reset(); |
- client_->CloseChannel(error_message); |
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
+ base::Bind(&Client::CloseChannel, weak_client_ui_, |
+ destination_port_, error_message)); |
} |
if (process_handle_ != base::kNullProcessHandle) { |