diff options
-rw-r--r-- | chrome/browser/browsing_data/browsing_data_remover.cc | 11 | ||||
-rw-r--r-- | chrome/browser/net/sdch_dictionary_fetcher.cc | 14 | ||||
-rw-r--r-- | chrome/browser/net/sdch_dictionary_fetcher.h | 3 | ||||
-rw-r--r-- | net/base/sdch_manager.cc | 38 | ||||
-rw-r--r-- | net/base/sdch_manager.h | 16 | ||||
-rw-r--r-- | net/base/sdch_manager_unittest.cc | 39 | ||||
-rw-r--r-- | net/filter/sdch_filter.cc | 8 |
7 files changed, 102 insertions, 27 deletions
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc index ba48751..29bf329 100644 --- a/chrome/browser/browsing_data/browsing_data_remover.cc +++ b/chrome/browser/browsing_data/browsing_data_remover.cc @@ -75,6 +75,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/user_metrics.h" #include "net/base/net_errors.h" +#include "net/base/sdch_manager.h" #include "net/cookies/cookie_store.h" #include "net/disk_cache/disk_cache.h" #include "net/http/http_cache.h" @@ -929,6 +930,16 @@ void BrowsingDataRemover::DoClearCache(int rv) { // Clear QUIC server information from memory and the disk cache. http_cache->GetSession()->quic_stream_factory()-> ClearCachedStatesInCryptoConfig(); + + // Clear SDCH dictionary state. + net::SdchManager* sdch_manager = + getter->GetURLRequestContext()->sdch_manager(); + // The test is probably overkill, since chrome should always have an + // SdchManager. But in general the URLRequestContext is *not* + // guaranteed to have an SdchManager, so checking is wise. + if (sdch_manager) + sdch_manager->ClearData(); + rv = http_cache->GetBackend( &cache_, base::Bind(&BrowsingDataRemover::DoClearCache, base::Unretained(this))); diff --git a/chrome/browser/net/sdch_dictionary_fetcher.cc b/chrome/browser/net/sdch_dictionary_fetcher.cc index 1130fe3..0a838bd 100644 --- a/chrome/browser/net/sdch_dictionary_fetcher.cc +++ b/chrome/browser/net/sdch_dictionary_fetcher.cc @@ -49,6 +49,16 @@ void SdchDictionaryFetcher::Schedule(const GURL& dictionary_url) { ScheduleDelayedRun(); } +void SdchDictionaryFetcher::Cancel() { + DCHECK(CalledOnValidThread()); + + while (!fetch_queue_.empty()) + fetch_queue_.pop(); + attempted_load_.clear(); + weak_factory_.InvalidateWeakPtrs(); + current_fetch_.reset(NULL); +} + void SdchDictionaryFetcher::ScheduleDelayedRun() { if (fetch_queue_.empty() || current_fetch_.get() || task_is_pending_) return; @@ -64,6 +74,10 @@ void SdchDictionaryFetcher::StartFetching() { DCHECK(task_is_pending_); task_is_pending_ = false; + // Handle losing the race against Cancel(). + if (fetch_queue_.empty()) + return; + DCHECK(context_.get()); current_fetch_.reset(net::URLFetcher::Create( fetch_queue_.front(), net::URLFetcher::GET, this)); diff --git a/chrome/browser/net/sdch_dictionary_fetcher.h b/chrome/browser/net/sdch_dictionary_fetcher.h index 7eea42a..968b42e 100644 --- a/chrome/browser/net/sdch_dictionary_fetcher.h +++ b/chrome/browser/net/sdch_dictionary_fetcher.h @@ -37,9 +37,8 @@ class SdchDictionaryFetcher virtual ~SdchDictionaryFetcher(); // Implementation of SdchFetcher class. - // This method gets the requested dictionary, and then calls back into the - // SdchManager class with the dictionary's text. virtual void Schedule(const GURL& dictionary_url) OVERRIDE; + virtual void Cancel() OVERRIDE; private: // Delay in ms between Schedule and actual download. diff --git a/net/base/sdch_manager.cc b/net/base/sdch_manager.cc index ad260a5..3cd838f 100644 --- a/net/base/sdch_manager.cc +++ b/net/base/sdch_manager.cc @@ -219,11 +219,24 @@ SdchManager::~SdchManager() { DCHECK(CalledOnValidThread()); while (!dictionaries_.empty()) { DictionaryMap::iterator it = dictionaries_.begin(); - it->second->Release(); dictionaries_.erase(it->first); } } +void SdchManager::ClearData() { + blacklisted_domains_.clear(); + exponential_blacklist_count_.clear(); + allow_latency_experiment_.clear(); + if (fetcher_.get()) + fetcher_->Cancel(); + + // Note that this may result in not having dictionaries we've advertised + // for incoming responses. The window is relatively small (as ClearData() + // is not expected to be called frequently), so we rely on meta-refresh + // to handle this case. + dictionaries_.clear(); +} + // static void SdchManager::SdchErrorRecovery(ProblemCodes problem) { UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_4", problem, MAX_PROBLEM_CODE); @@ -252,9 +265,9 @@ void SdchManager::BlacklistDomain(const GURL& url) { if (count > 0) return; // Domain is already blacklisted. - count = 1 + 2 * exponential_blacklist_count[domain]; + count = 1 + 2 * exponential_blacklist_count_[domain]; if (count > 0) - exponential_blacklist_count[domain] = count; + exponential_blacklist_count_[domain] = count; else count = INT_MAX; @@ -265,13 +278,13 @@ void SdchManager::BlacklistDomainForever(const GURL& url) { SetAllowLatencyExperiment(url, false); std::string domain(StringToLowerASCII(url.host())); - exponential_blacklist_count[domain] = INT_MAX; + exponential_blacklist_count_[domain] = INT_MAX; blacklisted_domains_[domain] = INT_MAX; } void SdchManager::ClearBlacklistings() { blacklisted_domains_.clear(); - exponential_blacklist_count.clear(); + exponential_blacklist_count_.clear(); } void SdchManager::ClearDomainBlacklisting(const std::string& domain) { @@ -285,10 +298,10 @@ int SdchManager::BlackListDomainCount(const std::string& domain) { } int SdchManager::BlacklistDomainExponential(const std::string& domain) { - if (exponential_blacklist_count.end() == - exponential_blacklist_count.find(domain)) + if (exponential_blacklist_count_.end() == + exponential_blacklist_count_.find(domain)) return 0; - return exponential_blacklist_count[StringToLowerASCII(domain)]; + return exponential_blacklist_count_[StringToLowerASCII(domain)]; } bool SdchManager::IsInSupportedDomain(const GURL& url) { @@ -455,20 +468,21 @@ bool SdchManager::AddSdchDictionary(const std::string& dictionary_text, Dictionary* dictionary = new Dictionary(dictionary_text, header_end + 2, client_hash, dictionary_url, domain, path, expiration, ports); - dictionary->AddRef(); dictionaries_[server_hash] = dictionary; return true; } -void SdchManager::GetVcdiffDictionary(const std::string& server_hash, - const GURL& referring_url, Dictionary** dictionary) { +void SdchManager::GetVcdiffDictionary( + const std::string& server_hash, + const GURL& referring_url, + scoped_refptr<Dictionary>* dictionary) { DCHECK(CalledOnValidThread()); *dictionary = NULL; DictionaryMap::iterator it = dictionaries_.find(server_hash); if (it == dictionaries_.end()) { return; } - Dictionary* matching_dictionary = it->second; + scoped_refptr<Dictionary> matching_dictionary = it->second; if (!IsInSupportedDomain(referring_url)) return; if (!matching_dictionary->CanUse(referring_url)) diff --git a/net/base/sdch_manager.h b/net/base/sdch_manager.h index c760313..37cac1b 100644 --- a/net/base/sdch_manager.h +++ b/net/base/sdch_manager.h @@ -49,6 +49,11 @@ class SdchFetcher { // from a server. The callee is responsible for getting that dictionary_text, // and then calling back to AddSdchDictionary() to the SdchManager instance. virtual void Schedule(const GURL& dictionary_url) = 0; + + // The Cancel() method is called to cancel all pending dictionary fetches. + // This is used for implementation of ClearData() below. + virtual void Cancel() = 0; + private: DISALLOW_COPY_AND_ASSIGN(SdchFetcher); }; @@ -234,6 +239,9 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { SdchManager(); ~SdchManager(); + // Clear data (for browser data removal). + void ClearData(); + // Record stats on various errors. static void SdchErrorRecovery(ProblemCodes problem); @@ -304,12 +312,10 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { // to use to decompreses data that arrived as SDCH encoded content. Check to // be sure the returned |dictionary| can be used for decoding content supplied // in response to a request for |referring_url|. - // Caller is responsible for AddRef()ing the dictionary, and Release()ing it - // when done. // Return null in |dictionary| if there is no matching legal dictionary. void GetVcdiffDictionary(const std::string& server_hash, const GURL& referring_url, - Dictionary** dictionary); + scoped_refptr<Dictionary>* dictionary); // Get list of available (pre-cached) dictionaries that we have already loaded // into memory. The list is a comma separated list of (client) hashes per @@ -335,7 +341,7 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { typedef std::set<std::string> ExperimentSet; // A map of dictionaries info indexed by the hash that the server provides. - typedef std::map<std::string, Dictionary*> DictionaryMap; + typedef std::map<std::string, scoped_refptr<Dictionary> > DictionaryMap; // Support SDCH compression, by advertising in headers. static bool g_sdch_enabled_; @@ -358,7 +364,7 @@ class NET_EXPORT SdchManager : public NON_EXPORTED_BASE(base::NonThreadSafe) { // Support exponential backoff in number of domain accesses before // blacklisting expires. - DomainCounter exponential_blacklist_count; + DomainCounter exponential_blacklist_count_; // List of hostnames for which a latency experiment is allowed (because a // round trip test has recently passed). diff --git a/net/base/sdch_manager_unittest.cc b/net/base/sdch_manager_unittest.cc index 6684e4a..87b01f4 100644 --- a/net/base/sdch_manager_unittest.cc +++ b/net/base/sdch_manager_unittest.cc @@ -192,7 +192,7 @@ TEST_F(SdchManagerTest, CanUseHTTPSDictionaryOverHTTPSIfEnabled) { EXPECT_FALSE(dictionary_list.empty()); // Dictionary should be available. - SdchManager::Dictionary* dictionary = NULL; + scoped_refptr<SdchManager::Dictionary> dictionary; std::string client_hash; std::string server_hash; sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); @@ -215,7 +215,7 @@ TEST_F(SdchManagerTest, CanNotUseHTTPDictionaryOverHTTPS) { sdch_manager()->GetAvailDictionaryList(target_url, &dictionary_list); EXPECT_TRUE(dictionary_list.empty()); - SdchManager::Dictionary* dictionary = NULL; + scoped_refptr<SdchManager::Dictionary> dictionary; std::string client_hash; std::string server_hash; sdch_manager()->GenerateHash(dictionary_text, &client_hash, &server_hash); @@ -401,7 +401,7 @@ TEST_F(SdchManagerTest, CanUseMultipleManagers) { // can't get them from the other. EXPECT_TRUE(sdch_manager()->AddSdchDictionary( dictionary_text_1, GURL("http://" + dictionary_domain_1))); - SdchManager::Dictionary* dictionary = NULL; + scoped_refptr<SdchManager::Dictionary> dictionary; sdch_manager()->GetVcdiffDictionary( server_hash_1, GURL("http://" + dictionary_domain_1 + "/random_url"), @@ -441,5 +441,38 @@ TEST_F(SdchManagerTest, HttpsCorrectlySupported) { EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(secure_url)); } +TEST_F(SdchManagerTest, ClearDictionaryData) { + std::string dictionary_domain("x.y.z.google.com"); + GURL blacklist_url("http://bad.chromium.org"); + + std::string dictionary_text(NewSdchDictionary(dictionary_domain)); + std::string tmp_hash; + std::string server_hash; + + SdchManager::GenerateHash(dictionary_text, &tmp_hash, &server_hash); + + EXPECT_TRUE(sdch_manager()->AddSdchDictionary( + dictionary_text, GURL("http://" + dictionary_domain))); + scoped_refptr<SdchManager::Dictionary> dictionary; + sdch_manager()->GetVcdiffDictionary( + server_hash, + GURL("http://" + dictionary_domain + "/random_url"), + &dictionary); + EXPECT_TRUE(dictionary); + + sdch_manager()->BlacklistDomain(GURL(blacklist_url)); + EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(blacklist_url)); + + sdch_manager()->ClearData(); + + dictionary = NULL; + sdch_manager()->GetVcdiffDictionary( + server_hash, + GURL("http://" + dictionary_domain + "/random_url"), + &dictionary); + EXPECT_FALSE(dictionary); + EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(blacklist_url)); +} + } // namespace net diff --git a/net/filter/sdch_filter.cc b/net/filter/sdch_filter.cc index 5590821..2ef5ad5 100644 --- a/net/filter/sdch_filter.cc +++ b/net/filter/sdch_filter.cc @@ -336,20 +336,19 @@ Filter::FilterStatus SdchFilter::InitializeDictionary() { else next_stream_data_ = NULL; - DCHECK(!dictionary_.get()); + DCHECK(!dictionary_); dictionary_hash_is_plausible_ = true; // Assume plausible, but check. - SdchManager::Dictionary* dictionary = NULL; if ('\0' == dictionary_hash_[kServerIdLength - 1]) { SdchManager* manager(url_request_context_->sdch_manager()); manager->GetVcdiffDictionary( std::string(dictionary_hash_, 0, kServerIdLength - 1), - url_, &dictionary); + url_, &dictionary_); } else { dictionary_hash_is_plausible_ = false; } - if (!dictionary) { + if (!dictionary_) { DCHECK(dictionary_hash_.size() == kServerIdLength); // Since dictionary was not found, check to see if hash was even plausible. for (size_t i = 0; i < kServerIdLength - 1; ++i) { @@ -366,7 +365,6 @@ Filter::FilterStatus SdchFilter::InitializeDictionary() { decoding_status_ = DECODING_ERROR; return FILTER_ERROR; } - dictionary_ = dictionary; vcdiff_streaming_decoder_.reset(new open_vcdiff::VCDiffStreamingDecoder); vcdiff_streaming_decoder_->SetAllowVcdTarget(false); vcdiff_streaming_decoder_->StartDecoding(dictionary_->text().data(), |