Allow only one bookmark to be added for multiple fast starring
[chromium-blink-merge.git] / components / precache / content / precache_manager.cc
bloba03277c9095da8835296b5708ebf2941f4a94041
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 : browser_context_(browser_context),
48 sync_service_(sync_service),
49 precache_database_(new PrecacheDatabase()),
50 is_precaching_(false) {
51 base::FilePath db_path(browser_context_->GetPath().Append(
52 base::FilePath(FILE_PATH_LITERAL("PrecacheDatabase"))));
54 BrowserThread::PostTask(
55 BrowserThread::DB, FROM_HERE,
56 base::Bind(base::IgnoreResult(&PrecacheDatabase::Init),
57 precache_database_, db_path));
60 PrecacheManager::~PrecacheManager() {}
62 // static
63 bool PrecacheManager::IsPrecachingEnabled() {
64 return base::FieldTrialList::FindFullName(kPrecacheFieldTrialName) ==
65 kPrecacheFieldTrialEnabledGroup ||
66 base::CommandLine::ForCurrentProcess()->HasSwitch(
67 switches::kEnablePrecache);
70 bool PrecacheManager::IsPrecachingAllowed() {
71 return sync_service_ &&
72 sync_service_->GetActiveDataTypes().Has(syncer::SESSIONS) &&
73 !sync_service_->GetEncryptedDataTypes().Has(syncer::SESSIONS);
76 void PrecacheManager::StartPrecaching(
77 const PrecacheCompletionCallback& precache_completion_callback,
78 const history::HistoryService& history_service) {
79 DCHECK_CURRENTLY_ON(BrowserThread::UI);
81 if (is_precaching_) {
82 DLOG(WARNING) << "Cannot start precaching because precaching is already "
83 "in progress.";
84 return;
86 is_precaching_ = true;
88 BrowserThread::PostTask(
89 BrowserThread::DB, FROM_HERE,
90 base::Bind(&PrecacheDatabase::DeleteExpiredPrecacheHistory,
91 precache_database_, base::Time::Now()));
93 precache_completion_callback_ = precache_completion_callback;
95 // Request NumTopHosts() top hosts. Note that PrecacheFetcher is further bound
96 // by the value of PrecacheConfigurationSettings.top_sites_count, as retrieved
97 // from the server.
98 history_service.TopHosts(
99 NumTopHosts(),
100 base::Bind(&PrecacheManager::OnHostsReceived, AsWeakPtr()));
103 void PrecacheManager::CancelPrecaching() {
104 DCHECK_CURRENTLY_ON(BrowserThread::UI);
106 if (!is_precaching_) {
107 // Do nothing if precaching is not in progress.
108 return;
110 is_precaching_ = false;
112 // Destroying the |precache_fetcher_| will cancel any fetch in progress.
113 precache_fetcher_.reset();
115 // Uninitialize the callback so that any scoped_refptrs in it are released.
116 precache_completion_callback_.Reset();
119 bool PrecacheManager::IsPrecaching() const {
120 DCHECK_CURRENTLY_ON(BrowserThread::UI);
121 return is_precaching_;
124 void PrecacheManager::RecordStatsForFetch(const GURL& url,
125 const base::Time& fetch_time,
126 int64 size,
127 bool was_cached) {
128 DCHECK_CURRENTLY_ON(BrowserThread::UI);
130 if (size == 0 || url.is_empty() || !url.SchemeIsHTTPOrHTTPS()) {
131 // Ignore empty responses, empty URLs, or URLs that aren't HTTP or HTTPS.
132 return;
135 if (is_precaching_) {
136 // Assume that precache is responsible for all requests made while
137 // precaching is currently in progress.
138 // TODO(sclittle): Make PrecacheFetcher explicitly mark precache-motivated
139 // fetches, and use that to determine whether or not a fetch was motivated
140 // by precaching.
141 BrowserThread::PostTask(
142 BrowserThread::DB, FROM_HERE,
143 base::Bind(&PrecacheDatabase::RecordURLPrecached, precache_database_,
144 url, fetch_time, size, was_cached));
145 } else {
146 bool is_connection_cellular =
147 net::NetworkChangeNotifier::IsConnectionCellular(
148 net::NetworkChangeNotifier::GetConnectionType());
150 BrowserThread::PostTask(
151 BrowserThread::DB, FROM_HERE,
152 base::Bind(&PrecacheDatabase::RecordURLFetched, precache_database_, url,
153 fetch_time, size, was_cached, is_connection_cellular));
157 void PrecacheManager::ClearHistory() {
158 // PrecacheDatabase::ClearHistory must run after PrecacheDatabase::Init has
159 // finished. Using PostNonNestableTask guarantees this, by definition. See
160 // base::SequencedTaskRunner for details.
161 BrowserThread::PostNonNestableTask(
162 BrowserThread::DB, FROM_HERE,
163 base::Bind(&PrecacheDatabase::ClearHistory, precache_database_));
166 void PrecacheManager::Shutdown() {
167 CancelPrecaching();
170 void PrecacheManager::OnDone() {
171 DCHECK_CURRENTLY_ON(BrowserThread::UI);
173 // If OnDone has been called, then we should just be finishing precaching.
174 DCHECK(is_precaching_);
175 is_precaching_ = false;
177 precache_fetcher_.reset();
179 precache_completion_callback_.Run();
180 // Uninitialize the callback so that any scoped_refptrs in it are released.
181 precache_completion_callback_.Reset();
184 void PrecacheManager::OnHostsReceived(
185 const history::TopHostsList& host_counts) {
186 DCHECK_CURRENTLY_ON(BrowserThread::UI);
188 if (!is_precaching_) {
189 // Don't start precaching if it was canceled while waiting for the list of
190 // hosts.
191 return;
194 std::vector<std::string> hosts;
195 for (const auto& host_count : host_counts)
196 hosts.push_back(host_count.first);
198 // Start precaching.
199 precache_fetcher_.reset(
200 new PrecacheFetcher(hosts, browser_context_->GetRequestContext(),
201 variations::GetVariationParamValue(
202 kPrecacheFieldTrialName, kManifestURLPrefixParam),
203 this));
204 precache_fetcher_->Start();
207 } // namespace precache