Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / signin / easy_unlock_service_regular.cc
blob5ea569515db2f27f221ba06b7f90f80d581a8b23
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/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"
26 #endif
28 namespace {
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";
39 } // namespace
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;
71 if (pairing_dict &&
72 pairing_dict->GetDictionary(kKeyPermitAccess, &permit_dict))
73 return permit_dict;
75 return NULL;
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))
96 return devices;
98 return NULL;
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)
118 return;
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) ||
132 !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);
136 return;
139 turn_off_flow_.reset(new EasyUnlockToggleFlow(
140 profile(),
141 phone_public_key,
142 false,
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());
168 registrar_.Add(
169 prefs::kEasyUnlockAllowed,
170 base::Bind(&EasyUnlockServiceRegular::OnPrefsChanged,
171 base::Unretained(this)));
172 OnPrefsChanged();
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())
184 return false;
186 if (!chromeos::ProfileHelper::IsPrimaryProfile(profile()))
187 return false;
189 if (!profile()->GetPrefs()->GetBoolean(prefs::kEasyUnlockAllowed))
190 return false;
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";
198 return true;
199 #else
200 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
201 return false;
202 #endif
205 void EasyUnlockServiceRegular::OnPrefsChanged() {
206 UpdateAppState();
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();
217 if (!success) {
218 SetTurnOffFlowStatus(FAIL);
219 return;
222 ClearRemoteDevices();
223 SetTurnOffFlowStatus(IDLE);
224 ReloadApp();