| 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 "chrome/browser/safe_browsing/protocol_manager.h" | 5 #include "chrome/browser/safe_browsing/protocol_manager.h" |
| 6 | 6 |
| 7 #ifndef NDEBUG | 7 #ifndef NDEBUG |
| 8 #include "base/base64.h" | 8 #include "base/base64.h" |
| 9 #endif | 9 #endif |
| 10 #include "base/environment.h" | 10 #include "base/environment.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 UPDATE_RESULT_BACKUP_START = UPDATE_RESULT_BACKUP_CONNECT_FAIL, | 47 UPDATE_RESULT_BACKUP_START = UPDATE_RESULT_BACKUP_CONNECT_FAIL, |
| 48 }; | 48 }; |
| 49 | 49 |
| 50 void RecordUpdateResult(UpdateResult result) { | 50 void RecordUpdateResult(UpdateResult result) { |
| 51 DCHECK(result >= 0 && result < UPDATE_RESULT_MAX); | 51 DCHECK(result >= 0 && result < UPDATE_RESULT_MAX); |
| 52 UMA_HISTOGRAM_ENUMERATION("SB2.UpdateResult", result, UPDATE_RESULT_MAX); | 52 UMA_HISTOGRAM_ENUMERATION("SB2.UpdateResult", result, UPDATE_RESULT_MAX); |
| 53 } | 53 } |
| 54 | 54 |
| 55 } // namespace | 55 } // namespace |
| 56 | 56 |
| 57 // The maximum staleness for a cached entry. |
| 58 // TODO(mattm): remove this when switching to Safebrowsing API 2.3. |
| 59 static const int kMaxStalenessMinutes = 45; |
| 60 |
| 57 // Minimum time, in seconds, from start up before we must issue an update query. | 61 // Minimum time, in seconds, from start up before we must issue an update query. |
| 58 static const int kSbTimerStartIntervalSecMin = 60; | 62 static const int kSbTimerStartIntervalSecMin = 60; |
| 59 | 63 |
| 60 // Maximum time, in seconds, from start up before we must issue an update query. | 64 // Maximum time, in seconds, from start up before we must issue an update query. |
| 61 static const int kSbTimerStartIntervalSecMax = 300; | 65 static const int kSbTimerStartIntervalSecMax = 300; |
| 62 | 66 |
| 63 // The maximum time, in seconds, to wait for a response to an update request. | 67 // The maximum time, in seconds, to wait for a response to an update request. |
| 64 static const int kSbMaxUpdateWaitSec = 30; | 68 static const int kSbMaxUpdateWaitSec = 30; |
| 65 | 69 |
| 66 // Maximum back off multiplier. | 70 // Maximum back off multiplier. |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 const std::vector<SBPrefix>& prefixes, | 170 const std::vector<SBPrefix>& prefixes, |
| 167 FullHashCallback callback, | 171 FullHashCallback callback, |
| 168 bool is_download) { | 172 bool is_download) { |
| 169 DCHECK(CalledOnValidThread()); | 173 DCHECK(CalledOnValidThread()); |
| 170 // If we are in GetHash backoff, we need to check if we're past the next | 174 // If we are in GetHash backoff, we need to check if we're past the next |
| 171 // allowed time. If we are, we can proceed with the request. If not, we are | 175 // allowed time. If we are, we can proceed with the request. If not, we are |
| 172 // required to return empty results (i.e. treat the page as safe). | 176 // required to return empty results (i.e. treat the page as safe). |
| 173 if (gethash_error_count_ && Time::Now() <= next_gethash_time_) { | 177 if (gethash_error_count_ && Time::Now() <= next_gethash_time_) { |
| 174 RecordGetHashResult(is_download, GET_HASH_BACKOFF_ERROR); | 178 RecordGetHashResult(is_download, GET_HASH_BACKOFF_ERROR); |
| 175 std::vector<SBFullHashResult> full_hashes; | 179 std::vector<SBFullHashResult> full_hashes; |
| 176 callback.Run(full_hashes, false); | 180 callback.Run(full_hashes, base::TimeDelta()); |
| 177 return; | 181 return; |
| 178 } | 182 } |
| 179 GURL gethash_url = GetHashUrl(); | 183 GURL gethash_url = GetHashUrl(); |
| 180 net::URLFetcher* fetcher = net::URLFetcher::Create( | 184 net::URLFetcher* fetcher = net::URLFetcher::Create( |
| 181 url_fetcher_id_++, gethash_url, net::URLFetcher::POST, this); | 185 url_fetcher_id_++, gethash_url, net::URLFetcher::POST, this); |
| 182 hash_requests_[fetcher] = FullHashDetails(callback, is_download); | 186 hash_requests_[fetcher] = FullHashDetails(callback, is_download); |
| 183 | 187 |
| 184 std::string get_hash; | 188 std::string get_hash; |
| 185 SafeBrowsingProtocolParser parser; | 189 SafeBrowsingProtocolParser parser; |
| 186 parser.FormatGetHash(prefixes, &get_hash); | 190 parser.FormatGetHash(prefixes, &get_hash); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 212 DCHECK(CalledOnValidThread()); | 216 DCHECK(CalledOnValidThread()); |
| 213 scoped_ptr<const net::URLFetcher> fetcher; | 217 scoped_ptr<const net::URLFetcher> fetcher; |
| 214 bool parsed_ok = true; | 218 bool parsed_ok = true; |
| 215 | 219 |
| 216 HashRequests::iterator it = hash_requests_.find(source); | 220 HashRequests::iterator it = hash_requests_.find(source); |
| 217 if (it != hash_requests_.end()) { | 221 if (it != hash_requests_.end()) { |
| 218 // GetHash response. | 222 // GetHash response. |
| 219 fetcher.reset(it->first); | 223 fetcher.reset(it->first); |
| 220 const FullHashDetails& details = it->second; | 224 const FullHashDetails& details = it->second; |
| 221 std::vector<SBFullHashResult> full_hashes; | 225 std::vector<SBFullHashResult> full_hashes; |
| 222 bool can_cache = false; | 226 base::TimeDelta cache_lifetime; |
| 223 if (source->GetStatus().is_success() && | 227 if (source->GetStatus().is_success() && |
| 224 (source->GetResponseCode() == 200 || | 228 (source->GetResponseCode() == 200 || |
| 225 source->GetResponseCode() == 204)) { | 229 source->GetResponseCode() == 204)) { |
| 226 // For tracking our GetHash false positive (204) rate, compared to real | 230 // For tracking our GetHash false positive (204) rate, compared to real |
| 227 // (200) responses. | 231 // (200) responses. |
| 228 if (source->GetResponseCode() == 200) | 232 if (source->GetResponseCode() == 200) |
| 229 RecordGetHashResult(details.is_download, GET_HASH_STATUS_200); | 233 RecordGetHashResult(details.is_download, GET_HASH_STATUS_200); |
| 230 else | 234 else |
| 231 RecordGetHashResult(details.is_download, GET_HASH_STATUS_204); | 235 RecordGetHashResult(details.is_download, GET_HASH_STATUS_204); |
| 232 can_cache = true; | 236 // In SB 2.3, cache lifetime will be part of the protocol message. For |
| 237 // now, use the old value of 45 minutes. |
| 238 cache_lifetime = base::TimeDelta::FromMinutes(kMaxStalenessMinutes); |
| 233 gethash_error_count_ = 0; | 239 gethash_error_count_ = 0; |
| 234 gethash_back_off_mult_ = 1; | 240 gethash_back_off_mult_ = 1; |
| 235 SafeBrowsingProtocolParser parser; | 241 SafeBrowsingProtocolParser parser; |
| 236 std::string data; | 242 std::string data; |
| 237 source->GetResponseAsString(&data); | 243 source->GetResponseAsString(&data); |
| 238 parsed_ok = parser.ParseGetHash( | 244 parsed_ok = parser.ParseGetHash( |
| 239 data.data(), | 245 data.data(), |
| 240 static_cast<int>(data.length()), | 246 static_cast<int>(data.length()), |
| 241 &full_hashes); | 247 &full_hashes); |
| 242 if (!parsed_ok) { | 248 if (!parsed_ok) { |
| 243 full_hashes.clear(); | 249 full_hashes.clear(); |
| 244 RecordGetHashResult(details.is_download, GET_HASH_PARSE_ERROR); | 250 RecordGetHashResult(details.is_download, GET_HASH_PARSE_ERROR); |
| 245 // TODO(cbentzel): Should can_cache be set to false here? (See | 251 // TODO(cbentzel): Should cache_lifetime be set to 0 here? (See |
| 246 // http://crbug.com/360232.) | 252 // http://crbug.com/360232.) |
| 247 } | 253 } |
| 248 } else { | 254 } else { |
| 249 HandleGetHashError(Time::Now()); | 255 HandleGetHashError(Time::Now()); |
| 250 if (source->GetStatus().status() == net::URLRequestStatus::FAILED) { | 256 if (source->GetStatus().status() == net::URLRequestStatus::FAILED) { |
| 251 RecordGetHashResult(details.is_download, GET_HASH_NETWORK_ERROR); | 257 RecordGetHashResult(details.is_download, GET_HASH_NETWORK_ERROR); |
| 252 VLOG(1) << "SafeBrowsing GetHash request for: " << source->GetURL() | 258 VLOG(1) << "SafeBrowsing GetHash request for: " << source->GetURL() |
| 253 << " failed with error: " << source->GetStatus().error(); | 259 << " failed with error: " << source->GetStatus().error(); |
| 254 } else { | 260 } else { |
| 255 RecordGetHashResult(details.is_download, GET_HASH_HTTP_ERROR); | 261 RecordGetHashResult(details.is_download, GET_HASH_HTTP_ERROR); |
| 256 VLOG(1) << "SafeBrowsing GetHash request for: " << source->GetURL() | 262 VLOG(1) << "SafeBrowsing GetHash request for: " << source->GetURL() |
| 257 << " failed with error: " << source->GetResponseCode(); | 263 << " failed with error: " << source->GetResponseCode(); |
| 258 } | 264 } |
| 259 } | 265 } |
| 260 | 266 |
| 261 // Invoke the callback with full_hashes, even if there was a parse error or | 267 // Invoke the callback with full_hashes, even if there was a parse error or |
| 262 // an error response code (in which case full_hashes will be empty). The | 268 // an error response code (in which case full_hashes will be empty). The |
| 263 // caller can't be blocked indefinitely. | 269 // caller can't be blocked indefinitely. |
| 264 details.callback.Run(full_hashes, can_cache); | 270 details.callback.Run(full_hashes, cache_lifetime); |
| 265 | 271 |
| 266 hash_requests_.erase(it); | 272 hash_requests_.erase(it); |
| 267 } else { | 273 } else { |
| 268 // Update or chunk response. | 274 // Update or chunk response. |
| 269 fetcher.reset(request_.release()); | 275 fetcher.reset(request_.release()); |
| 270 | 276 |
| 271 if (request_type_ == UPDATE_REQUEST || | 277 if (request_type_ == UPDATE_REQUEST || |
| 272 request_type_ == BACKUP_UPDATE_REQUEST) { | 278 request_type_ == BACKUP_UPDATE_REQUEST) { |
| 273 if (!fetcher.get()) { | 279 if (!fetcher.get()) { |
| 274 // We've timed out waiting for an update response, so we've cancelled | 280 // We've timed out waiting for an update response, so we've cancelled |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 FullHashCallback callback, bool is_download) | 783 FullHashCallback callback, bool is_download) |
| 778 : callback(callback), | 784 : callback(callback), |
| 779 is_download(is_download) { | 785 is_download(is_download) { |
| 780 } | 786 } |
| 781 | 787 |
| 782 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() { | 788 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() { |
| 783 } | 789 } |
| 784 | 790 |
| 785 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() { | 791 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() { |
| 786 } | 792 } |
| OLD | NEW |