Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "net/sdch/sdch_owner.h" | 5 #include "net/sdch/sdch_owner.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/metrics/histogram_macros.h" | 8 #include "base/metrics/histogram_macros.h" |
| 9 #include "base/strings/string_util.h" | |
| 9 #include "base/time/default_clock.h" | 10 #include "base/time/default_clock.h" |
| 10 #include "net/base/sdch_manager.h" | 11 #include "net/base/sdch_manager.h" |
| 11 #include "net/base/sdch_net_log_params.h" | 12 #include "net/base/sdch_net_log_params.h" |
| 12 | 13 |
| 13 namespace { | 14 namespace { |
| 14 | 15 |
| 15 enum DictionaryFate { | 16 enum DictionaryFate { |
| 16 // A Get-Dictionary header wasn't acted on. | 17 // A Get-Dictionary header wasn't acted on. |
| 17 DICTIONARY_FATE_GET_IGNORED = 1, | 18 DICTIONARY_FATE_GET_IGNORED = 1, |
| 18 | 19 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 fetcher_(context, | 80 fetcher_(context, |
| 80 base::Bind(&SdchOwner::OnDictionaryFetched, | 81 base::Bind(&SdchOwner::OnDictionaryFetched, |
| 81 // Because |fetcher_| is owned by SdchOwner, the | 82 // Because |fetcher_| is owned by SdchOwner, the |
| 82 // SdchOwner object will be available for the lifetime | 83 // SdchOwner object will be available for the lifetime |
| 83 // of |fetcher_|. | 84 // of |fetcher_|. |
| 84 base::Unretained(this))), | 85 base::Unretained(this))), |
| 85 total_dictionary_bytes_(0), | 86 total_dictionary_bytes_(0), |
| 86 clock_(new base::DefaultClock), | 87 clock_(new base::DefaultClock), |
| 87 max_total_dictionary_size_(kMaxTotalDictionarySize), | 88 max_total_dictionary_size_(kMaxTotalDictionarySize), |
| 88 min_space_for_dictionary_fetch_(kMinSpaceForDictionaryFetch), | 89 min_space_for_dictionary_fetch_(kMinSpaceForDictionaryFetch), |
| 90 #if defined(OS_CHROMEOS) | |
| 91 // For debugging http://crbug.com/454198; remove when resolved. | |
| 92 destroyed_(0), | |
| 93 #endif | |
| 89 memory_pressure_listener_( | 94 memory_pressure_listener_( |
| 90 base::Bind(&SdchOwner::OnMemoryPressure, | 95 base::Bind(&SdchOwner::OnMemoryPressure, |
| 91 // Because |memory_pressure_listener_| is owned by | 96 // Because |memory_pressure_listener_| is owned by |
| 92 // SdchOwner, the SdchOwner object will be available | 97 // SdchOwner, the SdchOwner object will be available |
| 93 // for the lifetime of |memory_pressure_listener_|. | 98 // for the lifetime of |memory_pressure_listener_|. |
| 94 base::Unretained(this))) { | 99 base::Unretained(this))) { |
| 100 // For debugging http://crbug.com/454198; remove when resolved. | |
| 101 AssertNotDestroyedAndClockNotNull(__LINE__, GURL()); | |
| 95 manager_->AddObserver(this); | 102 manager_->AddObserver(this); |
| 96 } | 103 } |
| 97 | 104 |
| 98 SdchOwner::~SdchOwner() { | 105 SdchOwner::~SdchOwner() { |
| 106 // For debugging http://crbug.com/454198; remove when resolved. | |
| 107 AssertNotDestroyedAndClockNotNull(__LINE__, GURL()); | |
| 108 | |
| 99 for (auto it = local_dictionary_info_.begin(); | 109 for (auto it = local_dictionary_info_.begin(); |
| 100 it != local_dictionary_info_.end(); ++it) { | 110 it != local_dictionary_info_.end(); ++it) { |
| 101 RecordDictionaryEviction(it->second.use_count, | 111 RecordDictionaryEviction(it->second.use_count, |
| 102 DICTIONARY_FATE_EVICT_FOR_DESTRUCTION); | 112 DICTIONARY_FATE_EVICT_FOR_DESTRUCTION); |
| 103 } | 113 } |
| 104 manager_->RemoveObserver(this); | 114 manager_->RemoveObserver(this); |
| 115 #if defined(OS_CHROMEOS) | |
| 116 destroyed_ = 0xdeadbeef; | |
| 117 #endif | |
| 105 } | 118 } |
| 106 | 119 |
| 107 void SdchOwner::SetMaxTotalDictionarySize(size_t max_total_dictionary_size) { | 120 void SdchOwner::SetMaxTotalDictionarySize(size_t max_total_dictionary_size) { |
| 108 max_total_dictionary_size_ = max_total_dictionary_size; | 121 max_total_dictionary_size_ = max_total_dictionary_size; |
| 109 } | 122 } |
| 110 | 123 |
| 111 void SdchOwner::SetMinSpaceForDictionaryFetch( | 124 void SdchOwner::SetMinSpaceForDictionaryFetch( |
| 112 size_t min_space_for_dictionary_fetch) { | 125 size_t min_space_for_dictionary_fetch) { |
| 113 min_space_for_dictionary_fetch_ = min_space_for_dictionary_fetch; | 126 min_space_for_dictionary_fetch_ = min_space_for_dictionary_fetch; |
| 114 } | 127 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 131 server_hash(server_hash), | 144 server_hash(server_hash), |
| 132 use_count(use_count), | 145 use_count(use_count), |
| 133 dictionary_size(dictionary_size) {} | 146 dictionary_size(dictionary_size) {} |
| 134 DictionaryItem(const DictionaryItem& rhs) = default; | 147 DictionaryItem(const DictionaryItem& rhs) = default; |
| 135 DictionaryItem& operator=(const DictionaryItem& rhs) = default; | 148 DictionaryItem& operator=(const DictionaryItem& rhs) = default; |
| 136 bool operator<(const DictionaryItem& rhs) const { | 149 bool operator<(const DictionaryItem& rhs) const { |
| 137 return last_used < rhs.last_used; | 150 return last_used < rhs.last_used; |
| 138 } | 151 } |
| 139 }; | 152 }; |
| 140 | 153 |
| 154 // For debugging http://crbug.com/454198; remove when resolved. | |
| 155 AssertNotDestroyedAndClockNotNull(__LINE__, dictionary_url); | |
|
mmenke
2015/02/20 17:30:09
Sorry, I really wasn't thinking when I signed off.
| |
| 156 | |
| 141 std::vector<DictionaryItem> stale_dictionary_list; | 157 std::vector<DictionaryItem> stale_dictionary_list; |
| 142 size_t recoverable_bytes = 0; | 158 size_t recoverable_bytes = 0; |
| 143 base::Time stale_boundary(clock_->Now() - base::TimeDelta::FromDays(1)); | 159 base::Time stale_boundary(clock_->Now() - base::TimeDelta::FromDays(1)); |
| 144 for (auto used_it = local_dictionary_info_.begin(); | 160 for (auto used_it = local_dictionary_info_.begin(); |
| 145 used_it != local_dictionary_info_.end(); ++used_it) { | 161 used_it != local_dictionary_info_.end(); ++used_it) { |
| 146 if (used_it->second.last_used < stale_boundary) { | 162 if (used_it->second.last_used < stale_boundary) { |
| 147 stale_dictionary_list.push_back( | 163 stale_dictionary_list.push_back( |
| 148 DictionaryItem(used_it->second.last_used, used_it->first, | 164 DictionaryItem(used_it->second.last_used, used_it->first, |
| 149 used_it->second.use_count, used_it->second.size)); | 165 used_it->second.use_count, used_it->second.size)); |
| 150 recoverable_bytes += used_it->second.size; | 166 recoverable_bytes += used_it->second.size; |
| 151 } | 167 } |
| 152 } | 168 } |
| 153 | 169 |
| 170 // For debugging http://crbug.com/454198; remove when resolved. | |
| 171 AssertNotDestroyedAndClockNotNull(__LINE__, dictionary_url); | |
| 172 | |
| 154 if (total_dictionary_bytes_ + dictionary_text.size() - recoverable_bytes > | 173 if (total_dictionary_bytes_ + dictionary_text.size() - recoverable_bytes > |
| 155 max_total_dictionary_size_) { | 174 max_total_dictionary_size_) { |
| 156 RecordDictionaryFate(DICTIONARY_FATE_FETCH_IGNORED_NO_SPACE); | 175 RecordDictionaryFate(DICTIONARY_FATE_FETCH_IGNORED_NO_SPACE); |
| 157 net::SdchManager::SdchErrorRecovery(SDCH_DICTIONARY_NO_ROOM); | 176 net::SdchManager::SdchErrorRecovery(SDCH_DICTIONARY_NO_ROOM); |
| 158 net_log.AddEvent(net::NetLog::TYPE_SDCH_DICTIONARY_ERROR, | 177 net_log.AddEvent(net::NetLog::TYPE_SDCH_DICTIONARY_ERROR, |
| 159 base::Bind(&net::NetLogSdchDictionaryFetchProblemCallback, | 178 base::Bind(&net::NetLogSdchDictionaryFetchProblemCallback, |
| 160 SDCH_DICTIONARY_NO_ROOM, dictionary_url, true)); | 179 SDCH_DICTIONARY_NO_ROOM, dictionary_url, true)); |
| 161 return; | 180 return; |
| 162 } | 181 } |
| 163 | 182 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 191 RecordDictionaryFate(DICTIONARY_FATE_ADDED); | 210 RecordDictionaryFate(DICTIONARY_FATE_ADDED); |
| 192 | 211 |
| 193 DCHECK(local_dictionary_info_.end() == | 212 DCHECK(local_dictionary_info_.end() == |
| 194 local_dictionary_info_.find(server_hash)); | 213 local_dictionary_info_.find(server_hash)); |
| 195 total_dictionary_bytes_ += dictionary_text.size(); | 214 total_dictionary_bytes_ += dictionary_text.size(); |
| 196 local_dictionary_info_[server_hash] = DictionaryInfo( | 215 local_dictionary_info_[server_hash] = DictionaryInfo( |
| 197 // Set the time last used to something to avoid thrashing, but not recent, | 216 // Set the time last used to something to avoid thrashing, but not recent, |
| 198 // to avoid taking too much time/space with useless dictionaries/one-off | 217 // to avoid taking too much time/space with useless dictionaries/one-off |
| 199 // visits to web sites. | 218 // visits to web sites. |
| 200 clock_->Now() - base::TimeDelta::FromHours(23), dictionary_text.size()); | 219 clock_->Now() - base::TimeDelta::FromHours(23), dictionary_text.size()); |
| 220 | |
| 221 // For debugging http://crbug.com/454198; remove when resolved. | |
| 222 AssertNotDestroyedAndClockNotNull(__LINE__, dictionary_url); | |
| 201 } | 223 } |
| 202 | 224 |
| 203 void SdchOwner::OnDictionaryUsed(SdchManager* manager, | 225 void SdchOwner::OnDictionaryUsed(SdchManager* manager, |
| 204 const std::string& server_hash) { | 226 const std::string& server_hash) { |
| 205 auto it = local_dictionary_info_.find(server_hash); | 227 auto it = local_dictionary_info_.find(server_hash); |
| 206 DCHECK(local_dictionary_info_.end() != it); | 228 DCHECK(local_dictionary_info_.end() != it); |
| 207 | 229 |
| 208 it->second.last_used = clock_->Now(); | 230 it->second.last_used = clock_->Now(); |
| 209 it->second.use_count++; | 231 it->second.use_count++; |
| 210 } | 232 } |
| 211 | 233 |
| 212 void SdchOwner::OnGetDictionary(net::SdchManager* manager, | 234 void SdchOwner::OnGetDictionary(net::SdchManager* manager, |
| 213 const GURL& request_url, | 235 const GURL& request_url, |
| 214 const GURL& dictionary_url) { | 236 const GURL& dictionary_url) { |
| 237 // For debugging http://crbug.com/454198; remove when resolved. | |
| 238 AssertNotDestroyedAndClockNotNull(__LINE__, dictionary_url); | |
| 239 | |
| 215 base::Time stale_boundary(clock_->Now() - base::TimeDelta::FromDays(1)); | 240 base::Time stale_boundary(clock_->Now() - base::TimeDelta::FromDays(1)); |
| 216 size_t avail_bytes = 0; | 241 size_t avail_bytes = 0; |
| 217 for (auto it = local_dictionary_info_.begin(); | 242 for (auto it = local_dictionary_info_.begin(); |
| 218 it != local_dictionary_info_.end(); ++it) { | 243 it != local_dictionary_info_.end(); ++it) { |
| 219 if (it->second.last_used < stale_boundary) | 244 if (it->second.last_used < stale_boundary) |
| 220 avail_bytes += it->second.size; | 245 avail_bytes += it->second.size; |
| 221 } | 246 } |
| 222 | 247 |
| 223 // Don't initiate the fetch if we wouldn't be able to store any | 248 // Don't initiate the fetch if we wouldn't be able to store any |
| 224 // reasonable dictionary. | 249 // reasonable dictionary. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 238 } | 263 } |
| 239 | 264 |
| 240 void SdchOwner::OnClearDictionaries(net::SdchManager* manager) { | 265 void SdchOwner::OnClearDictionaries(net::SdchManager* manager) { |
| 241 total_dictionary_bytes_ = 0; | 266 total_dictionary_bytes_ = 0; |
| 242 local_dictionary_info_.clear(); | 267 local_dictionary_info_.clear(); |
| 243 fetcher_.Cancel(); | 268 fetcher_.Cancel(); |
| 244 } | 269 } |
| 245 | 270 |
| 246 void SdchOwner::SetClockForTesting(scoped_ptr<base::Clock> clock) { | 271 void SdchOwner::SetClockForTesting(scoped_ptr<base::Clock> clock) { |
| 247 clock_ = clock.Pass(); | 272 clock_ = clock.Pass(); |
| 273 | |
| 274 // For debugging http://crbug.com/454198; remove when resolved. | |
| 275 AssertNotDestroyedAndClockNotNull(__LINE__, GURL()); | |
| 248 } | 276 } |
| 249 | 277 |
| 250 void SdchOwner::OnMemoryPressure( | 278 void SdchOwner::OnMemoryPressure( |
| 251 base::MemoryPressureListener::MemoryPressureLevel level) { | 279 base::MemoryPressureListener::MemoryPressureLevel level) { |
| 252 DCHECK_NE(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, level); | 280 DCHECK_NE(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, level); |
| 253 | 281 |
| 254 for (auto it = local_dictionary_info_.begin(); | 282 for (auto it = local_dictionary_info_.begin(); |
| 255 it != local_dictionary_info_.end(); ++it) { | 283 it != local_dictionary_info_.end(); ++it) { |
| 256 RecordDictionaryEviction(it->second.use_count, | 284 RecordDictionaryEviction(it->second.use_count, |
| 257 DICTIONARY_FATE_EVICT_FOR_MEMORY); | 285 DICTIONARY_FATE_EVICT_FOR_MEMORY); |
| 258 } | 286 } |
| 259 | 287 |
| 260 // TODO(rdsmith): Make a distinction between moderate and critical | 288 // TODO(rdsmith): Make a distinction between moderate and critical |
| 261 // memory pressure. | 289 // memory pressure. |
| 262 manager_->ClearData(); | 290 manager_->ClearData(); |
| 263 } | 291 } |
| 264 | 292 |
| 293 // For debugging http://crbug.com/454198; remove when resolved. | |
| 294 #if defined(OS_CHROMEOS) | |
| 295 void SdchOwner::AssertNotDestroyedAndClockNotNull(int line, const GURL& url) { | |
| 296 if (destroyed_ != 0u || clock_.get() == nullptr) { | |
| 297 char url_buf[128]; | |
| 298 base::strlcpy(url_buf, url.spec().c_str(), arraysize(url_buf)); | |
| 299 CHECK(false) << "454198 test tripped on line " << line << ", destroyed " | |
| 300 << destroyed_ << ", clock " << clock_.get(); | |
| 301 } | |
| 302 } | |
| 303 #else | |
| 304 void SdchOwner::AssertNotDestroyedAndClockNotNull(int line, const GURL& url) { | |
| 305 } | |
| 306 #endif | |
| 307 | |
| 265 } // namespace net | 308 } // namespace net |
| OLD | NEW |