| OLD | NEW |
| 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 "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/files/file_proxy.h" | 8 #include "base/files/file_proxy.h" |
| 9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 } | 161 } |
| 162 | 162 |
| 163 NaClBrowserDelegate* NaClBrowser::GetDelegate() { | 163 NaClBrowserDelegate* NaClBrowser::GetDelegate() { |
| 164 // The delegate is not owned by the IO thread. This accessor method can be | 164 // The delegate is not owned by the IO thread. This accessor method can be |
| 165 // called from other threads. | 165 // called from other threads. |
| 166 DCHECK(GetInstance()->browser_delegate_.get() != NULL); | 166 DCHECK(GetInstance()->browser_delegate_.get() != NULL); |
| 167 return GetInstance()->browser_delegate_.get(); | 167 return GetInstance()->browser_delegate_.get(); |
| 168 } | 168 } |
| 169 | 169 |
| 170 void NaClBrowser::EarlyStartup() { | 170 void NaClBrowser::EarlyStartup() { |
| 171 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 171 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 172 InitIrtFilePath(); | 172 InitIrtFilePath(); |
| 173 InitValidationCacheFilePath(); | 173 InitValidationCacheFilePath(); |
| 174 } | 174 } |
| 175 | 175 |
| 176 NaClBrowser::~NaClBrowser() { | 176 NaClBrowser::~NaClBrowser() { |
| 177 } | 177 } |
| 178 | 178 |
| 179 void NaClBrowser::InitIrtFilePath() { | 179 void NaClBrowser::InitIrtFilePath() { |
| 180 // Allow the IRT library to be overridden via an environment | 180 // Allow the IRT library to be overridden via an environment |
| 181 // variable. This allows the NaCl/Chromium integration bot to | 181 // variable. This allows the NaCl/Chromium integration bot to |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 return (IsOk() && | 218 return (IsOk() && |
| 219 irt_state_ == NaClResourceReady && | 219 irt_state_ == NaClResourceReady && |
| 220 validation_cache_state_ == NaClResourceReady); | 220 validation_cache_state_ == NaClResourceReady); |
| 221 } | 221 } |
| 222 | 222 |
| 223 bool NaClBrowser::IsOk() const { | 223 bool NaClBrowser::IsOk() const { |
| 224 return ok_; | 224 return ok_; |
| 225 } | 225 } |
| 226 | 226 |
| 227 const base::File& NaClBrowser::IrtFile() const { | 227 const base::File& NaClBrowser::IrtFile() const { |
| 228 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 228 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 229 CHECK_EQ(irt_state_, NaClResourceReady); | 229 CHECK_EQ(irt_state_, NaClResourceReady); |
| 230 CHECK(irt_file_.IsValid()); | 230 CHECK(irt_file_.IsValid()); |
| 231 return irt_file_; | 231 return irt_file_; |
| 232 } | 232 } |
| 233 | 233 |
| 234 void NaClBrowser::EnsureAllResourcesAvailable() { | 234 void NaClBrowser::EnsureAllResourcesAvailable() { |
| 235 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 235 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 236 EnsureIrtAvailable(); | 236 EnsureIrtAvailable(); |
| 237 EnsureValidationCacheAvailable(); | 237 EnsureValidationCacheAvailable(); |
| 238 } | 238 } |
| 239 | 239 |
| 240 // Load the IRT async. | 240 // Load the IRT async. |
| 241 void NaClBrowser::EnsureIrtAvailable() { | 241 void NaClBrowser::EnsureIrtAvailable() { |
| 242 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 242 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 243 if (IsOk() && irt_state_ == NaClResourceUninitialized) { | 243 if (IsOk() && irt_state_ == NaClResourceUninitialized) { |
| 244 irt_state_ = NaClResourceRequested; | 244 irt_state_ = NaClResourceRequested; |
| 245 // TODO(ncbray) use blocking pool. | 245 // TODO(ncbray) use blocking pool. |
| 246 scoped_ptr<base::FileProxy> file_proxy(new base::FileProxy( | 246 scoped_ptr<base::FileProxy> file_proxy(new base::FileProxy( |
| 247 content::BrowserThread::GetMessageLoopProxyForThread( | 247 content::BrowserThread::GetMessageLoopProxyForThread( |
| 248 content::BrowserThread::FILE).get())); | 248 content::BrowserThread::FILE).get())); |
| 249 base::FileProxy* proxy = file_proxy.get(); | 249 base::FileProxy* proxy = file_proxy.get(); |
| 250 if (!proxy->CreateOrOpen(irt_filepath_, | 250 if (!proxy->CreateOrOpen(irt_filepath_, |
| 251 base::File::FLAG_OPEN | base::File::FLAG_READ, | 251 base::File::FLAG_OPEN | base::File::FLAG_READ, |
| 252 base::Bind(&NaClBrowser::OnIrtOpened, | 252 base::Bind(&NaClBrowser::OnIrtOpened, |
| 253 weak_factory_.GetWeakPtr(), | 253 weak_factory_.GetWeakPtr(), |
| 254 Passed(&file_proxy)))) { | 254 Passed(&file_proxy)))) { |
| 255 LOG(ERROR) << "Internal error, NaCl disabled."; | 255 LOG(ERROR) << "Internal error, NaCl disabled."; |
| 256 MarkAsFailed(); | 256 MarkAsFailed(); |
| 257 } | 257 } |
| 258 } | 258 } |
| 259 } | 259 } |
| 260 | 260 |
| 261 void NaClBrowser::OnIrtOpened(scoped_ptr<base::FileProxy> file_proxy, | 261 void NaClBrowser::OnIrtOpened(scoped_ptr<base::FileProxy> file_proxy, |
| 262 base::File::Error error_code) { | 262 base::File::Error error_code) { |
| 263 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 263 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 264 DCHECK_EQ(irt_state_, NaClResourceRequested); | 264 DCHECK_EQ(irt_state_, NaClResourceRequested); |
| 265 if (file_proxy->IsValid()) { | 265 if (file_proxy->IsValid()) { |
| 266 irt_file_ = file_proxy->TakeFile(); | 266 irt_file_ = file_proxy->TakeFile(); |
| 267 } else { | 267 } else { |
| 268 LOG(ERROR) << "Failed to open NaCl IRT file \"" | 268 LOG(ERROR) << "Failed to open NaCl IRT file \"" |
| 269 << irt_filepath_.LossyDisplayName() | 269 << irt_filepath_.LossyDisplayName() |
| 270 << "\": " << error_code; | 270 << "\": " << error_code; |
| 271 MarkAsFailed(); | 271 MarkAsFailed(); |
| 272 } | 272 } |
| 273 irt_state_ = NaClResourceReady; | 273 irt_state_ = NaClResourceReady; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 // The cache directory may or may not be the user data directory. | 315 // The cache directory may or may not be the user data directory. |
| 316 base::FilePath cache_file_path; | 316 base::FilePath cache_file_path; |
| 317 browser_delegate_->GetCacheDirectory(&cache_file_path); | 317 browser_delegate_->GetCacheDirectory(&cache_file_path); |
| 318 // Append the base file name to the cache directory. | 318 // Append the base file name to the cache directory. |
| 319 | 319 |
| 320 validation_cache_file_path_ = | 320 validation_cache_file_path_ = |
| 321 cache_file_path.Append(kValidationCacheFileName); | 321 cache_file_path.Append(kValidationCacheFileName); |
| 322 } | 322 } |
| 323 | 323 |
| 324 void NaClBrowser::EnsureValidationCacheAvailable() { | 324 void NaClBrowser::EnsureValidationCacheAvailable() { |
| 325 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 325 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 326 if (IsOk() && validation_cache_state_ == NaClResourceUninitialized) { | 326 if (IsOk() && validation_cache_state_ == NaClResourceUninitialized) { |
| 327 if (ValidationCacheIsEnabled()) { | 327 if (ValidationCacheIsEnabled()) { |
| 328 validation_cache_state_ = NaClResourceRequested; | 328 validation_cache_state_ = NaClResourceRequested; |
| 329 | 329 |
| 330 // Structure for carrying data between the callbacks. | 330 // Structure for carrying data between the callbacks. |
| 331 std::string* data = new std::string(); | 331 std::string* data = new std::string(); |
| 332 // We can get away not giving this a sequence ID because this is the first | 332 // We can get away not giving this a sequence ID because this is the first |
| 333 // task and further file access will not occur until after we get a | 333 // task and further file access will not occur until after we get a |
| 334 // response. | 334 // response. |
| 335 if (!content::BrowserThread::PostBlockingPoolTaskAndReply( | 335 if (!content::BrowserThread::PostBlockingPoolTaskAndReply( |
| 336 FROM_HERE, | 336 FROM_HERE, |
| 337 base::Bind(ReadCache, validation_cache_file_path_, data), | 337 base::Bind(ReadCache, validation_cache_file_path_, data), |
| 338 base::Bind(&NaClBrowser::OnValidationCacheLoaded, | 338 base::Bind(&NaClBrowser::OnValidationCacheLoaded, |
| 339 weak_factory_.GetWeakPtr(), | 339 weak_factory_.GetWeakPtr(), |
| 340 base::Owned(data)))) { | 340 base::Owned(data)))) { |
| 341 RunWithoutValidationCache(); | 341 RunWithoutValidationCache(); |
| 342 } | 342 } |
| 343 } else { | 343 } else { |
| 344 RunWithoutValidationCache(); | 344 RunWithoutValidationCache(); |
| 345 } | 345 } |
| 346 } | 346 } |
| 347 } | 347 } |
| 348 | 348 |
| 349 void NaClBrowser::OnValidationCacheLoaded(const std::string *data) { | 349 void NaClBrowser::OnValidationCacheLoaded(const std::string *data) { |
| 350 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 350 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 351 // Did the cache get cleared before the load completed? If so, ignore the | 351 // Did the cache get cleared before the load completed? If so, ignore the |
| 352 // incoming data. | 352 // incoming data. |
| 353 if (validation_cache_state_ == NaClResourceReady) | 353 if (validation_cache_state_ == NaClResourceReady) |
| 354 return; | 354 return; |
| 355 | 355 |
| 356 if (data->size() == 0) { | 356 if (data->size() == 0) { |
| 357 // No file found. | 357 // No file found. |
| 358 validation_cache_.Reset(); | 358 validation_cache_.Reset(); |
| 359 } else { | 359 } else { |
| 360 Pickle pickle(data->data(), data->size()); | 360 Pickle pickle(data->data(), data->size()); |
| 361 validation_cache_.Deserialize(&pickle); | 361 validation_cache_.Deserialize(&pickle); |
| 362 } | 362 } |
| 363 validation_cache_state_ = NaClResourceReady; | 363 validation_cache_state_ = NaClResourceReady; |
| 364 CheckWaiting(); | 364 CheckWaiting(); |
| 365 } | 365 } |
| 366 | 366 |
| 367 void NaClBrowser::RunWithoutValidationCache() { | 367 void NaClBrowser::RunWithoutValidationCache() { |
| 368 // Be paranoid. | 368 // Be paranoid. |
| 369 validation_cache_.Reset(); | 369 validation_cache_.Reset(); |
| 370 validation_cache_is_enabled_ = false; | 370 validation_cache_is_enabled_ = false; |
| 371 validation_cache_state_ = NaClResourceReady; | 371 validation_cache_state_ = NaClResourceReady; |
| 372 CheckWaiting(); | 372 CheckWaiting(); |
| 373 } | 373 } |
| 374 | 374 |
| 375 void NaClBrowser::CheckWaiting() { | 375 void NaClBrowser::CheckWaiting() { |
| 376 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 376 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 377 if (!IsOk() || IsReady()) { | 377 if (!IsOk() || IsReady()) { |
| 378 // Queue the waiting tasks into the message loop. This helps avoid | 378 // Queue the waiting tasks into the message loop. This helps avoid |
| 379 // re-entrancy problems that could occur if the closure was invoked | 379 // re-entrancy problems that could occur if the closure was invoked |
| 380 // directly. For example, this could result in use-after-free of the | 380 // directly. For example, this could result in use-after-free of the |
| 381 // process host. | 381 // process host. |
| 382 for (std::vector<base::Closure>::iterator iter = waiting_.begin(); | 382 for (std::vector<base::Closure>::iterator iter = waiting_.begin(); |
| 383 iter != waiting_.end(); ++iter) { | 383 iter != waiting_.end(); ++iter) { |
| 384 base::MessageLoop::current()->PostTask(FROM_HERE, *iter); | 384 base::MessageLoop::current()->PostTask(FROM_HERE, *iter); |
| 385 } | 385 } |
| 386 waiting_.clear(); | 386 waiting_.clear(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 397 EnsureAllResourcesAvailable(); | 397 EnsureAllResourcesAvailable(); |
| 398 CheckWaiting(); | 398 CheckWaiting(); |
| 399 } | 399 } |
| 400 | 400 |
| 401 const base::FilePath& NaClBrowser::GetIrtFilePath() { | 401 const base::FilePath& NaClBrowser::GetIrtFilePath() { |
| 402 return irt_filepath_; | 402 return irt_filepath_; |
| 403 } | 403 } |
| 404 | 404 |
| 405 void NaClBrowser::PutFilePath(const base::FilePath& path, uint64* file_token_lo, | 405 void NaClBrowser::PutFilePath(const base::FilePath& path, uint64* file_token_lo, |
| 406 uint64* file_token_hi) { | 406 uint64* file_token_hi) { |
| 407 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 407 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 408 while (true) { | 408 while (true) { |
| 409 uint64 file_token[2] = {base::RandUint64(), base::RandUint64()}; | 409 uint64 file_token[2] = {base::RandUint64(), base::RandUint64()}; |
| 410 // A zero file_token indicates there is no file_token, if we get zero, ask | 410 // A zero file_token indicates there is no file_token, if we get zero, ask |
| 411 // for another number. | 411 // for another number. |
| 412 if (file_token[0] != 0 || file_token[1] != 0) { | 412 if (file_token[0] != 0 || file_token[1] != 0) { |
| 413 // If the file_token is in use, ask for another number. | 413 // If the file_token is in use, ask for another number. |
| 414 std::string key(reinterpret_cast<char*>(file_token), sizeof(file_token)); | 414 std::string key(reinterpret_cast<char*>(file_token), sizeof(file_token)); |
| 415 PathCacheType::iterator iter = path_cache_.Peek(key); | 415 PathCacheType::iterator iter = path_cache_.Peek(key); |
| 416 if (iter == path_cache_.end()) { | 416 if (iter == path_cache_.end()) { |
| 417 path_cache_.Put(key, path); | 417 path_cache_.Put(key, path); |
| 418 *file_token_lo = file_token[0]; | 418 *file_token_lo = file_token[0]; |
| 419 *file_token_hi = file_token[1]; | 419 *file_token_hi = file_token[1]; |
| 420 break; | 420 break; |
| 421 } | 421 } |
| 422 } | 422 } |
| 423 } | 423 } |
| 424 } | 424 } |
| 425 | 425 |
| 426 bool NaClBrowser::GetFilePath(uint64 file_token_lo, uint64 file_token_hi, | 426 bool NaClBrowser::GetFilePath(uint64 file_token_lo, uint64 file_token_hi, |
| 427 base::FilePath* path) { | 427 base::FilePath* path) { |
| 428 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 428 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 429 uint64 file_token[2] = {file_token_lo, file_token_hi}; | 429 uint64 file_token[2] = {file_token_lo, file_token_hi}; |
| 430 std::string key(reinterpret_cast<char*>(file_token), sizeof(file_token)); | 430 std::string key(reinterpret_cast<char*>(file_token), sizeof(file_token)); |
| 431 PathCacheType::iterator iter = path_cache_.Peek(key); | 431 PathCacheType::iterator iter = path_cache_.Peek(key); |
| 432 if (iter == path_cache_.end()) { | 432 if (iter == path_cache_.end()) { |
| 433 *path = base::FilePath(FILE_PATH_LITERAL("")); | 433 *path = base::FilePath(FILE_PATH_LITERAL("")); |
| 434 return false; | 434 return false; |
| 435 } | 435 } |
| 436 *path = iter->second; | 436 *path = iter->second; |
| 437 path_cache_.Erase(iter); | 437 path_cache_.Erase(iter); |
| 438 return true; | 438 return true; |
| 439 } | 439 } |
| 440 | 440 |
| 441 | 441 |
| 442 bool NaClBrowser::QueryKnownToValidate(const std::string& signature, | 442 bool NaClBrowser::QueryKnownToValidate(const std::string& signature, |
| 443 bool off_the_record) { | 443 bool off_the_record) { |
| 444 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 444 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 445 if (off_the_record) { | 445 if (off_the_record) { |
| 446 // If we're off the record, don't reorder the main cache. | 446 // If we're off the record, don't reorder the main cache. |
| 447 return validation_cache_.QueryKnownToValidate(signature, false) || | 447 return validation_cache_.QueryKnownToValidate(signature, false) || |
| 448 off_the_record_validation_cache_.QueryKnownToValidate(signature, true); | 448 off_the_record_validation_cache_.QueryKnownToValidate(signature, true); |
| 449 } else { | 449 } else { |
| 450 bool result = validation_cache_.QueryKnownToValidate(signature, true); | 450 bool result = validation_cache_.QueryKnownToValidate(signature, true); |
| 451 LogCacheQuery(result ? CACHE_HIT : CACHE_MISS); | 451 LogCacheQuery(result ? CACHE_HIT : CACHE_MISS); |
| 452 // Queries can modify the MRU order of the cache. | 452 // Queries can modify the MRU order of the cache. |
| 453 MarkValidationCacheAsModified(); | 453 MarkValidationCacheAsModified(); |
| 454 return result; | 454 return result; |
| 455 } | 455 } |
| 456 } | 456 } |
| 457 | 457 |
| 458 void NaClBrowser::SetKnownToValidate(const std::string& signature, | 458 void NaClBrowser::SetKnownToValidate(const std::string& signature, |
| 459 bool off_the_record) { | 459 bool off_the_record) { |
| 460 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 460 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 461 if (off_the_record) { | 461 if (off_the_record) { |
| 462 off_the_record_validation_cache_.SetKnownToValidate(signature); | 462 off_the_record_validation_cache_.SetKnownToValidate(signature); |
| 463 } else { | 463 } else { |
| 464 validation_cache_.SetKnownToValidate(signature); | 464 validation_cache_.SetKnownToValidate(signature); |
| 465 // The number of sets should be equal to the number of cache misses, minus | 465 // The number of sets should be equal to the number of cache misses, minus |
| 466 // validation failures and successful validations where stubout occurs. | 466 // validation failures and successful validations where stubout occurs. |
| 467 LogCacheSet(CACHE_HIT); | 467 LogCacheSet(CACHE_HIT); |
| 468 MarkValidationCacheAsModified(); | 468 MarkValidationCacheAsModified(); |
| 469 } | 469 } |
| 470 } | 470 } |
| 471 | 471 |
| 472 void NaClBrowser::ClearValidationCache(const base::Closure& callback) { | 472 void NaClBrowser::ClearValidationCache(const base::Closure& callback) { |
| 473 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 473 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 474 // Note: this method may be called before EnsureValidationCacheAvailable has | 474 // Note: this method may be called before EnsureValidationCacheAvailable has |
| 475 // been invoked. In other words, this method may be called before any NaCl | 475 // been invoked. In other words, this method may be called before any NaCl |
| 476 // processes have been created. This method must succeed and invoke the | 476 // processes have been created. This method must succeed and invoke the |
| 477 // callback in such a case. If it does not invoke the callback, Chrome's UI | 477 // callback in such a case. If it does not invoke the callback, Chrome's UI |
| 478 // will hang in that case. | 478 // will hang in that case. |
| 479 validation_cache_.Reset(); | 479 validation_cache_.Reset(); |
| 480 off_the_record_validation_cache_.Reset(); | 480 off_the_record_validation_cache_.Reset(); |
| 481 | 481 |
| 482 if (validation_cache_file_path_.empty()) { | 482 if (validation_cache_file_path_.empty()) { |
| 483 // Can't figure out what file to remove, but don't drop the callback. | 483 // Can't figure out what file to remove, but don't drop the callback. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 base::MessageLoop::current()->PostDelayedTask( | 515 base::MessageLoop::current()->PostDelayedTask( |
| 516 FROM_HERE, | 516 FROM_HERE, |
| 517 base::Bind(&NaClBrowser::PersistValidationCache, | 517 base::Bind(&NaClBrowser::PersistValidationCache, |
| 518 weak_factory_.GetWeakPtr()), | 518 weak_factory_.GetWeakPtr()), |
| 519 base::TimeDelta::FromMilliseconds(kValidationCacheCoalescingTimeMS)); | 519 base::TimeDelta::FromMilliseconds(kValidationCacheCoalescingTimeMS)); |
| 520 validation_cache_is_modified_ = true; | 520 validation_cache_is_modified_ = true; |
| 521 } | 521 } |
| 522 } | 522 } |
| 523 | 523 |
| 524 void NaClBrowser::PersistValidationCache() { | 524 void NaClBrowser::PersistValidationCache() { |
| 525 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 525 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 526 // validation_cache_is_modified_ may be false if the cache was cleared while | 526 // validation_cache_is_modified_ may be false if the cache was cleared while |
| 527 // this delayed task was pending. | 527 // this delayed task was pending. |
| 528 // validation_cache_file_path_ may be empty if something went wrong during | 528 // validation_cache_file_path_ may be empty if something went wrong during |
| 529 // initialization. | 529 // initialization. |
| 530 if (validation_cache_is_modified_ && !validation_cache_file_path_.empty()) { | 530 if (validation_cache_is_modified_ && !validation_cache_file_path_.empty()) { |
| 531 Pickle* pickle = new Pickle(); | 531 Pickle* pickle = new Pickle(); |
| 532 validation_cache_.Serialize(pickle); | 532 validation_cache_.Serialize(pickle); |
| 533 | 533 |
| 534 // Pass the serialized data to another thread to write to disk. File IO is | 534 // Pass the serialized data to another thread to write to disk. File IO is |
| 535 // not allowed on the IO thread (which is the thread this method runs on) | 535 // not allowed on the IO thread (which is the thread this method runs on) |
| 536 // because it can degrade the responsiveness of the browser. | 536 // because it can degrade the responsiveness of the browser. |
| 537 // The task is sequenced so that multiple writes happen in order. | 537 // The task is sequenced so that multiple writes happen in order. |
| 538 content::BrowserThread::PostBlockingPoolSequencedTask( | 538 content::BrowserThread::PostBlockingPoolSequencedTask( |
| 539 kValidationCacheSequenceName, | 539 kValidationCacheSequenceName, |
| 540 FROM_HERE, | 540 FROM_HERE, |
| 541 base::Bind(WriteCache, validation_cache_file_path_, | 541 base::Bind(WriteCache, validation_cache_file_path_, |
| 542 base::Owned(pickle))); | 542 base::Owned(pickle))); |
| 543 } | 543 } |
| 544 validation_cache_is_modified_ = false; | 544 validation_cache_is_modified_ = false; |
| 545 } | 545 } |
| 546 | 546 |
| 547 void NaClBrowser::OnProcessEnd(int process_id) { | 547 void NaClBrowser::OnProcessEnd(int process_id) { |
| 548 gdb_debug_stub_port_map_.erase(process_id); | 548 gdb_debug_stub_port_map_.erase(process_id); |
| 549 } | 549 } |
| 550 | 550 |
| 551 void NaClBrowser::OnProcessCrashed() { | 551 void NaClBrowser::OnProcessCrashed() { |
| 552 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 552 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 553 if (crash_times_.size() == kMaxCrashesPerInterval) { | 553 if (crash_times_.size() == kMaxCrashesPerInterval) { |
| 554 crash_times_.pop_front(); | 554 crash_times_.pop_front(); |
| 555 } | 555 } |
| 556 base::Time time = base::Time::Now(); | 556 base::Time time = base::Time::Now(); |
| 557 crash_times_.push_back(time); | 557 crash_times_.push_back(time); |
| 558 } | 558 } |
| 559 | 559 |
| 560 bool NaClBrowser::IsThrottled() { | 560 bool NaClBrowser::IsThrottled() { |
| 561 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 561 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 562 if (crash_times_.size() != kMaxCrashesPerInterval) { | 562 if (crash_times_.size() != kMaxCrashesPerInterval) { |
| 563 return false; | 563 return false; |
| 564 } | 564 } |
| 565 base::TimeDelta delta = base::Time::Now() - crash_times_.front(); | 565 base::TimeDelta delta = base::Time::Now() - crash_times_.front(); |
| 566 return delta.InSeconds() <= kCrashesIntervalInSeconds; | 566 return delta.InSeconds() <= kCrashesIntervalInSeconds; |
| 567 } | 567 } |
| 568 | 568 |
| 569 } // namespace nacl | 569 } // namespace nacl |
| OLD | NEW |