OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" | 5 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/command_line.h" |
8 #include "base/logging.h" | 9 #include "base/logging.h" |
9 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
10 #include "base/path_service.h" | 11 #include "base/path_service.h" |
11 #include "base/process_util.h" | 12 #include "base/process_util.h" |
12 #include "base/sequenced_task_runner.h" | 13 #include "base/string_split.h" |
13 #include "base/threading/sequenced_worker_pool.h" | 14 #include "base/threading/sequenced_worker_pool.h" |
| 15 #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest
.h" |
14 #include "chrome/common/chrome_paths.h" | 16 #include "chrome/common/chrome_paths.h" |
| 17 #include "chrome/common/chrome_switches.h" |
| 18 #include "googleurl/src/gurl.h" |
15 | 19 |
16 namespace extensions { | 20 namespace extensions { |
17 | 21 |
18 namespace { | 22 namespace { |
19 | 23 |
20 const char kNativeHostsDirectoryName[] = "native_hosts"; | 24 const char kNativeHostsDirectoryName[] = "native_hosts"; |
21 | 25 |
| 26 base::FilePath GetHostManifestPathFromCommandLine( |
| 27 const std::string& native_host_name) { |
| 28 const std::string& value = |
| 29 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 30 switches::kNativeMessagingHosts); |
| 31 if (value.empty()) |
| 32 return base::FilePath(); |
| 33 |
| 34 std::vector<std::string> hosts; |
| 35 base::SplitString(value, ',', &hosts); |
| 36 for (size_t i = 0; i < hosts.size(); ++i) { |
| 37 std::vector<std::string> key_and_value; |
| 38 base::SplitString(hosts[i], '=', &key_and_value); |
| 39 if (key_and_value.size() != 2) |
| 40 continue; |
| 41 if (key_and_value[0] == native_host_name) |
| 42 return base::FilePath::FromUTF8Unsafe(key_and_value[1]); |
| 43 } |
| 44 |
| 45 return base::FilePath(); |
| 46 } |
| 47 |
| 48 |
22 // Default implementation on NativeProcessLauncher interface. | 49 // Default implementation on NativeProcessLauncher interface. |
23 class NativeProcessLauncherImpl : public NativeProcessLauncher { | 50 class NativeProcessLauncherImpl : public NativeProcessLauncher { |
24 public: | 51 public: |
25 NativeProcessLauncherImpl(); | 52 NativeProcessLauncherImpl(); |
26 virtual ~NativeProcessLauncherImpl(); | 53 virtual ~NativeProcessLauncherImpl(); |
27 | 54 |
28 virtual void Launch(const std::string& native_host_name, | 55 virtual void Launch(const GURL& origin, |
| 56 const std::string& native_host_name, |
29 LaunchedCallback callback) const OVERRIDE; | 57 LaunchedCallback callback) const OVERRIDE; |
30 | 58 |
31 private: | 59 private: |
32 class Core : public base::RefCountedThreadSafe<Core> { | 60 class Core : public base::RefCountedThreadSafe<Core> { |
33 public: | 61 public: |
34 Core(); | 62 Core(); |
35 void Launch(const std::string& native_host_name, | 63 void Launch(const GURL& origin, |
| 64 const std::string& native_host_name, |
36 LaunchedCallback callback); | 65 LaunchedCallback callback); |
37 void Detach(); | 66 void Detach(); |
38 | 67 |
39 private: | 68 private: |
40 friend class base::RefCountedThreadSafe<Core>; | 69 friend class base::RefCountedThreadSafe<Core>; |
41 virtual ~Core(); | 70 virtual ~Core(); |
42 | 71 |
43 void DoLaunchOnThreadPool(const std::string& native_host_name, | 72 void DoLaunchOnThreadPool(const GURL& origin, |
| 73 const std::string& native_host_name, |
44 LaunchedCallback callback); | 74 LaunchedCallback callback); |
45 void CallCallbackOnIOThread(LaunchedCallback callback, | 75 void CallCallbackOnIOThread(LaunchedCallback callback, |
46 bool result, | 76 bool result, |
47 base::PlatformFile read_file, | 77 base::PlatformFile read_file, |
48 base::PlatformFile write_file); | 78 base::PlatformFile write_file); |
49 | 79 |
50 bool detached_; | 80 bool detached_; |
51 | 81 |
52 DISALLOW_COPY_AND_ASSIGN(Core); | 82 DISALLOW_COPY_AND_ASSIGN(Core); |
53 }; | 83 }; |
(...skipping 10 matching lines...) Expand all Loading... |
64 NativeProcessLauncherImpl::Core::~Core() { | 94 NativeProcessLauncherImpl::Core::~Core() { |
65 DCHECK(detached_); | 95 DCHECK(detached_); |
66 } | 96 } |
67 | 97 |
68 void NativeProcessLauncherImpl::Core::Detach() { | 98 void NativeProcessLauncherImpl::Core::Detach() { |
69 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 99 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
70 detached_ = true; | 100 detached_ = true; |
71 } | 101 } |
72 | 102 |
73 void NativeProcessLauncherImpl::Core::Launch( | 103 void NativeProcessLauncherImpl::Core::Launch( |
| 104 const GURL& origin, |
74 const std::string& native_host_name, | 105 const std::string& native_host_name, |
75 LaunchedCallback callback) { | 106 LaunchedCallback callback) { |
76 content::BrowserThread::PostBlockingPoolTask( | 107 content::BrowserThread::PostBlockingPoolTask( |
77 FROM_HERE, base::Bind(&Core::DoLaunchOnThreadPool, this, | 108 FROM_HERE, base::Bind(&Core::DoLaunchOnThreadPool, this, |
78 native_host_name, callback)); | 109 origin, native_host_name, callback)); |
79 } | 110 } |
80 | 111 |
81 void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool( | 112 void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool( |
| 113 const GURL& origin, |
82 const std::string& native_host_name, | 114 const std::string& native_host_name, |
83 LaunchedCallback callback) { | 115 LaunchedCallback callback) { |
84 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); | 116 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
85 | 117 |
86 base::FilePath native_host_program; | 118 std::string error_message; |
87 base::FilePath native_host_registry; | 119 scoped_ptr<NativeMessagingHostManifest> manifest; |
88 CHECK(PathService::Get(chrome::DIR_USER_DATA, &native_host_registry)); | |
89 native_host_registry = | |
90 native_host_registry.AppendASCII(kNativeHostsDirectoryName); | |
91 native_host_program = native_host_registry.AppendASCII(native_host_name); | |
92 | 120 |
93 // Make sure that the client is not trying to invoke something outside of the | 121 if (!NativeMessagingHostManifest::IsValidName(native_host_name)) { |
94 // proper directory. Eg. '../../dangerous_something.exe'. | 122 error_message = "Invalid native host name: " + native_host_name; |
95 if (!file_util::ContainsPath(native_host_registry, native_host_program)) { | 123 } else { |
96 LOG(ERROR) << "Could not find native host: " << native_host_name; | 124 // First check if the manifest location is specified in the command line. |
| 125 base::FilePath path = GetHostManifestPathFromCommandLine(native_host_name); |
| 126 if (!path.empty()) { |
| 127 manifest = NativeMessagingHostManifest::Load(path, &error_message); |
| 128 } else { |
| 129 // Try loading the manifest from the default location. |
| 130 manifest = FindAndLoadManifest(native_host_name, &error_message); |
| 131 } |
| 132 |
| 133 if (manifest && manifest->name() != native_host_name) { |
| 134 error_message = "Name specified in the manifest does not match."; |
| 135 manifest.reset(); |
| 136 } |
| 137 } |
| 138 |
| 139 if (!manifest) { |
| 140 // TODO(sergeyu): Report the error to the application. |
| 141 LOG(ERROR) << "Failed to load manifest for native messaging host " |
| 142 << native_host_name << ": " << error_message; |
97 content::BrowserThread::PostTask( | 143 content::BrowserThread::PostTask( |
98 content::BrowserThread::IO, FROM_HERE, | 144 content::BrowserThread::IO, FROM_HERE, |
99 base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread, | 145 base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread, |
| 146 this, callback, false, |
| 147 base::kInvalidPlatformFileValue, |
| 148 base::kInvalidPlatformFileValue)); |
| 149 return; |
| 150 } |
| 151 |
| 152 if (!manifest->allowed_origins().MatchesSecurityOrigin(origin)) { |
| 153 // Not an allowed origin. |
| 154 content::BrowserThread::PostTask( |
| 155 content::BrowserThread::IO, FROM_HERE, |
| 156 base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread, |
100 this, callback, false, | 157 this, callback, false, |
101 base::kInvalidPlatformFileValue, | 158 base::kInvalidPlatformFileValue, |
102 base::kInvalidPlatformFileValue)); | 159 base::kInvalidPlatformFileValue)); |
103 return; | 160 return; |
104 } | 161 } |
105 | 162 |
106 base::PlatformFile read_file; | 163 base::PlatformFile read_file; |
107 base::PlatformFile write_file; | 164 base::PlatformFile write_file; |
108 bool result = NativeProcessLauncher::LaunchNativeProcess( | 165 bool result = NativeProcessLauncher::LaunchNativeProcess( |
109 native_host_program, &read_file, &write_file); | 166 manifest->path(), &read_file, &write_file); |
110 | 167 |
111 content::BrowserThread::PostTask( | 168 content::BrowserThread::PostTask( |
112 content::BrowserThread::IO, FROM_HERE, | 169 content::BrowserThread::IO, FROM_HERE, |
113 base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread, | 170 base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread, |
114 this, callback, result, read_file, write_file)); | 171 this, callback, result, read_file, write_file)); |
115 } | 172 } |
116 | 173 |
117 void NativeProcessLauncherImpl::Core::CallCallbackOnIOThread( | 174 void NativeProcessLauncherImpl::Core::CallCallbackOnIOThread( |
118 LaunchedCallback callback, | 175 LaunchedCallback callback, |
119 bool result, | 176 bool result, |
(...skipping 12 matching lines...) Expand all Loading... |
132 } | 189 } |
133 | 190 |
134 NativeProcessLauncherImpl::NativeProcessLauncherImpl() | 191 NativeProcessLauncherImpl::NativeProcessLauncherImpl() |
135 : core_(new Core()) { | 192 : core_(new Core()) { |
136 } | 193 } |
137 | 194 |
138 NativeProcessLauncherImpl::~NativeProcessLauncherImpl() { | 195 NativeProcessLauncherImpl::~NativeProcessLauncherImpl() { |
139 core_->Detach(); | 196 core_->Detach(); |
140 } | 197 } |
141 | 198 |
142 void NativeProcessLauncherImpl::Launch(const std::string& native_host_name, | 199 void NativeProcessLauncherImpl::Launch(const GURL& origin, |
| 200 const std::string& native_host_name, |
143 LaunchedCallback callback) const { | 201 LaunchedCallback callback) const { |
144 core_->Launch(native_host_name, callback); | 202 core_->Launch(origin, native_host_name, callback); |
145 } | 203 } |
146 | 204 |
147 } // namespace | 205 } // namespace |
148 | 206 |
149 // static | 207 // static |
150 scoped_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault() { | 208 scoped_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault() { |
151 return scoped_ptr<NativeProcessLauncher>(new NativeProcessLauncherImpl()); | 209 return scoped_ptr<NativeProcessLauncher>(new NativeProcessLauncherImpl()); |
152 } | 210 } |
153 | 211 |
154 } // namespace extensions | 212 } // namespace extensions |
OLD | NEW |