Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / signin / easy_unlock_service_regular.cc
blob80fe3c2cdd4abe88bb8657216b411c5e73befc45
1 // Copyright 2014 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 "chrome/browser/signin/easy_unlock_service_regular.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/prefs/scoped_user_pref_update.h"
11 #include "base/sys_info.h"
12 #include "base/values.h"
13 #include "base/version.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
17 #include "chrome/browser/signin/screenlock_bridge.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/common/chrome_version_info.h"
20 #include "chrome/common/extensions/api/easy_unlock_private.h"
21 #include "chrome/common/extensions/extension_constants.h"
22 #include "chrome/common/pref_names.h"
23 #include "chromeos/login/user_names.h"
24 #include "components/pref_registry/pref_registry_syncable.h"
25 #include "components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.h"
26 #include "components/proximity_auth/cryptauth/cryptauth_client.h"
27 #include "components/proximity_auth/cryptauth/cryptauth_client_factory.h"
28 #include "components/proximity_auth/switches.h"
29 #include "components/signin/core/browser/profile_oauth2_token_service.h"
30 #include "components/signin/core/browser/signin_manager.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "extensions/browser/event_router.h"
33 #include "extensions/common/constants.h"
35 #if defined(OS_CHROMEOS)
36 #include "apps/app_lifetime_monitor_factory.h"
37 #include "base/thread_task_runner_handle.h"
38 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
39 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.h"
40 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
41 #include "chrome/browser/chromeos/profiles/profile_helper.h"
42 #include "components/user_manager/user_manager.h"
43 #endif
45 namespace {
47 // Key name of the local device permit record dictonary in kEasyUnlockPairing.
48 const char kKeyPermitAccess[] = "permitAccess";
50 // Key name of the remote device list in kEasyUnlockPairing.
51 const char kKeyDevices[] = "devices";
53 // Constructs the DeviceClassifier message that is sent to CryptAuth for all API
54 // requests.
55 cryptauth::DeviceClassifier GetDeviceClassifier() {
56 cryptauth::DeviceClassifier device_classifier;
58 #if defined(OS_CHROMEOS)
59 int32 major_version, minor_version, bugfix_version;
60 // TODO(tengs): base::OperatingSystemVersionNumbers only works for ChromeOS.
61 // We need to get different numbers for other platforms.
62 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
63 &bugfix_version);
64 device_classifier.set_device_os_version_code(major_version);
65 device_classifier.set_device_type(cryptauth::CHROME);
66 #endif
68 chrome::VersionInfo version_info;
69 const std::vector<uint32_t>& version_components =
70 base::Version(version_info.Version()).components();
71 if (version_components.size() > 0)
72 device_classifier.set_device_software_version_code(version_components[0]);
74 device_classifier.set_device_software_package(version_info.Name());
75 return device_classifier;
78 } // namespace
80 EasyUnlockServiceRegular::EasyUnlockServiceRegular(Profile* profile)
81 : EasyUnlockService(profile),
82 turn_off_flow_status_(EasyUnlockService::IDLE),
83 will_unlock_using_easy_unlock_(false),
84 lock_screen_last_shown_timestamp_(base::TimeTicks::Now()),
85 weak_ptr_factory_(this) {
88 EasyUnlockServiceRegular::~EasyUnlockServiceRegular() {
91 EasyUnlockService::Type EasyUnlockServiceRegular::GetType() const {
92 return EasyUnlockService::TYPE_REGULAR;
95 std::string EasyUnlockServiceRegular::GetUserEmail() const {
96 return ScreenlockBridge::GetAuthenticatedUserEmail(profile());
99 void EasyUnlockServiceRegular::LaunchSetup() {
100 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
101 #if defined(OS_CHROMEOS)
102 // Force the user to reauthenticate by showing a modal overlay (similar to the
103 // lock screen). The password obtained from the reauth is cached for a short
104 // period of time and used to create the cryptohome keys for sign-in.
105 if (short_lived_user_context_ && short_lived_user_context_->user_context()) {
106 OpenSetupApp();
107 } else {
108 bool reauth_success = chromeos::EasyUnlockReauth::ReauthForUserContext(
109 base::Bind(&EasyUnlockServiceRegular::OnUserContextFromReauth,
110 weak_ptr_factory_.GetWeakPtr()));
111 if (!reauth_success)
112 OpenSetupApp();
114 #else
115 OpenSetupApp();
116 #endif
119 #if defined(OS_CHROMEOS)
120 void EasyUnlockServiceRegular::OnUserContextFromReauth(
121 const chromeos::UserContext& user_context) {
122 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
123 short_lived_user_context_.reset(new chromeos::ShortLivedUserContext(
124 user_context, apps::AppLifetimeMonitorFactory::GetForProfile(profile()),
125 base::ThreadTaskRunnerHandle::Get().get()));
127 OpenSetupApp();
129 // Use this opportunity to clear the crytohome keys if it was not already
130 // cleared earlier.
131 const base::ListValue* devices = GetRemoteDevices();
132 if (!devices || devices->empty()) {
133 chromeos::EasyUnlockKeyManager* key_manager =
134 chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager();
135 key_manager->RefreshKeys(
136 user_context, base::ListValue(),
137 base::Bind(&EasyUnlockServiceRegular::SetHardlockAfterKeyOperation,
138 weak_ptr_factory_.GetWeakPtr(),
139 EasyUnlockScreenlockStateHandler::NO_PAIRING));
143 void EasyUnlockServiceRegular::SetHardlockAfterKeyOperation(
144 EasyUnlockScreenlockStateHandler::HardlockState state_on_success,
145 bool success) {
146 if (success)
147 SetHardlockStateForUser(GetUserEmail(), state_on_success);
149 // Even if the refresh keys operation suceeded, we still fetch and check the
150 // cryptohome keys against the keys in local preferences as a sanity check.
151 CheckCryptohomeKeysAndMaybeHardlock();
153 #endif
155 const base::DictionaryValue* EasyUnlockServiceRegular::GetPermitAccess() const {
156 const base::DictionaryValue* pairing_dict =
157 profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
158 const base::DictionaryValue* permit_dict = NULL;
159 if (pairing_dict &&
160 pairing_dict->GetDictionary(kKeyPermitAccess, &permit_dict))
161 return permit_dict;
163 return NULL;
166 void EasyUnlockServiceRegular::SetPermitAccess(
167 const base::DictionaryValue& permit) {
168 DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
169 prefs::kEasyUnlockPairing);
170 pairing_update->SetWithoutPathExpansion(kKeyPermitAccess, permit.DeepCopy());
173 void EasyUnlockServiceRegular::ClearPermitAccess() {
174 DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
175 prefs::kEasyUnlockPairing);
176 pairing_update->RemoveWithoutPathExpansion(kKeyPermitAccess, NULL);
179 const base::ListValue* EasyUnlockServiceRegular::GetRemoteDevices() const {
180 const base::DictionaryValue* pairing_dict =
181 profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
182 const base::ListValue* devices = NULL;
183 if (pairing_dict && pairing_dict->GetList(kKeyDevices, &devices))
184 return devices;
186 return NULL;
189 void EasyUnlockServiceRegular::SetRemoteDevices(
190 const base::ListValue& devices) {
191 DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
192 prefs::kEasyUnlockPairing);
193 if (devices.empty())
194 pairing_update->RemoveWithoutPathExpansion(kKeyDevices, NULL);
195 else
196 pairing_update->SetWithoutPathExpansion(kKeyDevices, devices.DeepCopy());
198 #if defined(OS_CHROMEOS)
199 // TODO(tengs): Investigate if we can determine if the remote devices were set
200 // from sync or from the setup app.
201 if (short_lived_user_context_ && short_lived_user_context_->user_context()) {
202 // We may already have the password cached, so proceed to create the
203 // cryptohome keys for sign-in or the system will be hardlocked.
204 chromeos::UserSessionManager::GetInstance()
205 ->GetEasyUnlockKeyManager()
206 ->RefreshKeys(
207 *short_lived_user_context_->user_context(), devices,
208 base::Bind(&EasyUnlockServiceRegular::SetHardlockAfterKeyOperation,
209 weak_ptr_factory_.GetWeakPtr(),
210 EasyUnlockScreenlockStateHandler::NO_HARDLOCK));
211 } else {
212 CheckCryptohomeKeysAndMaybeHardlock();
214 #else
215 CheckCryptohomeKeysAndMaybeHardlock();
216 #endif
219 void EasyUnlockServiceRegular::RunTurnOffFlow() {
220 if (turn_off_flow_status_ == PENDING)
221 return;
222 DCHECK(!cryptauth_client_);
224 SetTurnOffFlowStatus(PENDING);
226 proximity_auth::CryptAuthClientFactory factory(
227 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()),
228 SigninManagerFactory::GetForProfile(profile())
229 ->GetAuthenticatedAccountId(),
230 profile()->GetRequestContext(), GetDeviceClassifier());
231 cryptauth_client_ = factory.CreateInstance();
233 cryptauth::ToggleEasyUnlockRequest request;
234 request.set_enable(false);
235 request.set_apply_to_all(true);
236 cryptauth_client_->ToggleEasyUnlock(
237 request,
238 base::Bind(&EasyUnlockServiceRegular::OnToggleEasyUnlockApiComplete,
239 weak_ptr_factory_.GetWeakPtr()),
240 base::Bind(&EasyUnlockServiceRegular::OnToggleEasyUnlockApiFailed,
241 weak_ptr_factory_.GetWeakPtr()));
244 void EasyUnlockServiceRegular::ResetTurnOffFlow() {
245 cryptauth_client_.reset();
246 SetTurnOffFlowStatus(IDLE);
249 EasyUnlockService::TurnOffFlowStatus
250 EasyUnlockServiceRegular::GetTurnOffFlowStatus() const {
251 return turn_off_flow_status_;
254 std::string EasyUnlockServiceRegular::GetChallenge() const {
255 return std::string();
258 std::string EasyUnlockServiceRegular::GetWrappedSecret() const {
259 return std::string();
262 void EasyUnlockServiceRegular::RecordEasySignInOutcome(
263 const std::string& user_id,
264 bool success) const {
265 NOTREACHED();
268 void EasyUnlockServiceRegular::RecordPasswordLoginEvent(
269 const std::string& user_id) const {
270 NOTREACHED();
273 void EasyUnlockServiceRegular::StartAutoPairing(
274 const AutoPairingResultCallback& callback) {
275 if (!auto_pairing_callback_.is_null()) {
276 LOG(ERROR)
277 << "Start auto pairing when there is another auto pairing requested.";
278 callback.Run(false, std::string());
279 return;
282 auto_pairing_callback_ = callback;
284 scoped_ptr<base::ListValue> args(new base::ListValue());
285 scoped_ptr<extensions::Event> event(new extensions::Event(
286 extensions::api::easy_unlock_private::OnStartAutoPairing::kEventName,
287 args.Pass()));
288 extensions::EventRouter::Get(profile())->DispatchEventWithLazyListener(
289 extension_misc::kEasyUnlockAppId, event.Pass());
292 void EasyUnlockServiceRegular::SetAutoPairingResult(
293 bool success,
294 const std::string& error) {
295 DCHECK(!auto_pairing_callback_.is_null());
297 auto_pairing_callback_.Run(success, error);
298 auto_pairing_callback_.Reset();
301 void EasyUnlockServiceRegular::InitializeInternal() {
302 ScreenlockBridge::Get()->AddObserver(this);
303 registrar_.Init(profile()->GetPrefs());
304 registrar_.Add(
305 prefs::kEasyUnlockAllowed,
306 base::Bind(&EasyUnlockServiceRegular::OnPrefsChanged,
307 base::Unretained(this)));
308 registrar_.Add(prefs::kEasyUnlockProximityRequired,
309 base::Bind(&EasyUnlockServiceRegular::OnPrefsChanged,
310 base::Unretained(this)));
311 OnPrefsChanged();
314 void EasyUnlockServiceRegular::ShutdownInternal() {
315 #if defined(OS_CHROMEOS)
316 short_lived_user_context_.reset();
317 #endif
319 turn_off_flow_status_ = EasyUnlockService::IDLE;
320 registrar_.RemoveAll();
321 ScreenlockBridge::Get()->RemoveObserver(this);
324 bool EasyUnlockServiceRegular::IsAllowedInternal() const {
325 #if defined(OS_CHROMEOS)
326 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
327 if (!user_manager->IsLoggedInAsUserWithGaiaAccount())
328 return false;
330 // TODO(tengs): Ephemeral accounts generate a new enrollment every time they
331 // are added, so disable Smart Lock to reduce enrollments on server. However,
332 // ephemeral accounts can be locked, so we should revisit this use case.
333 if (user_manager->IsCurrentUserNonCryptohomeDataEphemeral())
334 return false;
336 if (!chromeos::ProfileHelper::IsPrimaryProfile(profile()))
337 return false;
339 if (!profile()->GetPrefs()->GetBoolean(prefs::kEasyUnlockAllowed))
340 return false;
342 return true;
343 #else
344 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
345 return false;
346 #endif
349 void EasyUnlockServiceRegular::OnWillFinalizeUnlock(bool success) {
350 will_unlock_using_easy_unlock_ = success;
353 void EasyUnlockServiceRegular::OnSuspendDone() {
354 lock_screen_last_shown_timestamp_ = base::TimeTicks::Now();
357 void EasyUnlockServiceRegular::OnScreenDidLock(
358 ScreenlockBridge::LockHandler::ScreenType screen_type) {
359 will_unlock_using_easy_unlock_ = false;
360 lock_screen_last_shown_timestamp_ = base::TimeTicks::Now();
363 void EasyUnlockServiceRegular::OnScreenDidUnlock(
364 ScreenlockBridge::LockHandler::ScreenType screen_type) {
365 // Notifications of signin screen unlock events can also reach this code path;
366 // disregard them.
367 if (screen_type != ScreenlockBridge::LockHandler::LOCK_SCREEN)
368 return;
370 // Only record metrics for users who have enabled the feature.
371 if (IsEnabled()) {
372 EasyUnlockAuthEvent event =
373 will_unlock_using_easy_unlock_
374 ? EASY_UNLOCK_SUCCESS
375 : GetPasswordAuthEvent();
376 RecordEasyUnlockScreenUnlockEvent(event);
378 if (will_unlock_using_easy_unlock_) {
379 RecordEasyUnlockScreenUnlockDuration(
380 base::TimeTicks::Now() - lock_screen_last_shown_timestamp_);
384 will_unlock_using_easy_unlock_ = false;
387 void EasyUnlockServiceRegular::OnFocusedUserChanged(
388 const std::string& user_id) {
389 // Nothing to do.
392 void EasyUnlockServiceRegular::OnPrefsChanged() {
393 SyncProfilePrefsToLocalState();
394 UpdateAppState();
397 void EasyUnlockServiceRegular::SetTurnOffFlowStatus(TurnOffFlowStatus status) {
398 turn_off_flow_status_ = status;
399 NotifyTurnOffOperationStatusChanged();
402 void EasyUnlockServiceRegular::OnToggleEasyUnlockApiComplete(
403 const cryptauth::ToggleEasyUnlockResponse& response) {
404 cryptauth_client_.reset();
406 SetRemoteDevices(base::ListValue());
407 SetTurnOffFlowStatus(IDLE);
408 ReloadAppAndLockScreen();
411 void EasyUnlockServiceRegular::OnToggleEasyUnlockApiFailed(
412 const std::string& error_message) {
413 LOG(WARNING) << "Failed to turn off Smart Lock: " << error_message;
414 SetTurnOffFlowStatus(FAIL);
417 void EasyUnlockServiceRegular::SyncProfilePrefsToLocalState() {
418 PrefService* local_state =
419 g_browser_process ? g_browser_process->local_state() : NULL;
420 PrefService* profile_prefs = profile()->GetPrefs();
421 if (!local_state || !profile_prefs)
422 return;
424 // Create the dictionary of Easy Unlock preferences for the current user. The
425 // items in the dictionary are the same profile prefs used for Easy Unlock.
426 scoped_ptr<base::DictionaryValue> user_prefs_dict(
427 new base::DictionaryValue());
428 user_prefs_dict->SetBooleanWithoutPathExpansion(
429 prefs::kEasyUnlockProximityRequired,
430 profile_prefs->GetBoolean(prefs::kEasyUnlockProximityRequired));
432 DictionaryPrefUpdate update(local_state,
433 prefs::kEasyUnlockLocalStateUserPrefs);
434 std::string user_email = GetUserEmail();
435 update->SetWithoutPathExpansion(user_email, user_prefs_dict.Pass());