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_screenlock_state_handler.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/string16.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chromeos/chromeos_utils.h"
12 #include "chrome/common/pref_names.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "ui/base/l10n/l10n_util.h"
18 size_t kIconSize = 27u;
19 size_t kSpinnerResourceWidth = 1215u;
20 size_t kSpinnerIntervalMs = 50u;
22 std::string GetIconURLForState(EasyUnlockScreenlockStateHandler::State state) {
24 case EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH:
25 case EasyUnlockScreenlockStateHandler::STATE_NO_PHONE:
26 case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED:
27 case EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED:
28 case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_NEARBY:
29 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE:
30 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED:
31 return "chrome://theme/IDR_EASY_UNLOCK_LOCKED";
32 case EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING:
33 return "chrome://theme/IDR_EASY_UNLOCK_SPINNER";
34 case EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED:
35 return "chrome://theme/IDR_EASY_UNLOCK_UNLOCKED";
41 bool HasAnimation(EasyUnlockScreenlockStateHandler::State state) {
42 return state == EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING;
45 bool HardlockOnClick(EasyUnlockScreenlockStateHandler::State state) {
46 return state != EasyUnlockScreenlockStateHandler::STATE_INACTIVE;
49 size_t GetTooltipResourceId(EasyUnlockScreenlockStateHandler::State state) {
51 case EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH:
52 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_NO_BLUETOOTH;
53 case EasyUnlockScreenlockStateHandler::STATE_NO_PHONE:
54 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_NO_PHONE;
55 case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED:
56 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_NOT_AUTHENTICATED;
57 case EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED:
58 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_LOCKED;
59 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE:
60 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_UNLOCKABLE;
61 case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_NEARBY:
62 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_NOT_NEARBY;
63 case EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED:
64 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_INSTRUCTIONS;
65 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED:
66 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_UNSUPPORTED_ANDROID_VERSION;
72 bool TooltipContainsDeviceType(EasyUnlockScreenlockStateHandler::State state) {
73 return state == EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED ||
74 state == EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE ||
75 state == EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH ||
76 state == EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED;
82 EasyUnlockScreenlockStateHandler::EasyUnlockScreenlockStateHandler(
83 const std::string& user_email,
84 PrefService* pref_service,
85 ScreenlockBridge* screenlock_bridge)
86 : state_(STATE_INACTIVE),
87 user_email_(user_email),
88 pref_service_(pref_service),
89 screenlock_bridge_(screenlock_bridge) {
90 DCHECK(screenlock_bridge_);
91 screenlock_bridge_->AddObserver(this);
94 EasyUnlockScreenlockStateHandler::~EasyUnlockScreenlockStateHandler() {
95 screenlock_bridge_->RemoveObserver(this);
96 // Make sure the screenlock state set by this gets cleared.
97 ChangeState(STATE_INACTIVE);
100 void EasyUnlockScreenlockStateHandler::ChangeState(State new_state) {
101 if (state_ == new_state)
106 // If lock screen is not active or it forces offline password, just cache the
107 // current state. The screenlock state will get refreshed in |ScreenDidLock|.
108 if (!screenlock_bridge_->IsLocked() ||
109 screenlock_bridge_->lock_handler()->GetAuthType(user_email_) ==
110 ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD) {
114 UpdateScreenlockAuthType();
116 ScreenlockBridge::UserPodCustomIconOptions icon_options;
118 std::string icon_url = GetIconURLForState(state_);
119 if (icon_url.empty()) {
120 screenlock_bridge_->lock_handler()->HideUserPodCustomIcon(user_email_);
123 icon_options.SetIconAsResourceURL(icon_url);
125 bool trial_run = IsTrialRun();
127 UpdateTooltipOptions(trial_run, &icon_options);
129 icon_options.SetSize(kIconSize, kIconSize);
131 if (HasAnimation(state_))
132 icon_options.SetAnimation(kSpinnerResourceWidth, kSpinnerIntervalMs);
134 // Hardlocking is disabled in trial run.
135 if (!trial_run && HardlockOnClick(state_))
136 icon_options.SetHardlockOnClick();
138 if (trial_run && state_ == STATE_AUTHENTICATED)
139 MarkTrialRunComplete();
141 screenlock_bridge_->lock_handler()->ShowUserPodCustomIcon(user_email_,
145 void EasyUnlockScreenlockStateHandler::OnScreenDidLock() {
146 State last_state = state_;
147 // This should force updating screenlock state.
148 state_ = STATE_INACTIVE;
149 ChangeState(last_state);
152 void EasyUnlockScreenlockStateHandler::OnScreenDidUnlock() {
155 void EasyUnlockScreenlockStateHandler::OnFocusedUserChanged(
156 const std::string& user_id) {
159 void EasyUnlockScreenlockStateHandler::UpdateTooltipOptions(
161 ScreenlockBridge::UserPodCustomIconOptions* icon_options) {
162 size_t resource_id = 0;
163 base::string16 device_name;
164 if (trial_run && state_ == STATE_AUTHENTICATED) {
165 resource_id = IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_TUTORIAL;
167 resource_id = GetTooltipResourceId(state_);
168 if (TooltipContainsDeviceType(state_))
169 device_name = GetDeviceName();
175 base::string16 tooltip;
176 if (device_name.empty()) {
177 tooltip = l10n_util::GetStringUTF16(resource_id);
179 tooltip = l10n_util::GetStringFUTF16(resource_id, device_name);
185 icon_options->SetTooltip(
187 state_ == STATE_AUTHENTICATED && trial_run /* autoshow tooltip */);
190 bool EasyUnlockScreenlockStateHandler::IsTrialRun() {
191 return pref_service_ &&
192 pref_service_->GetBoolean(prefs::kEasyUnlockShowTutorial);
195 void EasyUnlockScreenlockStateHandler::MarkTrialRunComplete() {
198 pref_service_->SetBoolean(prefs::kEasyUnlockShowTutorial, false);
201 base::string16 EasyUnlockScreenlockStateHandler::GetDeviceName() {
202 #if defined(OS_CHROMEOS)
203 return chromeos::GetChromeDeviceType();
205 // TODO(tbarzic): Figure out the name for non Chrome OS case.
206 return base::ASCIIToUTF16("Chrome");
210 void EasyUnlockScreenlockStateHandler::UpdateScreenlockAuthType() {
211 if (screenlock_bridge_->lock_handler()->GetAuthType(user_email_) ==
212 ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD)
215 if (state_ == STATE_AUTHENTICATED) {
216 screenlock_bridge_->lock_handler()->SetAuthType(
218 ScreenlockBridge::LockHandler::USER_CLICK,
219 l10n_util::GetStringUTF16(
220 IDS_EASY_UNLOCK_SCREENLOCK_USER_POD_AUTH_VALUE));
221 } else if (screenlock_bridge_->lock_handler()->GetAuthType(user_email_) !=
222 ScreenlockBridge::LockHandler::OFFLINE_PASSWORD) {
223 screenlock_bridge_->lock_handler()->SetAuthType(
225 ScreenlockBridge::LockHandler::OFFLINE_PASSWORD,