Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/http/infinite_cache.h" | 5 #include "net/http/infinite_cache.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 | 38 |
| 39 // Flags to use with a particular resource. | 39 // Flags to use with a particular resource. |
| 40 enum Flags { | 40 enum Flags { |
| 41 NO_CACHE = 1 << 0, | 41 NO_CACHE = 1 << 0, |
| 42 NO_STORE = 1 << 1, | 42 NO_STORE = 1 << 1, |
| 43 EXPIRED = 1 << 2, | 43 EXPIRED = 1 << 2, |
| 44 TRUNCATED = 1 << 3, | 44 TRUNCATED = 1 << 3, |
| 45 RESUMABLE = 1 << 4, | 45 RESUMABLE = 1 << 4, |
| 46 REVALIDATEABLE = 1 << 5, | 46 REVALIDATEABLE = 1 << 5, |
| 47 DOOM_METHOD = 1 << 6, | 47 DOOM_METHOD = 1 << 6, |
| 48 CACHED = 1 << 7 | 48 CACHED = 1 << 7, |
| 49 GA_JS_HTTP = 1 << 8, | |
| 50 GA_JS_HTTPS = 1 << 9, | |
| 49 }; | 51 }; |
| 50 | 52 |
| 53 const char kGaJsHttpUrl[] = "http://www.google-analytics.com/ga.js"; | |
| 54 const char kGaJsHttpsUrl[] = "https://ssl.google-analytics.com/ga.js"; | |
| 55 | |
| 51 const int kKeySizeBytes = 20; | 56 const int kKeySizeBytes = 20; |
| 52 COMPILE_ASSERT(base::kSHA1Length == static_cast<unsigned>(kKeySizeBytes), | 57 COMPILE_ASSERT(base::kSHA1Length == static_cast<unsigned>(kKeySizeBytes), |
| 53 invalid_key_length); | 58 invalid_key_length); |
| 54 struct Key { | 59 struct Key { |
| 55 char value[kKeySizeBytes]; | 60 char value[kKeySizeBytes]; |
| 56 }; | 61 }; |
| 57 | 62 |
| 58 // The actual data that we store for every resource. | 63 // The actual data that we store for every resource. |
| 59 struct Details { | 64 struct Details { |
| 60 int32 expiration; | 65 int32 expiration; |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 struct InfiniteCacheTransaction::ResourceData { | 234 struct InfiniteCacheTransaction::ResourceData { |
| 230 ResourceData() { | 235 ResourceData() { |
| 231 memset(this, 0, sizeof(*this)); | 236 memset(this, 0, sizeof(*this)); |
| 232 } | 237 } |
| 233 | 238 |
| 234 Key key; | 239 Key key; |
| 235 Details details; | 240 Details details; |
| 236 }; | 241 }; |
| 237 | 242 |
| 238 InfiniteCacheTransaction::InfiniteCacheTransaction(InfiniteCache* cache) | 243 InfiniteCacheTransaction::InfiniteCacheTransaction(InfiniteCache* cache) |
| 239 : cache_(cache->AsWeakPtr()), must_doom_entry_(false) { | 244 : cache_(cache->AsWeakPtr()) { |
| 240 } | 245 } |
| 241 | 246 |
| 242 InfiniteCacheTransaction::~InfiniteCacheTransaction() { | 247 InfiniteCacheTransaction::~InfiniteCacheTransaction() { |
| 243 Finish(); | 248 Finish(); |
| 244 } | 249 } |
| 245 | 250 |
| 246 void InfiniteCacheTransaction::OnRequestStart(const HttpRequestInfo* request) { | 251 void InfiniteCacheTransaction::OnRequestStart(const HttpRequestInfo* request) { |
| 247 if (!cache_) | 252 if (!cache_) |
| 248 return; | 253 return; |
| 249 | 254 |
| 250 std::string method = request->method; | 255 std::string method = request->method; |
| 251 if (method == "POST" || method == "DELETE" || method == "PUT") { | 256 if (method == "POST" || method == "DELETE" || method == "PUT") { |
| 252 must_doom_entry_ = true; | 257 resource_data_->details.flags |= DOOM_METHOD; |
| 253 } else if (method != "GET") { | 258 } else if (method != "GET") { |
| 254 cache_.reset(); | 259 cache_.reset(); |
| 255 return; | 260 return; |
| 256 } | 261 } |
| 262 const std::string cache_key = cache_->GenerateKey(request); | |
| 263 if (cache_key == kGaJsHttpUrl) { | |
| 264 resource_data_->details.flags &= GA_JS_HTTP; | |
|
rvargas (doing something else)
2012/09/29 02:28:16
I meant this one (and the next one)
willchan no longer on Chromium
2012/09/29 02:31:21
Argh, I fail. Thanks for the careful review. Done
| |
| 265 } else if (cache_key == kGaJsHttpsUrl) { | |
| 266 resource_data_->details.flags &= GA_JS_HTTPS; | |
| 267 } | |
| 257 | 268 |
| 258 resource_data_.reset(new ResourceData); | 269 CryptoHash(cache_key, &resource_data_->key); |
| 259 CryptoHash(cache_->GenerateKey(request), &resource_data_->key); | |
| 260 } | 270 } |
| 261 | 271 |
| 262 void InfiniteCacheTransaction::OnResponseReceived( | 272 void InfiniteCacheTransaction::OnResponseReceived( |
| 263 const HttpResponseInfo* response) { | 273 const HttpResponseInfo* response) { |
| 264 if (!cache_) | 274 if (!cache_) |
| 265 return; | 275 return; |
| 266 | 276 |
| 267 Details& details = resource_data_->details; | 277 Details& details = resource_data_->details; |
| 268 | 278 |
| 279 // Store the old flag values that we want to preserve. | |
| 280 const uint32 kPreserveFlagsBitMask = (GA_JS_HTTP | GA_JS_HTTPS | DOOM_METHOD); | |
| 281 uint32 old_flag_values = details.flags & kPreserveFlagsBitMask; | |
| 282 | |
| 269 details.expiration = GetExpiration(response); | 283 details.expiration = GetExpiration(response); |
| 270 details.last_access = TimeToInt(response->request_time); | 284 details.last_access = TimeToInt(response->request_time); |
| 271 details.flags = GetCacheability(response); | 285 details.flags = GetCacheability(response); |
| 272 details.vary_hash = GetVaryHash(response); | 286 details.vary_hash = GetVaryHash(response); |
| 273 details.response_hash = adler32(0, Z_NULL, 0); // Init the hash. | 287 details.response_hash = adler32(0, Z_NULL, 0); // Init the hash. |
| 274 | 288 |
| 275 if (!details.flags && | 289 if (!details.flags && |
| 276 TimeToInt(response->response_time) == details.expiration) { | 290 TimeToInt(response->response_time) == details.expiration) { |
| 277 details.flags = EXPIRED; | 291 details.flags = EXPIRED; |
| 278 } | 292 } |
| 293 | |
| 294 // Restore the old flag values we wanted to preserve. | |
| 295 details.flags |= old_flag_values; | |
| 296 | |
| 279 details.flags |= GetRevalidationFlags(response); | 297 details.flags |= GetRevalidationFlags(response); |
| 280 | 298 |
| 281 if (must_doom_entry_) | |
| 282 details.flags |= DOOM_METHOD; | |
| 283 | |
| 284 Pickle pickle; | 299 Pickle pickle; |
| 285 response->Persist(&pickle, true, false); // Skip transient headers. | 300 response->Persist(&pickle, true, false); // Skip transient headers. |
| 286 details.headers_size = pickle.size(); | 301 details.headers_size = pickle.size(); |
| 287 details.headers_hash = adler32(0, Z_NULL, 0); | 302 details.headers_hash = adler32(0, Z_NULL, 0); |
| 288 details.headers_hash = adler32(details.headers_hash, | 303 details.headers_hash = adler32(details.headers_hash, |
| 289 reinterpret_cast<const Bytef*>(pickle.data()), | 304 reinterpret_cast<const Bytef*>(pickle.data()), |
| 290 pickle.size()); | 305 pickle.size()); |
| 291 } | 306 } |
| 292 | 307 |
| 293 void InfiniteCacheTransaction::OnDataRead(const char* data, int data_len) { | 308 void InfiniteCacheTransaction::OnDataRead(const char* data, int data_len) { |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 765 | 780 |
| 766 void InfiniteCache::Worker::UpdateSize(int old_size, int new_size) { | 781 void InfiniteCache::Worker::UpdateSize(int old_size, int new_size) { |
| 767 header_->total_size += new_size - old_size; | 782 header_->total_size += new_size - old_size; |
| 768 DCHECK_GE(header_->total_size, 0); | 783 DCHECK_GE(header_->total_size, 0); |
| 769 } | 784 } |
| 770 | 785 |
| 771 void InfiniteCache::Worker::RecordHit(const Details& old, Details* details) { | 786 void InfiniteCache::Worker::RecordHit(const Details& old, Details* details) { |
| 772 header_->num_hits++; | 787 header_->num_hits++; |
| 773 int access_delta = (IntToTime(details->last_access) - | 788 int access_delta = (IntToTime(details->last_access) - |
| 774 IntToTime(old.last_access)).InMinutes(); | 789 IntToTime(old.last_access)).InMinutes(); |
| 775 if (old.use_count) | 790 if (old.use_count) { |
| 776 UMA_HISTOGRAM_COUNTS("InfiniteCache.ReuseAge", access_delta); | 791 UMA_HISTOGRAM_COUNTS("InfiniteCache.ReuseAge", access_delta); |
| 777 else | 792 if (details->flags & GA_JS_HTTP) { |
| 793 UMA_HISTOGRAM_COUNTS("InfiniteCache.GaJsHttpReuseAge", access_delta); | |
| 794 } else if (details->flags & GA_JS_HTTPS) { | |
| 795 UMA_HISTOGRAM_COUNTS("InfiniteCache.GaJsHttpsReuseAge", access_delta); | |
| 796 } | |
| 797 } else { | |
| 778 UMA_HISTOGRAM_COUNTS("InfiniteCache.FirstReuseAge", access_delta); | 798 UMA_HISTOGRAM_COUNTS("InfiniteCache.FirstReuseAge", access_delta); |
| 799 if (details->flags & GA_JS_HTTP) { | |
| 800 UMA_HISTOGRAM_COUNTS( | |
| 801 "InfiniteCache.GaJsHttpFirstReuseAge", access_delta); | |
| 802 } else if (details->flags & GA_JS_HTTPS) { | |
| 803 UMA_HISTOGRAM_COUNTS( | |
| 804 "InfiniteCache.GaJsHttpsFirstReuseAge", access_delta); | |
| 805 } | |
| 806 } | |
| 779 | 807 |
| 780 details->use_count = old.use_count; | 808 details->use_count = old.use_count; |
| 781 if (details->use_count < kuint8max) | 809 if (details->use_count < kuint8max) |
| 782 details->use_count++; | 810 details->use_count++; |
| 783 UMA_HISTOGRAM_CUSTOM_COUNTS("InfiniteCache.UseCount", details->use_count, 0, | 811 UMA_HISTOGRAM_CUSTOM_COUNTS("InfiniteCache.UseCount", details->use_count, 0, |
| 784 kuint8max, 25); | 812 kuint8max, 25); |
| 813 if (details->flags & GA_JS_HTTP) { | |
| 814 UMA_HISTOGRAM_CUSTOM_COUNTS("InfiniteCache.GaJsHttpUseCount", | |
| 815 details->use_count, 0, kuint8max, 25); | |
| 816 } else if (details->flags & GA_JS_HTTPS) { | |
| 817 UMA_HISTOGRAM_CUSTOM_COUNTS("InfiniteCache.GaJsHttpsUseCount", | |
| 818 details->use_count, 0, kuint8max, 25); | |
| 819 } | |
| 785 } | 820 } |
| 786 | 821 |
| 787 void InfiniteCache::Worker::RecordUpdate(const Details& old, Details* details) { | 822 void InfiniteCache::Worker::RecordUpdate(const Details& old, Details* details) { |
| 788 int access_delta = (IntToTime(details->last_access) - | 823 int access_delta = (IntToTime(details->last_access) - |
| 789 IntToTime(old.last_access)).InMinutes(); | 824 IntToTime(old.last_access)).InMinutes(); |
| 790 if (old.update_count) | 825 if (old.update_count) { |
| 791 UMA_HISTOGRAM_COUNTS("InfiniteCache.UpdateAge", access_delta); | 826 UMA_HISTOGRAM_COUNTS("InfiniteCache.UpdateAge", access_delta); |
| 792 else | 827 if (details->flags & GA_JS_HTTP) { |
| 828 UMA_HISTOGRAM_COUNTS( | |
| 829 "InfiniteCache.GaJsHttpUpdateAge", access_delta); | |
| 830 } else if (details->flags & GA_JS_HTTPS) { | |
| 831 UMA_HISTOGRAM_COUNTS( | |
| 832 "InfiniteCache.GaJsHttpsUpdateAge", access_delta); | |
| 833 } | |
| 834 } else { | |
| 793 UMA_HISTOGRAM_COUNTS("InfiniteCache.FirstUpdateAge", access_delta); | 835 UMA_HISTOGRAM_COUNTS("InfiniteCache.FirstUpdateAge", access_delta); |
| 836 if (details->flags & GA_JS_HTTP) { | |
| 837 UMA_HISTOGRAM_COUNTS( | |
| 838 "InfiniteCache.GaJsHttpFirstUpdateAge", access_delta); | |
| 839 } else if (details->flags & GA_JS_HTTPS) { | |
| 840 UMA_HISTOGRAM_COUNTS( | |
| 841 "InfiniteCache.GaJsHttpsFirstUpdateAge", access_delta); | |
| 842 } | |
| 843 } | |
| 794 | 844 |
| 795 details->update_count = old.update_count; | 845 details->update_count = old.update_count; |
| 796 if (details->update_count < kuint8max) | 846 if (details->update_count < kuint8max) |
| 797 details->update_count++; | 847 details->update_count++; |
| 798 | 848 |
| 799 UMA_HISTOGRAM_CUSTOM_COUNTS("InfiniteCache.UpdateCount", | 849 UMA_HISTOGRAM_CUSTOM_COUNTS("InfiniteCache.UpdateCount", |
| 800 details->update_count, 0, kuint8max, 25); | 850 details->update_count, 0, kuint8max, 25); |
| 851 if (details->flags & GA_JS_HTTP) { | |
| 852 UMA_HISTOGRAM_CUSTOM_COUNTS("InfiniteCache.GaJsHttpUpdateCount", | |
| 853 details->update_count, 0, kuint8max, 25); | |
| 854 } else if (details->flags & GA_JS_HTTPS) { | |
| 855 UMA_HISTOGRAM_CUSTOM_COUNTS("InfiniteCache.GaJsHttpsUpdateCount", | |
| 856 details->update_count, 0, kuint8max, 25); | |
| 857 } | |
| 801 details->use_count = 0; | 858 details->use_count = 0; |
| 802 } | 859 } |
| 803 | 860 |
| 804 void InfiniteCache::Worker::GenerateHistograms() { | 861 void InfiniteCache::Worker::GenerateHistograms() { |
| 805 bool new_size_step = (header_->total_size / kReportSizeStep != | 862 bool new_size_step = (header_->total_size / kReportSizeStep != |
| 806 header_->size_last_report / kReportSizeStep); | 863 header_->size_last_report / kReportSizeStep); |
| 807 header_->size_last_report = header_->total_size; | 864 header_->size_last_report = header_->total_size; |
| 808 if (!new_size_step && (header_->use_minutes % 60 != 0)) | 865 if (!new_size_step && (header_->use_minutes % 60 != 0)) |
| 809 return; | 866 return; |
| 810 | 867 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 883 reason = REUSE_TRUNCATED; | 940 reason = REUSE_TRUNCATED; |
| 884 | 941 |
| 885 if (old.vary_hash != current.vary_hash) | 942 if (old.vary_hash != current.vary_hash) |
| 886 reason = REUSE_VARY; | 943 reason = REUSE_VARY; |
| 887 | 944 |
| 888 bool have_to_drop = (old.flags & TRUNCATED) && !(old.flags & RESUMABLE); | 945 bool have_to_drop = (old.flags & TRUNCATED) && !(old.flags & RESUMABLE); |
| 889 if (reason && (old.flags & REVALIDATEABLE) && !have_to_drop) | 946 if (reason && (old.flags & REVALIDATEABLE) && !have_to_drop) |
| 890 reason += REUSE_REVALIDATEABLE; | 947 reason += REUSE_REVALIDATEABLE; |
| 891 | 948 |
| 892 UMA_HISTOGRAM_ENUMERATION("InfiniteCache.ReuseFailure", reason, 15); | 949 UMA_HISTOGRAM_ENUMERATION("InfiniteCache.ReuseFailure", reason, 15); |
| 950 if (current.flags & GA_JS_HTTP) { | |
| 951 UMA_HISTOGRAM_ENUMERATION( | |
| 952 "InfiniteCache.GaJsHttpReuseFailure", reason, 15); | |
| 953 } else if (current.flags & GA_JS_HTTPS) { | |
| 954 UMA_HISTOGRAM_ENUMERATION( | |
| 955 "InfiniteCache.GaJsHttpsReuseFailure", reason, 15); | |
| 956 } | |
| 893 return !reason; | 957 return !reason; |
| 894 } | 958 } |
| 895 | 959 |
| 896 bool InfiniteCache::Worker::DataChanged(const Details& old, | 960 bool InfiniteCache::Worker::DataChanged(const Details& old, |
| 897 const Details& current) { | 961 const Details& current) { |
| 898 if (current.flags & CACHED) | 962 if (current.flags & CACHED) |
| 899 return false; | 963 return false; |
| 900 | 964 |
| 901 bool changed = false; | 965 bool changed = false; |
| 902 if (old.response_size != current.response_size) { | 966 if (old.response_size != current.response_size) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1014 int InfiniteCache::FlushDataForTest(const CompletionCallback& callback) { | 1078 int InfiniteCache::FlushDataForTest(const CompletionCallback& callback) { |
| 1015 DCHECK(worker_); | 1079 DCHECK(worker_); |
| 1016 int* result = new int; | 1080 int* result = new int; |
| 1017 task_runner_->PostTaskAndReply( | 1081 task_runner_->PostTaskAndReply( |
| 1018 FROM_HERE, base::Bind(&InfiniteCache::Worker::Flush, worker_, result), | 1082 FROM_HERE, base::Bind(&InfiniteCache::Worker::Flush, worker_, result), |
| 1019 base::Bind(&OnComplete, callback, base::Owned(result))); | 1083 base::Bind(&OnComplete, callback, base::Owned(result))); |
| 1020 return net::ERR_IO_PENDING; | 1084 return net::ERR_IO_PENDING; |
| 1021 } | 1085 } |
| 1022 | 1086 |
| 1023 } // namespace net | 1087 } // namespace net |
| OLD | NEW |