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

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

Issue 2630443003: Add thread checks to NaClBrowser, and make it leaky (Closed)
Patch Set: Update NaClGdbDebugStubTest Created 3 years, 10 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_browser.h" 5 #include "components/nacl/browser/nacl_browser.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/files/file_proxy.h" 10 #include "base/files/file_proxy.h"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/lazy_instance.h"
12 #include "base/location.h" 13 #include "base/location.h"
13 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
14 #include "base/path_service.h" 15 #include "base/path_service.h"
15 #include "base/pickle.h" 16 #include "base/pickle.h"
16 #include "base/rand_util.h" 17 #include "base/rand_util.h"
17 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
18 #include "base/threading/thread_task_runner_handle.h" 19 #include "base/threading/thread_task_runner_handle.h"
19 #include "base/time/time.h" 20 #include "base/time/time.h"
20 #include "build/build_config.h" 21 #include "build/build_config.h"
21 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 void LogCacheSet(nacl::NaClBrowser::ValidationCacheStatus status) { 112 void LogCacheSet(nacl::NaClBrowser::ValidationCacheStatus status) {
112 // Bucket zero is reserved for future use. 113 // Bucket zero is reserved for future use.
113 UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Set", status, 114 UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Set", status,
114 nacl::NaClBrowser::CACHE_MAX); 115 nacl::NaClBrowser::CACHE_MAX);
115 } 116 }
116 117
117 // Crash throttling parameters. 118 // Crash throttling parameters.
118 const size_t kMaxCrashesPerInterval = 3; 119 const size_t kMaxCrashesPerInterval = 3;
119 const int64_t kCrashesIntervalInSeconds = 120; 120 const int64_t kCrashesIntervalInSeconds = 120;
120 121
122 // Holds the NaClBrowserDelegate, which is leaked on shutdown.
123 NaClBrowserDelegate* g_browser_delegate = nullptr;
124
121 } // namespace 125 } // namespace
122 126
123 namespace nacl { 127 namespace nacl {
124 128
125 base::File OpenNaClReadExecImpl(const base::FilePath& file_path, 129 base::File OpenNaClReadExecImpl(const base::FilePath& file_path,
126 bool is_executable) { 130 bool is_executable) {
127 // Get a file descriptor. On Windows, we need 'GENERIC_EXECUTE' in order to 131 // Get a file descriptor. On Windows, we need 'GENERIC_EXECUTE' in order to
128 // memory map the executable. 132 // memory map the executable.
129 // IMPORTANT: This file descriptor must not have write access - that could 133 // IMPORTANT: This file descriptor must not have write access - that could
130 // allow a NaCl inner sandbox escape. 134 // allow a NaCl inner sandbox escape.
(...skipping 15 matching lines...) Expand all
146 } 150 }
147 151
148 NaClBrowser::NaClBrowser() 152 NaClBrowser::NaClBrowser()
149 : irt_filepath_(), 153 : irt_filepath_(),
150 irt_state_(NaClResourceUninitialized), 154 irt_state_(NaClResourceUninitialized),
151 validation_cache_file_path_(), 155 validation_cache_file_path_(),
152 validation_cache_is_enabled_(false), 156 validation_cache_is_enabled_(false),
153 validation_cache_is_modified_(false), 157 validation_cache_is_modified_(false),
154 validation_cache_state_(NaClResourceUninitialized), 158 validation_cache_state_(NaClResourceUninitialized),
155 path_cache_(kFilePathCacheSize), 159 path_cache_(kFilePathCacheSize),
156 ok_(true), 160 has_failed_(false) {
157 weak_factory_(this) {
158 #if !defined(OS_ANDROID) 161 #if !defined(OS_ANDROID)
159 validation_cache_is_enabled_ = 162 validation_cache_is_enabled_ =
160 CheckEnvVar("NACL_VALIDATION_CACHE", 163 CheckEnvVar("NACL_VALIDATION_CACHE",
161 kValidationCacheEnabledByDefault); 164 kValidationCacheEnabledByDefault);
162 #endif 165 #endif
166 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
163 } 167 }
164 168
165 void NaClBrowser::SetDelegate(NaClBrowserDelegate* delegate) { 169 void NaClBrowser::SetDelegate(std::unique_ptr<NaClBrowserDelegate> delegate) {
166 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); 170 // In the browser SetDelegate is called after threads are initialized.
167 nacl_browser->browser_delegate_.reset(delegate); 171 // In tests it is called before initializing BrowserThreads.
172 if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI)) {
173 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
174 }
175 DCHECK(delegate);
176 DCHECK(!g_browser_delegate);
177 g_browser_delegate = delegate.release();
168 } 178 }
169 179
170 NaClBrowserDelegate* NaClBrowser::GetDelegate() { 180 NaClBrowserDelegate* NaClBrowser::GetDelegate() {
171 // The delegate is not owned by the IO thread. This accessor method can be 181 // NaClBrowser calls this on the IO thread, not the UI thread.
172 // called from other threads. 182 DCHECK(g_browser_delegate);
173 DCHECK(GetInstance()->browser_delegate_.get() != NULL); 183 return g_browser_delegate;
174 return GetInstance()->browser_delegate_.get(); 184 }
185
186 void NaClBrowser::ClearAndDeleteDelegateForTest() {
187 DCHECK(
188 !content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
189 DCHECK(g_browser_delegate);
190 delete g_browser_delegate;
191 g_browser_delegate = nullptr;
175 } 192 }
176 193
177 void NaClBrowser::EarlyStartup() { 194 void NaClBrowser::EarlyStartup() {
178 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 195 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
179 InitIrtFilePath(); 196 InitIrtFilePath();
180 InitValidationCacheFilePath(); 197 InitValidationCacheFilePath();
181 } 198 }
182 199
183 NaClBrowser::~NaClBrowser() { 200 NaClBrowser::~NaClBrowser() {
201 NOTREACHED();
bradnelson 2017/02/23 03:07:43 Good idea
184 } 202 }
185 203
186 void NaClBrowser::InitIrtFilePath() { 204 void NaClBrowser::InitIrtFilePath() {
187 // Allow the IRT library to be overridden via an environment 205 // Allow the IRT library to be overridden via an environment
188 // variable. This allows the NaCl/Chromium integration bot to 206 // variable. This allows the NaCl/Chromium integration bot to
189 // specify a newly-built IRT rather than using a prebuilt one 207 // specify a newly-built IRT rather than using a prebuilt one
190 // downloaded via Chromium's DEPS file. We use the same environment 208 // downloaded via Chromium's DEPS file. We use the same environment
191 // variable that the standalone NaCl PPAPI plugin accepts. 209 // variable that the standalone NaCl PPAPI plugin accepts.
192 const char* irt_path_var = getenv("NACL_IRT_LIBRARY"); 210 const char* irt_path_var = getenv("NACL_IRT_LIBRARY");
193 if (irt_path_var != NULL) { 211 if (irt_path_var != NULL) {
194 base::FilePath::StringType path_string( 212 base::FilePath::StringType path_string(
195 irt_path_var, const_cast<const char*>(strchr(irt_path_var, '\0'))); 213 irt_path_var, const_cast<const char*>(strchr(irt_path_var, '\0')));
196 irt_filepath_ = base::FilePath(path_string); 214 irt_filepath_ = base::FilePath(path_string);
197 } else { 215 } else {
198 base::FilePath plugin_dir; 216 base::FilePath plugin_dir;
199 if (!browser_delegate_->GetPluginDirectory(&plugin_dir)) { 217 if (!GetDelegate()->GetPluginDirectory(&plugin_dir)) {
200 DLOG(ERROR) << "Failed to locate the plugins directory, NaCl disabled."; 218 DLOG(ERROR) << "Failed to locate the plugins directory, NaCl disabled.";
201 MarkAsFailed(); 219 MarkAsFailed();
202 return; 220 return;
203 } 221 }
204 irt_filepath_ = plugin_dir.Append(NaClIrtName()); 222 irt_filepath_ = plugin_dir.Append(NaClIrtName());
205 } 223 }
206 } 224 }
207 225
208 #if defined(OS_WIN) 226 #if defined(OS_WIN)
209 bool NaClBrowser::GetNaCl64ExePath(base::FilePath* exe_path) { 227 bool NaClBrowser::GetNaCl64ExePath(base::FilePath* exe_path) {
228 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
210 base::FilePath module_path; 229 base::FilePath module_path;
211 if (!PathService::Get(base::FILE_MODULE, &module_path)) { 230 if (!PathService::Get(base::FILE_MODULE, &module_path)) {
212 LOG(ERROR) << "NaCl process launch failed: could not resolve module"; 231 LOG(ERROR) << "NaCl process launch failed: could not resolve module";
213 return false; 232 return false;
214 } 233 }
215 *exe_path = module_path.DirName().Append(L"nacl64"); 234 *exe_path = module_path.DirName().Append(L"nacl64");
216 return true; 235 return true;
217 } 236 }
218 #endif 237 #endif
219 238
239 // static
240 NaClBrowser* NaClBrowser::GetInstanceInternal() {
241 static NaClBrowser* g_instance = nullptr;
242 if (!g_instance)
243 g_instance = new NaClBrowser();
244 return g_instance;
245 }
246
220 NaClBrowser* NaClBrowser::GetInstance() { 247 NaClBrowser* NaClBrowser::GetInstance() {
221 return base::Singleton<NaClBrowser>::get(); 248 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
249 return GetInstanceInternal();
222 } 250 }
223 251
224 bool NaClBrowser::IsReady() const { 252 bool NaClBrowser::IsReady() const {
253 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
225 return (IsOk() && 254 return (IsOk() &&
226 irt_state_ == NaClResourceReady && 255 irt_state_ == NaClResourceReady &&
227 validation_cache_state_ == NaClResourceReady); 256 validation_cache_state_ == NaClResourceReady);
228 } 257 }
229 258
230 bool NaClBrowser::IsOk() const { 259 bool NaClBrowser::IsOk() const {
231 return ok_; 260 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
261 return !has_failed_;
232 } 262 }
233 263
234 const base::File& NaClBrowser::IrtFile() const { 264 const base::File& NaClBrowser::IrtFile() const {
235 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 265 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
236 CHECK_EQ(irt_state_, NaClResourceReady); 266 CHECK_EQ(irt_state_, NaClResourceReady);
237 CHECK(irt_file_.IsValid()); 267 CHECK(irt_file_.IsValid());
238 return irt_file_; 268 return irt_file_;
239 } 269 }
240 270
241 void NaClBrowser::EnsureAllResourcesAvailable() { 271 void NaClBrowser::EnsureAllResourcesAvailable() {
242 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 272 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
243 EnsureIrtAvailable(); 273 EnsureIrtAvailable();
244 EnsureValidationCacheAvailable(); 274 EnsureValidationCacheAvailable();
245 } 275 }
246 276
247 // Load the IRT async. 277 // Load the IRT async.
248 void NaClBrowser::EnsureIrtAvailable() { 278 void NaClBrowser::EnsureIrtAvailable() {
249 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 279 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
250 if (IsOk() && irt_state_ == NaClResourceUninitialized) { 280 if (IsOk() && irt_state_ == NaClResourceUninitialized) {
251 irt_state_ = NaClResourceRequested; 281 irt_state_ = NaClResourceRequested;
252 // TODO(ncbray) use blocking pool. 282 // TODO(ncbray) use blocking pool.
253 std::unique_ptr<base::FileProxy> file_proxy( 283 std::unique_ptr<base::FileProxy> file_proxy(
254 new base::FileProxy(content::BrowserThread::GetTaskRunnerForThread( 284 new base::FileProxy(content::BrowserThread::GetTaskRunnerForThread(
255 content::BrowserThread::FILE) 285 content::BrowserThread::FILE)
256 .get())); 286 .get()));
257 base::FileProxy* proxy = file_proxy.get(); 287 base::FileProxy* proxy = file_proxy.get();
258 if (!proxy->CreateOrOpen(irt_filepath_, 288 if (!proxy->CreateOrOpen(
259 base::File::FLAG_OPEN | base::File::FLAG_READ, 289 irt_filepath_, base::File::FLAG_OPEN | base::File::FLAG_READ,
260 base::Bind(&NaClBrowser::OnIrtOpened, 290 base::Bind(&NaClBrowser::OnIrtOpened, base::Unretained(this),
261 weak_factory_.GetWeakPtr(), 291 base::Passed(&file_proxy)))) {
262 Passed(&file_proxy)))) {
263 LOG(ERROR) << "Internal error, NaCl disabled."; 292 LOG(ERROR) << "Internal error, NaCl disabled.";
264 MarkAsFailed(); 293 MarkAsFailed();
265 } 294 }
266 } 295 }
267 } 296 }
268 297
269 void NaClBrowser::OnIrtOpened(std::unique_ptr<base::FileProxy> file_proxy, 298 void NaClBrowser::OnIrtOpened(std::unique_ptr<base::FileProxy> file_proxy,
270 base::File::Error error_code) { 299 base::File::Error error_code) {
271 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 300 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
272 DCHECK_EQ(irt_state_, NaClResourceRequested); 301 DCHECK_EQ(irt_state_, NaClResourceRequested);
273 if (file_proxy->IsValid()) { 302 if (file_proxy->IsValid()) {
274 irt_file_ = file_proxy->TakeFile(); 303 irt_file_ = file_proxy->TakeFile();
275 } else { 304 } else {
276 LOG(ERROR) << "Failed to open NaCl IRT file \"" 305 LOG(ERROR) << "Failed to open NaCl IRT file \""
277 << irt_filepath_.LossyDisplayName() 306 << irt_filepath_.LossyDisplayName()
278 << "\": " << error_code; 307 << "\": " << error_code;
279 MarkAsFailed(); 308 MarkAsFailed();
280 } 309 }
281 irt_state_ = NaClResourceReady; 310 irt_state_ = NaClResourceReady;
282 CheckWaiting(); 311 CheckWaiting();
283 } 312 }
284 313
285 void NaClBrowser::SetProcessGdbDebugStubPort(int process_id, int port) { 314 void NaClBrowser::SetProcessGdbDebugStubPort(int process_id, int port) {
315 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
286 gdb_debug_stub_port_map_[process_id] = port; 316 gdb_debug_stub_port_map_[process_id] = port;
287 if (port != kGdbDebugStubPortUnknown && 317 if (port != kGdbDebugStubPortUnknown &&
288 !debug_stub_port_listener_.is_null()) { 318 !debug_stub_port_listener_.is_null()) {
289 content::BrowserThread::PostTask( 319 content::BrowserThread::PostTask(
290 content::BrowserThread::IO, 320 content::BrowserThread::IO,
291 FROM_HERE, 321 FROM_HERE,
292 base::Bind(debug_stub_port_listener_, port)); 322 base::Bind(debug_stub_port_listener_, port));
293 } 323 }
294 } 324 }
295 325
296 void NaClBrowser::SetGdbDebugStubPortListener( 326 // static
327 void NaClBrowser::SetGdbDebugStubPortListenerForTest(
297 base::Callback<void(int)> listener) { 328 base::Callback<void(int)> listener) {
298 debug_stub_port_listener_ = listener; 329 GetInstanceInternal()->debug_stub_port_listener_ = listener;
299 } 330 }
300 331
301 void NaClBrowser::ClearGdbDebugStubPortListener() { 332 // static
302 debug_stub_port_listener_.Reset(); 333 void NaClBrowser::ClearGdbDebugStubPortListenerForTest() {
334 GetInstanceInternal()->debug_stub_port_listener_.Reset();
303 } 335 }
304 336
305 int NaClBrowser::GetProcessGdbDebugStubPort(int process_id) { 337 int NaClBrowser::GetProcessGdbDebugStubPort(int process_id) {
338 // Called from TaskManager TaskGroup impl, on CrBrowserMain.
339 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
306 GdbDebugStubPortMap::iterator i = gdb_debug_stub_port_map_.find(process_id); 340 GdbDebugStubPortMap::iterator i = gdb_debug_stub_port_map_.find(process_id);
307 if (i != gdb_debug_stub_port_map_.end()) { 341 if (i != gdb_debug_stub_port_map_.end()) {
308 return i->second; 342 return i->second;
309 } 343 }
310 return kGdbDebugStubPortUnused; 344 return kGdbDebugStubPortUnused;
311 } 345 }
312 346
313 void NaClBrowser::InitValidationCacheFilePath() { 347 void NaClBrowser::InitValidationCacheFilePath() {
348 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
314 // Determine where the validation cache resides in the file system. It 349 // Determine where the validation cache resides in the file system. It
315 // exists in Chrome's cache directory and is not tied to any specific 350 // exists in Chrome's cache directory and is not tied to any specific
316 // profile. 351 // profile.
317 // Start by finding the user data directory. 352 // Start by finding the user data directory.
318 base::FilePath user_data_dir; 353 base::FilePath user_data_dir;
319 if (!browser_delegate_->GetUserDirectory(&user_data_dir)) { 354 if (!GetDelegate()->GetUserDirectory(&user_data_dir)) {
320 RunWithoutValidationCache(); 355 RunWithoutValidationCache();
321 return; 356 return;
322 } 357 }
323 // The cache directory may or may not be the user data directory. 358 // The cache directory may or may not be the user data directory.
324 base::FilePath cache_file_path; 359 base::FilePath cache_file_path;
325 browser_delegate_->GetCacheDirectory(&cache_file_path); 360 GetDelegate()->GetCacheDirectory(&cache_file_path);
326 // Append the base file name to the cache directory. 361 // Append the base file name to the cache directory.
327 362
328 validation_cache_file_path_ = 363 validation_cache_file_path_ =
329 cache_file_path.Append(kValidationCacheFileName); 364 cache_file_path.Append(kValidationCacheFileName);
330 } 365 }
331 366
332 void NaClBrowser::EnsureValidationCacheAvailable() { 367 void NaClBrowser::EnsureValidationCacheAvailable() {
333 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 368 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
334 if (IsOk() && validation_cache_state_ == NaClResourceUninitialized) { 369 if (IsOk() && validation_cache_state_ == NaClResourceUninitialized) {
335 if (ValidationCacheIsEnabled()) { 370 if (ValidationCacheIsEnabled()) {
336 validation_cache_state_ = NaClResourceRequested; 371 validation_cache_state_ = NaClResourceRequested;
337 372
338 // Structure for carrying data between the callbacks. 373 // Structure for carrying data between the callbacks.
339 std::string* data = new std::string(); 374 std::string* data = new std::string();
340 // We can get away not giving this a sequence ID because this is the first 375 // We can get away not giving this a sequence ID because this is the first
341 // task and further file access will not occur until after we get a 376 // task and further file access will not occur until after we get a
342 // response. 377 // response.
343 if (!content::BrowserThread::PostBlockingPoolTaskAndReply( 378 if (!content::BrowserThread::PostBlockingPoolTaskAndReply(
344 FROM_HERE, 379 FROM_HERE,
345 base::Bind(ReadCache, validation_cache_file_path_, data), 380 base::Bind(ReadCache, validation_cache_file_path_, data),
346 base::Bind(&NaClBrowser::OnValidationCacheLoaded, 381 base::Bind(&NaClBrowser::OnValidationCacheLoaded,
347 weak_factory_.GetWeakPtr(), 382 base::Unretained(this), base::Owned(data)))) {
348 base::Owned(data)))) {
349 RunWithoutValidationCache(); 383 RunWithoutValidationCache();
350 } 384 }
351 } else { 385 } else {
352 RunWithoutValidationCache(); 386 RunWithoutValidationCache();
353 } 387 }
354 } 388 }
355 } 389 }
356 390
357 void NaClBrowser::OnValidationCacheLoaded(const std::string *data) { 391 void NaClBrowser::OnValidationCacheLoaded(const std::string *data) {
358 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 392 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
359 // Did the cache get cleared before the load completed? If so, ignore the 393 // Did the cache get cleared before the load completed? If so, ignore the
360 // incoming data. 394 // incoming data.
361 if (validation_cache_state_ == NaClResourceReady) 395 if (validation_cache_state_ == NaClResourceReady)
362 return; 396 return;
363 397
364 if (data->size() == 0) { 398 if (data->size() == 0) {
365 // No file found. 399 // No file found.
366 validation_cache_.Reset(); 400 validation_cache_.Reset();
367 } else { 401 } else {
368 base::Pickle pickle(data->data(), data->size()); 402 base::Pickle pickle(data->data(), data->size());
369 validation_cache_.Deserialize(&pickle); 403 validation_cache_.Deserialize(&pickle);
370 } 404 }
371 validation_cache_state_ = NaClResourceReady; 405 validation_cache_state_ = NaClResourceReady;
372 CheckWaiting(); 406 CheckWaiting();
373 } 407 }
374 408
375 void NaClBrowser::RunWithoutValidationCache() { 409 void NaClBrowser::RunWithoutValidationCache() {
410 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
376 // Be paranoid. 411 // Be paranoid.
377 validation_cache_.Reset(); 412 validation_cache_.Reset();
378 validation_cache_is_enabled_ = false; 413 validation_cache_is_enabled_ = false;
379 validation_cache_state_ = NaClResourceReady; 414 validation_cache_state_ = NaClResourceReady;
380 CheckWaiting(); 415 CheckWaiting();
381 } 416 }
382 417
383 void NaClBrowser::CheckWaiting() { 418 void NaClBrowser::CheckWaiting() {
384 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 419 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
385 if (!IsOk() || IsReady()) { 420 if (!IsOk() || IsReady()) {
386 // Queue the waiting tasks into the message loop. This helps avoid 421 // Queue the waiting tasks into the message loop. This helps avoid
387 // re-entrancy problems that could occur if the closure was invoked 422 // re-entrancy problems that could occur if the closure was invoked
388 // directly. For example, this could result in use-after-free of the 423 // directly. For example, this could result in use-after-free of the
389 // process host. 424 // process host.
390 for (std::vector<base::Closure>::iterator iter = waiting_.begin(); 425 for (std::vector<base::Closure>::iterator iter = waiting_.begin();
391 iter != waiting_.end(); ++iter) { 426 iter != waiting_.end(); ++iter) {
392 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, *iter); 427 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, *iter);
393 } 428 }
394 waiting_.clear(); 429 waiting_.clear();
395 } 430 }
396 } 431 }
397 432
398 void NaClBrowser::MarkAsFailed() { 433 void NaClBrowser::MarkAsFailed() {
399 ok_ = false; 434 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
435 has_failed_ = true;
400 CheckWaiting(); 436 CheckWaiting();
401 } 437 }
402 438
403 void NaClBrowser::WaitForResources(const base::Closure& reply) { 439 void NaClBrowser::WaitForResources(const base::Closure& reply) {
440 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
404 waiting_.push_back(reply); 441 waiting_.push_back(reply);
405 EnsureAllResourcesAvailable(); 442 EnsureAllResourcesAvailable();
406 CheckWaiting(); 443 CheckWaiting();
407 } 444 }
408 445
409 const base::FilePath& NaClBrowser::GetIrtFilePath() { 446 const base::FilePath& NaClBrowser::GetIrtFilePath() {
447 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
410 return irt_filepath_; 448 return irt_filepath_;
411 } 449 }
412 450
413 void NaClBrowser::PutFilePath(const base::FilePath& path, 451 void NaClBrowser::PutFilePath(const base::FilePath& path,
414 uint64_t* file_token_lo, 452 uint64_t* file_token_lo,
415 uint64_t* file_token_hi) { 453 uint64_t* file_token_hi) {
416 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 454 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
417 while (true) { 455 while (true) {
418 uint64_t file_token[2] = {base::RandUint64(), base::RandUint64()}; 456 uint64_t file_token[2] = {base::RandUint64(), base::RandUint64()};
419 // A zero file_token indicates there is no file_token, if we get zero, ask 457 // A zero file_token indicates there is no file_token, if we get zero, ask
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 550
513 // If the cache is cleared before it is loaded from the filesystem, act as if 551 // If the cache is cleared before it is loaded from the filesystem, act as if
514 // we just loaded an empty cache. 552 // we just loaded an empty cache.
515 if (validation_cache_state_ != NaClResourceReady) { 553 if (validation_cache_state_ != NaClResourceReady) {
516 validation_cache_state_ = NaClResourceReady; 554 validation_cache_state_ = NaClResourceReady;
517 CheckWaiting(); 555 CheckWaiting();
518 } 556 }
519 } 557 }
520 558
521 void NaClBrowser::MarkValidationCacheAsModified() { 559 void NaClBrowser::MarkValidationCacheAsModified() {
560 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
522 if (!validation_cache_is_modified_) { 561 if (!validation_cache_is_modified_) {
523 // Wait before persisting to disk. This can coalesce multiple cache 562 // Wait before persisting to disk. This can coalesce multiple cache
524 // modifications info a single disk write. 563 // modifications info a single disk write.
525 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 564 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
526 FROM_HERE, base::Bind(&NaClBrowser::PersistValidationCache, 565 FROM_HERE, base::Bind(&NaClBrowser::PersistValidationCache,
527 weak_factory_.GetWeakPtr()), 566 base::Unretained(this)),
528 base::TimeDelta::FromMilliseconds(kValidationCacheCoalescingTimeMS)); 567 base::TimeDelta::FromMilliseconds(kValidationCacheCoalescingTimeMS));
529 validation_cache_is_modified_ = true; 568 validation_cache_is_modified_ = true;
530 } 569 }
531 } 570 }
532 571
533 void NaClBrowser::PersistValidationCache() { 572 void NaClBrowser::PersistValidationCache() {
534 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 573 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
535 // validation_cache_is_modified_ may be false if the cache was cleared while 574 // validation_cache_is_modified_ may be false if the cache was cleared while
536 // this delayed task was pending. 575 // this delayed task was pending.
537 // validation_cache_file_path_ may be empty if something went wrong during 576 // validation_cache_file_path_ may be empty if something went wrong during
538 // initialization. 577 // initialization.
539 if (validation_cache_is_modified_ && !validation_cache_file_path_.empty()) { 578 if (validation_cache_is_modified_ && !validation_cache_file_path_.empty()) {
540 base::Pickle* pickle = new base::Pickle(); 579 base::Pickle* pickle = new base::Pickle();
541 validation_cache_.Serialize(pickle); 580 validation_cache_.Serialize(pickle);
542 581
543 // Pass the serialized data to another thread to write to disk. File IO is 582 // Pass the serialized data to another thread to write to disk. File IO is
544 // not allowed on the IO thread (which is the thread this method runs on) 583 // not allowed on the IO thread (which is the thread this method runs on)
545 // because it can degrade the responsiveness of the browser. 584 // because it can degrade the responsiveness of the browser.
546 // The task is sequenced so that multiple writes happen in order. 585 // The task is sequenced so that multiple writes happen in order.
547 content::BrowserThread::PostBlockingPoolSequencedTask( 586 content::BrowserThread::PostBlockingPoolSequencedTask(
548 kValidationCacheSequenceName, 587 kValidationCacheSequenceName,
549 FROM_HERE, 588 FROM_HERE,
550 base::Bind(WriteCache, validation_cache_file_path_, 589 base::Bind(WriteCache, validation_cache_file_path_,
551 base::Owned(pickle))); 590 base::Owned(pickle)));
552 } 591 }
553 validation_cache_is_modified_ = false; 592 validation_cache_is_modified_ = false;
554 } 593 }
555 594
556 void NaClBrowser::OnProcessEnd(int process_id) { 595 void NaClBrowser::OnProcessEnd(int process_id) {
596 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
557 gdb_debug_stub_port_map_.erase(process_id); 597 gdb_debug_stub_port_map_.erase(process_id);
558 } 598 }
559 599
560 void NaClBrowser::OnProcessCrashed() { 600 void NaClBrowser::OnProcessCrashed() {
561 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 601 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
562 if (crash_times_.size() == kMaxCrashesPerInterval) { 602 if (crash_times_.size() == kMaxCrashesPerInterval) {
563 crash_times_.pop_front(); 603 crash_times_.pop_front();
564 } 604 }
565 base::Time time = base::Time::Now(); 605 base::Time time = base::Time::Now();
566 crash_times_.push_back(time); 606 crash_times_.push_back(time);
567 } 607 }
568 608
569 bool NaClBrowser::IsThrottled() { 609 bool NaClBrowser::IsThrottled() {
570 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 610 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
571 if (crash_times_.size() != kMaxCrashesPerInterval) { 611 if (crash_times_.size() != kMaxCrashesPerInterval) {
572 return false; 612 return false;
573 } 613 }
574 base::TimeDelta delta = base::Time::Now() - crash_times_.front(); 614 base::TimeDelta delta = base::Time::Now() - crash_times_.front();
575 return delta.InSeconds() <= kCrashesIntervalInSeconds; 615 return delta.InSeconds() <= kCrashesIntervalInSeconds;
576 } 616 }
577 617
578 } // namespace nacl 618 } // namespace nacl
OLDNEW
« no previous file with comments | « components/nacl/browser/nacl_browser.h ('k') | components/nacl/browser/nacl_file_host_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698