• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "components/precache/content/precache_manager.h"
6 
7 #include "base/bind.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"
22 
23 using content::BrowserThread;
24 
25 namespace {
26 
27 const char kPrecacheFieldTrialName[] = "Precache";
28 const char kPrecacheFieldTrialEnabledGroup[] = "Enabled";
29 
30 }  // namespace
31 
32 namespace precache {
33 
PrecacheManager(content::BrowserContext * browser_context)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"))));
40 
41   BrowserThread::PostTask(
42       BrowserThread::DB, FROM_HERE,
43       base::Bind(base::IgnoreResult(&PrecacheDatabase::Init),
44                  precache_database_, db_path));
45 }
46 
~PrecacheManager()47 PrecacheManager::~PrecacheManager() {}
48 
49 // static
IsPrecachingEnabled()50 bool PrecacheManager::IsPrecachingEnabled() {
51   return base::FieldTrialList::FindFullName(kPrecacheFieldTrialName) ==
52              kPrecacheFieldTrialEnabledGroup ||
53          CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePrecache);
54 }
55 
IsPrecachingAllowed()56 bool PrecacheManager::IsPrecachingAllowed() {
57   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
58   return user_prefs::UserPrefs::Get(browser_context_)->GetBoolean(
59       data_reduction_proxy::prefs::kDataReductionProxyEnabled);
60 }
61 
StartPrecaching(const PrecacheCompletionCallback & precache_completion_callback,URLListProvider * url_list_provider)62 void PrecacheManager::StartPrecaching(
63     const PrecacheCompletionCallback& precache_completion_callback,
64     URLListProvider* url_list_provider) {
65   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
66 
67   if (is_precaching_) {
68     DLOG(WARNING) << "Cannot start precaching because precaching is already "
69                      "in progress.";
70     return;
71   }
72   is_precaching_ = true;
73 
74   BrowserThread::PostTask(
75       BrowserThread::DB, FROM_HERE,
76       base::Bind(&PrecacheDatabase::DeleteExpiredPrecacheHistory,
77                  precache_database_, base::Time::Now()));
78 
79   precache_completion_callback_ = precache_completion_callback;
80 
81   url_list_provider->GetURLs(
82       base::Bind(&PrecacheManager::OnURLsReceived, AsWeakPtr()));
83 }
84 
CancelPrecaching()85 void PrecacheManager::CancelPrecaching() {
86   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
87 
88   if (!is_precaching_) {
89     // Do nothing if precaching is not in progress.
90     return;
91   }
92   is_precaching_ = false;
93 
94   // Destroying the |precache_fetcher_| will cancel any fetch in progress.
95   precache_fetcher_.reset();
96 
97   // Uninitialize the callback so that any scoped_refptrs in it are released.
98   precache_completion_callback_.Reset();
99 }
100 
IsPrecaching() const101 bool PrecacheManager::IsPrecaching() const {
102   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
103   return is_precaching_;
104 }
105 
RecordStatsForFetch(const GURL & url,const base::Time & fetch_time,int64 size,bool was_cached)106 void PrecacheManager::RecordStatsForFetch(const GURL& url,
107                                           const base::Time& fetch_time,
108                                           int64 size,
109                                           bool was_cached) {
110   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
111 
112   if (size == 0 || url.is_empty() || !url.SchemeIsHTTPOrHTTPS()) {
113     // Ignore empty responses, empty URLs, or URLs that aren't HTTP or HTTPS.
114     return;
115   }
116 
117   if (is_precaching_) {
118     // Assume that precache is responsible for all requests made while
119     // precaching is currently in progress.
120     // TODO(sclittle): Make PrecacheFetcher explicitly mark precache-motivated
121     // fetches, and use that to determine whether or not a fetch was motivated
122     // by precaching.
123     BrowserThread::PostTask(
124         BrowserThread::DB, FROM_HERE,
125         base::Bind(&PrecacheDatabase::RecordURLPrecached, precache_database_,
126                    url, fetch_time, size, was_cached));
127   } else {
128     bool is_connection_cellular =
129         net::NetworkChangeNotifier::IsConnectionCellular(
130             net::NetworkChangeNotifier::GetConnectionType());
131 
132     BrowserThread::PostTask(
133         BrowserThread::DB, FROM_HERE,
134         base::Bind(&PrecacheDatabase::RecordURLFetched, precache_database_, url,
135                    fetch_time, size, was_cached, is_connection_cellular));
136   }
137 }
138 
Shutdown()139 void PrecacheManager::Shutdown() {
140   CancelPrecaching();
141 }
142 
OnDone()143 void PrecacheManager::OnDone() {
144   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145 
146   // If OnDone has been called, then we should just be finishing precaching.
147   DCHECK(is_precaching_);
148   is_precaching_ = false;
149 
150   precache_fetcher_.reset();
151 
152   precache_completion_callback_.Run();
153   // Uninitialize the callback so that any scoped_refptrs in it are released.
154   precache_completion_callback_.Reset();
155 }
156 
OnURLsReceived(const std::list<GURL> & urls)157 void PrecacheManager::OnURLsReceived(const std::list<GURL>& urls) {
158   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
159 
160   if (!is_precaching_) {
161     // Don't start precaching if it was canceled while waiting for the list of
162     // URLs.
163     return;
164   }
165 
166   // Start precaching.
167   precache_fetcher_.reset(
168       new PrecacheFetcher(urls, browser_context_->GetRequestContext(), this));
169   precache_fetcher_->Start();
170 }
171 
172 }  // namespace precache
173