OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/predictors/loading_predictor.h" | 5 #include "chrome/browser/predictors/loading_predictor.h" |
6 | 6 |
7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
| 8 #include "base/metrics/histogram_macros.h" |
| 9 #include "chrome/browser/predictors/resource_prefetch_common.h" |
8 #include "chrome/browser/predictors/resource_prefetch_predictor.h" | 10 #include "chrome/browser/predictors/resource_prefetch_predictor.h" |
9 | 11 |
10 namespace predictors { | 12 namespace predictors { |
11 | 13 |
| 14 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; |
| 15 |
12 LoadingPredictor::LoadingPredictor(const LoadingPredictorConfig& config, | 16 LoadingPredictor::LoadingPredictor(const LoadingPredictorConfig& config, |
13 Profile* profile) { | 17 Profile* profile) |
14 resource_prefetch_predictor_ = | 18 : config_(config), |
15 base::MakeUnique<ResourcePrefetchPredictor>(config, profile); | 19 profile_(profile), |
16 } | 20 resource_prefetch_predictor_( |
| 21 base::MakeUnique<ResourcePrefetchPredictor>(config, profile)) {} |
17 | 22 |
18 LoadingPredictor::~LoadingPredictor() = default; | 23 LoadingPredictor::~LoadingPredictor() = default; |
19 | 24 |
20 void LoadingPredictor::PrepareForPageLoad(const GURL& url, HintOrigin origin) { | 25 void LoadingPredictor::PrepareForPageLoad(const GURL& url, HintOrigin origin) { |
21 resource_prefetch_predictor_->StartPrefetching(url, origin); | 26 if (active_hints_.find(url) != active_hints_.end() || |
| 27 !resource_prefetch_predictor_->IsUrlPrefetchable(url)) |
| 28 return; |
| 29 |
| 30 // To report hint durations. |
| 31 active_hints_.emplace(url, base::TimeTicks::Now()); |
| 32 |
| 33 if (config_.IsPrefetchingEnabledForOrigin(profile_, origin)) |
| 34 resource_prefetch_predictor_->StartPrefetching(url); |
22 } | 35 } |
23 | 36 |
24 void LoadingPredictor::CancelPageLoadHint(const GURL& url) { | 37 void LoadingPredictor::CancelPageLoadHint(const GURL& url) { |
25 resource_prefetch_predictor_->StopPrefetching(url); | 38 CancelActiveHint(active_hints_.find(url)); |
26 } | 39 } |
27 | 40 |
28 void LoadingPredictor::StartInitialization() { | 41 void LoadingPredictor::StartInitialization() { |
29 resource_prefetch_predictor_->StartInitialization(); | 42 resource_prefetch_predictor_->StartInitialization(); |
30 } | 43 } |
31 | 44 |
32 ResourcePrefetchPredictor* LoadingPredictor::resource_prefetch_predictor() | 45 ResourcePrefetchPredictor* LoadingPredictor::resource_prefetch_predictor() |
33 const { | 46 const { |
34 return resource_prefetch_predictor_.get(); | 47 return resource_prefetch_predictor_.get(); |
35 } | 48 } |
36 | 49 |
37 void LoadingPredictor::Shutdown() { | 50 void LoadingPredictor::Shutdown() { |
38 resource_prefetch_predictor_->Shutdown(); | 51 resource_prefetch_predictor_->Shutdown(); |
39 } | 52 } |
40 | 53 |
| 54 void LoadingPredictor::OnMainFrameRequest(const URLRequestSummary& summary) { |
| 55 DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME); |
| 56 |
| 57 const NavigationID& navigation_id = summary.navigation_id; |
| 58 CleanupAbandonedHintsAndNavigations(navigation_id); |
| 59 active_navigations_.emplace(navigation_id, navigation_id.main_frame_url); |
| 60 PrepareForPageLoad(navigation_id.main_frame_url, HintOrigin::NAVIGATION); |
| 61 } |
| 62 |
| 63 void LoadingPredictor::OnMainFrameRedirect(const URLRequestSummary& summary) { |
| 64 DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME); |
| 65 |
| 66 auto it = active_navigations_.find(summary.navigation_id); |
| 67 if (it != active_navigations_.end()) { |
| 68 if (summary.navigation_id.main_frame_url == summary.redirect_url) |
| 69 return; |
| 70 NavigationID navigation_id = summary.navigation_id; |
| 71 navigation_id.main_frame_url = summary.redirect_url; |
| 72 active_navigations_.emplace(navigation_id, it->second); |
| 73 active_navigations_.erase(it); |
| 74 } |
| 75 } |
| 76 |
| 77 void LoadingPredictor::OnMainFrameResponse(const URLRequestSummary& summary) { |
| 78 DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME); |
| 79 |
| 80 const NavigationID& navigation_id = summary.navigation_id; |
| 81 auto it = active_navigations_.find(navigation_id); |
| 82 if (it != active_navigations_.end()) { |
| 83 const GURL& initial_url = it->second; |
| 84 CancelPageLoadHint(initial_url); |
| 85 active_navigations_.erase(it); |
| 86 } else { |
| 87 CancelPageLoadHint(navigation_id.main_frame_url); |
| 88 } |
| 89 } |
| 90 |
| 91 std::map<GURL, base::TimeTicks>::iterator LoadingPredictor::CancelActiveHint( |
| 92 std::map<GURL, base::TimeTicks>::iterator hint_it) { |
| 93 if (hint_it == active_hints_.end()) |
| 94 return hint_it; |
| 95 |
| 96 const GURL& url = hint_it->first; |
| 97 resource_prefetch_predictor_->StopPrefetching(url); |
| 98 |
| 99 UMA_HISTOGRAM_TIMES( |
| 100 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, |
| 101 base::TimeTicks::Now() - hint_it->second); |
| 102 return active_hints_.erase(hint_it); |
| 103 } |
| 104 |
| 105 void LoadingPredictor::CleanupAbandonedHintsAndNavigations( |
| 106 const NavigationID& navigation_id) { |
| 107 base::TimeTicks time_now = base::TimeTicks::Now(); |
| 108 const base::TimeDelta max_navigation_age = |
| 109 base::TimeDelta::FromSeconds(config_.max_navigation_lifetime_seconds); |
| 110 |
| 111 // Hints. |
| 112 for (auto it = active_hints_.begin(); it != active_hints_.end();) { |
| 113 base::TimeDelta prefetch_age = time_now - it->second; |
| 114 if (prefetch_age > max_navigation_age) { |
| 115 // Will go to the last bucket in the duration reported in |
| 116 // CancelActiveHint() meaning that the duration was unlimited. |
| 117 it = CancelActiveHint(it); |
| 118 } else { |
| 119 ++it; |
| 120 } |
| 121 } |
| 122 |
| 123 // Navigations. |
| 124 for (auto it = active_navigations_.begin(); |
| 125 it != active_navigations_.end();) { |
| 126 if ((it->first.tab_id == navigation_id.tab_id) || |
| 127 (time_now - it->first.creation_time > max_navigation_age)) { |
| 128 const GURL& initial_url = it->second; |
| 129 CancelActiveHint(active_hints_.find(initial_url)); |
| 130 it = active_navigations_.erase(it); |
| 131 } else { |
| 132 ++it; |
| 133 } |
| 134 } |
| 135 } |
| 136 |
41 } // namespace predictors | 137 } // namespace predictors |
OLD | NEW |