Chromium Code Reviews| Index: components/precache/content/precache_manager.cc |
| diff --git a/components/precache/content/precache_manager.cc b/components/precache/content/precache_manager.cc |
| index 1d2ddb653b7742cb2d7257d3ea1aeaa37f5aba25..b5091fb40b518e79ca1925d7b1ef2336ce827649 100644 |
| --- a/components/precache/content/precache_manager.cc |
| +++ b/components/precache/content/precache_manager.cc |
| @@ -18,6 +18,7 @@ |
| #include "components/history/core/browser/history_service.h" |
| #include "components/precache/core/precache_database.h" |
| #include "components/precache/core/precache_switches.h" |
| +#include "components/precache/core/proto/unfinished_work.pb.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/sync_driver/sync_service.h" |
| #include "components/variations/variations_associated_data.h" |
| @@ -48,14 +49,14 @@ size_t NumTopHosts() { |
| PrecacheManager::PrecacheManager( |
| content::BrowserContext* browser_context, |
| const sync_driver::SyncService* const sync_service, |
| - const history::HistoryService* const history_service) |
| + const history::HistoryService* const history_service, |
| + std::unique_ptr<PrecacheDatabase> precache_database, |
| + const base::FilePath& db_path) |
| : browser_context_(browser_context), |
| sync_service_(sync_service), |
| history_service_(history_service), |
| - precache_database_(new PrecacheDatabase()), |
| is_precaching_(false) { |
| - base::FilePath db_path(browser_context_->GetPath().Append( |
| - base::FilePath(FILE_PATH_LITERAL("PrecacheDatabase")))); |
| + precache_database_ = std::move(precache_database); |
| BrowserThread::PostTask( |
| BrowserThread::DB, FROM_HERE, |
| @@ -122,9 +123,25 @@ void PrecacheManager::StartPrecaching( |
| } |
| precache_completion_callback_ = precache_completion_callback; |
| - if (IsInExperimentGroup()) { |
| - is_precaching_ = true; |
| + is_precaching_ = true; |
| + BrowserThread::PostTaskAndReplyWithResult( |
| + BrowserThread::DB, |
| + FROM_HERE, |
| + base::Bind(&PrecacheDatabase::GetUnfinishedWork, |
| + base::Unretained(precache_database_.get())), |
| + base::Bind(&PrecacheManager::OnGetUnfinishedWorkDone, AsWeakPtr())); |
| +} |
| + |
| +void PrecacheManager::OnGetUnfinishedWorkDone( |
| + std::unique_ptr<PrecacheUnfinishedWork> unfinished_work) { |
| + if (base::Time::Now() - base::Time::FromInternalValue( |
| + unfinished_work->start_time()) > base::TimeDelta::FromHours(6)) { |
| + unfinished_work.reset(new PrecacheUnfinishedWork); |
| + } |
| + unfinished_work_ = std::move(unfinished_work); |
| + bool needs_top_hosts = unfinished_work_->top_host_size() == 0; |
| + if (IsInExperimentGroup()) { |
| BrowserThread::PostTask( |
| BrowserThread::DB, FROM_HERE, |
| base::Bind(&PrecacheDatabase::DeleteExpiredPrecacheHistory, |
| @@ -134,25 +151,33 @@ void PrecacheManager::StartPrecaching( |
| // Request NumTopHosts() top hosts. Note that PrecacheFetcher is further |
| // bound by the value of PrecacheConfigurationSettings.top_sites_count, as |
| // retrieved from the server. |
| - history_service_->TopHosts( |
| - NumTopHosts(), |
| - base::Bind(&PrecacheManager::OnHostsReceived, AsWeakPtr())); |
| + if (needs_top_hosts) { |
| + history_service_->TopHosts( |
| + NumTopHosts(), |
| + base::Bind(&PrecacheManager::OnHostsReceived, AsWeakPtr())); |
| + } else { |
| + std::vector<std::string> hosts; |
| + for (int i = 0; i < unfinished_work_->top_host_size(); ++i) { |
|
sclittle
2016/05/19 01:59:45
Could the hosts just be stored in the unfinished_w
bengr
2016/05/19 23:19:31
Done.
|
| + if (unfinished_work_->top_host(i).has_hostname()) |
| + hosts.push_back(unfinished_work_->top_host(i).hostname()); |
| + } |
| + InitializeAndStartFetcher(hosts); |
| + } |
| } else if (IsInControlGroup()) { |
| - // Set is_precaching_ so that the longer delay is placed between calls to |
| - // TopHosts. |
| - is_precaching_ = true; |
| - |
| // Calculate TopHosts solely for metrics purposes. |
| + if (needs_top_hosts) { |
| history_service_->TopHosts( |
| NumTopHosts(), |
| base::Bind(&PrecacheManager::OnHostsReceivedThenDone, AsWeakPtr())); |
| + } else { |
| + OnDone(); |
| + } |
| } else { |
| if (PrecachingAllowed() != AllowedType::PENDING) { |
| // We are not waiting on the sync backend to be initialized. The user |
| // either is not in the field trial, or does not have sync enabled. |
| // Pretend that precaching started, so that the PrecacheServiceLauncher |
| // doesn't try to start it again. |
| - is_precaching_ = true; |
| } |
| OnDone(); |
| @@ -161,13 +186,36 @@ void PrecacheManager::StartPrecaching( |
| void PrecacheManager::CancelPrecaching() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - |
| if (!is_precaching_) { |
| // Do nothing if precaching is not in progress. |
| return; |
| } |
| is_precaching_ = false; |
| + // If cancellation occurs after StartPrecaching but before OnHostsReceived, |
| + // is_precaching will be true, but the precache_fetcher_ will not yet be |
| + // constructed. |
| + if (precache_fetcher_) { |
| + std::unique_ptr<PrecacheUnfinishedWork> unfinished_work = |
| + precache_fetcher_->GetUnfinishedWork(); |
| + for (int i = 0; i < unfinished_work_->top_host_size(); ++i) { |
| + if (unfinished_work_->top_host(i).has_hostname()) { |
| + unfinished_work->mutable_top_host(i)->CopyFrom( |
| + unfinished_work_->top_host(i)); |
| + } |
| + } |
| + BrowserThread::PostTaskAndReplyWithResult( |
| + BrowserThread::DB, |
| + FROM_HERE, |
| + base::Bind(&PrecacheDatabase::SaveUnfinishedWork, |
| + base::Unretained(precache_database_.get()), |
| + base::Passed(&unfinished_work)), |
| + base::Bind(&PrecacheManager::OnSaveUnfinishedWorkDone, AsWeakPtr())); |
| + } else { |
| + precache_completion_callback_.Reset(); |
| + } |
| +} |
| +void PrecacheManager::OnSaveUnfinishedWorkDone(bool /* success */) { |
| // Destroying the |precache_fetcher_| will cancel any fetch in progress. |
| precache_fetcher_.reset(); |
| @@ -250,7 +298,6 @@ void PrecacheManager::Shutdown() { |
| void PrecacheManager::OnDone() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - |
| precache_fetcher_.reset(); |
| // Run completion callback if not null. It's null if the client is in the |
| @@ -269,16 +316,19 @@ void PrecacheManager::OnHostsReceived( |
| const history::TopHostsList& host_counts) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + std::vector<std::string> hosts; |
| + for (const auto& host_count : host_counts) |
| + hosts.push_back(host_count.first); |
| + InitializeAndStartFetcher(hosts); |
| +} |
| + |
| +void PrecacheManager::InitializeAndStartFetcher( |
| + const std::vector<std::string>& hosts) { |
| if (!is_precaching_) { |
| // Don't start precaching if it was canceled while waiting for the list of |
| // hosts. |
| return; |
| } |
| - |
| - std::vector<std::string> hosts; |
| - for (const auto& host_count : host_counts) |
| - hosts.push_back(host_count.first); |
| - |
| // Start precaching. |
| precache_fetcher_.reset(new PrecacheFetcher( |
| hosts, |
| @@ -288,6 +338,7 @@ void PrecacheManager::OnHostsReceived( |
| kPrecacheFieldTrialName, kConfigURLParam)), |
| variations::GetVariationParamValue( |
| kPrecacheFieldTrialName, kManifestURLPrefixParam), |
| + unfinished_work_.get(), |
| this)); |
| precache_fetcher_->Start(); |
| } |