diff options
-rw-r--r-- | chrome/browser/browsing_data_remover.cc | 60 | ||||
-rw-r--r-- | chrome/browser/browsing_data_remover.h | 25 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_browser.cc | 91 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_browser.h | 2 |
4 files changed, 148 insertions, 30 deletions
diff --git a/chrome/browser/browsing_data_remover.cc b/chrome/browser/browsing_data_remover.cc index ee88523..1185202 100644 --- a/chrome/browser/browsing_data_remover.cc +++ b/chrome/browser/browsing_data_remover.cc @@ -23,6 +23,7 @@ #include "chrome/browser/extensions/extension_special_storage_policy.h" #include "chrome/browser/history/history.h" #include "chrome/browser/io_thread.h" +#include "chrome/browser/nacl_host/nacl_browser.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/net/predictor.h" #include "chrome/browser/password_manager/password_store.h" @@ -112,6 +113,7 @@ BrowsingDataRemover::BrowsingDataRemover(Profile* profile, media_context_getter_(profile->GetRequestContextForMedia()), deauthorize_content_licenses_request_id_(0), waiting_for_clear_cache_(false), + waiting_for_clear_nacl_cache_(false), waiting_for_clear_cookies_count_(0), waiting_for_clear_history_(false), waiting_for_clear_local_storage_(false), @@ -141,6 +143,7 @@ BrowsingDataRemover::BrowsingDataRemover(Profile* profile, media_context_getter_(profile->GetRequestContextForMedia()), deauthorize_content_licenses_request_id_(0), waiting_for_clear_cache_(false), + waiting_for_clear_nacl_cache_(false), waiting_for_clear_cookies_count_(0), waiting_for_clear_history_(false), waiting_for_clear_local_storage_(false), @@ -156,7 +159,7 @@ BrowsingDataRemover::BrowsingDataRemover(Profile* profile, } BrowsingDataRemover::~BrowsingDataRemover() { - DCHECK(all_done()); + DCHECK(AllDone()); } // Static. @@ -411,6 +414,15 @@ void BrowsingDataRemover::RemoveImpl(int remove_mask, base::Bind(&BrowsingDataRemover::ClearCacheOnIOThread, base::Unretained(this))); +#if !defined(DISABLE_NACL) + waiting_for_clear_nacl_cache_ = true; + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&BrowsingDataRemover::ClearNaClCacheOnIOThread, + base::Unretained(this))); +#endif + // The PrerenderManager may have a page actively being prerendered, which // is essentially a preemptively cached page. prerender::PrerenderManager* prerender_manager = @@ -486,6 +498,20 @@ base::Time BrowsingDataRemover::CalculateBeginDeleteTime( return delete_begin_time - diff; } +bool BrowsingDataRemover::AllDone() { + return registrar_.IsEmpty() && + !waiting_for_clear_cache_ && + !waiting_for_clear_nacl_cache_ && + !waiting_for_clear_cookies_count_&& + !waiting_for_clear_history_ && + !waiting_for_clear_local_storage_ && + !waiting_for_clear_networking_history_ && + !waiting_for_clear_server_bound_certs_ && + !waiting_for_clear_plugin_data_ && + !waiting_for_clear_quota_managed_data_ && + !waiting_for_clear_content_licenses_; +} + void BrowsingDataRemover::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { @@ -503,7 +529,7 @@ void BrowsingDataRemover::Observe(int type, void BrowsingDataRemover::NotifyAndDeleteIfDone() { // TODO(brettw) bug 1139736: see TODO in Observe() above. - if (!all_done()) + if (!AllDone()) return; set_removing(false); @@ -630,6 +656,36 @@ void BrowsingDataRemover::DoClearCache(int rv) { } } +#if !defined(DISABLE_NACL) +void BrowsingDataRemover::ClearedNaClCache() { + // This function should be called on the UI thread. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + waiting_for_clear_nacl_cache_ = false; + + NotifyAndDeleteIfDone(); +} + +void BrowsingDataRemover::ClearedNaClCacheOnIOThread() { + // This function should be called on the IO thread. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + // Notify the UI thread that we are done. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&BrowsingDataRemover::ClearedNaClCache, + base::Unretained(this))); +} + +void BrowsingDataRemover::ClearNaClCacheOnIOThread() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + NaClBrowser::GetInstance()->ClearValidationCache( + base::Bind(&BrowsingDataRemover::ClearedNaClCacheOnIOThread, + base::Unretained(this))); +} +#endif + void BrowsingDataRemover::ClearLocalStorageOnUIThread() { DCHECK(waiting_for_clear_local_storage_); diff --git a/chrome/browser/browsing_data_remover.h b/chrome/browser/browsing_data_remover.h index 85b5280..d89541c 100644 --- a/chrome/browser/browsing_data_remover.h +++ b/chrome/browser/browsing_data_remover.h @@ -220,6 +220,18 @@ class BrowsingDataRemover : public content::NotificationObserver, // Performs the actual work to delete the cache. void DoClearCache(int rv); +#if !defined(DISABLE_NACL) + // Callback for when the NaCl cache has been deleted. Invokes + // NotifyAndDeleteIfDone. + void ClearedNaClCache(); + + // Invokes the ClearedNaClCache on the UI thread. + void ClearedNaClCacheOnIOThread(); + + // Invoked on the IO thread to delete the NaCl cache. + void ClearNaClCacheOnIOThread(); +#endif + // Invoked on the UI thread to delete local storage. void ClearLocalStorageOnUIThread(); @@ -270,17 +282,7 @@ class BrowsingDataRemover : public content::NotificationObserver, base::Time CalculateBeginDeleteTime(TimePeriod time_period); // Returns true if we're all done. - bool all_done() { - return registrar_.IsEmpty() && !waiting_for_clear_cache_ && - !waiting_for_clear_cookies_count_&& - !waiting_for_clear_history_ && - !waiting_for_clear_local_storage_ && - !waiting_for_clear_networking_history_ && - !waiting_for_clear_server_bound_certs_ && - !waiting_for_clear_plugin_data_ && - !waiting_for_clear_quota_managed_data_ && - !waiting_for_clear_content_licenses_; - } + bool AllDone(); // Setter for removing_; DCHECKs that we can only start removing if we're not // already removing, and vice-versa. @@ -328,6 +330,7 @@ class BrowsingDataRemover : public content::NotificationObserver, // True if we're waiting for various data to be deleted. // These may only be accessed from UI thread in order to avoid races! bool waiting_for_clear_cache_; + bool waiting_for_clear_nacl_cache_; // Non-zero if waiting for cookies to be cleared. int waiting_for_clear_cookies_count_; bool waiting_for_clear_history_; diff --git a/chrome/browser/nacl_host/nacl_browser.cc b/chrome/browser/nacl_host/nacl_browser.cc index 637c83c..7e62a0a 100644 --- a/chrome/browser/nacl_host/nacl_browser.cc +++ b/chrome/browser/nacl_host/nacl_browser.cc @@ -85,6 +85,12 @@ void WriteCache(const FilePath& filename, const Pickle* pickle) { pickle->size()); } +void RemoveCache(const FilePath& filename, const base::Closure& callback) { + file_util::Delete(filename, false); + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + callback); +} + void LogCacheQuery(ValidationCacheStatus status) { UMA_HISTOGRAM_ENUMERATION("NaCl.ValidationCache.Query", status, CACHE_MAX); } @@ -109,6 +115,7 @@ NaClBrowser::NaClBrowser() validation_cache_state_(NaClResourceUninitialized), ok_(true) { InitIrtFilePath(); + InitValidationCacheFilePath(); } NaClBrowser::~NaClBrowser() { @@ -198,27 +205,30 @@ void NaClBrowser::OnIrtOpened(base::PlatformFileError error_code, CheckWaiting(); } +void NaClBrowser::InitValidationCacheFilePath() { + // Determine where the validation cache resides in the file system. It + // exists in Chrome's cache directory and is not tied to any specific + // profile. + // Start by finding the user data directory. + FilePath user_data_dir; + if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { + RunWithoutValidationCache(); + return; + } + // The cache directory may or may not be the user data directory. + FilePath cache_file_path; + chrome::GetUserCacheDirectory(user_data_dir, &cache_file_path); + // Append the base file name to the cache directory. + + validation_cache_file_path_ = + cache_file_path.Append(kValidationCacheFileName); +} + void NaClBrowser::EnsureValidationCacheAvailable() { if (IsOk() && validation_cache_state_ == NaClResourceUninitialized) { if (ValidationCacheIsEnabled()) { validation_cache_state_ = NaClResourceRequested; - // Determine where the validation cache resides in the file system. It - // exists in Chrome's cache directory and is not tied to any specific - // profile. - // Start by finding the user data directory. - FilePath user_data_dir; - if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { - RunWithoutValidationCache(); - return; - } - // The cache directory may or may not be the user data directory. - FilePath cache_file_path; - chrome::GetUserCacheDirectory(user_data_dir, &cache_file_path); - // Append the base file name to the cache directory. - validation_cache_file_path_ = - cache_file_path.Append(kValidationCacheFileName); - // Structure for carrying data between the callbacks. std::string* data = new std::string(); // We can get away not giving this a sequence ID because this is the first @@ -239,6 +249,11 @@ void NaClBrowser::EnsureValidationCacheAvailable() { } void NaClBrowser::OnValidationCacheLoaded(const std::string *data) { + // Did the cache get cleared before the load completed? If so, ignore the + // incoming data. + if (validation_cache_state_ == NaClResourceReady) + return; + if (data->size() == 0) { // No file found. validation_cache_.Reset(); @@ -315,6 +330,44 @@ void NaClBrowser::SetKnownToValidate(const std::string& signature, } } +void NaClBrowser::ClearValidationCache(const base::Closure& callback) { + // Note: this method may be called before EnsureValidationCacheAvailable has + // been invoked. In other words, this method may be called before any NaCl + // processes have been created. This method must succeed and invoke the + // callback in such a case. If it does not invoke the callback, Chrome's UI + // will hang in that case. + validation_cache_.Reset(); + off_the_record_validation_cache_.Reset(); + + if (validation_cache_file_path_.empty()) { + // Can't figure out what file to remove, but don't drop the callback. + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + callback); + } else { + // Delegate the removal of the cache from the filesystem to another thread + // to avoid blocking the IO thread. + // This task is dispatched immediately, not delayed and coalesced, because + // the user interface for cache clearing is likely waiting for the callback. + // In addition, we need to make sure the cache is actually cleared before + // invoking the callback to meet the implicit guarantees of the UI. + content::BrowserThread::PostBlockingPoolSequencedTask( + kValidationCacheSequenceName, + FROM_HERE, + base::Bind(RemoveCache, validation_cache_file_path_, callback)); + } + + // Make sure any delayed tasks to persist the cache to the filesystem are + // squelched. + validation_cache_is_modified_ = false; + + // If the cache is cleared before it is loaded from the filesystem, act as if + // we just loaded an empty cache. + if (validation_cache_state_ != NaClResourceReady) { + validation_cache_state_ = NaClResourceReady; + CheckWaiting(); + } +} + void NaClBrowser::MarkValidationCacheAsModified() { if (!validation_cache_is_modified_) { // Wait before persisting to disk. This can coalesce multiple cache @@ -329,7 +382,11 @@ void NaClBrowser::MarkValidationCacheAsModified() { } void NaClBrowser::PersistValidationCache() { - if (!validation_cache_file_path_.empty()) { + // validation_cache_is_modified_ may be false if the cache was cleared while + // this delayed task was pending. + // validation_cache_file_path_ may be empty if something went wrong during + // initialization. + if (validation_cache_is_modified_ && !validation_cache_file_path_.empty()) { Pickle* pickle = new Pickle(); validation_cache_.Serialize(pickle); diff --git a/chrome/browser/nacl_host/nacl_browser.h b/chrome/browser/nacl_host/nacl_browser.h index f90e542..d6298f4 100644 --- a/chrome/browser/nacl_host/nacl_browser.h +++ b/chrome/browser/nacl_host/nacl_browser.h @@ -54,6 +54,7 @@ class NaClBrowser { bool QueryKnownToValidate(const std::string& signature, bool off_the_record); void SetKnownToValidate(const std::string& signature, bool off_the_record); + void ClearValidationCache(const base::Closure& callback); private: friend struct DefaultSingletonTraits<NaClBrowser>; @@ -74,6 +75,7 @@ class NaClBrowser { void OnIrtOpened(base::PlatformFileError error_code, base::PassPlatformFile file, bool created); + void InitValidationCacheFilePath(); void EnsureValidationCacheAvailable(); void OnValidationCacheLoaded(const std::string* data); void RunWithoutValidationCache(); |