| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/precache/core/precache_fetcher.h" | 5 #include "components/precache/core/precache_fetcher.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 int num_bytes, | 132 int num_bytes, |
| 133 const net::CompletionCallback& callback) override { | 133 const net::CompletionCallback& callback) override { |
| 134 return num_bytes; | 134 return num_bytes; |
| 135 } | 135 } |
| 136 | 136 |
| 137 int Finish(const net::CompletionCallback& callback) override { | 137 int Finish(const net::CompletionCallback& callback) override { |
| 138 return net::OK; | 138 return net::OK; |
| 139 } | 139 } |
| 140 }; | 140 }; |
| 141 | 141 |
| 142 void AppendManifestURLIfNew(const std::string& prefix, |
| 143 const std::string& name, |
| 144 base::hash_set<std::string>* seen_manifest_urls, |
| 145 std::list<GURL>* unique_manifest_urls) { |
| 146 const std::string manifest_url = ConstructManifestURL(prefix, name); |
| 147 bool first_seen = seen_manifest_urls->insert(manifest_url).second; |
| 148 if (first_seen) |
| 149 unique_manifest_urls->push_back(GURL(manifest_url)); |
| 150 } |
| 151 |
| 142 } // namespace | 152 } // namespace |
| 143 | 153 |
| 144 PrecacheFetcher::Fetcher::Fetcher( | 154 PrecacheFetcher::Fetcher::Fetcher( |
| 145 net::URLRequestContextGetter* request_context, | 155 net::URLRequestContextGetter* request_context, |
| 146 const GURL& url, | 156 const GURL& url, |
| 147 const base::Callback<void(const Fetcher&)>& callback, | 157 const base::Callback<void(const Fetcher&)>& callback, |
| 148 bool is_resource_request, | 158 bool is_resource_request, |
| 149 size_t max_bytes) | 159 size_t max_bytes) |
| 150 : request_context_(request_context), | 160 : request_context_(request_context), |
| 151 url_(url), | 161 url_(url), |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 DCHECK(request_context_.get()); // Request context must be non-NULL. | 274 DCHECK(request_context_.get()); // Request context must be non-NULL. |
| 265 DCHECK(precache_delegate_); // Precache delegate must be non-NULL. | 275 DCHECK(precache_delegate_); // Precache delegate must be non-NULL. |
| 266 | 276 |
| 267 DCHECK_NE(GURL(), GetDefaultConfigURL()) | 277 DCHECK_NE(GURL(), GetDefaultConfigURL()) |
| 268 << "Could not determine the precache config settings URL."; | 278 << "Could not determine the precache config settings URL."; |
| 269 DCHECK_NE(std::string(), GetDefaultManifestURLPrefix()) | 279 DCHECK_NE(std::string(), GetDefaultManifestURLPrefix()) |
| 270 << "Could not determine the default precache manifest URL prefix."; | 280 << "Could not determine the default precache manifest URL prefix."; |
| 271 } | 281 } |
| 272 | 282 |
| 273 PrecacheFetcher::~PrecacheFetcher() { | 283 PrecacheFetcher::~PrecacheFetcher() { |
| 284 base::TimeDelta time_to_fetch = base::TimeTicks::Now() - start_time_; |
| 285 UMA_HISTOGRAM_CUSTOM_TIMES("Precache.Fetch.TimeToComplete", time_to_fetch, |
| 286 base::TimeDelta::FromSeconds(1), |
| 287 base::TimeDelta::FromHours(4), 50); |
| 288 |
| 274 // Number of manifests for which we have downloaded all resources. | 289 // Number of manifests for which we have downloaded all resources. |
| 275 int manifests_completed = | 290 int manifests_completed = |
| 276 num_manifest_urls_to_fetch_ - manifest_urls_to_fetch_.size(); | 291 num_manifest_urls_to_fetch_ - manifest_urls_to_fetch_.size(); |
| 277 | 292 |
| 278 // If there are resource URLs left to fetch, the last manifest is not yet | 293 // If there are resource URLs left to fetch, the last manifest is not yet |
| 279 // completed. | 294 // completed. |
| 280 if (!resource_urls_to_fetch_.empty()) | 295 if (!resource_urls_to_fetch_.empty()) |
| 281 --manifests_completed; | 296 --manifests_completed; |
| 282 | 297 |
| 283 DCHECK_GE(manifests_completed, 0); | 298 DCHECK_GE(manifests_completed, 0); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 298 GURL config_url = | 313 GURL config_url = |
| 299 config_url_.is_empty() ? GetDefaultConfigURL() : config_url_; | 314 config_url_.is_empty() ? GetDefaultConfigURL() : config_url_; |
| 300 | 315 |
| 301 DCHECK(config_url.is_valid()) << "Config URL not valid: " | 316 DCHECK(config_url.is_valid()) << "Config URL not valid: " |
| 302 << config_url.possibly_invalid_spec(); | 317 << config_url.possibly_invalid_spec(); |
| 303 | 318 |
| 304 start_time_ = base::TimeTicks::Now(); | 319 start_time_ = base::TimeTicks::Now(); |
| 305 | 320 |
| 306 // Fetch the precache configuration settings from the server. | 321 // Fetch the precache configuration settings from the server. |
| 307 DCHECK(pool_.IsEmpty()) << "All parallel requests should be available"; | 322 DCHECK(pool_.IsEmpty()) << "All parallel requests should be available"; |
| 323 VLOG(3) << "Fetching " << config_url; |
| 308 pool_.Add(scoped_ptr<Fetcher>(new Fetcher( | 324 pool_.Add(scoped_ptr<Fetcher>(new Fetcher( |
| 309 request_context_.get(), config_url, | 325 request_context_.get(), config_url, |
| 310 base::Bind(&PrecacheFetcher::OnConfigFetchComplete, | 326 base::Bind(&PrecacheFetcher::OnConfigFetchComplete, |
| 311 base::Unretained(this)), | 327 base::Unretained(this)), |
| 312 false /* is_resource_request */, std::numeric_limits<int32_t>::max()))); | 328 false /* is_resource_request */, std::numeric_limits<int32_t>::max()))); |
| 313 } | 329 } |
| 314 | 330 |
| 315 void PrecacheFetcher::StartNextResourceFetch() { | 331 void PrecacheFetcher::StartNextResourceFetch() { |
| 316 while (!resource_urls_to_fetch_.empty() && pool_.IsAvailable()) { | 332 while (!resource_urls_to_fetch_.empty() && pool_.IsAvailable()) { |
| 317 const size_t max_bytes = | 333 const size_t max_bytes = |
| 318 std::min(config_->max_bytes_per_resource(), | 334 std::min(config_->max_bytes_per_resource(), |
| 319 config_->max_bytes_total() - total_response_bytes_); | 335 config_->max_bytes_total() - total_response_bytes_); |
| 336 VLOG(3) << "Fetching " << resource_urls_to_fetch_.front(); |
| 320 pool_.Add(scoped_ptr<Fetcher>( | 337 pool_.Add(scoped_ptr<Fetcher>( |
| 321 new Fetcher(request_context_.get(), resource_urls_to_fetch_.front(), | 338 new Fetcher(request_context_.get(), resource_urls_to_fetch_.front(), |
| 322 base::Bind(&PrecacheFetcher::OnResourceFetchComplete, | 339 base::Bind(&PrecacheFetcher::OnResourceFetchComplete, |
| 323 base::Unretained(this)), | 340 base::Unretained(this)), |
| 324 true /* is_resource_request */, max_bytes))); | 341 true /* is_resource_request */, max_bytes))); |
| 325 | 342 |
| 326 resource_urls_to_fetch_.pop_front(); | 343 resource_urls_to_fetch_.pop_front(); |
| 327 } | 344 } |
| 328 } | 345 } |
| 329 | 346 |
| 330 void PrecacheFetcher::StartNextManifestFetch() { | 347 void PrecacheFetcher::StartNextManifestFetch() { |
| 331 if (manifest_urls_to_fetch_.empty()) | 348 if (manifest_urls_to_fetch_.empty()) |
| 332 return; | 349 return; |
| 333 | 350 |
| 334 // We only fetch one manifest at a time to keep the size of | 351 // We only fetch one manifest at a time to keep the size of |
| 335 // resource_urls_to_fetch_ as small as possible. | 352 // resource_urls_to_fetch_ as small as possible. |
| 336 DCHECK(pool_.IsAvailable()) | 353 DCHECK(pool_.IsAvailable()) |
| 337 << "There are no available parallel requests to fetch the next manifest. " | 354 << "There are no available parallel requests to fetch the next manifest. " |
| 338 "Did you forget to call Delete?"; | 355 "Did you forget to call Delete?"; |
| 356 VLOG(3) << "Fetching " << manifest_urls_to_fetch_.front(); |
| 339 pool_.Add(scoped_ptr<Fetcher>(new Fetcher( | 357 pool_.Add(scoped_ptr<Fetcher>(new Fetcher( |
| 340 request_context_.get(), manifest_urls_to_fetch_.front(), | 358 request_context_.get(), manifest_urls_to_fetch_.front(), |
| 341 base::Bind(&PrecacheFetcher::OnManifestFetchComplete, | 359 base::Bind(&PrecacheFetcher::OnManifestFetchComplete, |
| 342 base::Unretained(this)), | 360 base::Unretained(this)), |
| 343 false /* is_resource_request */, std::numeric_limits<int32_t>::max()))); | 361 false /* is_resource_request */, std::numeric_limits<int32_t>::max()))); |
| 344 | 362 |
| 345 manifest_urls_to_fetch_.pop_front(); | 363 manifest_urls_to_fetch_.pop_front(); |
| 346 } | 364 } |
| 347 | 365 |
| 348 void PrecacheFetcher::StartNextFetch() { | 366 void PrecacheFetcher::StartNextFetch() { |
| 349 // If over the precache total size cap, then stop prefetching. | 367 // If over the precache total size cap, then stop prefetching. |
| 350 if (total_response_bytes_ > config_->max_bytes_total()) { | 368 if (total_response_bytes_ > config_->max_bytes_total()) { |
| 351 resource_urls_to_fetch_.clear(); | 369 precache_delegate_->OnDone(); |
| 352 manifest_urls_to_fetch_.clear(); | 370 return; |
| 353 } | 371 } |
| 354 | 372 |
| 355 StartNextResourceFetch(); | 373 StartNextResourceFetch(); |
| 356 StartNextManifestFetch(); | 374 StartNextManifestFetch(); |
| 357 | 375 |
| 358 if (pool_.IsEmpty()) { | 376 if (pool_.IsEmpty()) { |
| 359 // There are no more URLs to fetch, so end the precache cycle. | 377 // There are no more URLs to fetch, so end the precache cycle. |
| 360 base::TimeDelta time_to_fetch = base::TimeTicks::Now() - start_time_; | |
| 361 UMA_HISTOGRAM_CUSTOM_TIMES("Precache.Fetch.TimeToComplete", time_to_fetch, | |
| 362 base::TimeDelta::FromSeconds(1), | |
| 363 base::TimeDelta::FromHours(4), 50); | |
| 364 | |
| 365 precache_delegate_->OnDone(); | 378 precache_delegate_->OnDone(); |
| 366 // OnDone may have deleted this PrecacheFetcher, so don't do anything after | 379 // OnDone may have deleted this PrecacheFetcher, so don't do anything after |
| 367 // it is called. | 380 // it is called. |
| 368 } | 381 } |
| 369 } | 382 } |
| 370 | 383 |
| 371 void PrecacheFetcher::OnConfigFetchComplete(const Fetcher& source) { | 384 void PrecacheFetcher::OnConfigFetchComplete(const Fetcher& source) { |
| 372 UpdateStats(source.response_bytes(), source.network_response_bytes()); | 385 UpdateStats(source.response_bytes(), source.network_response_bytes()); |
| 373 if (source.network_url_fetcher() == nullptr) { | 386 if (source.network_url_fetcher() == nullptr) { |
| 374 pool_.DeleteAll(); // Cancel any other ongoing request. | 387 pool_.DeleteAll(); // Cancel any other ongoing request. |
| 375 } else { | 388 } else { |
| 376 // Attempt to parse the config proto. On failure, continue on with the | 389 // Attempt to parse the config proto. On failure, continue on with the |
| 377 // default configuration. | 390 // default configuration. |
| 378 ParseProtoFromFetchResponse(*source.network_url_fetcher(), config_.get()); | 391 ParseProtoFromFetchResponse(*source.network_url_fetcher(), config_.get()); |
| 379 | 392 |
| 380 std::string prefix = manifest_url_prefix_.empty() | 393 std::string prefix = manifest_url_prefix_.empty() |
| 381 ? GetDefaultManifestURLPrefix() | 394 ? GetDefaultManifestURLPrefix() |
| 382 : manifest_url_prefix_; | 395 : manifest_url_prefix_; |
| 383 DCHECK_NE(std::string(), prefix) | 396 DCHECK_NE(std::string(), prefix) |
| 384 << "Could not determine the precache manifest URL prefix."; | 397 << "Could not determine the precache manifest URL prefix."; |
| 385 | 398 |
| 386 // Keep track of manifest URLs that are being fetched, in order to remove | 399 // Keep track of manifest URLs that are being fetched, in order to elide |
| 387 // duplicates. | 400 // duplicates. |
| 388 base::hash_set<std::string> unique_manifest_urls; | 401 base::hash_set<std::string> seen_manifest_urls; |
| 389 | 402 |
| 390 // Attempt to fetch manifests for starting hosts up to the maximum top sites | 403 // Attempt to fetch manifests for starting hosts up to the maximum top sites |
| 391 // count. If a manifest does not exist for a particular starting host, then | 404 // count. If a manifest does not exist for a particular starting host, then |
| 392 // the fetch will fail, and that starting host will be ignored. | 405 // the fetch will fail, and that starting host will be ignored. |
| 393 int64_t rank = 0; | 406 int64_t rank = 0; |
| 394 for (const std::string& host : starting_hosts_) { | 407 for (const std::string& host : starting_hosts_) { |
| 395 ++rank; | 408 ++rank; |
| 396 if (rank > config_->top_sites_count()) | 409 if (rank > config_->top_sites_count()) |
| 397 break; | 410 break; |
| 398 unique_manifest_urls.insert(ConstructManifestURL(prefix, host)); | 411 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls, |
| 412 &manifest_urls_to_fetch_); |
| 399 } | 413 } |
| 400 | 414 |
| 401 for (const std::string& url : config_->forced_site()) | 415 for (const std::string& host : config_->forced_site()) |
| 402 unique_manifest_urls.insert(ConstructManifestURL(prefix, url)); | 416 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls, |
| 417 &manifest_urls_to_fetch_); |
| 403 | 418 |
| 404 for (const std::string& manifest_url : unique_manifest_urls) | |
| 405 manifest_urls_to_fetch_.push_back(GURL(manifest_url)); | |
| 406 num_manifest_urls_to_fetch_ = manifest_urls_to_fetch_.size(); | 419 num_manifest_urls_to_fetch_ = manifest_urls_to_fetch_.size(); |
| 407 } | 420 } |
| 408 pool_.Delete(source); | 421 pool_.Delete(source); |
| 409 | 422 |
| 410 StartNextFetch(); | 423 StartNextFetch(); |
| 411 } | 424 } |
| 412 | 425 |
| 413 void PrecacheFetcher::OnManifestFetchComplete(const Fetcher& source) { | 426 void PrecacheFetcher::OnManifestFetchComplete(const Fetcher& source) { |
| 414 UpdateStats(source.response_bytes(), source.network_response_bytes()); | 427 UpdateStats(source.response_bytes(), source.network_response_bytes()); |
| 415 if (source.network_url_fetcher() == nullptr) { | 428 if (source.network_url_fetcher() == nullptr) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 440 StartNextFetch(); | 453 StartNextFetch(); |
| 441 } | 454 } |
| 442 | 455 |
| 443 void PrecacheFetcher::UpdateStats(int64_t response_bytes, | 456 void PrecacheFetcher::UpdateStats(int64_t response_bytes, |
| 444 int64_t network_response_bytes) { | 457 int64_t network_response_bytes) { |
| 445 total_response_bytes_ += response_bytes; | 458 total_response_bytes_ += response_bytes; |
| 446 network_response_bytes_ += network_response_bytes; | 459 network_response_bytes_ += network_response_bytes; |
| 447 } | 460 } |
| 448 | 461 |
| 449 } // namespace precache | 462 } // namespace precache |
| OLD | NEW |