Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1059)

Side by Side Diff: components/precache/core/precache_fetcher.cc

Issue 1961153003: Add pause/resume functionality to precache (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added a proto Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
21 #include "components/precache/core/precache_switches.h" 24 #include "components/precache/core/precache_switches.h"
22 #include "components/precache/core/proto/precache.pb.h" 25 #include "components/precache/core/proto/precache.pb.h"
26 #include "components/precache/core/proto/unfinished_work.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"
31 #include "net/url_request/url_request_status.h" 35 #include "net/url_request/url_request_status.h"
32 36
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
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,
268 const PrecacheUnfinishedWork* unfinished_work,
264 PrecacheFetcher::PrecacheDelegate* precache_delegate) 269 PrecacheFetcher::PrecacheDelegate* precache_delegate)
265 : starting_hosts_(starting_hosts), 270 : starting_hosts_(starting_hosts),
266 request_context_(request_context), 271 request_context_(request_context),
272 has_config_(unfinished_work && unfinished_work->has_config_settings()),
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),
271 total_response_bytes_(0), 277 total_response_bytes_(0),
272 network_response_bytes_(0), 278 network_response_bytes_(0),
273 num_manifest_urls_to_fetch_(0), 279 num_manifest_urls_to_fetch_(0),
274 pool_(kMaxParallelFetches) { 280 pool_(kMaxParallelFetches) {
275 DCHECK(request_context_.get()); // Request context must be non-NULL. 281 DCHECK(request_context_.get()); // Request context must be non-NULL.
276 DCHECK(precache_delegate_); // Precache delegate must be non-NULL. 282 DCHECK(precache_delegate_); // Precache delegate must be non-NULL.
277 283
278 DCHECK_NE(GURL(), GetDefaultConfigURL()) 284 DCHECK_NE(GURL(), GetDefaultConfigURL())
279 << "Could not determine the precache config settings URL."; 285 << "Could not determine the precache config settings URL.";
280 DCHECK_NE(std::string(), GetDefaultManifestURLPrefix()) 286 DCHECK_NE(std::string(), GetDefaultManifestURLPrefix())
281 << "Could not determine the default precache manifest URL prefix."; 287 << "Could not determine the default precache manifest URL prefix.";
288
289 if (has_config_)
sclittle 2016/05/19 01:59:45 This seems unnecessary, just check has_config_sett
bengr 2016/05/19 23:19:31 Done.
290 config_->CopyFrom(unfinished_work->config_settings());
291 for (int i = 0; i < unfinished_work->manifest_size(); ++i)
sclittle 2016/05/19 01:59:45 nit: use range-based for, e.g. for (const auto& bl
sclittle 2016/05/19 01:59:45 nit: braces
bengr 2016/05/19 23:19:31 Done.
bengr 2016/05/19 23:19:31 Done.
292 if (unfinished_work->manifest(i).has_url())
293 manifest_urls_to_fetch_.push_back(
294 GURL(unfinished_work->manifest(i).url()));
295 for (int i = 0; i < unfinished_work->resource_size(); ++i) {
296 if (unfinished_work->resource(i).has_url())
297 resource_urls_to_fetch_.push_back(
298 GURL(unfinished_work->resource(i).url()));
299 }
300 if (unfinished_work->has_total_bytes())
301 total_response_bytes_ = unfinished_work->total_bytes();
302 if (unfinished_work->has_network_bytes())
303 network_response_bytes_ = unfinished_work->network_bytes();
304 if (unfinished_work->has_num_manifest_urls())
305 num_manifest_urls_to_fetch_ = unfinished_work->num_manifest_urls();
306 if (unfinished_work->has_start_time())
307 start_time_ = base::Time::FromInternalValue(unfinished_work->start_time());
282 } 308 }
283 309
284 PrecacheFetcher::~PrecacheFetcher() { 310 PrecacheFetcher::~PrecacheFetcher() {
285 base::TimeDelta time_to_fetch = base::TimeTicks::Now() - start_time_; 311 base::TimeDelta time_to_fetch = base::Time::Now() - start_time_;
286 UMA_HISTOGRAM_CUSTOM_TIMES("Precache.Fetch.TimeToComplete", time_to_fetch, 312 UMA_HISTOGRAM_CUSTOM_TIMES("Precache.Fetch.TimeToComplete", time_to_fetch,
287 base::TimeDelta::FromSeconds(1), 313 base::TimeDelta::FromSeconds(1),
288 base::TimeDelta::FromHours(4), 50); 314 base::TimeDelta::FromHours(4), 50);
289 315
290 // Number of manifests for which we have downloaded all resources. 316 // Number of manifests for which we have downloaded all resources.
291 int manifests_completed = 317 int manifests_completed =
292 num_manifest_urls_to_fetch_ - manifest_urls_to_fetch_.size(); 318 num_manifest_urls_to_fetch_ - manifest_urls_to_fetch_.size();
293 319
294 // If there are resource URLs left to fetch, the last manifest is not yet 320 // If there are resource URLs left to fetch, the last manifest is not yet
295 // completed. 321 // completed.
296 if (!resource_urls_to_fetch_.empty()) 322 if (!resource_urls_to_fetch_.empty())
297 --manifests_completed; 323 --manifests_completed;
298 324
299 DCHECK_GE(manifests_completed, 0); 325 DCHECK_GE(manifests_completed, 0);
300 int percent_completed = num_manifest_urls_to_fetch_ == 0 326 int percent_completed = num_manifest_urls_to_fetch_ == 0
301 ? 0 327 ? 0
302 : (static_cast<double>(manifests_completed) / 328 : (static_cast<double>(manifests_completed) /
303 num_manifest_urls_to_fetch_ * 100); 329 num_manifest_urls_to_fetch_ * 100);
304 UMA_HISTOGRAM_PERCENTAGE("Precache.Fetch.PercentCompleted", 330 UMA_HISTOGRAM_PERCENTAGE("Precache.Fetch.PercentCompleted",
305 percent_completed); 331 percent_completed);
306 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Total", 332 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Total",
307 total_response_bytes_, 1, kMaxResponseBytes, 100); 333 total_response_bytes_, 1, kMaxResponseBytes, 100);
308 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Network", 334 UMA_HISTOGRAM_CUSTOM_COUNTS("Precache.Fetch.ResponseBytes.Network",
309 network_response_bytes_, 1, kMaxResponseBytes, 335 network_response_bytes_, 1, kMaxResponseBytes,
310 100); 336 100);
311 } 337 }
312 338
339 std::unique_ptr<PrecacheUnfinishedWork> PrecacheFetcher::GetUnfinishedWork() {
340 std::unique_ptr<PrecacheUnfinishedWork> unfinished_work(
341 new PrecacheUnfinishedWork());
342 if (has_config_)
343 unfinished_work->mutable_config_settings()->CopyFrom(*(config_.get()));
344 for (const auto& manifest : manifest_urls_to_fetch_)
345 unfinished_work->add_manifest()->set_url(manifest.spec());
346 for (const auto& resource : resource_urls_to_fetch_)
347 unfinished_work->add_resource()->set_url(resource.spec());
348 unfinished_work->set_total_bytes(total_response_bytes_);
349 unfinished_work->set_network_bytes(network_response_bytes_);
350 unfinished_work->set_num_manifest_urls(num_manifest_urls_to_fetch_);
351 unfinished_work->set_start_time(start_time_.ToInternalValue());
352 return unfinished_work;
353 }
354
313 void PrecacheFetcher::Start() { 355 void PrecacheFetcher::Start() {
356 if (has_config_) {
357 DetermineManifests();
358 return;
359 }
360
314 GURL config_url = 361 GURL config_url =
315 config_url_.is_empty() ? GetDefaultConfigURL() : config_url_; 362 config_url_.is_empty() ? GetDefaultConfigURL() : config_url_;
316 363
317 DCHECK(config_url.is_valid()) << "Config URL not valid: " 364 DCHECK(config_url.is_valid()) << "Config URL not valid: "
318 << config_url.possibly_invalid_spec(); 365 << config_url.possibly_invalid_spec();
319 366
320 start_time_ = base::TimeTicks::Now(); 367 start_time_ = base::Time::Now();
321 368
322 // Fetch the precache configuration settings from the server. 369 // Fetch the precache configuration settings from the server.
323 DCHECK(pool_.IsEmpty()) << "All parallel requests should be available"; 370 DCHECK(pool_.IsEmpty()) << "All parallel requests should be available";
324 VLOG(3) << "Fetching " << config_url; 371 VLOG(3) << "Fetching " << config_url;
325 pool_.Add(base::WrapUnique(new Fetcher( 372 pool_.Add(base::WrapUnique(new Fetcher(
326 request_context_.get(), config_url, 373 request_context_.get(), config_url,
327 base::Bind(&PrecacheFetcher::OnConfigFetchComplete, 374 base::Bind(&PrecacheFetcher::OnConfigFetchComplete,
328 base::Unretained(this)), 375 base::Unretained(this)),
329 false /* is_resource_request */, std::numeric_limits<int32_t>::max()))); 376 false /* is_resource_request */, std::numeric_limits<int32_t>::max())));
330 } 377 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 413
367 void PrecacheFetcher::StartNextFetch() { 414 void PrecacheFetcher::StartNextFetch() {
368 // If over the precache total size cap, then stop prefetching. 415 // If over the precache total size cap, then stop prefetching.
369 if (total_response_bytes_ > config_->max_bytes_total()) { 416 if (total_response_bytes_ > config_->max_bytes_total()) {
370 precache_delegate_->OnDone(); 417 precache_delegate_->OnDone();
371 return; 418 return;
372 } 419 }
373 420
374 StartNextResourceFetch(); 421 StartNextResourceFetch();
375 StartNextManifestFetch(); 422 StartNextManifestFetch();
376
377 if (pool_.IsEmpty()) { 423 if (pool_.IsEmpty()) {
378 // There are no more URLs to fetch, so end the precache cycle. 424 // There are no more URLs to fetch, so end the precache cycle.
379 precache_delegate_->OnDone(); 425 precache_delegate_->OnDone();
380 // OnDone may have deleted this PrecacheFetcher, so don't do anything after 426 // OnDone may have deleted this PrecacheFetcher, so don't do anything after
381 // it is called. 427 // it is called.
382 } 428 }
383 } 429 }
384 430
385 void PrecacheFetcher::OnConfigFetchComplete(const Fetcher& source) { 431 void PrecacheFetcher::OnConfigFetchComplete(const Fetcher& source) {
386 UpdateStats(source.response_bytes(), source.network_response_bytes()); 432 UpdateStats(source.response_bytes(), source.network_response_bytes());
387 if (source.network_url_fetcher() == nullptr) { 433 if (source.network_url_fetcher() == nullptr) {
388 pool_.DeleteAll(); // Cancel any other ongoing request. 434 pool_.DeleteAll(); // Cancel any other ongoing request.
389 } else { 435 } else {
390 // Attempt to parse the config proto. On failure, continue on with the 436 // Attempt to parse the config proto. On failure, continue on with the
391 // default configuration. 437 // default configuration.
392 ParseProtoFromFetchResponse(*source.network_url_fetcher(), config_.get()); 438 has_config_ =
439 ParseProtoFromFetchResponse(
440 *source.network_url_fetcher(), config_.get());
441 pool_.Delete(source);
442 DetermineManifests();
443 }
444 }
393 445
446 void PrecacheFetcher::DetermineManifests() {
394 std::string prefix = manifest_url_prefix_.empty() 447 std::string prefix = manifest_url_prefix_.empty()
395 ? GetDefaultManifestURLPrefix() 448 ? GetDefaultManifestURLPrefix()
396 : manifest_url_prefix_; 449 : manifest_url_prefix_;
397 DCHECK_NE(std::string(), prefix) 450 DCHECK_NE(std::string(), prefix)
398 << "Could not determine the precache manifest URL prefix."; 451 << "Could not determine the precache manifest URL prefix.";
399 452
400 // Keep track of manifest URLs that are being fetched, in order to elide 453 // Keep track of manifest URLs that are being fetched, in order to elide
401 // duplicates. 454 // duplicates.
402 base::hash_set<std::string> seen_manifest_urls; 455 base::hash_set<std::string> seen_manifest_urls;
403 456
404 // Attempt to fetch manifests for starting hosts up to the maximum top sites 457 // 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 458 // 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. 459 // the fetch will fail, and that starting host will be ignored. Starting
407 int64_t rank = 0; 460 // hosts are not added if this is a continuation from a previous precache
408 for (const std::string& host : starting_hosts_) { 461 // session.
409 ++rank; 462 if (manifest_urls_to_fetch_.empty() &&
410 if (rank > config_->top_sites_count()) 463 resource_urls_to_fetch_.empty()) {
411 break; 464 int64_t rank = 0;
412 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls, 465 for (const std::string& host : starting_hosts_) {
413 &manifest_urls_to_fetch_); 466 ++rank;
467 if (rank > config_->top_sites_count())
468 break;
469 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls,
470 &manifest_urls_to_fetch_);
471 }
472
473 for (const std::string& host : config_->forced_site()) {
474 AppendManifestURLIfNew(prefix, host, &seen_manifest_urls,
475 &manifest_urls_to_fetch_);
476 }
414 } 477 }
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(); 478 num_manifest_urls_to_fetch_ = manifest_urls_to_fetch_.size();
421 } 479 StartNextFetch();
422 pool_.Delete(source);
423
424 StartNextFetch();
425 } 480 }
426 481
427 void PrecacheFetcher::OnManifestFetchComplete(const Fetcher& source) { 482 void PrecacheFetcher::OnManifestFetchComplete(const Fetcher& source) {
428 UpdateStats(source.response_bytes(), source.network_response_bytes()); 483 UpdateStats(source.response_bytes(), source.network_response_bytes());
429 if (source.network_url_fetcher() == nullptr) { 484 if (source.network_url_fetcher() == nullptr) {
430 pool_.DeleteAll(); // Cancel any other ongoing request. 485 pool_.DeleteAll(); // Cancel any other ongoing request.
431 } else { 486 } else {
432 PrecacheManifest manifest; 487 PrecacheManifest manifest;
433 488
434 if (ParseProtoFromFetchResponse(*source.network_url_fetcher(), &manifest)) { 489 if (ParseProtoFromFetchResponse(*source.network_url_fetcher(), &manifest)) {
435 const int32_t len = 490 const int32_t len =
436 std::min(manifest.resource_size(), config_->top_resources_count()); 491 std::min(manifest.resource_size(), config_->top_resources_count());
437 for (int i = 0; i < len; ++i) { 492 for (int i = 0; i < len; ++i) {
438 if (manifest.resource(i).has_url()) { 493 if (manifest.resource(i).has_url())
439 resource_urls_to_fetch_.push_back(GURL(manifest.resource(i).url())); 494 resource_urls_to_fetch_.push_back(GURL(manifest.resource(i).url()));
440 }
441 } 495 }
442 } 496 }
443 } 497 }
444 498
445 pool_.Delete(source); 499 pool_.Delete(source);
446 StartNextFetch(); 500 StartNextFetch();
447 } 501 }
448 502
449 void PrecacheFetcher::OnResourceFetchComplete(const Fetcher& source) { 503 void PrecacheFetcher::OnResourceFetchComplete(const Fetcher& source) {
450 UpdateStats(source.response_bytes(), source.network_response_bytes()); 504 UpdateStats(source.response_bytes(), source.network_response_bytes());
451 pool_.Delete(source); 505 pool_.Delete(source);
452 // The resource has already been put in the cache during the fetch process, so 506 // The resource has already been put in the cache during the fetch process, so
453 // nothing more needs to be done for the resource. 507 // nothing more needs to be done for the resource.
454 StartNextFetch(); 508 StartNextFetch();
455 } 509 }
456 510
457 void PrecacheFetcher::UpdateStats(int64_t response_bytes, 511 void PrecacheFetcher::UpdateStats(int64_t response_bytes,
458 int64_t network_response_bytes) { 512 int64_t network_response_bytes) {
459 total_response_bytes_ += response_bytes; 513 total_response_bytes_ += response_bytes;
460 network_response_bytes_ += network_response_bytes; 514 network_response_bytes_ += network_response_bytes;
461 } 515 }
462 516
517 void PrecacheFetcher::AssignWorkForTest(const std::list<GURL>& manifests,
518 const std::list<GURL>& resources,
519 size_t total_response_bytes,
520 size_t network_response_bytes,
521 size_t num_manifest_urls_to_fetch,
522 const base::Time& start_time) {
523 DCHECK(manifest_urls_to_fetch_.empty());
524 DCHECK(resource_urls_to_fetch_.empty());
525 manifest_urls_to_fetch_ = manifests;
526 resource_urls_to_fetch_ = resources;
527 total_response_bytes_ = total_response_bytes;
528 network_response_bytes_ = network_response_bytes;
529 num_manifest_urls_to_fetch_ = num_manifest_urls_to_fetch;
530 start_time_ = start_time;
531 }
532
463 } // namespace precache 533 } // namespace precache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698