| Index: components/precache/content/precache_manager.cc | 
| diff --git a/components/precache/content/precache_manager.cc b/components/precache/content/precache_manager.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..748f730e373825a3c1da87744e842565cbe2dad0 | 
| --- /dev/null | 
| +++ b/components/precache/content/precache_manager.cc | 
| @@ -0,0 +1,149 @@ | 
| +// Copyright 2013 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "components/precache/content/precache_manager.h" | 
| + | 
| +#include "base/bind.h" | 
| +#include "base/command_line.h" | 
| +#include "base/files/file_path.h" | 
| +#include "base/logging.h" | 
| +#include "base/time/time.h" | 
| +#include "components/precache/core/precache_database.h" | 
| +#include "components/precache/core/precache_switches.h" | 
| +#include "components/precache/core/url_list_provider.h" | 
| +#include "content/public/browser/browser_context.h" | 
| +#include "content/public/browser/browser_thread.h" | 
| +#include "sql/connection.h" | 
| + | 
| +using content::BrowserThread; | 
| + | 
| +namespace { | 
| + | 
| +const base::FilePath::CharType kPrecacheDatabaseName[] = | 
| +    FILE_PATH_LITERAL("PrecacheDatabase"); | 
| + | 
| +void InitPrecacheDatabaseOnDBThread( | 
| +    base::FilePath dir_path, | 
| +    scoped_refptr<precache::PrecacheDatabase> precache_database) { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 
| + | 
| +  scoped_ptr<sql::Connection> db(new sql::Connection()); | 
| +  if (!db->Open(dir_path.Append(kPrecacheDatabaseName))) { | 
| +    DLOG(WARNING) << "Could not open precache database. No precache data will " | 
| +                     "be tracked."; | 
| +  } | 
| + | 
| +  // Initialize the precache database with the connection even if it failed to | 
| +  // open. The precache database will take ownership of the connection. | 
| +  precache_database->Init(db.Pass()); | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| +namespace precache { | 
| + | 
| +PrecacheManager::PrecacheManager(content::BrowserContext* browser_context) | 
| +    : browser_context_(browser_context), | 
| +      precache_database_(new PrecacheDatabase()), | 
| +      is_precaching_(false) { | 
| +  BrowserThread::PostTask( | 
| +      BrowserThread::DB, FROM_HERE, | 
| +      base::Bind(&InitPrecacheDatabaseOnDBThread, browser_context->GetPath(), | 
| +                 precache_database_)); | 
| +} | 
| + | 
| +PrecacheManager::~PrecacheManager() {} | 
| + | 
| +// static | 
| +bool PrecacheManager::IsPrecachingEnabled() { | 
| +  // TODO(sclittle): Test for Finch trial as well when it exists. | 
| +  return CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePrecache); | 
| +} | 
| + | 
| +void PrecacheManager::Shutdown() { | 
| +  CancelPrecaching(); | 
| +} | 
| + | 
| +void PrecacheManager::OnDone() { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| + | 
| +  { | 
| +    base::AutoLock lock(lock_); | 
| +    is_precaching_ = false; | 
| +  } | 
| + | 
| +  precache_fetcher_.reset(); | 
| +} | 
| + | 
| +void PrecacheManager::StartPrecaching( | 
| +    URLListProvider* interesting_urls_provider) { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| + | 
| +  { | 
| +    base::AutoLock lock(lock_); | 
| +    if (is_precaching_) { | 
| +      DLOG(WARNING) << "Cannot start precaching because precaching is already " | 
| +                       "in progress."; | 
| +      return; | 
| +    } | 
| +    is_precaching_ = true; | 
| +  } | 
| + | 
| +  // The start of the day before today. Don't just use (base::Time::Now() - | 
| +  // base::TimeDelta::FromDays(1)).LocalMidnight() because that wouldn't account | 
| +  // for daylight savings, i.e. some days are 23 or 25 hours long. | 
| +  base::Time yesterday = (base::Time::Now().LocalMidnight() - | 
| +                          base::TimeDelta::FromHours(1)).LocalMidnight(); | 
| + | 
| +  // Report any UMA of precache stats for days before the current date and | 
| +  // delete expired precache history. | 
| +  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 
| +                          base::Bind(&PrecacheDatabase::ReportAndDeleteOldStats, | 
| +                                     precache_database_, yesterday)); | 
| + | 
| +  interesting_urls_provider->GetURLs( | 
| +      base::Bind(&PrecacheManager::OnURLsReceived, base::Unretained(this))); | 
| +} | 
| + | 
| +void PrecacheManager::CancelPrecaching() { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| + | 
| +  { | 
| +    base::AutoLock lock(lock_); | 
| +    if (!is_precaching_) { | 
| +      // Do nothing if precaching is not in progress. | 
| +      return; | 
| +    } | 
| +    is_precaching_ = false; | 
| +  } | 
| + | 
| +  // Destroying the |precache_fetcher_| will cancel any fetch in progress. | 
| +  precache_fetcher_.reset(); | 
| +} | 
| + | 
| +bool PrecacheManager::IsPrecaching() { | 
| +  base::AutoLock lock(lock_); | 
| +  return is_precaching_; | 
| +} | 
| + | 
| +scoped_refptr<PrecacheDatabase> PrecacheManager::precache_database() { | 
| +  return precache_database_; | 
| +} | 
| + | 
| +void PrecacheManager::OnURLsReceived(const std::list<GURL>& interesting_urls) { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| + | 
| +  if (!IsPrecaching()) { | 
| +    // Don't start precaching if it was canceled while waiting for the list of | 
| +    // interesting URLs. | 
| +    return; | 
| +  } | 
| + | 
| +  // Start precaching. | 
| +  precache_fetcher_.reset(new PrecacheFetcher( | 
| +      interesting_urls, browser_context_->GetRequestContext(), this)); | 
| +  precache_fetcher_->Start(); | 
| +} | 
| + | 
| +}  // namespace precache | 
|  |