| 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
|
|
|