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"
8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/metrics/field_trial.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/time/time.h"
14 #include "components/data_reduction_proxy/common/data_reduction_proxy_pref_names.h"
15 #include "components/precache/core/precache_database.h"
16 #include "components/precache/core/precache_switches.h"
17 #include "components/precache/core/url_list_provider.h"
18 #include "components/user_prefs/user_prefs.h"
19 #include "content/public/browser/browser_context.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "net/base/network_change_notifier.h"
23 using content::BrowserThread
;
27 const char kPrecacheFieldTrialName
[] = "Precache";
28 const char kPrecacheFieldTrialEnabledGroup
[] = "Enabled";
34 PrecacheManager::PrecacheManager(content::BrowserContext
* browser_context
)
35 : browser_context_(browser_context
),
36 precache_database_(new PrecacheDatabase()),
37 is_precaching_(false) {
38 base::FilePath
db_path(browser_context_
->GetPath().Append(
39 base::FilePath(FILE_PATH_LITERAL("PrecacheDatabase"))));
41 BrowserThread::PostTask(
42 BrowserThread::DB
, FROM_HERE
,
43 base::Bind(base::IgnoreResult(&PrecacheDatabase::Init
),
44 precache_database_
, db_path
));
47 PrecacheManager::~PrecacheManager() {}
50 bool PrecacheManager::IsPrecachingEnabled() {
51 return base::FieldTrialList::FindFullName(kPrecacheFieldTrialName
) ==
52 kPrecacheFieldTrialEnabledGroup
||
53 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePrecache
);
56 bool PrecacheManager::IsPrecachingAllowed() {
57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
58 #if defined(SPDY_PROXY_AUTH_ORIGIN)
59 return user_prefs::UserPrefs::Get(browser_context_
)->GetBoolean(
60 data_reduction_proxy::prefs::kDataReductionProxyEnabled
);
66 void PrecacheManager::StartPrecaching(
67 const PrecacheCompletionCallback
& precache_completion_callback
,
68 URLListProvider
* url_list_provider
) {
69 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
72 DLOG(WARNING
) << "Cannot start precaching because precaching is already "
76 is_precaching_
= true;
78 BrowserThread::PostTask(
79 BrowserThread::DB
, FROM_HERE
,
80 base::Bind(&PrecacheDatabase::DeleteExpiredPrecacheHistory
,
81 precache_database_
, base::Time::Now()));
83 precache_completion_callback_
= precache_completion_callback
;
85 url_list_provider
->GetURLs(
86 base::Bind(&PrecacheManager::OnURLsReceived
, AsWeakPtr()));
89 void PrecacheManager::CancelPrecaching() {
90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
92 if (!is_precaching_
) {
93 // Do nothing if precaching is not in progress.
96 is_precaching_
= false;
98 // Destroying the |precache_fetcher_| will cancel any fetch in progress.
99 precache_fetcher_
.reset();
101 // Uninitialize the callback so that any scoped_refptrs in it are released.
102 precache_completion_callback_
.Reset();
105 bool PrecacheManager::IsPrecaching() const {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
107 return is_precaching_
;
110 void PrecacheManager::RecordStatsForFetch(const GURL
& url
,
111 const base::Time
& fetch_time
,
114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
116 if (size
== 0 || url
.is_empty() || !url
.SchemeIsHTTPOrHTTPS()) {
117 // Ignore empty responses, empty URLs, or URLs that aren't HTTP or HTTPS.
121 if (is_precaching_
) {
122 // Assume that precache is responsible for all requests made while
123 // precaching is currently in progress.
124 // TODO(sclittle): Make PrecacheFetcher explicitly mark precache-motivated
125 // fetches, and use that to determine whether or not a fetch was motivated
127 BrowserThread::PostTask(
128 BrowserThread::DB
, FROM_HERE
,
129 base::Bind(&PrecacheDatabase::RecordURLPrecached
, precache_database_
,
130 url
, fetch_time
, size
, was_cached
));
132 bool is_connection_cellular
=
133 net::NetworkChangeNotifier::IsConnectionCellular(
134 net::NetworkChangeNotifier::GetConnectionType());
136 BrowserThread::PostTask(
137 BrowserThread::DB
, FROM_HERE
,
138 base::Bind(&PrecacheDatabase::RecordURLFetched
, precache_database_
, url
,
139 fetch_time
, size
, was_cached
, is_connection_cellular
));
143 void PrecacheManager::Shutdown() {
147 void PrecacheManager::OnDone() {
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
150 // If OnDone has been called, then we should just be finishing precaching.
151 DCHECK(is_precaching_
);
152 is_precaching_
= false;
154 precache_fetcher_
.reset();
156 precache_completion_callback_
.Run();
157 // Uninitialize the callback so that any scoped_refptrs in it are released.
158 precache_completion_callback_
.Reset();
161 void PrecacheManager::OnURLsReceived(const std::list
<GURL
>& urls
) {
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
164 if (!is_precaching_
) {
165 // Don't start precaching if it was canceled while waiting for the list of
171 precache_fetcher_
.reset(
172 new PrecacheFetcher(urls
, browser_context_
->GetRequestContext(), this));
173 precache_fetcher_
->Start();
176 } // namespace precache