[Smart Lock] Update UI strings to match latest mocks.
[chromium-blink-merge.git] / chrome / browser / signin / easy_unlock_screenlock_state_handler.cc
blobc93613b82d0fb8b463330f518208089eb0534dd2
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"
7 #include "base/bind.h"
8 #include "base/strings/string16.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/chromeos/chromeos_utils.h"
11 #include "chrome/grit/generated_resources.h"
12 #include "ui/base/l10n/l10n_util.h"
14 namespace {
16 ScreenlockBridge::UserPodCustomIcon GetIconForState(
17 EasyUnlockScreenlockStateHandler::State state) {
18 switch (state) {
19 case EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH:
20 case EasyUnlockScreenlockStateHandler::STATE_NO_PHONE:
21 case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED:
22 case EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED:
23 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE:
24 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED:
25 case EasyUnlockScreenlockStateHandler::STATE_RSSI_TOO_LOW:
26 return ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED;
27 case EasyUnlockScreenlockStateHandler::STATE_TX_POWER_TOO_HIGH:
28 return ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED_WITH_PROXIMITY_HINT;
29 case EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING:
30 return ScreenlockBridge::USER_POD_CUSTOM_ICON_SPINNER;
31 case EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED:
32 return ScreenlockBridge::USER_POD_CUSTOM_ICON_UNLOCKED;
33 default:
34 return ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE;
38 bool HardlockOnClick(EasyUnlockScreenlockStateHandler::State state) {
39 return state != EasyUnlockScreenlockStateHandler::STATE_INACTIVE;
42 size_t GetTooltipResourceId(EasyUnlockScreenlockStateHandler::State state) {
43 switch (state) {
44 case EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH:
45 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_NO_BLUETOOTH;
46 case EasyUnlockScreenlockStateHandler::STATE_NO_PHONE:
47 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_NO_PHONE;
48 case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED:
49 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_NOT_AUTHENTICATED;
50 case EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED:
51 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_LOCKED;
52 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE:
53 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_UNLOCKABLE;
54 case EasyUnlockScreenlockStateHandler::STATE_RSSI_TOO_LOW:
55 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_RSSI_TOO_LOW;
56 case EasyUnlockScreenlockStateHandler::STATE_TX_POWER_TOO_HIGH:
57 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_TX_POWER_TOO_HIGH;
58 case EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED:
59 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_INSTRUCTIONS;
60 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED:
61 return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_UNSUPPORTED_ANDROID_VERSION;
62 default:
63 return 0;
67 bool TooltipContainsDeviceType(EasyUnlockScreenlockStateHandler::State state) {
68 return state == EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED ||
69 state == EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE ||
70 state == EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH ||
71 state == EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED ||
72 state == EasyUnlockScreenlockStateHandler::STATE_RSSI_TOO_LOW ||
73 state == EasyUnlockScreenlockStateHandler::STATE_TX_POWER_TOO_HIGH;
76 } // namespace
79 EasyUnlockScreenlockStateHandler::EasyUnlockScreenlockStateHandler(
80 const std::string& user_email,
81 HardlockState initial_hardlock_state,
82 ScreenlockBridge* screenlock_bridge)
83 : state_(STATE_INACTIVE),
84 user_email_(user_email),
85 screenlock_bridge_(screenlock_bridge),
86 hardlock_state_(initial_hardlock_state),
87 hardlock_ui_shown_(false),
88 is_trial_run_(false) {
89 DCHECK(screenlock_bridge_);
90 screenlock_bridge_->AddObserver(this);
93 EasyUnlockScreenlockStateHandler::~EasyUnlockScreenlockStateHandler() {
94 screenlock_bridge_->RemoveObserver(this);
95 // Make sure the screenlock state set by this gets cleared.
96 ChangeState(STATE_INACTIVE);
99 bool EasyUnlockScreenlockStateHandler::IsActive() const {
100 return state_ != STATE_INACTIVE;
103 bool EasyUnlockScreenlockStateHandler::InStateValidOnRemoteAuthFailure() const {
104 // Note that NO_PHONE is not valid in this case because the phone may close
105 // the connection if the auth challenge sent to it is invalid. This case
106 // should be handled as authentication failure.
107 return state_ == EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH ||
108 state_ == EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED;
111 void EasyUnlockScreenlockStateHandler::ChangeState(State new_state) {
112 if (state_ == new_state)
113 return;
115 state_ = new_state;
117 // If lock screen is not active or it forces offline password, just cache the
118 // current state. The screenlock state will get refreshed in |ScreenDidLock|.
119 if (!screenlock_bridge_->IsLocked())
120 return;
122 // Do nothing when auth type is online.
123 if (screenlock_bridge_->lock_handler()->GetAuthType(user_email_) ==
124 ScreenlockBridge::LockHandler::ONLINE_SIGN_IN) {
125 return;
128 // No hardlock UI for trial run.
129 if (!is_trial_run_ && hardlock_state_ != NO_HARDLOCK) {
130 ShowHardlockUI();
131 return;
134 UpdateScreenlockAuthType();
136 ScreenlockBridge::UserPodCustomIcon icon = GetIconForState(state_);
138 if (icon == ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE) {
139 screenlock_bridge_->lock_handler()->HideUserPodCustomIcon(user_email_);
140 return;
143 ScreenlockBridge::UserPodCustomIconOptions icon_options;
144 icon_options.SetIcon(icon);
146 // Don't hardlock on trial run.
147 if (!is_trial_run_ && HardlockOnClick(state_))
148 icon_options.SetHardlockOnClick();
150 UpdateTooltipOptions(is_trial_run_, &icon_options);
152 // For states without tooltips, we still need to set an accessibility label.
153 if (state_ == EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING) {
154 icon_options.SetAriaLabel(
155 l10n_util::GetStringUTF16(IDS_SMART_LOCK_SPINNER_ACCESSIBILITY_LABEL));
158 screenlock_bridge_->lock_handler()->ShowUserPodCustomIcon(user_email_,
159 icon_options);
162 void EasyUnlockScreenlockStateHandler::SetHardlockState(
163 HardlockState new_state) {
164 if (hardlock_state_ == new_state)
165 return;
167 if (new_state == LOGIN_FAILED && hardlock_state_ != NO_HARDLOCK)
168 return;
170 hardlock_state_ = new_state;
172 // If hardlock_state_ was set to NO_HARDLOCK, this means the screen is about
173 // to get unlocked. No need to update it in this case.
174 if (hardlock_state_ != NO_HARDLOCK) {
175 hardlock_ui_shown_ = false;
177 RefreshScreenlockState();
181 void EasyUnlockScreenlockStateHandler::MaybeShowHardlockUI() {
182 if (hardlock_state_ != NO_HARDLOCK)
183 ShowHardlockUI();
186 void EasyUnlockScreenlockStateHandler::SetTrialRun() {
187 if (is_trial_run_)
188 return;
189 is_trial_run_ = true;
190 RefreshScreenlockState();
193 void EasyUnlockScreenlockStateHandler::OnScreenDidLock() {
194 RefreshScreenlockState();
197 void EasyUnlockScreenlockStateHandler::OnScreenDidUnlock() {
198 if (hardlock_state_ == LOGIN_FAILED)
199 hardlock_state_ = NO_HARDLOCK;
200 hardlock_ui_shown_ = false;
201 is_trial_run_ = false;
204 void EasyUnlockScreenlockStateHandler::OnFocusedUserChanged(
205 const std::string& user_id) {
208 void EasyUnlockScreenlockStateHandler::RefreshScreenlockState() {
209 State last_state = state_;
210 // This should force updating screenlock state.
211 state_ = STATE_INACTIVE;
212 ChangeState(last_state);
215 void EasyUnlockScreenlockStateHandler::ShowHardlockUI() {
216 DCHECK(hardlock_state_ != NO_HARDLOCK);
218 if (!screenlock_bridge_->IsLocked())
219 return;
221 // Do not override online signin.
222 const ScreenlockBridge::LockHandler::AuthType existing_auth_type =
223 screenlock_bridge_->lock_handler()->GetAuthType(user_email_);
224 if (existing_auth_type == ScreenlockBridge::LockHandler::ONLINE_SIGN_IN)
225 return;
227 if (existing_auth_type != ScreenlockBridge::LockHandler::OFFLINE_PASSWORD) {
228 screenlock_bridge_->lock_handler()->SetAuthType(
229 user_email_,
230 ScreenlockBridge::LockHandler::OFFLINE_PASSWORD,
231 base::string16());
234 if (hardlock_state_ == NO_PAIRING) {
235 screenlock_bridge_->lock_handler()->HideUserPodCustomIcon(user_email_);
236 hardlock_ui_shown_ = false;
237 return;
240 if (hardlock_ui_shown_)
241 return;
243 ScreenlockBridge::UserPodCustomIconOptions icon_options;
244 if (hardlock_state_ == LOGIN_FAILED) {
245 icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED);
246 } else if (hardlock_state_ == PAIRING_CHANGED ||
247 hardlock_state_ == PAIRING_ADDED) {
248 icon_options.SetIcon(
249 ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED_TO_BE_ACTIVATED);
250 } else {
251 icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_HARDLOCKED);
254 base::string16 device_name = GetDeviceName();
255 base::string16 tooltip;
256 if (hardlock_state_ == USER_HARDLOCK) {
257 tooltip = l10n_util::GetStringFUTF16(
258 IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_USER, device_name);
259 } else if (hardlock_state_ == PAIRING_CHANGED) {
260 tooltip = l10n_util::GetStringUTF16(
261 IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_PAIRING_CHANGED);
262 } else if (hardlock_state_ == PAIRING_ADDED) {
263 tooltip = l10n_util::GetStringFUTF16(
264 IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_PAIRING_ADDED, device_name,
265 device_name);
266 } else if (hardlock_state_ == LOGIN_FAILED) {
267 tooltip = l10n_util::GetStringUTF16(
268 IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_LOGIN_FAILURE);
269 } else {
270 LOG(ERROR) << "Unknown hardlock state " << hardlock_state_;
272 icon_options.SetTooltip(tooltip, true /* autoshow */);
274 screenlock_bridge_->lock_handler()->ShowUserPodCustomIcon(user_email_,
275 icon_options);
276 hardlock_ui_shown_ = true;
279 void EasyUnlockScreenlockStateHandler::UpdateTooltipOptions(
280 bool trial_run,
281 ScreenlockBridge::UserPodCustomIconOptions* icon_options) {
282 size_t resource_id = 0;
283 base::string16 device_name;
284 if (trial_run && state_ == STATE_AUTHENTICATED) {
285 resource_id = IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_INITIAL_AUTHENTICATED;
286 } else {
287 resource_id = GetTooltipResourceId(state_);
288 if (TooltipContainsDeviceType(state_))
289 device_name = GetDeviceName();
292 if (!resource_id)
293 return;
295 base::string16 tooltip;
296 if (device_name.empty()) {
297 tooltip = l10n_util::GetStringUTF16(resource_id);
298 } else {
299 tooltip = l10n_util::GetStringFUTF16(resource_id, device_name);
302 if (tooltip.empty())
303 return;
305 icon_options->SetTooltip(tooltip, trial_run /* autoshow tooltip */);
308 base::string16 EasyUnlockScreenlockStateHandler::GetDeviceName() {
309 #if defined(OS_CHROMEOS)
310 return chromeos::GetChromeDeviceType();
311 #else
312 // TODO(tbarzic): Figure out the name for non Chrome OS case.
313 return base::ASCIIToUTF16("Chrome");
314 #endif
317 void EasyUnlockScreenlockStateHandler::UpdateScreenlockAuthType() {
318 if (!is_trial_run_ && hardlock_state_ != NO_HARDLOCK)
319 return;
321 // Do not override online signin.
322 const ScreenlockBridge::LockHandler::AuthType existing_auth_type =
323 screenlock_bridge_->lock_handler()->GetAuthType(user_email_);
324 DCHECK_NE(ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, existing_auth_type);
326 if (state_ == STATE_AUTHENTICATED) {
327 if (existing_auth_type != ScreenlockBridge::LockHandler::USER_CLICK) {
328 screenlock_bridge_->lock_handler()->SetAuthType(
329 user_email_,
330 ScreenlockBridge::LockHandler::USER_CLICK,
331 l10n_util::GetStringUTF16(
332 IDS_EASY_UNLOCK_SCREENLOCK_USER_POD_AUTH_VALUE));
334 } else if (existing_auth_type !=
335 ScreenlockBridge::LockHandler::OFFLINE_PASSWORD) {
336 screenlock_bridge_->lock_handler()->SetAuthType(
337 user_email_,
338 ScreenlockBridge::LockHandler::OFFLINE_PASSWORD,
339 base::string16());