Chromium Code Reviews| 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> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/bind_helpers.h" | |
| 14 #include "base/callback.h" | 15 #include "base/callback.h" |
| 15 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 16 #include "base/compiler_specific.h" | 17 #include "base/compiler_specific.h" |
| 17 #include "base/containers/hash_tables.h" | 18 #include "base/containers/hash_tables.h" |
| 19 #include "base/location.h" | |
| 18 #include "base/logging.h" | 20 #include "base/logging.h" |
| 19 #include "base/memory/ptr_util.h" | 21 #include "base/memory/ptr_util.h" |
| 22 #include "base/memory/ref_counted.h" | |
| 20 #include "base/metrics/histogram_macros.h" | 23 #include "base/metrics/histogram_macros.h" |
| 24 #include "components/precache/core/precache_database.h" | |
| 21 #include "components/precache/core/precache_switches.h" | 25 #include "components/precache/core/precache_switches.h" |
| 22 #include "components/precache/core/proto/precache.pb.h" | 26 #include "components/precache/core/proto/precache.pb.h" |
| 23 #include "net/base/completion_callback.h" | 27 #include "net/base/completion_callback.h" |
| 24 #include "net/base/escape.h" | 28 #include "net/base/escape.h" |
| 25 #include "net/base/io_buffer.h" | 29 #include "net/base/io_buffer.h" |
| 26 #include "net/base/load_flags.h" | 30 #include "net/base/load_flags.h" |
| 27 #include "net/base/net_errors.h" | 31 #include "net/base/net_errors.h" |
| 28 #include "net/http/http_response_headers.h" | 32 #include "net/http/http_response_headers.h" |
| 29 #include "net/url_request/url_fetcher_response_writer.h" | 33 #include "net/url_request/url_fetcher_response_writer.h" |
| 30 #include "net/url_request/url_request_context_getter.h" | 34 #include "net/url_request/url_request_context_getter.h" |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 254 response_bytes_ = source->GetReceivedResponseContentLength(); | 258 response_bytes_ = source->GetReceivedResponseContentLength(); |
| 255 network_response_bytes_ = source->GetTotalReceivedBytes(); | 259 network_response_bytes_ = source->GetTotalReceivedBytes(); |
| 256 callback_.Run(*this); | 260 callback_.Run(*this); |
| 257 } | 261 } |
| 258 | 262 |
| 259 PrecacheFetcher::PrecacheFetcher( | 263 PrecacheFetcher::PrecacheFetcher( |
| 260 const std::vector<std::string>& starting_hosts, | 264 const std::vector<std::string>& starting_hosts, |
| 261 net::URLRequestContextGetter* request_context, | 265 net::URLRequestContextGetter* request_context, |
| 262 const GURL& config_url, | 266 const GURL& config_url, |
| 263 const std::string& manifest_url_prefix, | 267 const std::string& manifest_url_prefix, |
| 264 PrecacheFetcher::PrecacheDelegate* precache_delegate) | 268 PrecacheFetcher::PrecacheDelegate* precache_delegate, |
| 269 base::WeakPtr<PrecacheDatabase> precache_database, | |
| 270 scoped_refptr<base::SingleThreadTaskRunner> database_task_runner) | |
| 265 : starting_hosts_(starting_hosts), | 271 : starting_hosts_(starting_hosts), |
| 266 request_context_(request_context), | 272 request_context_(request_context), |
| 267 config_url_(config_url), | 273 config_url_(config_url), |
| 268 manifest_url_prefix_(manifest_url_prefix), | 274 manifest_url_prefix_(manifest_url_prefix), |
| 269 precache_delegate_(precache_delegate), | 275 precache_delegate_(precache_delegate), |
| 270 config_(new PrecacheConfigurationSettings), | 276 config_(new PrecacheConfigurationSettings), |
| 277 precache_database_(precache_database), | |
| 278 database_task_runner_(database_task_runner), | |
| 271 total_response_bytes_(0), | 279 total_response_bytes_(0), |
| 272 network_response_bytes_(0), | 280 network_response_bytes_(0), |
| 273 num_manifest_urls_to_fetch_(0), | 281 num_manifest_urls_to_fetch_(0), |
| 274 pool_(kMaxParallelFetches) { | 282 pool_(kMaxParallelFetches) { |
| 275 DCHECK(request_context_.get()); // Request context must be non-NULL. | 283 DCHECK(request_context_.get()); // Request context must be non-NULL. |
| 276 DCHECK(precache_delegate_); // Precache delegate must be non-NULL. | 284 DCHECK(precache_delegate_); // Precache delegate must be non-NULL. |
| 277 | 285 |
| 278 DCHECK_NE(GURL(), GetDefaultConfigURL()) | 286 DCHECK_NE(GURL(), GetDefaultConfigURL()) |
| 279 << "Could not determine the precache config settings URL."; | 287 << "Could not determine the precache config settings URL."; |
| 280 DCHECK_NE(std::string(), GetDefaultManifestURLPrefix()) | 288 DCHECK_NE(std::string(), GetDefaultManifestURLPrefix()) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 303 num_manifest_urls_to_fetch_ * 100); | 311 num_manifest_urls_to_fetch_ * 100); |
| 304 UMA_HISTOGRAM_PERCENTAGE("Precache.Fetch.PercentCompleted", | 312 UMA_HISTOGRAM_PERCENTAGE("Precache.Fetch.PercentCompleted", |
| 305 percent_completed); | 313 percent_completed); |
| 306 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Total", | 314 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Total", |
| 307 total_response_bytes_, 1, kMaxResponseBytes, 100); | 315 total_response_bytes_, 1, kMaxResponseBytes, 100); |
| 308 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Network", | 316 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Network", |
| 309 network_response_bytes_, 1, kMaxResponseBytes, | 317 network_response_bytes_, 1, kMaxResponseBytes, |
| 310 100); | 318 100); |
| 311 } | 319 } |
| 312 | 320 |
| 321 | |
| 322 | |
| 323 | |
| 324 void PrecacheFetcher::Init( | |
| 325 const base::TimeDelta& max_age) { | |
| 326 // Fetch unfinished work that is no older than |max_age|. | |
| 327 scoped_refptr<UnfinishedWork> unfinished_work = | |
| 328 new UnfinishedWork(base::TimeTicks::Now() - max_age); | |
| 329 database_task_runner_->PostTaskAndReply( | |
|
sclittle
2016/05/10 00:01:26
I'm not sure that UnfinishedWork needs to be refco
bengr
2016/05/19 01:25:44
Done.
| |
| 330 FROM_HERE, | |
| 331 base::Bind(&PrecacheDatabase::GetUnfinishedWork, precache_database_, | |
| 332 unfinished_work), | |
| 333 base::Bind(&PrecacheFetcher::OnInitDone, AsWeakPtr(), | |
| 334 unfinished_work)); | |
| 335 } | |
| 336 | |
| 337 void PrecacheFetcher::OnInitDone( | |
| 338 scoped_refptr<UnfinishedWork> unfinished_work) { | |
| 339 if (unfinished_work->manifests.empty() && | |
| 340 unfinished_work->resources.empty()) { | |
| 341 if (unfinished_work->total_bytes > 0) { | |
| 342 //TODO(rajendrant): report expired unfinished job. | |
|
sclittle
2016/05/10 00:01:26
nit: add space between "//" and "TODO", and capita
bengr
2016/05/19 01:25:44
Done.
| |
| 343 } | |
| 344 } else { | |
| 345 // Starting hosts are cleared because this is a continuation. | |
| 346 manifest_urls_to_fetch_ = unfinished_work->manifests; | |
|
sclittle
2016/05/10 00:01:26
Use std::move on the lists here to avoid copying t
bengr
2016/05/19 01:25:44
Done.
| |
| 347 resource_urls_to_fetch_ = unfinished_work->resources; | |
| 348 total_response_bytes_ = unfinished_work->total_bytes; | |
| 349 network_response_bytes_ = unfinished_work->network_bytes; | |
| 350 num_manifest_urls_to_fetch_ = unfinished_work->num_manifest_urls; | |
| 351 start_time_ = unfinished_work->start_time; | |
| 352 } | |
| 353 precache_delegate_->OnInitDone(); | |
| 354 } | |
| 355 | |
| 356 void PrecacheFetcher::Shutdown() { | |
| 357 scoped_refptr<UnfinishedWork> unfinished_work = new UnfinishedWork( | |
| 358 manifest_urls_to_fetch_, resource_urls_to_fetch_, | |
| 359 total_response_bytes_, network_response_bytes_, | |
| 360 num_manifest_urls_to_fetch_, start_time_); | |
| 361 database_task_runner_->PostTaskAndReply( | |
| 362 FROM_HERE, | |
| 363 base::Bind(&PrecacheDatabase::SaveUnfinishedWork, precache_database_, | |
| 364 unfinished_work), | |
| 365 base::Bind(&PrecacheFetcher::OnShutdownDone, AsWeakPtr())); | |
| 366 } | |
| 367 | |
| 368 void PrecacheFetcher::OnShutdownDone() { | |
| 369 precache_delegate_->OnShutdownDone(); | |
| 370 } | |
| 371 | |
| 313 void PrecacheFetcher::Start() { | 372 void PrecacheFetcher::Start() { |
| 314 GURL config_url = | 373 GURL config_url = |
| 315 config_url_.is_empty() ? GetDefaultConfigURL() : config_url_; | 374 config_url_.is_empty() ? GetDefaultConfigURL() : config_url_; |
| 316 | 375 |
| 317 DCHECK(config_url.is_valid()) << "Config URL not valid: " | 376 DCHECK(config_url.is_valid()) << "Config URL not valid: " |
| 318 << config_url.possibly_invalid_spec(); | 377 << config_url.possibly_invalid_spec(); |
| 319 | 378 |
| 320 start_time_ = base::TimeTicks::Now(); | 379 if (start_time_.is_null()) |
| 380 start_time_ = base::TimeTicks::Now(); | |
| 321 | 381 |
| 322 // Fetch the precache configuration settings from the server. | 382 // Fetch the precache configuration settings from the server. |
| 323 DCHECK(pool_.IsEmpty()) << "All parallel requests should be available"; | 383 DCHECK(pool_.IsEmpty()) << "All parallel requests should be available"; |
| 324 VLOG(3) << "Fetching " << config_url; | 384 VLOG(3) << "Fetching " << config_url; |
| 325 pool_.Add(base::WrapUnique(new Fetcher( | 385 pool_.Add(base::WrapUnique(new Fetcher( |
| 326 request_context_.get(), config_url, | 386 request_context_.get(), config_url, |
| 327 base::Bind(&PrecacheFetcher::OnConfigFetchComplete, | 387 base::Bind(&PrecacheFetcher::OnConfigFetchComplete, |
| 328 base::Unretained(this)), | 388 base::Unretained(this)), |
| 329 false /* is_resource_request */, std::numeric_limits<int32_t>::max()))); | 389 false /* is_resource_request */, std::numeric_limits<int32_t>::max()))); |
| 330 } | 390 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 : manifest_url_prefix_; | 456 : manifest_url_prefix_; |
| 397 DCHECK_NE(std::string(), prefix) | 457 DCHECK_NE(std::string(), prefix) |
| 398 << "Could not determine the precache manifest URL prefix."; | 458 << "Could not determine the precache manifest URL prefix."; |
| 399 | 459 |
| 400 // Keep track of manifest URLs that are being fetched, in order to elide | 460 // Keep track of manifest URLs that are being fetched, in order to elide |
| 401 // duplicates. | 461 // duplicates. |
| 402 base::hash_set<std::string> seen_manifest_urls; | 462 base::hash_set<std::string> seen_manifest_urls; |
| 403 | 463 |
| 404 // Attempt to fetch manifests for starting hosts up to the maximum top sites | 464 // Attempt to fetch manifests for starting hosts up to the maximum top sites |
| 405 // count. If a manifest does not exist for a particular starting host, then | 465 // count. If a manifest does not exist for a particular starting host, then |
| 406 // the fetch will fail, and that starting host will be ignored. | 466 // the fetch will fail, and that starting host will be ignored. Starting |
| 407 int64_t rank = 0; | 467 // hosts are not added if this is a continuation from a previous precache |
| 408 for (const std::string& host : starting_hosts_) { | 468 // session. |
| 409 ++rank; | 469 if (manifest_urls_to_fetch_.empty()) { |
|
sclittle
2016/05/10 00:01:26
What about if the UnfinishedWork already finished
bengr
2016/05/19 01:25:44
Good catch. Thanks.
| |
| 410 if (rank > config_->top_sites_count()) | 470 int64_t rank = 0; |
| 411 break; | 471 for (const std::string& host : starting_hosts_) { |
| 412 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls, | 472 ++rank; |
| 413 &manifest_urls_to_fetch_); | 473 if (rank > config_->top_sites_count()) |
| 474 break; | |
| 475 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls, | |
| 476 &manifest_urls_to_fetch_); | |
| 477 } | |
| 478 | |
| 479 for (const std::string& host : config_->forced_site()) { | |
| 480 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls, | |
| 481 &manifest_urls_to_fetch_); | |
| 482 } | |
| 414 } | 483 } |
| 415 | |
| 416 for (const std::string& host : config_->forced_site()) | |
| 417 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls, | |
| 418 &manifest_urls_to_fetch_); | |
| 419 | |
| 420 num_manifest_urls_to_fetch_ = manifest_urls_to_fetch_.size(); | 484 num_manifest_urls_to_fetch_ = manifest_urls_to_fetch_.size(); |
| 421 } | 485 } |
| 422 pool_.Delete(source); | 486 pool_.Delete(source); |
| 423 | 487 |
| 424 StartNextFetch(); | 488 StartNextFetch(); |
| 425 } | 489 } |
| 426 | 490 |
| 427 void PrecacheFetcher::OnManifestFetchComplete(const Fetcher& source) { | 491 void PrecacheFetcher::OnManifestFetchComplete(const Fetcher& source) { |
| 428 UpdateStats(source.response_bytes(), source.network_response_bytes()); | 492 UpdateStats(source.response_bytes(), source.network_response_bytes()); |
| 429 if (source.network_url_fetcher() == nullptr) { | 493 if (source.network_url_fetcher() == nullptr) { |
| 430 pool_.DeleteAll(); // Cancel any other ongoing request. | 494 pool_.DeleteAll(); // Cancel any other ongoing request. |
| 431 } else { | 495 } else { |
| 432 PrecacheManifest manifest; | 496 PrecacheManifest manifest; |
| 433 | 497 |
| 434 if (ParseProtoFromFetchResponse(*source.network_url_fetcher(), &manifest)) { | 498 if (ParseProtoFromFetchResponse(*source.network_url_fetcher(), &manifest)) { |
| 435 const int32_t len = | 499 const int32_t len = |
| 436 std::min(manifest.resource_size(), config_->top_resources_count()); | 500 std::min(manifest.resource_size(), config_->top_resources_count()); |
| 437 for (int i = 0; i < len; ++i) { | 501 for (int i = 0; i < len; ++i) { |
| 438 if (manifest.resource(i).has_url()) { | 502 if (manifest.resource(i).has_url()) |
| 439 resource_urls_to_fetch_.push_back(GURL(manifest.resource(i).url())); | 503 resource_urls_to_fetch_.push_back(GURL(manifest.resource(i).url())); |
| 440 } | |
| 441 } | 504 } |
| 442 } | 505 } |
| 443 } | 506 } |
| 444 | 507 |
| 445 pool_.Delete(source); | 508 pool_.Delete(source); |
| 446 StartNextFetch(); | 509 StartNextFetch(); |
| 447 } | 510 } |
| 448 | 511 |
| 449 void PrecacheFetcher::OnResourceFetchComplete(const Fetcher& source) { | 512 void PrecacheFetcher::OnResourceFetchComplete(const Fetcher& source) { |
| 450 UpdateStats(source.response_bytes(), source.network_response_bytes()); | 513 UpdateStats(source.response_bytes(), source.network_response_bytes()); |
| 451 pool_.Delete(source); | 514 pool_.Delete(source); |
| 452 // The resource has already been put in the cache during the fetch process, so | 515 // The resource has already been put in the cache during the fetch process, so |
| 453 // nothing more needs to be done for the resource. | 516 // nothing more needs to be done for the resource. |
| 454 StartNextFetch(); | 517 StartNextFetch(); |
| 455 } | 518 } |
| 456 | 519 |
| 457 void PrecacheFetcher::UpdateStats(int64_t response_bytes, | 520 void PrecacheFetcher::UpdateStats(int64_t response_bytes, |
| 458 int64_t network_response_bytes) { | 521 int64_t network_response_bytes) { |
| 459 total_response_bytes_ += response_bytes; | 522 total_response_bytes_ += response_bytes; |
| 460 network_response_bytes_ += network_response_bytes; | 523 network_response_bytes_ += network_response_bytes; |
| 461 } | 524 } |
| 462 | 525 |
| 526 void PrecacheFetcher::AssignWorkForTest(const std::list<GURL>& manifests, | |
| 527 const std::list<GURL>& resources, | |
| 528 size_t total_response_bytes, | |
| 529 size_t network_response_bytes, | |
| 530 int num_manifest_urls_to_fetch, | |
| 531 const base::TimeTicks& start_time) { | |
| 532 DCHECK(manifest_urls_to_fetch_.empty()); | |
| 533 DCHECK(resource_urls_to_fetch_.empty()); | |
| 534 manifest_urls_to_fetch_ = manifests; | |
| 535 resource_urls_to_fetch_ = resources; | |
| 536 total_response_bytes_ = total_response_bytes; | |
| 537 network_response_bytes_ = network_response_bytes; | |
| 538 num_manifest_urls_to_fetch_ = num_manifest_urls_to_fetch; | |
| 539 start_time_ = start_time; | |
| 540 } | |
| 541 | |
| 463 } // namespace precache | 542 } // namespace precache |
| OLD | NEW |