Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: components/nacl/browser/nacl_file_host.cc

Issue 2514323004: Convert NaCl renderer-browser messages to mojo. (Closed)
Patch Set: rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "components/nacl/browser/nacl_file_host.h" 5 #include "components/nacl/browser/nacl_file_host.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/files/file.h" 12 #include "base/files/file.h"
13 #include "base/files/file_path.h" 13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h" 14 #include "base/files/file_util.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "base/threading/sequenced_worker_pool.h" 16 #include "base/threading/sequenced_worker_pool.h"
17 #include "components/nacl/browser/bad_message.h" 17 #include "components/nacl/browser/bad_message.h"
18 #include "components/nacl/browser/nacl_browser.h" 18 #include "components/nacl/browser/nacl_browser.h"
19 #include "components/nacl/browser/nacl_browser_delegate.h" 19 #include "components/nacl/browser/nacl_browser_delegate.h"
20 #include "components/nacl/browser/nacl_host_message_filter.h"
21 #include "components/nacl/common/nacl_host_messages.h"
22 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/render_view_host.h" 21 #include "content/public/browser/render_view_host.h"
24 #include "content/public/browser/site_instance.h" 22 #include "content/public/browser/site_instance.h"
25 #include "ipc/ipc_platform_file.h"
26 23
27 using content::BrowserThread; 24 using content::BrowserThread;
28 25
26 namespace nacl_file_host {
29 namespace { 27 namespace {
30 28
31 // Force a prefix to prevent user from opening "magic" files. 29 // Force a prefix to prevent user from opening "magic" files.
32 const char* kExpectedFilePrefix = "pnacl_public_"; 30 const char* kExpectedFilePrefix = "pnacl_public_";
33 31
34 // Restrict PNaCl file lengths to reduce likelyhood of hitting bugs 32 // Restrict PNaCl file lengths to reduce likelyhood of hitting bugs
35 // in file name limit error-handling-code-paths, etc. 33 // in file name limit error-handling-code-paths, etc.
36 const size_t kMaxFileLength = 40; 34 const size_t kMaxFileLength = 40;
37 35
38 void NotifyRendererOfError( 36 void NotifyRendererOfError(
39 nacl::NaClHostMessageFilter* nacl_host_message_filter, 37 const scoped_refptr<base::TaskRunner>& origin_task_runner,
40 IPC::Message* reply_msg) { 38 const OpenFileCallback& callback) {
41 reply_msg->set_reply_error(); 39 origin_task_runner->PostTask(
42 nacl_host_message_filter->Send(reply_msg); 40 FROM_HERE, base::Bind(callback, base::Passed(base::File()), 0, 0));
43 } 41 }
44 42
45 typedef void (*WriteFileInfoReply)(IPC::Message* reply_msg,
46 const IPC::PlatformFileForTransit& file_desc,
47 const uint64_t& file_token_lo,
48 const uint64_t& file_token_hi);
49
50 void DoRegisterOpenedNaClExecutableFile( 43 void DoRegisterOpenedNaClExecutableFile(
51 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
52 base::File file, 44 base::File file,
53 base::FilePath file_path, 45 base::FilePath file_path,
54 IPC::Message* reply_msg, 46 const scoped_refptr<base::TaskRunner>& origin_task_runner,
55 WriteFileInfoReply write_reply_message) { 47 const OpenFileCallback& callback) {
56 // IO thread owns the NaClBrowser singleton. 48 // IO thread owns the NaClBrowser singleton.
57 DCHECK_CURRENTLY_ON(BrowserThread::IO); 49 DCHECK_CURRENTLY_ON(BrowserThread::IO);
58 50
59 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); 51 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance();
60 uint64_t file_token_lo = 0; 52 uint64_t file_token_lo = 0;
61 uint64_t file_token_hi = 0; 53 uint64_t file_token_hi = 0;
62 nacl_browser->PutFilePath(file_path, &file_token_lo, &file_token_hi); 54 nacl_browser->PutFilePath(file_path, &file_token_lo, &file_token_hi);
63 55
64 IPC::PlatformFileForTransit file_desc = 56 origin_task_runner->PostTask(
65 IPC::TakePlatformFileForTransit(std::move(file)); 57 FROM_HERE,
66 58 base::Bind(callback, base::Passed(&file), file_token_lo, file_token_hi));
67 write_reply_message(reply_msg, file_desc, file_token_lo, file_token_hi);
68 nacl_host_message_filter->Send(reply_msg);
69 } 59 }
70 60
71 void DoOpenPnaclFile( 61 void DoOpenPnaclFile(const std::string& filename,
72 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 62 bool is_executable,
73 const std::string& filename, 63 const scoped_refptr<base::TaskRunner>& origin_task_runner,
74 bool is_executable, 64 const OpenFileCallback& callback) {
75 IPC::Message* reply_msg) {
76 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 65 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
77 base::FilePath full_filepath; 66 base::FilePath full_filepath;
78 67
79 // PNaCl must be installed. 68 // PNaCl must be installed.
80 base::FilePath pnacl_dir; 69 base::FilePath pnacl_dir;
81 if (!nacl::NaClBrowser::GetDelegate()->GetPnaclDirectory(&pnacl_dir) || 70 if (!nacl::NaClBrowser::GetDelegate()->GetPnaclDirectory(&pnacl_dir) ||
82 !base::PathExists(pnacl_dir)) { 71 !base::PathExists(pnacl_dir)) {
83 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 72 NotifyRendererOfError(origin_task_runner, callback);
84 return; 73 return;
85 } 74 }
86 75
87 // Do some validation. 76 // Do some validation.
88 if (!nacl_file_host::PnaclCanOpenFile(filename, &full_filepath)) { 77 if (!nacl_file_host::PnaclCanOpenFile(filename, &full_filepath)) {
89 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 78 NotifyRendererOfError(origin_task_runner, callback);
90 return; 79 return;
91 } 80 }
92 81
93 base::File file_to_open = nacl::OpenNaClReadExecImpl(full_filepath, 82 base::File file_to_open = nacl::OpenNaClReadExecImpl(full_filepath,
94 is_executable); 83 is_executable);
95 if (!file_to_open.IsValid()) { 84 if (!file_to_open.IsValid()) {
96 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 85 NotifyRendererOfError(origin_task_runner, callback);
97 return; 86 return;
98 } 87 }
99 88
100 // This function is running on the blocking pool, but the path needs to be 89 // This function is running on the blocking pool, but the path needs to be
101 // registered in a structure owned by the IO thread. 90 // registered in a structure owned by the IO thread.
102 // Not all PNaCl files are executable. Only register those that are 91 // Not all PNaCl files are executable. Only register those that are
103 // executable in the NaCl file_path cache. 92 // executable in the NaCl file_path cache.
104 if (is_executable) { 93 if (is_executable) {
105 BrowserThread::PostTask( 94 BrowserThread::PostTask(
106 BrowserThread::IO, FROM_HERE, 95 BrowserThread::IO, FROM_HERE,
107 base::Bind(&DoRegisterOpenedNaClExecutableFile, 96 base::Bind(&DoRegisterOpenedNaClExecutableFile, Passed(&file_to_open),
108 nacl_host_message_filter, Passed(std::move(file_to_open)), 97 full_filepath, origin_task_runner, callback));
109 full_filepath, reply_msg,
110 static_cast<WriteFileInfoReply>(
111 NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams)));
112 } else { 98 } else {
113 IPC::PlatformFileForTransit target_desc = 99 constexpr uint64_t kDummyFileToken = 0;
114 IPC::TakePlatformFileForTransit(std::move(file_to_open)); 100 origin_task_runner->PostTask(
115 uint64_t dummy_file_token = 0; 101 FROM_HERE, base::Bind(callback, base::Passed(&file_to_open),
116 NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams( 102 kDummyFileToken, kDummyFileToken));
117 reply_msg, target_desc, dummy_file_token, dummy_file_token);
118 nacl_host_message_filter->Send(reply_msg);
119 } 103 }
120 } 104 }
121 105
122 // Convert the file URL into a file descriptor. 106 // Convert the file URL into a file descriptor.
123 // This function is security sensitive. Be sure to check with a security 107 // This function is security sensitive. Be sure to check with a security
124 // person before you modify it. 108 // person before you modify it.
125 void DoOpenNaClExecutableOnThreadPool( 109 void DoOpenNaClExecutableOnThreadPool(
126 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
127 const GURL& file_url, 110 const GURL& file_url,
128 bool enable_validation_caching, 111 bool enable_validation_caching,
129 IPC::Message* reply_msg) { 112 const base::FilePath& profile_directory,
113 const scoped_refptr<base::TaskRunner>& origin_task_runner,
114 const OpenFileCallback& callback) {
130 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 115 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
131 116
132 base::FilePath file_path; 117 base::FilePath file_path;
133 if (!nacl::NaClBrowser::GetDelegate()->MapUrlToLocalFilePath( 118 if (!nacl::NaClBrowser::GetDelegate()->MapUrlToLocalFilePath(
134 file_url, 119 file_url, true /* use_blocking_api */, profile_directory,
135 true /* use_blocking_api */,
136 nacl_host_message_filter->profile_directory(),
137 &file_path)) { 120 &file_path)) {
138 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 121 NotifyRendererOfError(origin_task_runner, callback);
139 return; 122 return;
140 } 123 }
141 124
142 base::File file = nacl::OpenNaClReadExecImpl(file_path, 125 base::File file = nacl::OpenNaClReadExecImpl(file_path,
143 true /* is_executable */); 126 true /* is_executable */);
144 if (file.IsValid()) { 127 if (file.IsValid()) {
145 // Opening a NaCl executable works with or without validation caching. 128 // Opening a NaCl executable works with or without validation caching.
146 // Validation caching requires that the file descriptor is registered now 129 // Validation caching requires that the file descriptor is registered now
147 // for later use, which will save time. 130 // for later use, which will save time.
148 // When validation caching isn't used (e.g. Non-SFI mode), there is no 131 // When validation caching isn't used (e.g. Non-SFI mode), there is no
149 // reason to do that unnecessary registration. 132 // reason to do that unnecessary registration.
150 if (enable_validation_caching) { 133 if (enable_validation_caching) {
151 // This function is running on the blocking pool, but the path needs to be 134 // This function is running on the blocking pool, but the path needs to be
152 // registered in a structure owned by the IO thread. 135 // registered in a structure owned by the IO thread.
153 BrowserThread::PostTask( 136 BrowserThread::PostTask(
154 BrowserThread::IO, FROM_HERE, 137 BrowserThread::IO, FROM_HERE,
155 base::Bind(&DoRegisterOpenedNaClExecutableFile, 138 base::Bind(&DoRegisterOpenedNaClExecutableFile, Passed(&file),
156 nacl_host_message_filter, Passed(std::move(file)), 139 file_path, origin_task_runner, callback));
157 file_path, reply_msg,
158 static_cast<WriteFileInfoReply>(
159 NaClHostMsg_OpenNaClExecutable::WriteReplyParams)));
160 } else { 140 } else {
161 IPC::PlatformFileForTransit file_desc = 141 constexpr uint64_t kDummyFileToken = 0;
162 IPC::TakePlatformFileForTransit(std::move(file)); 142 origin_task_runner->PostTask(
163 uint64_t dummy_file_token = 0; 143 FROM_HERE, base::Bind(callback, base::Passed(&file), kDummyFileToken,
164 NaClHostMsg_OpenNaClExecutable::WriteReplyParams( 144 kDummyFileToken));
165 reply_msg, file_desc, dummy_file_token, dummy_file_token);
166 nacl_host_message_filter->Send(reply_msg);
167 } 145 }
168 } else { 146 } else {
169 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 147 NotifyRendererOfError(origin_task_runner, callback);
170 return; 148 return;
171 } 149 }
172 } 150 }
173 151
174 } // namespace 152 } // namespace
175 153
176 namespace nacl_file_host { 154 void GetReadonlyPnaclFd(const std::string& filename,
177 155 bool is_executable,
178 void GetReadonlyPnaclFd( 156 const OpenFileCallback& callback) {
179 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
180 const std::string& filename,
181 bool is_executable,
182 IPC::Message* reply_msg) {
183 if (!BrowserThread::PostBlockingPoolTask( 157 if (!BrowserThread::PostBlockingPoolTask(
184 FROM_HERE, 158 FROM_HERE,
185 base::Bind(&DoOpenPnaclFile, 159 base::Bind(&DoOpenPnaclFile, filename, is_executable,
186 nacl_host_message_filter, 160 base::ThreadTaskRunnerHandle::Get(), callback))) {
187 filename, 161 NotifyRendererOfError(base::ThreadTaskRunnerHandle::Get(), callback);
188 is_executable,
189 reply_msg))) {
190 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
191 } 162 }
192 } 163 }
193 164
194 // This function is security sensitive. Be sure to check with a security 165 // This function is security sensitive. Be sure to check with a security
195 // person before you modify it. 166 // person before you modify it.
196 bool PnaclCanOpenFile(const std::string& filename, 167 bool PnaclCanOpenFile(const std::string& filename,
197 base::FilePath* file_to_open) { 168 base::FilePath* file_to_open) {
198 if (filename.length() > kMaxFileLength) 169 if (filename.length() > kMaxFileLength)
199 return false; 170 return false;
200 171
(...skipping 17 matching lines...) Expand all
218 return false; 189 return false;
219 190
220 // Prepend the prefix to restrict files to a whitelisted set. 191 // Prepend the prefix to restrict files to a whitelisted set.
221 base::FilePath full_path = pnacl_dir.AppendASCII( 192 base::FilePath full_path = pnacl_dir.AppendASCII(
222 std::string(kExpectedFilePrefix) + filename); 193 std::string(kExpectedFilePrefix) + filename);
223 *file_to_open = full_path; 194 *file_to_open = full_path;
224 return true; 195 return true;
225 } 196 }
226 197
227 void OpenNaClExecutable( 198 void OpenNaClExecutable(
228 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
229 int render_view_id, 199 int render_view_id,
230 const GURL& file_url, 200 const GURL& file_url,
231 bool enable_validation_caching, 201 bool enable_validation_caching,
232 IPC::Message* reply_msg) { 202 int render_process_id,
203 const base::FilePath& profile_directory,
204 const scoped_refptr<base::TaskRunner>& origin_task_runner,
205 const OpenFileCallback& callback) {
233 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 206 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
234 BrowserThread::PostTask( 207 BrowserThread::PostTask(
235 BrowserThread::UI, FROM_HERE, 208 BrowserThread::UI, FROM_HERE,
236 base::Bind( 209 base::Bind(&OpenNaClExecutable, render_view_id, file_url,
237 &OpenNaClExecutable, 210 enable_validation_caching, render_process_id,
238 nacl_host_message_filter, 211 profile_directory, origin_task_runner, callback));
239 render_view_id,
240 file_url,
241 enable_validation_caching,
242 reply_msg));
243 return; 212 return;
244 } 213 }
245 214
246 // Make sure render_view_id is valid and that the URL is a part of the 215 // Make sure render_view_id is valid and that the URL is a part of the
247 // render view's site. Without these checks, apps could probe the extension 216 // render view's site. Without these checks, apps could probe the extension
248 // directory or run NaCl code from other extensions. 217 // directory or run NaCl code from other extensions.
249 content::RenderViewHost* rvh = content::RenderViewHost::FromID( 218 content::RenderViewHost* rvh =
250 nacl_host_message_filter->render_process_id(), render_view_id); 219 content::RenderViewHost::FromID(render_process_id, render_view_id);
251 if (!rvh) { 220 if (!rvh) {
252 nacl::bad_message::ReceivedBadMessage( 221 nacl::bad_message::ReceivedBadMessage(
253 nacl_host_message_filter.get(), 222 render_process_id,
254 nacl::bad_message::NFH_OPEN_EXECUTABLE_BAD_ROUTING_ID); 223 nacl::bad_message::NFH_OPEN_EXECUTABLE_BAD_ROUTING_ID);
255 delete reply_msg; 224 // The callback must be called even if the message was invalid.
225 NotifyRendererOfError(origin_task_runner, callback);
256 return; 226 return;
257 } 227 }
258 content::SiteInstance* site_instance = rvh->GetSiteInstance(); 228 content::SiteInstance* site_instance = rvh->GetSiteInstance();
259 if (!content::SiteInstance::IsSameWebSite(site_instance->GetBrowserContext(), 229 if (!content::SiteInstance::IsSameWebSite(site_instance->GetBrowserContext(),
260 site_instance->GetSiteURL(), 230 site_instance->GetSiteURL(),
261 file_url)) { 231 file_url)) {
262 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 232 NotifyRendererOfError(origin_task_runner, callback);
263 return; 233 return;
264 } 234 }
265 235
266 // The URL is part of the current app. Now query the extension system for the 236 // The URL is part of the current app. Now query the extension system for the
267 // file path and convert that to a file descriptor. This should be done on a 237 // file path and convert that to a file descriptor. This should be done on a
268 // blocking pool thread. 238 // blocking pool thread.
269 if (!BrowserThread::PostBlockingPoolTask( 239 if (!BrowserThread::PostBlockingPoolTask(
270 FROM_HERE, 240 FROM_HERE, base::Bind(&DoOpenNaClExecutableOnThreadPool, file_url,
271 base::Bind( 241 enable_validation_caching, profile_directory,
272 &DoOpenNaClExecutableOnThreadPool, 242 origin_task_runner, callback))) {
273 nacl_host_message_filter, 243 NotifyRendererOfError(origin_task_runner, callback);
274 file_url,
275 enable_validation_caching,
276 reply_msg))) {
277 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
278 } 244 }
279 } 245 }
280 246
281 } // namespace nacl_file_host 247 } // namespace nacl_file_host
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698