| 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 #include "base/environment.h" | 7 #include "base/environment.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_vector.h" | 9 #include "base/memory/scoped_vector.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 kSBUpdateFrequencyFinchExperiment, kSBUpdateFrequencyFinchParam); | 67 kSBUpdateFrequencyFinchExperiment, kSBUpdateFrequencyFinchParam); |
| 68 int finch_next_update_interval_minutes = 0; | 68 int finch_next_update_interval_minutes = 0; |
| 69 if (!base::StringToInt(num_str, &finch_next_update_interval_minutes)) { | 69 if (!base::StringToInt(num_str, &finch_next_update_interval_minutes)) { |
| 70 finch_next_update_interval_minutes = 0; // Defaults to 0. | 70 finch_next_update_interval_minutes = 0; // Defaults to 0. |
| 71 } | 71 } |
| 72 return base::TimeDelta::FromMinutes(finch_next_update_interval_minutes); | 72 return base::TimeDelta::FromMinutes(finch_next_update_interval_minutes); |
| 73 } | 73 } |
| 74 | 74 |
| 75 } // namespace | 75 } // namespace |
| 76 | 76 |
| 77 namespace safe_browsing { |
| 78 |
| 77 // Minimum time, in seconds, from start up before we must issue an update query. | 79 // Minimum time, in seconds, from start up before we must issue an update query. |
| 78 static const int kSbTimerStartIntervalSecMin = 60; | 80 static const int kSbTimerStartIntervalSecMin = 60; |
| 79 | 81 |
| 80 // Maximum time, in seconds, from start up before we must issue an update query. | 82 // Maximum time, in seconds, from start up before we must issue an update query. |
| 81 static const int kSbTimerStartIntervalSecMax = 300; | 83 static const int kSbTimerStartIntervalSecMax = 300; |
| 82 | 84 |
| 83 // The maximum time, in seconds, to wait for a response to an update request. | 85 // The maximum time, in seconds, to wait for a response to an update request. |
| 84 static const int kSbMaxUpdateWaitSec = 30; | 86 static const int kSbMaxUpdateWaitSec = 30; |
| 85 | 87 |
| 86 // Maximum back off multiplier. | 88 // Maximum back off multiplier. |
| 87 static const size_t kSbMaxBackOff = 8; | 89 static const size_t kSbMaxBackOff = 8; |
| 88 | 90 |
| 89 const char kUmaHashResponseMetricName[] = "SB2.GetHashResponseOrErrorCode"; | 91 const char kUmaHashResponseMetricName[] = "SB2.GetHashResponseOrErrorCode"; |
| 90 | 92 |
| 91 // The default SBProtocolManagerFactory. | 93 // The default SBProtocolManagerFactory. |
| 92 class SBProtocolManagerFactoryImpl : public SBProtocolManagerFactory { | 94 class SBProtocolManagerFactoryImpl : public SBProtocolManagerFactory { |
| 93 public: | 95 public: |
| 94 SBProtocolManagerFactoryImpl() { } | 96 SBProtocolManagerFactoryImpl() {} |
| 95 ~SBProtocolManagerFactoryImpl() override {} | 97 ~SBProtocolManagerFactoryImpl() override {} |
| 96 SafeBrowsingProtocolManager* CreateProtocolManager( | 98 SafeBrowsingProtocolManager* CreateProtocolManager( |
| 97 SafeBrowsingProtocolManagerDelegate* delegate, | 99 SafeBrowsingProtocolManagerDelegate* delegate, |
| 98 net::URLRequestContextGetter* request_context_getter, | 100 net::URLRequestContextGetter* request_context_getter, |
| 99 const SafeBrowsingProtocolConfig& config) override { | 101 const SafeBrowsingProtocolConfig& config) override { |
| 100 return new SafeBrowsingProtocolManager( | 102 return new SafeBrowsingProtocolManager(delegate, request_context_getter, |
| 101 delegate, request_context_getter, config); | 103 config); |
| 102 } | 104 } |
| 105 |
| 103 private: | 106 private: |
| 104 DISALLOW_COPY_AND_ASSIGN(SBProtocolManagerFactoryImpl); | 107 DISALLOW_COPY_AND_ASSIGN(SBProtocolManagerFactoryImpl); |
| 105 }; | 108 }; |
| 106 | 109 |
| 107 // SafeBrowsingProtocolManager implementation ---------------------------------- | 110 // SafeBrowsingProtocolManager implementation ---------------------------------- |
| 108 | 111 |
| 109 // static | 112 // static |
| 110 SBProtocolManagerFactory* SafeBrowsingProtocolManager::factory_ = NULL; | 113 SBProtocolManagerFactory* SafeBrowsingProtocolManager::factory_ = NULL; |
| 111 | 114 |
| 112 // static | 115 // static |
| 113 SafeBrowsingProtocolManager* SafeBrowsingProtocolManager::Create( | 116 SafeBrowsingProtocolManager* SafeBrowsingProtocolManager::Create( |
| 114 SafeBrowsingProtocolManagerDelegate* delegate, | 117 SafeBrowsingProtocolManagerDelegate* delegate, |
| 115 net::URLRequestContextGetter* request_context_getter, | 118 net::URLRequestContextGetter* request_context_getter, |
| 116 const SafeBrowsingProtocolConfig& config) { | 119 const SafeBrowsingProtocolConfig& config) { |
| 117 // TODO(cbentzel): Remove ScopedTracker below once crbug.com/483689 is fixed. | 120 // TODO(cbentzel): Remove ScopedTracker below once crbug.com/483689 is fixed. |
| 118 tracked_objects::ScopedTracker tracking_profile( | 121 tracked_objects::ScopedTracker tracking_profile( |
| 119 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 122 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 120 "483689 SafeBrowsingProtocolManager::Create")); | 123 "483689 SafeBrowsingProtocolManager::Create")); |
| 121 if (!factory_) | 124 if (!factory_) |
| 122 factory_ = new SBProtocolManagerFactoryImpl(); | 125 factory_ = new SBProtocolManagerFactoryImpl(); |
| 123 return factory_->CreateProtocolManager( | 126 return factory_->CreateProtocolManager(delegate, request_context_getter, |
| 124 delegate, request_context_getter, config); | 127 config); |
| 125 } | 128 } |
| 126 | 129 |
| 127 SafeBrowsingProtocolManager::SafeBrowsingProtocolManager( | 130 SafeBrowsingProtocolManager::SafeBrowsingProtocolManager( |
| 128 SafeBrowsingProtocolManagerDelegate* delegate, | 131 SafeBrowsingProtocolManagerDelegate* delegate, |
| 129 net::URLRequestContextGetter* request_context_getter, | 132 net::URLRequestContextGetter* request_context_getter, |
| 130 const SafeBrowsingProtocolConfig& config) | 133 const SafeBrowsingProtocolConfig& config) |
| 131 : delegate_(delegate), | 134 : delegate_(delegate), |
| 132 request_type_(NO_REQUEST), | 135 request_type_(NO_REQUEST), |
| 133 update_error_count_(0), | 136 update_error_count_(0), |
| 134 gethash_error_count_(0), | 137 gethash_error_count_(0), |
| (...skipping 21 matching lines...) Expand all Loading... |
| 156 backup_url_prefixes_[BACKUP_UPDATE_REASON_NETWORK] = | 159 backup_url_prefixes_[BACKUP_UPDATE_REASON_NETWORK] = |
| 157 config.backup_network_error_url_prefix; | 160 config.backup_network_error_url_prefix; |
| 158 | 161 |
| 159 // Set the backoff multiplier fuzz to a random value between 0 and 1. | 162 // Set the backoff multiplier fuzz to a random value between 0 and 1. |
| 160 back_off_fuzz_ = static_cast<float>(base::RandDouble()); | 163 back_off_fuzz_ = static_cast<float>(base::RandDouble()); |
| 161 if (version_.empty()) | 164 if (version_.empty()) |
| 162 version_ = SafeBrowsingProtocolManagerHelper::Version(); | 165 version_ = SafeBrowsingProtocolManagerHelper::Version(); |
| 163 } | 166 } |
| 164 | 167 |
| 165 // static | 168 // static |
| 166 void SafeBrowsingProtocolManager::RecordGetHashResult( | 169 void SafeBrowsingProtocolManager::RecordGetHashResult(bool is_download, |
| 167 bool is_download, ResultType result_type) { | 170 ResultType result_type) { |
| 168 if (is_download) { | 171 if (is_download) { |
| 169 UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResultDownload", result_type, | 172 UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResultDownload", result_type, |
| 170 GET_HASH_RESULT_MAX); | 173 GET_HASH_RESULT_MAX); |
| 171 } else { | 174 } else { |
| 172 UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResult", result_type, | 175 UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResult", result_type, |
| 173 GET_HASH_RESULT_MAX); | 176 GET_HASH_RESULT_MAX); |
| 174 } | 177 } |
| 175 } | 178 } |
| 176 | 179 |
| 177 void SafeBrowsingProtocolManager::RecordHttpResponseOrErrorCode( | 180 void SafeBrowsingProtocolManager::RecordHttpResponseOrErrorCode( |
| 178 const char* metric_name, const net::URLRequestStatus& status, | 181 const char* metric_name, |
| 182 const net::URLRequestStatus& status, |
| 179 int response_code) { | 183 int response_code) { |
| 180 UMA_HISTOGRAM_SPARSE_SLOWLY( | 184 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 181 metric_name, status.is_success() ? response_code : status.error()); | 185 metric_name, status.is_success() ? response_code : status.error()); |
| 182 } | 186 } |
| 183 | 187 |
| 184 bool SafeBrowsingProtocolManager::IsUpdateScheduled() const { | 188 bool SafeBrowsingProtocolManager::IsUpdateScheduled() const { |
| 185 return update_timer_.IsRunning(); | 189 return update_timer_.IsRunning(); |
| 186 } | 190 } |
| 187 | 191 |
| 188 SafeBrowsingProtocolManager::~SafeBrowsingProtocolManager() { | 192 SafeBrowsingProtocolManager::~SafeBrowsingProtocolManager() { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 206 // required to return empty results (i.e. treat the page as safe). | 210 // required to return empty results (i.e. treat the page as safe). |
| 207 if (gethash_error_count_ && Time::Now() <= next_gethash_time_) { | 211 if (gethash_error_count_ && Time::Now() <= next_gethash_time_) { |
| 208 RecordGetHashResult(is_download, GET_HASH_BACKOFF_ERROR); | 212 RecordGetHashResult(is_download, GET_HASH_BACKOFF_ERROR); |
| 209 std::vector<SBFullHashResult> full_hashes; | 213 std::vector<SBFullHashResult> full_hashes; |
| 210 callback.Run(full_hashes, base::TimeDelta()); | 214 callback.Run(full_hashes, base::TimeDelta()); |
| 211 return; | 215 return; |
| 212 } | 216 } |
| 213 GURL gethash_url = GetHashUrl(is_extended_reporting); | 217 GURL gethash_url = GetHashUrl(is_extended_reporting); |
| 214 net::URLFetcher* fetcher = | 218 net::URLFetcher* fetcher = |
| 215 net::URLFetcher::Create(url_fetcher_id_++, gethash_url, | 219 net::URLFetcher::Create(url_fetcher_id_++, gethash_url, |
| 216 net::URLFetcher::POST, this).release(); | 220 net::URLFetcher::POST, this) |
| 221 .release(); |
| 217 hash_requests_[fetcher] = FullHashDetails(callback, is_download); | 222 hash_requests_[fetcher] = FullHashDetails(callback, is_download); |
| 218 | 223 |
| 219 const std::string get_hash = safe_browsing::FormatGetHash(prefixes); | 224 const std::string get_hash = FormatGetHash(prefixes); |
| 220 | 225 |
| 221 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE); | 226 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE); |
| 222 fetcher->SetRequestContext(request_context_getter_.get()); | 227 fetcher->SetRequestContext(request_context_getter_.get()); |
| 223 fetcher->SetUploadData("text/plain", get_hash); | 228 fetcher->SetUploadData("text/plain", get_hash); |
| 224 fetcher->Start(); | 229 fetcher->Start(); |
| 225 } | 230 } |
| 226 | 231 |
| 227 void SafeBrowsingProtocolManager::GetNextUpdate() { | 232 void SafeBrowsingProtocolManager::GetNextUpdate() { |
| 228 DCHECK(CalledOnValidThread()); | 233 DCHECK(CalledOnValidThread()); |
| 229 if (request_.get() || request_type_ != NO_REQUEST) | 234 if (request_.get() || request_type_ != NO_REQUEST) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 243 // do will report all the chunks we have. If that chunk is still | 248 // do will report all the chunks we have. If that chunk is still |
| 244 // required, the SafeBrowsing servers will tell us to get it again. | 249 // required, the SafeBrowsing servers will tell us to get it again. |
| 245 void SafeBrowsingProtocolManager::OnURLFetchComplete( | 250 void SafeBrowsingProtocolManager::OnURLFetchComplete( |
| 246 const net::URLFetcher* source) { | 251 const net::URLFetcher* source) { |
| 247 DCHECK(CalledOnValidThread()); | 252 DCHECK(CalledOnValidThread()); |
| 248 scoped_ptr<const net::URLFetcher> fetcher; | 253 scoped_ptr<const net::URLFetcher> fetcher; |
| 249 | 254 |
| 250 HashRequests::iterator it = hash_requests_.find(source); | 255 HashRequests::iterator it = hash_requests_.find(source); |
| 251 int response_code = source->GetResponseCode(); | 256 int response_code = source->GetResponseCode(); |
| 252 net::URLRequestStatus status = source->GetStatus(); | 257 net::URLRequestStatus status = source->GetStatus(); |
| 253 RecordHttpResponseOrErrorCode( | 258 RecordHttpResponseOrErrorCode(kUmaHashResponseMetricName, status, |
| 254 kUmaHashResponseMetricName, status, response_code); | 259 response_code); |
| 255 if (it != hash_requests_.end()) { | 260 if (it != hash_requests_.end()) { |
| 256 // GetHash response. | 261 // GetHash response. |
| 257 fetcher.reset(it->first); | 262 fetcher.reset(it->first); |
| 258 const FullHashDetails& details = it->second; | 263 const FullHashDetails& details = it->second; |
| 259 std::vector<SBFullHashResult> full_hashes; | 264 std::vector<SBFullHashResult> full_hashes; |
| 260 base::TimeDelta cache_lifetime; | 265 base::TimeDelta cache_lifetime; |
| 261 if (status.is_success() && | 266 if (status.is_success() && (response_code == net::HTTP_OK || |
| 262 (response_code == net::HTTP_OK || | 267 response_code == net::HTTP_NO_CONTENT)) { |
| 263 response_code == net::HTTP_NO_CONTENT)) { | |
| 264 // For tracking our GetHash false positive (net::HTTP_NO_CONTENT) rate, | 268 // For tracking our GetHash false positive (net::HTTP_NO_CONTENT) rate, |
| 265 // compared to real (net::HTTP_OK) responses. | 269 // compared to real (net::HTTP_OK) responses. |
| 266 if (response_code == net::HTTP_OK) | 270 if (response_code == net::HTTP_OK) |
| 267 RecordGetHashResult(details.is_download, GET_HASH_STATUS_200); | 271 RecordGetHashResult(details.is_download, GET_HASH_STATUS_200); |
| 268 else | 272 else |
| 269 RecordGetHashResult(details.is_download, GET_HASH_STATUS_204); | 273 RecordGetHashResult(details.is_download, GET_HASH_STATUS_204); |
| 270 | 274 |
| 271 gethash_error_count_ = 0; | 275 gethash_error_count_ = 0; |
| 272 gethash_back_off_mult_ = 1; | 276 gethash_back_off_mult_ = 1; |
| 273 std::string data; | 277 std::string data; |
| 274 source->GetResponseAsString(&data); | 278 source->GetResponseAsString(&data); |
| 275 if (!safe_browsing::ParseGetHash( | 279 if (!ParseGetHash(data.data(), data.length(), &cache_lifetime, |
| 276 data.data(), data.length(), &cache_lifetime, &full_hashes)) { | 280 &full_hashes)) { |
| 277 full_hashes.clear(); | 281 full_hashes.clear(); |
| 278 RecordGetHashResult(details.is_download, GET_HASH_PARSE_ERROR); | 282 RecordGetHashResult(details.is_download, GET_HASH_PARSE_ERROR); |
| 279 // TODO(cbentzel): Should cache_lifetime be set to 0 here? (See | 283 // TODO(cbentzel): Should cache_lifetime be set to 0 here? (See |
| 280 // http://crbug.com/360232.) | 284 // http://crbug.com/360232.) |
| 281 } | 285 } |
| 282 } else { | 286 } else { |
| 283 HandleGetHashError(Time::Now()); | 287 HandleGetHashError(Time::Now()); |
| 284 if (status.status() == net::URLRequestStatus::FAILED) { | 288 if (status.status() == net::URLRequestStatus::FAILED) { |
| 285 RecordGetHashResult(details.is_download, GET_HASH_NETWORK_ERROR); | 289 RecordGetHashResult(details.is_download, GET_HASH_NETWORK_ERROR); |
| 286 DVLOG(1) << "SafeBrowsing GetHash request for: " << source->GetURL() | 290 DVLOG(1) << "SafeBrowsing GetHash request for: " << source->GetURL() |
| (...skipping 27 matching lines...) Expand all Loading... |
| 314 timeout_timer_.Stop(); | 318 timeout_timer_.Stop(); |
| 315 } | 319 } |
| 316 | 320 |
| 317 if (status.is_success() && response_code == net::HTTP_OK) { | 321 if (status.is_success() && response_code == net::HTTP_OK) { |
| 318 // We have data from the SafeBrowsing service. | 322 // We have data from the SafeBrowsing service. |
| 319 std::string data; | 323 std::string data; |
| 320 source->GetResponseAsString(&data); | 324 source->GetResponseAsString(&data); |
| 321 | 325 |
| 322 // TODO(shess): Cleanup the flow of this code so that |parsed_ok| can be | 326 // TODO(shess): Cleanup the flow of this code so that |parsed_ok| can be |
| 323 // removed or omitted. | 327 // removed or omitted. |
| 324 const bool parsed_ok = HandleServiceResponse( | 328 const bool parsed_ok = |
| 325 source->GetURL(), data.data(), data.length()); | 329 HandleServiceResponse(source->GetURL(), data.data(), data.length()); |
| 326 if (!parsed_ok) { | 330 if (!parsed_ok) { |
| 327 DVLOG(1) << "SafeBrowsing request for: " << source->GetURL() | 331 DVLOG(1) << "SafeBrowsing request for: " << source->GetURL() |
| 328 << " failed parse."; | 332 << " failed parse."; |
| 329 chunk_request_urls_.clear(); | 333 chunk_request_urls_.clear(); |
| 330 if (request_type_ == UPDATE_REQUEST && | 334 if (request_type_ == UPDATE_REQUEST && |
| 331 IssueBackupUpdateRequest(BACKUP_UPDATE_REASON_HTTP)) { | 335 IssueBackupUpdateRequest(BACKUP_UPDATE_REASON_HTTP)) { |
| 332 return; | 336 return; |
| 333 } | 337 } |
| 334 UpdateFinished(false); | 338 UpdateFinished(false); |
| 335 } | 339 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 } | 393 } |
| 390 } | 394 } |
| 391 UpdateFinished(false); | 395 UpdateFinished(false); |
| 392 } | 396 } |
| 393 } | 397 } |
| 394 | 398 |
| 395 // Get the next chunk if available. | 399 // Get the next chunk if available. |
| 396 IssueChunkRequest(); | 400 IssueChunkRequest(); |
| 397 } | 401 } |
| 398 | 402 |
| 399 bool SafeBrowsingProtocolManager::HandleServiceResponse( | 403 bool SafeBrowsingProtocolManager::HandleServiceResponse(const GURL& url, |
| 400 const GURL& url, const char* data, size_t length) { | 404 const char* data, |
| 405 size_t length) { |
| 401 DCHECK(CalledOnValidThread()); | 406 DCHECK(CalledOnValidThread()); |
| 402 | 407 |
| 403 switch (request_type_) { | 408 switch (request_type_) { |
| 404 case UPDATE_REQUEST: | 409 case UPDATE_REQUEST: |
| 405 case BACKUP_UPDATE_REQUEST: { | 410 case BACKUP_UPDATE_REQUEST: { |
| 406 size_t next_update_sec = 0; | 411 size_t next_update_sec = 0; |
| 407 bool reset = false; | 412 bool reset = false; |
| 408 scoped_ptr<std::vector<SBChunkDelete> > chunk_deletes( | 413 scoped_ptr<std::vector<SBChunkDelete>> chunk_deletes( |
| 409 new std::vector<SBChunkDelete>); | 414 new std::vector<SBChunkDelete>); |
| 410 std::vector<ChunkUrl> chunk_urls; | 415 std::vector<ChunkUrl> chunk_urls; |
| 411 if (!safe_browsing::ParseUpdate(data, length, &next_update_sec, &reset, | 416 if (!ParseUpdate(data, length, &next_update_sec, &reset, |
| 412 chunk_deletes.get(), &chunk_urls)) { | 417 chunk_deletes.get(), &chunk_urls)) { |
| 413 return false; | 418 return false; |
| 414 } | 419 } |
| 415 | 420 |
| 416 // New time for the next update. | 421 // New time for the next update. |
| 417 base::TimeDelta finch_next_update_interval = | 422 base::TimeDelta finch_next_update_interval = |
| 418 GetNextUpdateIntervalFromFinch(); | 423 GetNextUpdateIntervalFromFinch(); |
| 419 if (finch_next_update_interval > base::TimeDelta()) { | 424 if (finch_next_update_interval > base::TimeDelta()) { |
| 420 next_update_interval_ = finch_next_update_interval; | 425 next_update_interval_ = finch_next_update_interval; |
| 421 } else { | 426 } else { |
| 422 base::TimeDelta next_update_interval = | 427 base::TimeDelta next_update_interval = |
| 423 base::TimeDelta::FromSeconds(next_update_sec); | 428 base::TimeDelta::FromSeconds(next_update_sec); |
| 424 if (next_update_interval > base::TimeDelta()) { | 429 if (next_update_interval > base::TimeDelta()) { |
| 425 next_update_interval_ = next_update_interval; | 430 next_update_interval_ = next_update_interval; |
| 426 } | 431 } |
| 427 } | 432 } |
| 428 last_update_ = Time::Now(); | 433 last_update_ = Time::Now(); |
| 429 | 434 |
| 430 // New chunks to download. | 435 // New chunks to download. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 445 if (!chunk_deletes->empty()) | 450 if (!chunk_deletes->empty()) |
| 446 delegate_->DeleteChunks(chunk_deletes.Pass()); | 451 delegate_->DeleteChunks(chunk_deletes.Pass()); |
| 447 | 452 |
| 448 break; | 453 break; |
| 449 } | 454 } |
| 450 case CHUNK_REQUEST: { | 455 case CHUNK_REQUEST: { |
| 451 UMA_HISTOGRAM_TIMES("SB2.ChunkRequest", | 456 UMA_HISTOGRAM_TIMES("SB2.ChunkRequest", |
| 452 base::Time::Now() - chunk_request_start_); | 457 base::Time::Now() - chunk_request_start_); |
| 453 | 458 |
| 454 const ChunkUrl chunk_url = chunk_request_urls_.front(); | 459 const ChunkUrl chunk_url = chunk_request_urls_.front(); |
| 455 scoped_ptr<ScopedVector<SBChunkData> > | 460 scoped_ptr<ScopedVector<SBChunkData>> chunks( |
| 456 chunks(new ScopedVector<SBChunkData>); | 461 new ScopedVector<SBChunkData>); |
| 457 UMA_HISTOGRAM_COUNTS("SB2.ChunkSize", length); | 462 UMA_HISTOGRAM_COUNTS("SB2.ChunkSize", length); |
| 458 update_size_ += length; | 463 update_size_ += length; |
| 459 if (!safe_browsing::ParseChunk(data, length, chunks.get())) | 464 if (!ParseChunk(data, length, chunks.get())) |
| 460 return false; | 465 return false; |
| 461 | 466 |
| 462 // Chunks to add to storage. Pass ownership of |chunks|. | 467 // Chunks to add to storage. Pass ownership of |chunks|. |
| 463 if (!chunks->empty()) { | 468 if (!chunks->empty()) { |
| 464 chunk_pending_to_write_ = true; | 469 chunk_pending_to_write_ = true; |
| 465 delegate_->AddChunks( | 470 delegate_->AddChunks( |
| 466 chunk_url.list_name, chunks.Pass(), | 471 chunk_url.list_name, chunks.Pass(), |
| 467 base::Bind(&SafeBrowsingProtocolManager::OnAddChunksComplete, | 472 base::Bind(&SafeBrowsingProtocolManager::OnAddChunksComplete, |
| 468 base::Unretained(this))); | 473 base::Unretained(this))); |
| 469 } | 474 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 next = GetNextBackOffInterval(&update_error_count_, &update_back_off_mult_); | 530 next = GetNextBackOffInterval(&update_error_count_, &update_back_off_mult_); |
| 526 } else { | 531 } else { |
| 527 // Successful response means error reset. | 532 // Successful response means error reset. |
| 528 update_error_count_ = 0; | 533 update_error_count_ = 0; |
| 529 update_back_off_mult_ = 1; | 534 update_back_off_mult_ = 1; |
| 530 } | 535 } |
| 531 return next; | 536 return next; |
| 532 } | 537 } |
| 533 | 538 |
| 534 base::TimeDelta SafeBrowsingProtocolManager::GetNextBackOffInterval( | 539 base::TimeDelta SafeBrowsingProtocolManager::GetNextBackOffInterval( |
| 535 size_t* error_count, size_t* multiplier) const { | 540 size_t* error_count, |
| 541 size_t* multiplier) const { |
| 536 DCHECK(CalledOnValidThread()); | 542 DCHECK(CalledOnValidThread()); |
| 537 DCHECK(multiplier && error_count); | 543 DCHECK(multiplier && error_count); |
| 538 (*error_count)++; | 544 (*error_count)++; |
| 539 if (*error_count > 1 && *error_count < 6) { | 545 if (*error_count > 1 && *error_count < 6) { |
| 540 base::TimeDelta next = base::TimeDelta::FromMinutes( | 546 base::TimeDelta next = |
| 541 *multiplier * (1 + back_off_fuzz_) * 30); | 547 base::TimeDelta::FromMinutes(*multiplier * (1 + back_off_fuzz_) * 30); |
| 542 *multiplier *= 2; | 548 *multiplier *= 2; |
| 543 if (*multiplier > kSbMaxBackOff) | 549 if (*multiplier > kSbMaxBackOff) |
| 544 *multiplier = kSbMaxBackOff; | 550 *multiplier = kSbMaxBackOff; |
| 545 return next; | 551 return next; |
| 546 } | 552 } |
| 547 if (*error_count >= 6) | 553 if (*error_count >= 6) |
| 548 return base::TimeDelta::FromHours(8); | 554 return base::TimeDelta::FromHours(8); |
| 549 return base::TimeDelta::FromMinutes(1); | 555 return base::TimeDelta::FromMinutes(1); |
| 550 } | 556 } |
| 551 | 557 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 if (database_error) { | 630 if (database_error) { |
| 625 // The update was not successful, but don't back off. | 631 // The update was not successful, but don't back off. |
| 626 UpdateFinished(false, false); | 632 UpdateFinished(false, false); |
| 627 return; | 633 return; |
| 628 } | 634 } |
| 629 | 635 |
| 630 // Format our stored chunks: | 636 // Format our stored chunks: |
| 631 bool found_malware = false; | 637 bool found_malware = false; |
| 632 bool found_phishing = false; | 638 bool found_phishing = false; |
| 633 for (size_t i = 0; i < lists.size(); ++i) { | 639 for (size_t i = 0; i < lists.size(); ++i) { |
| 634 update_list_data_.append(safe_browsing::FormatList(lists[i])); | 640 update_list_data_.append(FormatList(lists[i])); |
| 635 if (lists[i].name == safe_browsing::kPhishingList) | 641 if (lists[i].name == kPhishingList) |
| 636 found_phishing = true; | 642 found_phishing = true; |
| 637 | 643 |
| 638 if (lists[i].name == safe_browsing::kMalwareList) | 644 if (lists[i].name == kMalwareList) |
| 639 found_malware = true; | 645 found_malware = true; |
| 640 } | 646 } |
| 641 | 647 |
| 642 // If we have an empty database, let the server know we want data for these | 648 // If we have an empty database, let the server know we want data for these |
| 643 // lists. | 649 // lists. |
| 644 // TODO(shess): These cases never happen because the database fills in the | 650 // TODO(shess): These cases never happen because the database fills in the |
| 645 // lists in GetChunks(). Refactor the unit tests so that this code can be | 651 // lists in GetChunks(). Refactor the unit tests so that this code can be |
| 646 // removed. | 652 // removed. |
| 647 if (!found_phishing) { | 653 if (!found_phishing) { |
| 648 update_list_data_.append(safe_browsing::FormatList( | 654 update_list_data_.append(FormatList(SBListChunkRanges(kPhishingList))); |
| 649 SBListChunkRanges(safe_browsing::kPhishingList))); | |
| 650 } | 655 } |
| 651 if (!found_malware) { | 656 if (!found_malware) { |
| 652 update_list_data_.append(safe_browsing::FormatList( | 657 update_list_data_.append(FormatList(SBListChunkRanges(kMalwareList))); |
| 653 SBListChunkRanges(safe_browsing::kMalwareList))); | |
| 654 } | 658 } |
| 655 | 659 |
| 656 // Large requests are (probably) a sign of database corruption. | 660 // Large requests are (probably) a sign of database corruption. |
| 657 // Record stats to inform decisions about whether to automate | 661 // Record stats to inform decisions about whether to automate |
| 658 // deletion of such databases. http://crbug.com/120219 | 662 // deletion of such databases. http://crbug.com/120219 |
| 659 UMA_HISTOGRAM_COUNTS("SB2.UpdateRequestSize", update_list_data_.size()); | 663 UMA_HISTOGRAM_COUNTS("SB2.UpdateRequestSize", update_list_data_.size()); |
| 660 | 664 |
| 661 GURL update_url = UpdateUrl(is_extended_reporting); | 665 GURL update_url = UpdateUrl(is_extended_reporting); |
| 662 request_ = net::URLFetcher::Create(url_fetcher_id_++, update_url, | 666 request_ = net::URLFetcher::Create(url_fetcher_id_++, update_url, |
| 663 net::URLFetcher::POST, this); | 667 net::URLFetcher::POST, this); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 693 if (chunk_request_urls_.empty()) { | 697 if (chunk_request_urls_.empty()) { |
| 694 UMA_HISTOGRAM_LONG_TIMES("SB2.Update", Time::Now() - last_update_); | 698 UMA_HISTOGRAM_LONG_TIMES("SB2.Update", Time::Now() - last_update_); |
| 695 UpdateFinished(true); | 699 UpdateFinished(true); |
| 696 } else { | 700 } else { |
| 697 IssueChunkRequest(); | 701 IssueChunkRequest(); |
| 698 } | 702 } |
| 699 } | 703 } |
| 700 | 704 |
| 701 void SafeBrowsingProtocolManager::HandleGetHashError(const Time& now) { | 705 void SafeBrowsingProtocolManager::HandleGetHashError(const Time& now) { |
| 702 DCHECK(CalledOnValidThread()); | 706 DCHECK(CalledOnValidThread()); |
| 703 base::TimeDelta next = GetNextBackOffInterval( | 707 base::TimeDelta next = |
| 704 &gethash_error_count_, &gethash_back_off_mult_); | 708 GetNextBackOffInterval(&gethash_error_count_, &gethash_back_off_mult_); |
| 705 next_gethash_time_ = now + next; | 709 next_gethash_time_ = now + next; |
| 706 } | 710 } |
| 707 | 711 |
| 708 void SafeBrowsingProtocolManager::UpdateFinished(bool success) { | 712 void SafeBrowsingProtocolManager::UpdateFinished(bool success) { |
| 709 UpdateFinished(success, !success); | 713 UpdateFinished(success, !success); |
| 710 } | 714 } |
| 711 | 715 |
| 712 void SafeBrowsingProtocolManager::UpdateFinished(bool success, bool back_off) { | 716 void SafeBrowsingProtocolManager::UpdateFinished(bool success, bool back_off) { |
| 713 DCHECK(CalledOnValidThread()); | 717 DCHECK(CalledOnValidThread()); |
| 714 UMA_HISTOGRAM_COUNTS("SB2.UpdateSize", update_size_); | 718 UMA_HISTOGRAM_COUNTS("SB2.UpdateSize", update_size_); |
| 715 update_size_ = 0; | 719 update_size_ = 0; |
| 716 bool update_success = success || request_type_ == CHUNK_REQUEST; | 720 bool update_success = success || request_type_ == CHUNK_REQUEST; |
| 717 if (backup_update_reason_ == BACKUP_UPDATE_REASON_MAX) { | 721 if (backup_update_reason_ == BACKUP_UPDATE_REASON_MAX) { |
| 718 RecordUpdateResult( | 722 RecordUpdateResult(update_success ? UPDATE_RESULT_SUCCESS |
| 719 update_success ? UPDATE_RESULT_SUCCESS : UPDATE_RESULT_FAIL); | 723 : UPDATE_RESULT_FAIL); |
| 720 } else { | 724 } else { |
| 721 UpdateResult update_result = static_cast<UpdateResult>( | 725 UpdateResult update_result = static_cast<UpdateResult>( |
| 722 UPDATE_RESULT_BACKUP_START + | 726 UPDATE_RESULT_BACKUP_START + |
| 723 (static_cast<int>(backup_update_reason_) * 2) + | 727 (static_cast<int>(backup_update_reason_) * 2) + update_success); |
| 724 update_success); | |
| 725 RecordUpdateResult(update_result); | 728 RecordUpdateResult(update_result); |
| 726 } | 729 } |
| 727 backup_update_reason_ = BACKUP_UPDATE_REASON_MAX; | 730 backup_update_reason_ = BACKUP_UPDATE_REASON_MAX; |
| 728 request_type_ = NO_REQUEST; | 731 request_type_ = NO_REQUEST; |
| 729 update_list_data_.clear(); | 732 update_list_data_.clear(); |
| 730 delegate_->UpdateFinished(success); | 733 delegate_->UpdateFinished(success); |
| 731 ScheduleNextUpdate(back_off); | 734 ScheduleNextUpdate(back_off); |
| 732 } | 735 } |
| 733 | 736 |
| 734 GURL SafeBrowsingProtocolManager::UpdateUrl(bool is_extended_reporting) const { | 737 GURL SafeBrowsingProtocolManager::UpdateUrl(bool is_extended_reporting) const { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 752 GURL SafeBrowsingProtocolManager::GetHashUrl(bool is_extended_reporting) const { | 755 GURL SafeBrowsingProtocolManager::GetHashUrl(bool is_extended_reporting) const { |
| 753 std::string url = SafeBrowsingProtocolManagerHelper::ComposeUrl( | 756 std::string url = SafeBrowsingProtocolManagerHelper::ComposeUrl( |
| 754 url_prefix_, "gethash", client_name_, version_, additional_query_, | 757 url_prefix_, "gethash", client_name_, version_, additional_query_, |
| 755 is_extended_reporting); | 758 is_extended_reporting); |
| 756 return GURL(url); | 759 return GURL(url); |
| 757 } | 760 } |
| 758 | 761 |
| 759 GURL SafeBrowsingProtocolManager::NextChunkUrl(const std::string& url) const { | 762 GURL SafeBrowsingProtocolManager::NextChunkUrl(const std::string& url) const { |
| 760 DCHECK(CalledOnValidThread()); | 763 DCHECK(CalledOnValidThread()); |
| 761 std::string next_url; | 764 std::string next_url; |
| 762 if (!base::StartsWith(url, "http://", | 765 if (!base::StartsWith(url, "http://", base::CompareCase::INSENSITIVE_ASCII) && |
| 763 base::CompareCase::INSENSITIVE_ASCII) && | |
| 764 !base::StartsWith(url, "https://", | 766 !base::StartsWith(url, "https://", |
| 765 base::CompareCase::INSENSITIVE_ASCII)) { | 767 base::CompareCase::INSENSITIVE_ASCII)) { |
| 766 // Use https if we updated via https, otherwise http (useful for testing). | 768 // Use https if we updated via https, otherwise http (useful for testing). |
| 767 if (base::StartsWith(url_prefix_, "https://", | 769 if (base::StartsWith(url_prefix_, "https://", |
| 768 base::CompareCase::INSENSITIVE_ASCII)) | 770 base::CompareCase::INSENSITIVE_ASCII)) |
| 769 next_url.append("https://"); | 771 next_url.append("https://"); |
| 770 else | 772 else |
| 771 next_url.append("http://"); | 773 next_url.append("http://"); |
| 772 next_url.append(url); | 774 next_url.append(url); |
| 773 } else { | 775 } else { |
| 774 next_url = url; | 776 next_url = url; |
| 775 } | 777 } |
| 776 if (!additional_query_.empty()) { | 778 if (!additional_query_.empty()) { |
| 777 if (next_url.find("?") != std::string::npos) { | 779 if (next_url.find("?") != std::string::npos) { |
| 778 next_url.append("&"); | 780 next_url.append("&"); |
| 779 } else { | 781 } else { |
| 780 next_url.append("?"); | 782 next_url.append("?"); |
| 781 } | 783 } |
| 782 next_url.append(additional_query_); | 784 next_url.append(additional_query_); |
| 783 } | 785 } |
| 784 return GURL(next_url); | 786 return GURL(next_url); |
| 785 } | 787 } |
| 786 | 788 |
| 787 SafeBrowsingProtocolManager::FullHashDetails::FullHashDetails() | 789 SafeBrowsingProtocolManager::FullHashDetails::FullHashDetails() |
| 788 : callback(), | 790 : callback(), is_download(false) {} |
| 789 is_download(false) { | |
| 790 } | |
| 791 | 791 |
| 792 SafeBrowsingProtocolManager::FullHashDetails::FullHashDetails( | 792 SafeBrowsingProtocolManager::FullHashDetails::FullHashDetails( |
| 793 FullHashCallback callback, bool is_download) | 793 FullHashCallback callback, |
| 794 : callback(callback), | 794 bool is_download) |
| 795 is_download(is_download) { | 795 : callback(callback), is_download(is_download) {} |
| 796 } | |
| 797 | 796 |
| 798 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() { | 797 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() {} |
| 799 } | |
| 800 | 798 |
| 801 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() { | 799 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() {} |
| 802 } | 800 |
| 801 } // namespace safe_browsing |
| OLD | NEW |