| Index: components/doodle/doodle_service.cc
|
| diff --git a/components/doodle/doodle_service.cc b/components/doodle/doodle_service.cc
|
| index 12a56200bb613a7a9dae0f583c444d2082489220..dbf7d17ca0085d876cc05c2afcc139ff62a486cc 100644
|
| --- a/components/doodle/doodle_service.cc
|
| +++ b/components/doodle/doodle_service.cc
|
| @@ -7,6 +7,7 @@
|
| #include <utility>
|
|
|
| #include "base/bind.h"
|
| +#include "base/metrics/histogram_macros.h"
|
| #include "base/time/time.h"
|
| #include "base/values.h"
|
| #include "components/doodle/pref_names.h"
|
| @@ -28,21 +29,26 @@ void DoodleService::RegisterProfilePrefs(PrefRegistrySimple* pref_registry) {
|
| DoodleService::DoodleService(PrefService* pref_service,
|
| std::unique_ptr<DoodleFetcher> fetcher,
|
| std::unique_ptr<base::OneShotTimer> expiry_timer,
|
| - std::unique_ptr<base::Clock> clock)
|
| + std::unique_ptr<base::Clock> clock,
|
| + std::unique_ptr<base::TickClock> tick_clock)
|
| : pref_service_(pref_service),
|
| fetcher_(std::move(fetcher)),
|
| expiry_timer_(std::move(expiry_timer)),
|
| - clock_(std::move(clock)) {
|
| + clock_(std::move(clock)),
|
| + tick_clock_(std::move(tick_clock)) {
|
| DCHECK(pref_service_);
|
| DCHECK(fetcher_);
|
| DCHECK(expiry_timer_);
|
| DCHECK(clock_);
|
| + DCHECK(tick_clock_);
|
|
|
| base::Time expiry_date = base::Time::FromInternalValue(
|
| pref_service_->GetInt64(prefs::kCachedConfigExpiry));
|
| base::Optional<DoodleConfig> config = DoodleConfig::FromDictionary(
|
| *pref_service_->GetDictionary(prefs::kCachedConfig), base::nullopt);
|
| - UpdateCachedConfig(expiry_date - clock_->Now(), config);
|
| + DoodleState state =
|
| + config.has_value() ? DoodleState::AVAILABLE : DoodleState::NO_DOODLE;
|
| + UpdateCachedConfig(state, expiry_date - clock_->Now(), config);
|
| }
|
|
|
| DoodleService::~DoodleService() = default;
|
| @@ -58,18 +64,53 @@ void DoodleService::RemoveObserver(Observer* observer) {
|
| }
|
|
|
| void DoodleService::Refresh() {
|
| - fetcher_->FetchDoodle(
|
| - base::BindOnce(&DoodleService::DoodleFetched, base::Unretained(this)));
|
| + fetcher_->FetchDoodle(base::BindOnce(&DoodleService::DoodleFetched,
|
| + base::Unretained(this),
|
| + tick_clock_->NowTicks()));
|
| +}
|
| +
|
| +// static
|
| +bool DoodleService::DownloadOutcomeIsSuccess(DownloadOutcome outcome) {
|
| + switch (outcome) {
|
| + case OUTCOME_NEW_DOODLE:
|
| + case OUTCOME_REVALIDATED_DOODLE:
|
| + case OUTCOME_CHANGED_DOODLE:
|
| + case OUTCOME_NO_DOODLE:
|
| + return true;
|
| + case OUTCOME_EXPIRED:
|
| + case OUTCOME_DOWNLOAD_ERROR:
|
| + case OUTCOME_PARSING_ERROR:
|
| + return false;
|
| + case OUTCOME_COUNT:
|
| + NOTREACHED();
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +// static
|
| +void DoodleService::RecordDownloadMetrics(DownloadOutcome outcome,
|
| + base::TimeDelta download_time) {
|
| + UMA_HISTOGRAM_ENUMERATION("Doodle.ConfigDownloadOutcome", outcome,
|
| + OUTCOME_COUNT);
|
| +
|
| + if (DownloadOutcomeIsSuccess(outcome)) {
|
| + UMA_HISTOGRAM_MEDIUM_TIMES("Doodle.ConfigDownloadTime", download_time);
|
| + }
|
| }
|
|
|
| void DoodleService::DoodleFetched(
|
| + base::TimeTicks start_time,
|
| DoodleState state,
|
| base::TimeDelta time_to_live,
|
| const base::Optional<DoodleConfig>& doodle_config) {
|
| - UpdateCachedConfig(time_to_live, doodle_config);
|
| + base::TimeDelta download_time = tick_clock_->NowTicks() - start_time;
|
| + DownloadOutcome outcome =
|
| + UpdateCachedConfig(state, time_to_live, doodle_config);
|
| + RecordDownloadMetrics(outcome, download_time);
|
| }
|
|
|
| -void DoodleService::UpdateCachedConfig(
|
| +DoodleService::DownloadOutcome DoodleService::UpdateCachedConfig(
|
| + DoodleState state,
|
| base::TimeDelta time_to_live,
|
| const base::Optional<DoodleConfig>& doodle_config) {
|
| // Handle the case where the new config is already expired.
|
| @@ -77,18 +118,26 @@ void DoodleService::UpdateCachedConfig(
|
| const base::Optional<DoodleConfig>& new_config =
|
| expired ? base::nullopt : doodle_config;
|
|
|
| + DownloadOutcome outcome = OUTCOME_COUNT;
|
| +
|
| // If the config changed, update our cache and notify observers.
|
| // Note that this checks both for existence changes as well as changes of the
|
| // configs themselves.
|
| if (cached_config_ != new_config) {
|
| + bool had_config_before = cached_config_.has_value();
|
| +
|
| cached_config_ = new_config;
|
|
|
| if (cached_config_.has_value()) {
|
| + outcome = had_config_before ? OUTCOME_CHANGED_DOODLE : OUTCOME_NEW_DOODLE;
|
| +
|
| pref_service_->Set(prefs::kCachedConfig, *cached_config_->ToDictionary());
|
| base::Time expiry_date = clock_->Now() + time_to_live;
|
| pref_service_->SetInt64(prefs::kCachedConfigExpiry,
|
| expiry_date.ToInternalValue());
|
| } else {
|
| + outcome = OUTCOME_NO_DOODLE;
|
| +
|
| pref_service_->ClearPref(prefs::kCachedConfig);
|
| pref_service_->ClearPref(prefs::kCachedConfigExpiry);
|
| }
|
| @@ -96,6 +145,28 @@ void DoodleService::UpdateCachedConfig(
|
| for (auto& observer : observers_) {
|
| observer.OnDoodleConfigUpdated(cached_config_);
|
| }
|
| + } else {
|
| + outcome = cached_config_.has_value() ? OUTCOME_REVALIDATED_DOODLE
|
| + : OUTCOME_NO_DOODLE;
|
| + }
|
| +
|
| + DCHECK(outcome != OUTCOME_COUNT);
|
| + // Determine the final outcome. ERROR or EXPIRED override NO_DOODLE.
|
| + switch (state) {
|
| + case DoodleState::AVAILABLE:
|
| + case DoodleState::NO_DOODLE:
|
| + if (expired) {
|
| + outcome = OUTCOME_EXPIRED;
|
| + }
|
| + break;
|
| +
|
| + case DoodleState::DOWNLOAD_ERROR:
|
| + outcome = OUTCOME_DOWNLOAD_ERROR;
|
| + break;
|
| +
|
| + case DoodleState::PARSING_ERROR:
|
| + outcome = OUTCOME_PARSING_ERROR;
|
| + break;
|
| }
|
|
|
| // Even if the configs are identical, the time-to-live might have changed.
|
| @@ -107,11 +178,13 @@ void DoodleService::UpdateCachedConfig(
|
| } else {
|
| expiry_timer_->Stop();
|
| }
|
| +
|
| + return outcome;
|
| }
|
|
|
| void DoodleService::DoodleExpired() {
|
| DCHECK(cached_config_.has_value());
|
| - UpdateCachedConfig(base::TimeDelta(), base::nullopt);
|
| + UpdateCachedConfig(DoodleState::NO_DOODLE, base::TimeDelta(), base::nullopt);
|
| }
|
|
|
| } // namespace doodle
|
|
|