| 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 ce223aee22b9d892df9d52b7b62fe7fdb6a9ef8c..c0c6c12aa031408edbe2840439e455b02d59ea6f 100644
|
| --- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc
|
| +++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
|
| @@ -5,12 +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/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 {
|
|
|
| @@ -18,27 +23,53 @@ 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();
|
| private:
|
| 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,
|
| base::ProcessHandle native_process_handle,
|
| @@ -69,29 +100,45 @@ 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::IsValidHostName(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,
|
| @@ -101,6 +148,19 @@ void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool(
|
| return;
|
| }
|
|
|
| + if (!manifest->allowed_origins().MatchesSecurityOrigin(origin)) {
|
| + // Not an allowed origin.
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread,
|
| + this, callback, base::kNullProcessHandle,
|
| + base::kInvalidPlatformFileValue,
|
| + base::kInvalidPlatformFileValue));
|
| + return;
|
| + }
|
| +
|
| + FilePath native_host_program = manifest->path();
|
| +
|
| base::ProcessHandle native_process_handle;
|
| base::PlatformFile read_file;
|
| base::PlatformFile write_file;
|
| @@ -145,9 +205,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
|
|
|