Chromium Code Reviews| 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..9195653a7c86736e3a8713dd2d719272c280b112 100644 |
| --- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc |
| +++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc |
| @@ -5,12 +5,16 @@ |
| #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" |
| namespace extensions { |
| @@ -18,27 +22,63 @@ namespace { |
| const char kNativeHostsDirectoryName[] = "native_hosts"; |
| +scoped_ptr<NativeMessagingHostManifest> LoadHostManifestFromCommandLine( |
| + const std::string& native_host_name) { |
| + const std::string& value = |
| + CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| + switches::kNativeMessagingHosts); |
| + if (value.empty()) |
| + return scoped_ptr<NativeMessagingHostManifest>(NULL); |
| + |
| + std::vector<std::string> hosts; |
| + base::SplitString(value, ',', &hosts); |
|
Matt Perry
2013/02/16 02:00:51
note this means that you can't have commas or equa
Sergey Ulanov
2013/02/20 00:05:36
Current design doc says that these names should be
|
| + 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) { |
| + std::string error_message; |
| + scoped_ptr<NativeMessagingHostManifest> result = |
| + NativeMessagingHostManifest::Load( |
| + FilePath::FromUTF8Unsafe(key_and_value[1]), |
| + &error_message); |
| + if (!result) { |
| + LOG(ERROR) << "Failed to load Native Messaging Host manifest " |
| + << key_and_value[1] << " " << error_message; |
| + } |
| + return result.Pass(); |
| + } |
| + } |
| + |
| + return scoped_ptr<NativeMessagingHostManifest>(NULL); |
| +} |
| + |
| + |
| // 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 std::string& 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 std::string& 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 std::string& origin, |
| + const std::string& native_host_name, |
| LaunchedCallback callback); |
| void CallCallbackOnIOThread(LaunchedCallback callback, |
| base::ProcessHandle native_process_handle, |
| @@ -69,29 +109,40 @@ void NativeProcessLauncherImpl::Core::Detach() { |
| } |
| void NativeProcessLauncherImpl::Core::Launch( |
| + const std::string& 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 std::string& 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; |
| + |
| + // First try loading the host from the location specified in the command line. |
| + manifest = LoadHostManifestFromCommandLine(native_host_name); |
| + |
| + // If the manifest location wasn't specified in the command line then load it |
| + // from the default location. |
| + if (!manifest) |
| + manifest = FindAndLoadManifest(native_host_name, &error_message); |
| + |
| + if (manifest && manifest->name() != native_host_name) { |
| + error_message = "Invalid name specified in the manifest."; |
|
Matt Perry
2013/02/16 02:00:51
"Name specified in the manifest does not match"?
Sergey Ulanov
2013/02/20 00:05:36
Done.
|
| + 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 +152,19 @@ void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool( |
| return; |
| } |
| + if (!manifest->IsAllowedOrigin(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 +209,10 @@ NativeProcessLauncherImpl::~NativeProcessLauncherImpl() { |
| core_->Detach(); |
| } |
| -void NativeProcessLauncherImpl::Launch(const std::string& native_host_name, |
| +void NativeProcessLauncherImpl::Launch(const std::string& origin, |
| + const std::string& native_host_name, |
| LaunchedCallback callback) const { |
| - core_->Launch(native_host_name, callback); |
| + core_->Launch(origin, native_host_name, callback); |
| } |
| } // namespace |