Index: chrome/browser/extensions/api/messaging/native_process_launcher.cc |
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chrome/browser/extensions/api/messaging/native_process_launcher.cc |
index 36beaf2798646d0f8cb5075bf78983bac0b544f6..ee53ec7c07e6d1e82c56a6853dd2a130d8ed1a8b 100644 |
--- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc |
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc |
@@ -5,13 +5,17 @@ |
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h" |
#include "base/basictypes.h" |
+#include "base/command_line.h" |
#include "base/logging.h" |
#include "base/memory/ref_counted.h" |
#include "base/path_service.h" |
#include "base/process_util.h" |
-#include "base/sequenced_task_runner.h" |
+#include "base/string_split.h" |
#include "base/threading/sequenced_worker_pool.h" |
+#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h" |
#include "chrome/common/chrome_paths.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "googleurl/src/gurl.h" |
namespace extensions { |
@@ -19,20 +23,45 @@ namespace { |
const char kNativeHostsDirectoryName[] = "native_hosts"; |
+base::FilePath GetHostManifestPathFromCommandLine( |
+ const std::string& native_host_name) { |
+ const std::string& value = |
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
+ switches::kNativeMessagingHosts); |
+ if (value.empty()) |
+ return base::FilePath(); |
+ |
+ std::vector<std::string> hosts; |
+ base::SplitString(value, ',', &hosts); |
+ for (size_t i = 0; i < hosts.size(); ++i) { |
+ std::vector<std::string> key_and_value; |
+ base::SplitString(hosts[i], '=', &key_and_value); |
+ if (key_and_value.size() != 2) |
+ continue; |
+ if (key_and_value[0] == native_host_name) |
+ return base::FilePath::FromUTF8Unsafe(key_and_value[1]); |
+ } |
+ |
+ return base::FilePath(); |
+} |
+ |
+ |
// Default implementation on NativeProcessLauncher interface. |
class NativeProcessLauncherImpl : public NativeProcessLauncher { |
public: |
NativeProcessLauncherImpl(); |
virtual ~NativeProcessLauncherImpl(); |
- virtual void Launch(const std::string& native_host_name, |
+ virtual void Launch(const GURL& origin, |
+ const std::string& native_host_name, |
LaunchedCallback callback) const OVERRIDE; |
private: |
class Core : public base::RefCountedThreadSafe<Core> { |
public: |
Core(); |
- void Launch(const std::string& native_host_name, |
+ void Launch(const GURL& origin, |
+ const std::string& native_host_name, |
LaunchedCallback callback); |
void Detach(); |
@@ -40,7 +69,8 @@ class NativeProcessLauncherImpl : public NativeProcessLauncher { |
friend class base::RefCountedThreadSafe<Core>; |
virtual ~Core(); |
- void DoLaunchOnThreadPool(const std::string& native_host_name, |
+ void DoLaunchOnThreadPool(const GURL& origin, |
+ const std::string& native_host_name, |
LaunchedCallback callback); |
void CallCallbackOnIOThread(LaunchedCallback callback, |
bool result, |
@@ -71,29 +101,56 @@ void NativeProcessLauncherImpl::Core::Detach() { |
} |
void NativeProcessLauncherImpl::Core::Launch( |
+ const GURL& origin, |
const std::string& native_host_name, |
LaunchedCallback callback) { |
content::BrowserThread::PostBlockingPoolTask( |
FROM_HERE, base::Bind(&Core::DoLaunchOnThreadPool, this, |
- native_host_name, callback)); |
+ origin, native_host_name, callback)); |
} |
void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool( |
+ const GURL& origin, |
const std::string& native_host_name, |
LaunchedCallback callback) { |
DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
- base::FilePath native_host_program; |
- base::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_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_host_name; |
+ std::string error_message; |
+ scoped_ptr<NativeMessagingHostManifest> manifest; |
+ |
+ if (!NativeMessagingHostManifest::IsValidName(native_host_name)) { |
+ error_message = "Invalid native host name: " + native_host_name; |
+ } else { |
+ // First check if the manifest location is specified in the command line. |
+ base::FilePath path = GetHostManifestPathFromCommandLine(native_host_name); |
+ if (!path.empty()) { |
+ manifest = NativeMessagingHostManifest::Load(path, &error_message); |
+ } else { |
+ // Try loading the manifest from the default location. |
+ manifest = FindAndLoadManifest(native_host_name, &error_message); |
+ } |
+ |
+ if (manifest && manifest->name() != native_host_name) { |
+ error_message = "Name specified in the manifest does not match."; |
+ manifest.reset(); |
+ } |
+ } |
+ |
+ if (!manifest) { |
+ // TODO(sergeyu): Report the error to the application. |
+ LOG(ERROR) << "Failed to load manifest for native messaging host " |
+ << native_host_name << ": " << error_message; |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, FROM_HERE, |
+ base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread, |
+ this, callback, false, |
+ base::kInvalidPlatformFileValue, |
+ base::kInvalidPlatformFileValue)); |
+ return; |
+ } |
+ |
+ if (!manifest->allowed_origins().MatchesSecurityOrigin(origin)) { |
+ // Not an allowed origin. |
content::BrowserThread::PostTask( |
content::BrowserThread::IO, FROM_HERE, |
base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread, |
@@ -106,7 +163,7 @@ void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool( |
base::PlatformFile read_file; |
base::PlatformFile write_file; |
bool result = NativeProcessLauncher::LaunchNativeProcess( |
- native_host_program, &read_file, &write_file); |
+ manifest->path(), &read_file, &write_file); |
content::BrowserThread::PostTask( |
content::BrowserThread::IO, FROM_HERE, |
@@ -139,9 +196,10 @@ NativeProcessLauncherImpl::~NativeProcessLauncherImpl() { |
core_->Detach(); |
} |
-void NativeProcessLauncherImpl::Launch(const std::string& native_host_name, |
+void NativeProcessLauncherImpl::Launch(const GURL& origin, |
+ const std::string& native_host_name, |
LaunchedCallback callback) const { |
- core_->Launch(native_host_name, callback); |
+ core_->Launch(origin, native_host_name, callback); |
} |
} // namespace |