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/prefs/pref_service.h"
10 #include "base/prefs/scoped_user_pref_update.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/signin/easy_unlock_toggle_flow.h"
15 #include "chrome/browser/signin/screenlock_bridge.h"
16 #include "chrome/browser/ui/extensions/application_launch.h"
17 #include "chrome/common/extensions/extension_constants.h"
18 #include "chrome/common/pref_names.h"
19 #include "components/pref_registry/pref_registry_syncable.h"
20 #include "extensions/browser/extension_system.h"
22 #if defined(OS_CHROMEOS)
23 #include "chrome/browser/chromeos/profiles/profile_helper.h"
24 #include "components/user_manager/user_manager.h"
29 // Key name of the local device permit record dictonary in kEasyUnlockPairing.
30 const char kKeyPermitAccess[] = "permitAccess";
32 // Key name of the remote device list in kEasyUnlockPairing.
33 const char kKeyDevices[] = "devices";
35 // Key name of the phone public key in a device dictionary.
36 const char kKeyPhoneId[] = "permitRecord.id";
40 EasyUnlockServiceRegular::EasyUnlockServiceRegular(Profile* profile)
41 : EasyUnlockService(profile),
42 turn_off_flow_status_(EasyUnlockService::IDLE) {
45 EasyUnlockServiceRegular::~EasyUnlockServiceRegular() {
48 EasyUnlockService::Type EasyUnlockServiceRegular::GetType() const {
49 return EasyUnlockService::TYPE_REGULAR;
52 std::string EasyUnlockServiceRegular::GetUserEmail() const {
53 return ScreenlockBridge::GetAuthenticatedUserEmail(profile());
56 void EasyUnlockServiceRegular::LaunchSetup() {
57 ExtensionService* service =
58 extensions::ExtensionSystem::Get(profile())->extension_service();
59 const extensions::Extension* extension =
60 service->GetExtensionById(extension_misc::kEasyUnlockAppId, false);
62 OpenApplication(AppLaunchParams(
63 profile(), extension, extensions::LAUNCH_CONTAINER_WINDOW, NEW_WINDOW));
66 const base::DictionaryValue* EasyUnlockServiceRegular::GetPermitAccess() const {
67 const base::DictionaryValue* pairing_dict =
68 profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
69 const base::DictionaryValue* permit_dict = NULL;
71 pairing_dict->GetDictionary(kKeyPermitAccess, &permit_dict))
77 void EasyUnlockServiceRegular::SetPermitAccess(
78 const base::DictionaryValue& permit) {
79 DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
80 prefs::kEasyUnlockPairing);
81 pairing_update->SetWithoutPathExpansion(kKeyPermitAccess, permit.DeepCopy());
84 void EasyUnlockServiceRegular::ClearPermitAccess() {
85 DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
86 prefs::kEasyUnlockPairing);
87 pairing_update->RemoveWithoutPathExpansion(kKeyPermitAccess, NULL);
90 const base::ListValue* EasyUnlockServiceRegular::GetRemoteDevices() const {
91 const base::DictionaryValue* pairing_dict =
92 profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
93 const base::ListValue* devices = NULL;
94 if (pairing_dict && pairing_dict->GetList(kKeyDevices, &devices))
100 void EasyUnlockServiceRegular::SetRemoteDevices(
101 const base::ListValue& devices) {
102 DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
103 prefs::kEasyUnlockPairing);
104 pairing_update->SetWithoutPathExpansion(kKeyDevices, devices.DeepCopy());
107 void EasyUnlockServiceRegular::ClearRemoteDevices() {
108 DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
109 prefs::kEasyUnlockPairing);
110 pairing_update->RemoveWithoutPathExpansion(kKeyDevices, NULL);
113 void EasyUnlockServiceRegular::RunTurnOffFlow() {
114 if (turn_off_flow_status_ == PENDING)
117 SetTurnOffFlowStatus(PENDING);
119 // Currently there should only be one registered phone.
120 // TODO(xiyuan): Revisit this when server supports toggle for all or
121 // there are multiple phones.
122 const base::DictionaryValue* pairing_dict =
123 profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
124 const base::ListValue* devices_list = NULL;
125 const base::DictionaryValue* first_device = NULL;
126 std::string phone_public_key;
127 if (!pairing_dict || !pairing_dict->GetList(kKeyDevices, &devices_list) ||
128 !devices_list || !devices_list->GetDictionary(0, &first_device) ||
130 !first_device->GetString(kKeyPhoneId, &phone_public_key)) {
131 LOG(WARNING) << "Bad easy unlock pairing data, wiping out local data";
132 OnTurnOffFlowFinished(true);
136 turn_off_flow_.reset(new EasyUnlockToggleFlow(
140 base::Bind(&EasyUnlockServiceRegular::OnTurnOffFlowFinished,
141 base::Unretained(this))));
142 turn_off_flow_->Start();
145 void EasyUnlockServiceRegular::ResetTurnOffFlow() {
146 turn_off_flow_.reset();
147 SetTurnOffFlowStatus(IDLE);
150 EasyUnlockService::TurnOffFlowStatus
151 EasyUnlockServiceRegular::GetTurnOffFlowStatus() const {
152 return turn_off_flow_status_;
155 std::string EasyUnlockServiceRegular::GetChallenge() const {
156 return std::string();
159 std::string EasyUnlockServiceRegular::GetWrappedSecret() const {
160 return std::string();
163 void EasyUnlockServiceRegular::InitializeInternal() {
164 registrar_.Init(profile()->GetPrefs());
166 prefs::kEasyUnlockAllowed,
167 base::Bind(&EasyUnlockServiceRegular::OnPrefsChanged,
168 base::Unretained(this)));
172 void EasyUnlockServiceRegular::ShutdownInternal() {
173 turn_off_flow_.reset();
174 turn_off_flow_status_ = EasyUnlockService::IDLE;
175 registrar_.RemoveAll();
178 bool EasyUnlockServiceRegular::IsAllowedInternal() {
179 #if defined(OS_CHROMEOS)
180 if (!user_manager::UserManager::Get()->IsLoggedInAsRegularUser())
183 if (!chromeos::ProfileHelper::IsPrimaryProfile(profile()))
188 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
193 void EasyUnlockServiceRegular::OnPrefsChanged() {
197 void EasyUnlockServiceRegular::SetTurnOffFlowStatus(TurnOffFlowStatus status) {
198 turn_off_flow_status_ = status;
199 NotifyTurnOffOperationStatusChanged();
202 void EasyUnlockServiceRegular::OnTurnOffFlowFinished(bool success) {
203 turn_off_flow_.reset();
206 SetTurnOffFlowStatus(FAIL);
210 ClearRemoteDevices();
211 SetTurnOffFlowStatus(IDLE);