Stack sampling profiler: add fire-and-forget interface
[chromium-blink-merge.git] / components / proximity_auth / cryptauth / cryptauth_enrollment_manager.cc
blob6c080731e8554dd66fffcbb6628472b0faa42bae
1 // Copyright 2015 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/proximity_auth/cryptauth/cryptauth_enrollment_manager.h"
7 #include "base/prefs/pref_registry_simple.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/time/clock.h"
10 #include "base/time/time.h"
11 #include "components/proximity_auth/cryptauth/cryptauth_enroller.h"
12 #include "components/proximity_auth/cryptauth/pref_names.h"
13 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
14 #include "components/proximity_auth/cryptauth/sync_scheduler_impl.h"
15 #include "components/proximity_auth/logging/logging.h"
17 namespace proximity_auth {
19 namespace {
21 // The number of days that an enrollment is valid. Note that we try to refresh
22 // the enrollment well before this time elapses.
23 const int kValidEnrollmentPeriodDays = 45;
25 // The normal period between successful enrollments in days.
26 const int kEnrollmentRefreshPeriodDays = 30;
28 // A more aggressive period between enrollments to recover when the last
29 // enrollment fails, in minutes. This is a base time that increases for each
30 // subsequent failure.
31 const int kEnrollmentBaseRecoveryPeriodMinutes = 10;
33 // The bound on the amount to jitter the period between enrollments.
34 const double kEnrollmentMaxJitterRatio = 0.2;
36 } // namespace
38 CryptAuthEnrollmentManager::CryptAuthEnrollmentManager(
39 scoped_ptr<base::Clock> clock,
40 scoped_ptr<CryptAuthEnrollerFactory> enroller_factory,
41 const std::string& user_public_key,
42 const std::string& user_private_key,
43 const cryptauth::GcmDeviceInfo& device_info,
44 CryptAuthGCMManager* gcm_manager,
45 PrefService* pref_service)
46 : clock_(clock.Pass()),
47 enroller_factory_(enroller_factory.Pass()),
48 user_public_key_(user_public_key),
49 user_private_key_(user_private_key),
50 device_info_(device_info),
51 gcm_manager_(gcm_manager),
52 pref_service_(pref_service),
53 weak_ptr_factory_(this) {}
55 CryptAuthEnrollmentManager::~CryptAuthEnrollmentManager() {
56 gcm_manager_->RemoveObserver(this);
59 // static
60 void CryptAuthEnrollmentManager::RegisterPrefs(PrefRegistrySimple* registry) {
61 registry->RegisterBooleanPref(
62 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure, false);
63 registry->RegisterDoublePref(
64 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds, 0.0);
65 registry->RegisterIntegerPref(prefs::kCryptAuthEnrollmentReason,
66 cryptauth::INVOCATION_REASON_UNKNOWN);
69 void CryptAuthEnrollmentManager::Start() {
70 gcm_manager_->AddObserver(this);
72 bool is_recovering_from_failure =
73 pref_service_->GetBoolean(
74 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure) ||
75 !IsEnrollmentValid();
77 base::Time last_successful_enrollment = GetLastEnrollmentTime();
78 base::TimeDelta elapsed_time_since_last_sync =
79 clock_->Now() - last_successful_enrollment;
81 scheduler_ = CreateSyncScheduler();
82 scheduler_->Start(elapsed_time_since_last_sync,
83 is_recovering_from_failure
84 ? SyncScheduler::Strategy::AGGRESSIVE_RECOVERY
85 : SyncScheduler::Strategy::PERIODIC_REFRESH);
88 void CryptAuthEnrollmentManager::AddObserver(Observer* observer) {
89 observers_.AddObserver(observer);
92 void CryptAuthEnrollmentManager::RemoveObserver(Observer* observer) {
93 observers_.RemoveObserver(observer);
96 void CryptAuthEnrollmentManager::ForceEnrollmentNow(
97 cryptauth::InvocationReason invocation_reason) {
98 // We store the invocation reason in a preference so that it can persist
99 // across browser restarts. If the sync fails, the next retry should still use
100 // this original reason instead of INVOCATION_REASON_FAILURE_RECOVERY.
101 pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
102 invocation_reason);
103 scheduler_->ForceSync();
106 bool CryptAuthEnrollmentManager::IsEnrollmentValid() const {
107 base::Time last_enrollment_time = GetLastEnrollmentTime();
108 return !last_enrollment_time.is_null() &&
109 (clock_->Now() - last_enrollment_time) <
110 base::TimeDelta::FromDays(kValidEnrollmentPeriodDays);
113 base::Time CryptAuthEnrollmentManager::GetLastEnrollmentTime() const {
114 return base::Time::FromDoubleT(pref_service_->GetDouble(
115 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds));
118 base::TimeDelta CryptAuthEnrollmentManager::GetTimeToNextAttempt() const {
119 return scheduler_->GetTimeToNextSync();
122 bool CryptAuthEnrollmentManager::IsEnrollmentInProgress() const {
123 return scheduler_->GetSyncState() ==
124 SyncScheduler::SyncState::SYNC_IN_PROGRESS;
127 bool CryptAuthEnrollmentManager::IsRecoveringFromFailure() const {
128 return scheduler_->GetStrategy() ==
129 SyncScheduler::Strategy::AGGRESSIVE_RECOVERY;
132 void CryptAuthEnrollmentManager::OnEnrollmentFinished(bool success) {
133 if (success) {
134 pref_service_->SetDouble(
135 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
136 clock_->Now().ToDoubleT());
137 pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
138 cryptauth::INVOCATION_REASON_UNKNOWN);
141 pref_service_->SetBoolean(prefs::kCryptAuthEnrollmentIsRecoveringFromFailure,
142 !success);
144 sync_request_->OnDidComplete(success);
145 cryptauth_enroller_.reset();
146 sync_request_.reset();
147 FOR_EACH_OBSERVER(Observer, observers_, OnEnrollmentFinished(success));
150 scoped_ptr<SyncScheduler> CryptAuthEnrollmentManager::CreateSyncScheduler() {
151 return make_scoped_ptr(new SyncSchedulerImpl(
152 this, base::TimeDelta::FromDays(kEnrollmentRefreshPeriodDays),
153 base::TimeDelta::FromMinutes(kEnrollmentBaseRecoveryPeriodMinutes),
154 kEnrollmentMaxJitterRatio, "CryptAuth Enrollment"));
157 void CryptAuthEnrollmentManager::OnGCMRegistrationResult(bool success) {
158 if (!sync_request_)
159 return;
161 PA_LOG(INFO) << "GCM registration for CryptAuth Enrollment completed: "
162 << success;
163 if (success)
164 DoCryptAuthEnrollment();
165 else
166 OnEnrollmentFinished(false);
169 void CryptAuthEnrollmentManager::OnReenrollMessage() {
170 ForceEnrollmentNow(cryptauth::INVOCATION_REASON_SERVER_INITIATED);
173 void CryptAuthEnrollmentManager::OnSyncRequested(
174 scoped_ptr<SyncScheduler::SyncRequest> sync_request) {
175 FOR_EACH_OBSERVER(Observer, observers_, OnEnrollmentStarted());
177 sync_request_ = sync_request.Pass();
179 if (gcm_manager_->GetRegistrationId().empty()) {
180 gcm_manager_->RegisterWithGCM();
181 } else {
182 DoCryptAuthEnrollment();
186 void CryptAuthEnrollmentManager::DoCryptAuthEnrollment() {
187 DCHECK(sync_request_);
188 cryptauth::InvocationReason invocation_reason =
189 cryptauth::INVOCATION_REASON_UNKNOWN;
191 int reason_stored_in_prefs =
192 pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason);
194 if (cryptauth::InvocationReason_IsValid(reason_stored_in_prefs) &&
195 reason_stored_in_prefs != cryptauth::INVOCATION_REASON_UNKNOWN) {
196 invocation_reason =
197 static_cast<cryptauth::InvocationReason>(reason_stored_in_prefs);
198 } else if (GetLastEnrollmentTime().is_null()) {
199 invocation_reason = cryptauth::INVOCATION_REASON_INITIALIZATION;
200 } else if (!IsEnrollmentValid()) {
201 invocation_reason = cryptauth::INVOCATION_REASON_EXPIRATION;
202 } else if (scheduler_->GetStrategy() ==
203 SyncScheduler::Strategy::PERIODIC_REFRESH) {
204 invocation_reason = cryptauth::INVOCATION_REASON_PERIODIC;
205 } else if (scheduler_->GetStrategy() ==
206 SyncScheduler::Strategy::AGGRESSIVE_RECOVERY) {
207 invocation_reason = cryptauth::INVOCATION_REASON_FAILURE_RECOVERY;
210 PA_LOG(INFO) << "Making enrollment with reason: " << invocation_reason;
211 cryptauth_enroller_ = enroller_factory_->CreateInstance();
212 cryptauth_enroller_->Enroll(
213 user_public_key_, user_private_key_, device_info_, invocation_reason,
214 base::Bind(&CryptAuthEnrollmentManager::OnEnrollmentFinished,
215 weak_ptr_factory_.GetWeakPtr()));
218 } // namespace proximity_auth