Fix waterfall bots to not use fastbuild and add presubmit validation.
[chromium-blink-merge.git] / components / precache / content / precache_manager.cc
blobdc673c62c4d6d88661fe355c57c6db1035fe419b
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
3 // found in the LICENSE file.
5 #include "components/precache/content/precache_manager.h"
7 #include <string>
8 #include <utility>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/files/file_path.h"
14 #include "base/logging.h"
15 #include "base/metrics/field_trial.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/time/time.h"
18 #include "components/history/core/browser/history_service.h"
19 #include "components/precache/core/precache_database.h"
20 #include "components/precache/core/precache_switches.h"
21 #include "components/sync_driver/sync_service.h"
22 #include "components/variations/variations_associated_data.h"
23 #include "content/public/browser/browser_context.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "net/base/network_change_notifier.h"
27 using content::BrowserThread;
29 namespace {
31 const char kPrecacheFieldTrialName[] = "Precache";
32 const char kPrecacheFieldTrialEnabledGroup[] = "Enabled";
33 const char kManifestURLPrefixParam[] = "manifest_url_prefix";
34 const int kNumTopHosts = 100;
36 } // namespace
38 namespace precache {
40 int NumTopHosts() {
41 return kNumTopHosts;
44 PrecacheManager::PrecacheManager(
45 content::BrowserContext* browser_context,
46 const sync_driver::SyncService* const sync_service,
47 const history::HistoryService* const history_service)
48 : browser_context_(browser_context),
49 sync_service_(sync_service),
50 history_service_(history_service),
51 precache_database_(new PrecacheDatabase()),
52 is_precaching_(false) {
53 base::FilePath db_path(browser_context_->GetPath().Append(
54 base::FilePath(FILE_PATH_LITERAL("PrecacheDatabase"))));
56 BrowserThread::PostTask(
57 BrowserThread::DB, FROM_HERE,
58 base::Bind(base::IgnoreResult(&PrecacheDatabase::Init),
59 precache_database_, db_path));
62 PrecacheManager::~PrecacheManager() {}
64 bool PrecacheManager::ShouldRun() const {
65 // Verify PrecachingAllowed() before calling IsPrecachingEnabled(). This is
66 // because field trials are only assigned when requested. This allows us to
67 // create Control and Experiment groups that are limited to users for whom
68 // PrecachingAllowed() is true, thus accentuating the impact of precaching.
69 return PrecachingAllowed() == AllowedType::ALLOWED && IsPrecachingEnabled();
72 bool PrecacheManager::WouldRun() const {
73 return PrecachingAllowed() == AllowedType::ALLOWED;
76 // static
77 bool PrecacheManager::IsPrecachingEnabled() {
78 return base::FieldTrialList::FindFullName(kPrecacheFieldTrialName) ==
79 kPrecacheFieldTrialEnabledGroup ||
80 base::CommandLine::ForCurrentProcess()->HasSwitch(
81 switches::kEnablePrecache);
84 PrecacheManager::AllowedType PrecacheManager::PrecachingAllowed() const {
85 if (!(sync_service_ && sync_service_->backend_initialized()))
86 return AllowedType::PENDING;
88 // SyncService delegates to SyncPrefs, which must be called on the UI thread.
89 if (sync_service_->GetActiveDataTypes().Has(syncer::SESSIONS) &&
90 !sync_service_->GetEncryptedDataTypes().Has(syncer::SESSIONS))
91 return AllowedType::ALLOWED;
93 return AllowedType::DISALLOWED;
96 void PrecacheManager::StartPrecaching(
97 const PrecacheCompletionCallback& precache_completion_callback) {
98 DCHECK_CURRENTLY_ON(BrowserThread::UI);
100 if (is_precaching_) {
101 DLOG(WARNING) << "Cannot start precaching because precaching is already "
102 "in progress.";
103 return;
105 precache_completion_callback_ = precache_completion_callback;
107 if (history_service_ && ShouldRun()) {
108 is_precaching_ = true;
110 BrowserThread::PostTask(
111 BrowserThread::DB, FROM_HERE,
112 base::Bind(&PrecacheDatabase::DeleteExpiredPrecacheHistory,
113 precache_database_, base::Time::Now()));
115 // Request NumTopHosts() top hosts. Note that PrecacheFetcher is further
116 // bound by the value of PrecacheConfigurationSettings.top_sites_count, as
117 // retrieved from the server.
118 history_service_->TopHosts(
119 NumTopHosts(),
120 base::Bind(&PrecacheManager::OnHostsReceived, AsWeakPtr()));
121 } else {
122 if (PrecachingAllowed() != AllowedType::PENDING) {
123 // We are not waiting on the sync backend to be initialized. The user
124 // either is not in the field trial, or does not have sync enabled.
125 // Pretend that precaching started, so that the PrecacheServiceLauncher
126 // doesn't try to start it again.
127 is_precaching_ = true;
130 OnDone();
134 void PrecacheManager::CancelPrecaching() {
135 DCHECK_CURRENTLY_ON(BrowserThread::UI);
137 if (!is_precaching_) {
138 // Do nothing if precaching is not in progress.
139 return;
141 is_precaching_ = false;
143 // Destroying the |precache_fetcher_| will cancel any fetch in progress.
144 precache_fetcher_.reset();
146 // Uninitialize the callback so that any scoped_refptrs in it are released.
147 precache_completion_callback_.Reset();
150 bool PrecacheManager::IsPrecaching() const {
151 DCHECK_CURRENTLY_ON(BrowserThread::UI);
152 return is_precaching_;
155 void PrecacheManager::RecordStatsForFetch(const GURL& url,
156 const base::TimeDelta& latency,
157 const base::Time& fetch_time,
158 int64 size,
159 bool was_cached) {
160 DCHECK_CURRENTLY_ON(BrowserThread::UI);
162 if (size == 0 || url.is_empty() || !url.SchemeIsHTTPOrHTTPS()) {
163 // Ignore empty responses, empty URLs, or URLs that aren't HTTP or HTTPS.
164 return;
167 if (is_precaching_) {
168 // Assume that precache is responsible for all requests made while
169 // precaching is currently in progress.
170 // TODO(sclittle): Make PrecacheFetcher explicitly mark precache-motivated
171 // fetches, and use that to determine whether or not a fetch was motivated
172 // by precaching.
173 BrowserThread::PostTask(
174 BrowserThread::DB, FROM_HERE,
175 base::Bind(&PrecacheDatabase::RecordURLPrefetch, precache_database_,
176 url, latency, fetch_time, size, was_cached));
177 } else {
178 bool is_connection_cellular =
179 net::NetworkChangeNotifier::IsConnectionCellular(
180 net::NetworkChangeNotifier::GetConnectionType());
182 BrowserThread::PostTask(
183 BrowserThread::DB, FROM_HERE,
184 base::Bind(&PrecacheDatabase::RecordURLNonPrefetch, precache_database_,
185 url, latency, fetch_time, size, was_cached,
186 is_connection_cellular));
190 void PrecacheManager::ClearHistory() {
191 // PrecacheDatabase::ClearHistory must run after PrecacheDatabase::Init has
192 // finished. Using PostNonNestableTask guarantees this, by definition. See
193 // base::SequencedTaskRunner for details.
194 BrowserThread::PostNonNestableTask(
195 BrowserThread::DB, FROM_HERE,
196 base::Bind(&PrecacheDatabase::ClearHistory, precache_database_));
199 void PrecacheManager::Shutdown() {
200 CancelPrecaching();
203 void PrecacheManager::OnDone() {
204 DCHECK_CURRENTLY_ON(BrowserThread::UI);
206 precache_fetcher_.reset();
208 precache_completion_callback_.Run(!is_precaching_);
209 // Uninitialize the callback so that any scoped_refptrs in it are released.
210 precache_completion_callback_.Reset();
212 is_precaching_ = false;
215 void PrecacheManager::OnHostsReceived(
216 const history::TopHostsList& host_counts) {
217 DCHECK_CURRENTLY_ON(BrowserThread::UI);
219 if (!is_precaching_) {
220 // Don't start precaching if it was canceled while waiting for the list of
221 // hosts.
222 return;
225 std::vector<std::string> hosts;
226 for (const auto& host_count : host_counts)
227 hosts.push_back(host_count.first);
229 // Start precaching.
230 precache_fetcher_.reset(
231 new PrecacheFetcher(hosts, browser_context_->GetRequestContext(),
232 variations::GetVariationParamValue(
233 kPrecacheFieldTrialName, kManifestURLPrefixParam),
234 this));
235 precache_fetcher_->Start();
238 } // namespace precache