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 |