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"
8 #include "base/logging.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/prefs/scoped_user_pref_update.h"
12 #include "base/values.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/signin/easy_unlock_toggle_flow.h"
16 #include "chrome/browser/signin/screenlock_bridge.h"
17 #include "chrome/browser/ui/extensions/application_launch.h"
18 #include "chrome/common/extensions/extension_constants.h"
19 #include "chrome/common/pref_names.h"
20 #include "components/pref_registry/pref_registry_syncable.h"
21 #include "extensions/browser/extension_system.h"
23 #if defined(OS_CHROMEOS)
24 #include "chrome/browser/chromeos/profiles/profile_helper.h"
25 #include "components/user_manager/user_manager.h"
30 // Key name of the local device permit record dictonary in kEasyUnlockPairing.
31 const char kKeyPermitAccess
[] = "permitAccess";
33 // Key name of the remote device list in kEasyUnlockPairing.
34 const char kKeyDevices
[] = "devices";
36 // Key name of the phone public key in a device dictionary.
37 const char kKeyPhoneId
[] = "permitRecord.id";
41 EasyUnlockServiceRegular::EasyUnlockServiceRegular(Profile
* profile
)
42 : EasyUnlockService(profile
),
43 turn_off_flow_status_(EasyUnlockService::IDLE
) {
46 EasyUnlockServiceRegular::~EasyUnlockServiceRegular() {
49 EasyUnlockService::Type
EasyUnlockServiceRegular::GetType() const {
50 return EasyUnlockService::TYPE_REGULAR
;
53 std::string
EasyUnlockServiceRegular::GetUserEmail() const {
54 return ScreenlockBridge::GetAuthenticatedUserEmail(profile());
57 void EasyUnlockServiceRegular::LaunchSetup() {
58 ExtensionService
* service
=
59 extensions::ExtensionSystem::Get(profile())->extension_service();
60 const extensions::Extension
* extension
=
61 service
->GetExtensionById(extension_misc::kEasyUnlockAppId
, false);
63 OpenApplication(AppLaunchParams(
64 profile(), extension
, extensions::LAUNCH_CONTAINER_WINDOW
, NEW_WINDOW
));
67 const base::DictionaryValue
* EasyUnlockServiceRegular::GetPermitAccess() const {
68 const base::DictionaryValue
* pairing_dict
=
69 profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing
);
70 const base::DictionaryValue
* permit_dict
= NULL
;
72 pairing_dict
->GetDictionary(kKeyPermitAccess
, &permit_dict
))
78 void EasyUnlockServiceRegular::SetPermitAccess(
79 const base::DictionaryValue
& permit
) {
80 DictionaryPrefUpdate
pairing_update(profile()->GetPrefs(),
81 prefs::kEasyUnlockPairing
);
82 pairing_update
->SetWithoutPathExpansion(kKeyPermitAccess
, permit
.DeepCopy());
85 void EasyUnlockServiceRegular::ClearPermitAccess() {
86 DictionaryPrefUpdate
pairing_update(profile()->GetPrefs(),
87 prefs::kEasyUnlockPairing
);
88 pairing_update
->RemoveWithoutPathExpansion(kKeyPermitAccess
, NULL
);
91 const base::ListValue
* EasyUnlockServiceRegular::GetRemoteDevices() const {
92 const base::DictionaryValue
* pairing_dict
=
93 profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing
);
94 const base::ListValue
* devices
= NULL
;
95 if (pairing_dict
&& pairing_dict
->GetList(kKeyDevices
, &devices
))
101 void EasyUnlockServiceRegular::SetRemoteDevices(
102 const base::ListValue
& devices
) {
103 DictionaryPrefUpdate
pairing_update(profile()->GetPrefs(),
104 prefs::kEasyUnlockPairing
);
105 pairing_update
->SetWithoutPathExpansion(kKeyDevices
, devices
.DeepCopy());
106 CheckCryptohomeKeysAndMaybeHardlock();
109 void EasyUnlockServiceRegular::ClearRemoteDevices() {
110 DictionaryPrefUpdate
pairing_update(profile()->GetPrefs(),
111 prefs::kEasyUnlockPairing
);
112 pairing_update
->RemoveWithoutPathExpansion(kKeyDevices
, NULL
);
113 CheckCryptohomeKeysAndMaybeHardlock();
116 void EasyUnlockServiceRegular::RunTurnOffFlow() {
117 if (turn_off_flow_status_
== PENDING
)
120 SetTurnOffFlowStatus(PENDING
);
122 // Currently there should only be one registered phone.
123 // TODO(xiyuan): Revisit this when server supports toggle for all or
124 // there are multiple phones.
125 const base::DictionaryValue
* pairing_dict
=
126 profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing
);
127 const base::ListValue
* devices_list
= NULL
;
128 const base::DictionaryValue
* first_device
= NULL
;
129 std::string phone_public_key
;
130 if (!pairing_dict
|| !pairing_dict
->GetList(kKeyDevices
, &devices_list
) ||
131 !devices_list
|| !devices_list
->GetDictionary(0, &first_device
) ||
133 !first_device
->GetString(kKeyPhoneId
, &phone_public_key
)) {
134 LOG(WARNING
) << "Bad easy unlock pairing data, wiping out local data";
135 OnTurnOffFlowFinished(true);
139 turn_off_flow_
.reset(new EasyUnlockToggleFlow(
143 base::Bind(&EasyUnlockServiceRegular::OnTurnOffFlowFinished
,
144 base::Unretained(this))));
145 turn_off_flow_
->Start();
148 void EasyUnlockServiceRegular::ResetTurnOffFlow() {
149 turn_off_flow_
.reset();
150 SetTurnOffFlowStatus(IDLE
);
153 EasyUnlockService::TurnOffFlowStatus
154 EasyUnlockServiceRegular::GetTurnOffFlowStatus() const {
155 return turn_off_flow_status_
;
158 std::string
EasyUnlockServiceRegular::GetChallenge() const {
159 return std::string();
162 std::string
EasyUnlockServiceRegular::GetWrappedSecret() const {
163 return std::string();
166 void EasyUnlockServiceRegular::InitializeInternal() {
167 registrar_
.Init(profile()->GetPrefs());
169 prefs::kEasyUnlockAllowed
,
170 base::Bind(&EasyUnlockServiceRegular::OnPrefsChanged
,
171 base::Unretained(this)));
175 void EasyUnlockServiceRegular::ShutdownInternal() {
176 turn_off_flow_
.reset();
177 turn_off_flow_status_
= EasyUnlockService::IDLE
;
178 registrar_
.RemoveAll();
181 bool EasyUnlockServiceRegular::IsAllowedInternal() {
182 #if defined(OS_CHROMEOS)
183 if (!user_manager::UserManager::Get()->IsLoggedInAsRegularUser())
186 if (!chromeos::ProfileHelper::IsPrimaryProfile(profile()))
189 if (!profile()->GetPrefs()->GetBoolean(prefs::kEasyUnlockAllowed
))
192 // Respect existing policy and skip finch test.
193 if (!profile()->GetPrefs()->IsManagedPreference(prefs::kEasyUnlockAllowed
)) {
194 // It is enabled when the trial exists and is in "Enable" group.
195 return base::FieldTrialList::FindFullName("EasyUnlock") == "Enable";
200 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
205 void EasyUnlockServiceRegular::OnPrefsChanged() {
209 void EasyUnlockServiceRegular::SetTurnOffFlowStatus(TurnOffFlowStatus status
) {
210 turn_off_flow_status_
= status
;
211 NotifyTurnOffOperationStatusChanged();
214 void EasyUnlockServiceRegular::OnTurnOffFlowFinished(bool success
) {
215 turn_off_flow_
.reset();
218 SetTurnOffFlowStatus(FAIL
);
222 ClearRemoteDevices();
223 SetTurnOffFlowStatus(IDLE
);