summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-16 05:50:23 +0000
committertbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-16 05:50:23 +0000
commit5975bc36fe10b3b9908ad2201b07b9a577c4f560 (patch)
tree7cdc7407e1d865b45c7eb4cb20ec90b7803f6b98
parent2317849378238f140346278a6a5661beeac39645 (diff)
downloadchromium_src-5975bc36fe10b3b9908ad2201b07b9a577c4f560.zip
chromium_src-5975bc36fe10b3b9908ad2201b07b9a577c4f560.tar.gz
chromium_src-5975bc36fe10b3b9908ad2201b07b9a577c4f560.tar.bz2
Easy Unlock: Add support for hard locking
When user clicks on the easy-unlock icon on "Click to enter" lock screen (i.e. when lock screen auth type is USER_CLICK), the lock screen changes to state in which password is required to unlock the screen. This adds new auth state FORCE_OFFLINE_PASSWORD which, unlike OFFLINE_PASSWORD, can't be changed to any other. BUG=397363 TBR=asargent@chromium.org Review URL: https://codereview.chromium.org/456943003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@290096 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/login/screens/user_selection_screen.cc3
-rw-r--r--chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc2
-rw-r--r--chrome/browser/signin/easy_unlock_screenlock_state_handler.cc50
-rw-r--r--chrome/browser/signin/easy_unlock_screenlock_state_handler.h17
-rw-r--r--chrome/browser/signin/screenlock_bridge.cc11
-rw-r--r--chrome/browser/signin/screenlock_bridge.h7
-rw-r--r--chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc12
-rw-r--r--chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h1
-rw-r--r--chrome/browser/ui/webui/signin/user_manager_screen_handler.cc14
-rw-r--r--chrome/browser/ui/webui/signin/user_manager_screen_handler.h1
-rw-r--r--ui/login/account_picker/user_pod_row.css8
-rw-r--r--ui/login/account_picker/user_pod_row.js161
12 files changed, 246 insertions, 41 deletions
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
index 41c3024..e969589 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -362,6 +362,9 @@ void UserSelectionScreen::HandleGetUsers() {
void UserSelectionScreen::SetAuthType(
const std::string& username,
ScreenlockBridge::LockHandler::AuthType auth_type) {
+ DCHECK(GetAuthType(username) !=
+ ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD ||
+ auth_type == ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD);
user_auth_type_map_[username] = auth_type;
}
diff --git a/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc b/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
index eb7b6e2..f5e44b2 100644
--- a/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
+++ b/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
@@ -57,6 +57,8 @@ screenlock::AuthType FromLockHandlerAuthType(
// locking.
NOTREACHED();
return screenlock::AUTH_TYPE_NONE;
+ case ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD:
+ return screenlock::AUTH_TYPE_OFFLINEPASSWORD;
}
NOTREACHED();
return screenlock::AUTH_TYPE_OFFLINEPASSWORD;
diff --git a/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc b/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc
index 13816fc..5ddb98f 100644
--- a/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc
+++ b/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc
@@ -49,6 +49,10 @@ bool HasAnimation(EasyUnlockScreenlockStateHandler::State state) {
return state == EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING;
}
+bool HardlockOnClick(EasyUnlockScreenlockStateHandler::State state) {
+ return state == EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED;
+}
+
size_t GetTooltipResourceId(EasyUnlockScreenlockStateHandler::State state) {
switch (state) {
case EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH:
@@ -64,9 +68,7 @@ size_t GetTooltipResourceId(EasyUnlockScreenlockStateHandler::State state) {
case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_NEARBY:
return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_NOT_NEARBY;
case EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED:
- // TODO(tbarzic): When hard lock is enabled change this to
- // IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_INSTRUCTIONS.
- return 0;
+ return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_INSTRUCTIONS;
default:
return 0;
}
@@ -99,10 +101,13 @@ void EasyUnlockScreenlockStateHandler::ChangeState(State new_state) {
state_ = new_state;
- // If lock screen is not active, just cache the current state.
- // The screenlock state will get refreshed in |ScreenDidLock|.
- if (!screenlock_bridge_->IsLocked())
+ // If lock screen is not active or it forces offline password, just cache the
+ // current state. The screenlock state will get refreshed in |ScreenDidLock|.
+ if (!screenlock_bridge_->IsLocked() ||
+ screenlock_bridge_->lock_handler()->GetAuthType(user_email_) ==
+ ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD) {
return;
+ }
UpdateScreenlockAuthType();
@@ -115,7 +120,9 @@ void EasyUnlockScreenlockStateHandler::ChangeState(State new_state) {
}
icon_options.SetIconAsResourceURL(icon_url);
- UpdateTooltipOptions(&icon_options);
+ bool trial_run = IsTrialRun();
+
+ UpdateTooltipOptions(trial_run, &icon_options);
if (UseOpaqueIcon(state_))
icon_options.SetOpacity(kOpaqueIconOpacity);
@@ -125,6 +132,13 @@ void EasyUnlockScreenlockStateHandler::ChangeState(State new_state) {
if (HasAnimation(state_))
icon_options.SetAnimation(kSpinnerResourceWidth, kSpinnerIntervalMs);
+ // Hardlocking is disabled in trial run.
+ if (!trial_run && HardlockOnClick(state_))
+ icon_options.SetHardlockOnClick();
+
+ if (trial_run && state_ == STATE_AUTHENTICATED)
+ MarkTrialRunComplete();
+
screenlock_bridge_->lock_handler()->ShowUserPodCustomIcon(user_email_,
icon_options);
}
@@ -140,12 +154,11 @@ void EasyUnlockScreenlockStateHandler::OnScreenDidUnlock() {
}
void EasyUnlockScreenlockStateHandler::UpdateTooltipOptions(
+ bool trial_run,
ScreenlockBridge::UserPodCustomIconOptions* icon_options) {
- bool show_tutorial = ShouldShowTutorial();
-
size_t resource_id = 0;
base::string16 device_name;
- if (show_tutorial) {
+ if (trial_run && state_ == STATE_AUTHENTICATED) {
resource_id = IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_TUTORIAL;
} else {
resource_id = GetTooltipResourceId(state_);
@@ -166,20 +179,17 @@ void EasyUnlockScreenlockStateHandler::UpdateTooltipOptions(
if (tooltip.empty())
return;
- if (show_tutorial)
- MarkTutorialShown();
-
- icon_options->SetTooltip(tooltip, show_tutorial /* autoshow tooltip */);
+ icon_options->SetTooltip(
+ tooltip,
+ state_ == STATE_AUTHENTICATED && trial_run /* autoshow tooltip */);
}
-bool EasyUnlockScreenlockStateHandler::ShouldShowTutorial() {
- if (state_ != STATE_AUTHENTICATED)
- return false;
+bool EasyUnlockScreenlockStateHandler::IsTrialRun() {
return pref_service_ &&
pref_service_->GetBoolean(prefs::kEasyUnlockShowTutorial);
}
-void EasyUnlockScreenlockStateHandler::MarkTutorialShown() {
+void EasyUnlockScreenlockStateHandler::MarkTrialRunComplete() {
if (!pref_service_)
return;
pref_service_->SetBoolean(prefs::kEasyUnlockShowTutorial, false);
@@ -195,6 +205,10 @@ base::string16 EasyUnlockScreenlockStateHandler::GetDeviceName() {
}
void EasyUnlockScreenlockStateHandler::UpdateScreenlockAuthType() {
+ if (screenlock_bridge_->lock_handler()->GetAuthType(user_email_) ==
+ ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD)
+ return;
+
if (state_ == STATE_AUTHENTICATED) {
screenlock_bridge_->lock_handler()->SetAuthType(
user_email_,
diff --git a/chrome/browser/signin/easy_unlock_screenlock_state_handler.h b/chrome/browser/signin/easy_unlock_screenlock_state_handler.h
index dc5c2cc..e99c09b 100644
--- a/chrome/browser/signin/easy_unlock_screenlock_state_handler.h
+++ b/chrome/browser/signin/easy_unlock_screenlock_state_handler.h
@@ -61,17 +61,20 @@ class EasyUnlockScreenlockStateHandler : public ScreenlockBridge::Observer {
virtual void OnScreenDidLock() OVERRIDE;
virtual void OnScreenDidUnlock() OVERRIDE;
+ // Updates icon's tooltip options.
+ // |trial_run|: Whether the trial Easy Unlock run is in progress.
void UpdateTooltipOptions(
+ bool trial_run,
ScreenlockBridge::UserPodCustomIconOptions* icon_options);
- // Whether the tutorial message should be shown to the user. The message is
- // shown only once, when the user encounters STATE_AUTHENTICATED for the first
- // time (across sessions). After the tutorial message is shown,
- // |MarkTutorialShown| should be called to prevent further tutorial message.
- bool ShouldShowTutorial();
+ // Whether this is the first, trial Easy Unlock run. If this is the case, a
+ // tutorial message should be shown and hard-locking be disabled in
+ // Authenticated state. The trial run will be active if Easy Unlock never
+ // entered Authenticated state (across sessions).
+ bool IsTrialRun();
- // Sets user preference that prevents showing of tutorial messages.
- void MarkTutorialShown();
+ // Sets user preference that marks trial run completed.
+ void MarkTrialRunComplete();
// Gets the name to be used for the device. The name depends on the device
// type (example values: Chromebook and Chromebox).
diff --git a/chrome/browser/signin/screenlock_bridge.cc b/chrome/browser/signin/screenlock_bridge.cc
index 56c2910..4a95429 100644
--- a/chrome/browser/signin/screenlock_bridge.cc
+++ b/chrome/browser/signin/screenlock_bridge.cc
@@ -37,7 +37,8 @@ ScreenlockBridge::UserPodCustomIconOptions::UserPodCustomIconOptions()
animation_resource_width_(0u),
animation_frame_length_ms_(0u),
opacity_(100u),
- autoshow_tooltip_(false) {
+ autoshow_tooltip_(false),
+ hardlock_on_click_(false) {
}
ScreenlockBridge::UserPodCustomIconOptions::~UserPodCustomIconOptions() {}
@@ -86,6 +87,10 @@ ScreenlockBridge::UserPodCustomIconOptions::ToDictionaryValue() const {
animation_frame_length_ms_);
result->Set("animation", animation);
}
+
+ if (hardlock_on_click_)
+ result->SetBoolean("hardlockOnClick", true);
+
return result.Pass();
}
@@ -130,6 +135,10 @@ void ScreenlockBridge::UserPodCustomIconOptions::SetTooltip(
autoshow_tooltip_ = autoshow;
}
+void ScreenlockBridge::UserPodCustomIconOptions::SetHardlockOnClick() {
+ hardlock_on_click_ = true;
+}
+
// static
std::string ScreenlockBridge::GetAuthenticatedUserEmail(Profile* profile) {
// |profile| has to be a signed-in profile with SigninManager already
diff --git a/chrome/browser/signin/screenlock_bridge.h b/chrome/browser/signin/screenlock_bridge.h
index 72cec43..5391ca3 100644
--- a/chrome/browser/signin/screenlock_bridge.h
+++ b/chrome/browser/signin/screenlock_bridge.h
@@ -78,6 +78,10 @@ class ScreenlockBridge {
// shown with the icon.
void SetTooltip(const base::string16& tooltip, bool autoshow);
+ // If hardlock on click is set, clicking the icon in the screenlock will
+ // go to state where password is required for unlock.
+ void SetHardlockOnClick();
+
private:
std::string icon_resource_url_;
scoped_ptr<gfx::Image> icon_image_;
@@ -95,6 +99,8 @@ class ScreenlockBridge {
base::string16 tooltip_;
bool autoshow_tooltip_;
+ bool hardlock_on_click_;
+
DISALLOW_COPY_AND_ASSIGN(UserPodCustomIconOptions);
};
@@ -108,6 +114,7 @@ class ScreenlockBridge {
NUMERIC_PIN = 2,
USER_CLICK = 3,
EXPAND_THEN_USER_CLICK = 4,
+ FORCE_OFFLINE_PASSWORD = 5
};
// Displays |message| in a banner on the lock screen.
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index 9ff3d1f..b6ff43c 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -764,6 +764,7 @@ void SigninScreenHandler::RegisterMessages() {
AddCallback("updateOfflineLogin",
&SigninScreenHandler::HandleUpdateOfflineLogin);
AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod);
+ AddCallback("hardlockPod", &SigninScreenHandler::HandleHardlockPod);
AddCallback("retrieveAuthenticatedUserEmail",
&SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail);
AddCallback("getPublicSessionKeyboardLayouts",
@@ -948,6 +949,10 @@ void SigninScreenHandler::SetAuthType(
const std::string& username,
ScreenlockBridge::LockHandler::AuthType auth_type,
const base::string16& initial_value) {
+ if (delegate_->GetAuthType(username) ==
+ ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD)
+ return;
+
delegate_->SetAuthType(username, auth_type);
CallJS("login.AccountPickerScreen.setAuthType",
@@ -1304,6 +1309,13 @@ void SigninScreenHandler::HandleFocusPod(const std::string& user_id) {
WallpaperManager::Get()->SetUserWallpaperDelayed(user_id);
}
+void SigninScreenHandler::HandleHardlockPod(const std::string& user_id) {
+ SetAuthType(user_id,
+ ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD,
+ base::string16());
+ HideUserPodCustomIcon(user_id);
+}
+
void SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail(
double attempt_token) {
// TODO(antrim) : move GaiaSigninScreen dependency to GaiaSigninScreen.
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index 86d4dda..4656185 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -370,6 +370,7 @@ class SigninScreenHandler
void HandleUpdateOfflineLogin(bool offline_login_active);
void HandleShowSupervisedUserCreationScreen();
void HandleFocusPod(const std::string& user_id);
+ void HandleHardlockPod(const std::string& user_id);
void HandleLaunchKioskApp(const std::string& app_id, bool diagnostic_mode);
void HandleRetrieveAuthenticatedUserEmail(double attempt_token);
void HandleGetPublicSessionKeyboardLayouts(const std::string& user_id,
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index c8104f7..4314bc0 100644
--- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -257,6 +257,10 @@ void UserManagerScreenHandler::SetAuthType(
const std::string& user_email,
ScreenlockBridge::LockHandler::AuthType auth_type,
const base::string16& auth_value) {
+ if (GetAuthType(user_email) ==
+ ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD)
+ return;
+
user_auth_type_map_[user_email] = auth_type;
web_ui()->CallJavascriptFunction(
"login.AccountPickerScreen.setAuthType",
@@ -430,6 +434,16 @@ void UserManagerScreenHandler::HandleAttemptUnlock(
GetScreenlockRouter(email)->OnAuthAttempted(GetAuthType(email), "");
}
+void UserManagerScreenHandler::HandleHardlockUserPod(
+ const base::ListValue* args) {
+ std::string email;
+ CHECK(args->GetString(0, &email));
+ SetAuthType(email,
+ ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD,
+ base::string16());
+ HideUserPodCustomIcon(email);
+}
+
void UserManagerScreenHandler::OnClientLoginSuccess(
const ClientLoginResult& result) {
chrome::SetLocalAuthCredentials(authenticating_profile_index_,
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.h b/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
index 8339d61f..1e7d1b6 100644
--- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
@@ -63,6 +63,7 @@ class UserManagerScreenHandler : public content::WebUIMessageHandler,
void HandleLaunchUser(const base::ListValue* args);
void HandleRemoveUser(const base::ListValue* args);
void HandleAttemptUnlock(const base::ListValue* args);
+ void HandleHardlockUserPod(const base::ListValue* args);
// Handle GAIA auth results.
virtual void OnClientLoginSuccess(const ClientLoginResult& result) OVERRIDE;
diff --git a/ui/login/account_picker/user_pod_row.css b/ui/login/account_picker/user_pod_row.css
index 01a3b7a..089dc5e 100644
--- a/ui/login/account_picker/user_pod_row.css
+++ b/ui/login/account_picker/user_pod_row.css
@@ -171,7 +171,8 @@ html[dir=rtl] .main-pane {
display: none;
}
-.pod[auth-type='offlinePassword'].focused .password-entry-container {
+.pod[auth-type='offlinePassword'].focused .password-entry-container,
+.pod[auth-type='forceOfflinePassword'].focused .password-entry-container {
display: flex;
flex: auto;
}
@@ -226,6 +227,11 @@ html[dir=rtl] .main-pane {
flex: none;
}
+.custom-icon.faded {
+ -webkit-transition: opacity 200ms ease-in-out,
+ visibility 200ms ease-in-out;
+}
+
.custom-icon-container {
display: flex;
flex: none;
diff --git a/ui/login/account_picker/user_pod_row.js b/ui/login/account_picker/user_pod_row.js
index 39b5c7d..e83344b 100644
--- a/ui/login/account_picker/user_pod_row.js
+++ b/ui/login/account_picker/user_pod_row.js
@@ -85,10 +85,11 @@ cr.define('login', function() {
* @const
*/
var UserPodTabOrder = {
- POD_INPUT: 1, // Password input fields (and whole pods themselves).
- HEADER_BAR: 2, // Buttons on the header bar (Shutdown, Add User).
- ACTION_BOX: 3, // Action box buttons.
- PAD_MENU_ITEM: 4 // User pad menu items (Remove this user).
+ POD_INPUT: 1, // Password input fields (and whole pods themselves).
+ POD_CUSTOM_ICON: 2, // Pod custom icon next to passwrod input field.
+ HEADER_BAR: 3, // Buttons on the header bar (Shutdown, Add User).
+ ACTION_BOX: 4, // Action box buttons.
+ PAD_MENU_ITEM: 5 // User pad menu items (Remove this user).
};
/**
@@ -103,6 +104,7 @@ cr.define('login', function() {
NUMERIC_PIN: 2,
USER_CLICK: 3,
EXPAND_THEN_USER_CLICK: 4,
+ FORCE_OFFLINE_PASSWORD: 5
};
/**
@@ -114,6 +116,7 @@ cr.define('login', function() {
2: 'numericPin',
3: 'userClick',
4: 'expandThenUserClick',
+ 5: 'forceOfflinePassword'
};
// Focus and tab order are organized as follows:
@@ -121,9 +124,12 @@ cr.define('login', function() {
// (1) all user pods have tab index 1 so they are traversed first;
// (2) when a user pod is activated, its tab index is set to -1 and its
// main input field gets focus and tab index 1;
- // (3) buttons on the header bar have tab index 2 so they follow user pods;
- // (4) Action box buttons have tab index 3 and follow header bar buttons;
- // (5) lastly, focus jumps to the Status Area and back to user pods.
+ // (3) if user pod custom icon is interactive, it has tab index 2 so it
+ // follows the input.
+ // (4) buttons on the header bar have tab index 3 so they follow the custom
+ // icon, or user pod if custom icon is not interactive;
+ // (5) Action box buttons have tab index 4 and follow header bar buttons;
+ // (6) lastly, focus jumps to the Status Area and back to user pods.
//
// 'Focus' event is handled by a capture handler for the whole document
// and in some cases 'mousedown' event handlers are used instead of 'click'
@@ -252,6 +258,23 @@ cr.define('login', function() {
*/
animationResourceSize_: 0,
+ /**
+ * When {@code fadeOut} is called, the element gets hidden using fadeout
+ * animation. This is reference to the listener for transition end added to
+ * the icon element while it's fading out.
+ * @type {?function(Event)}
+ * @private
+ */
+ hideTransitionListener_: null,
+
+ /**
+ * Callback for click and 'Enter' key events that gets set if the icon is
+ * interactive.
+ * @type {?function()}
+ * @private
+ */
+ actionHandler_: null,
+
/** @override */
decorate: function() {
this.iconElement.addEventListener('mouseover',
@@ -260,6 +283,16 @@ cr.define('login', function() {
this.hideTooltip_.bind(this, false));
this.iconElement.addEventListener('mousedown',
this.hideTooltip_.bind(this, false));
+ this.iconElement.addEventListener('click',
+ this.handleClick_.bind(this));
+ this.iconElement.addEventListener('keydown',
+ this.handleKeyDown_.bind(this));
+
+ // When the icon is focused using mouse, there should be no outline shown.
+ // Preventing default mousedown event accomplishes this.
+ this.iconElement.addEventListener('mousedown', function(e) {
+ e.preventDefault();
+ });
},
/**
@@ -298,16 +331,24 @@ cr.define('login', function() {
* Shows the icon.
*/
show: function() {
+ this.resetHideTransitionState_();
this.hidden = false;
},
/**
- * Hides the icon. Makes sure the tooltip is hidden and animation reset.
+ * Hides the icon using a fade-out animation.
*/
- hide: function() {
+ fadeOut: function() {
+ // The icon is already being hidden.
+ if (this.iconElement.classList.contains('faded'))
+ return;
+
this.hideTooltip_(true);
- this.setAnimation(null);
- this.hidden = true;
+ this.iconElement.classList.add('faded');
+ this.hideTransitionListener_ = this.hide_.bind(this);
+ this.iconElement.addEventListener('webkitTransitionEnd',
+ this.hideTransitionListener_);
+ ensureTransitionEndEvent(this.iconElement, 200);
},
/**
@@ -403,6 +444,80 @@ cr.define('login', function() {
},
/**
+ * Sets up icon tabIndex attribute and handler for click and 'Enter' key
+ * down events.
+ * @param {?function()} callback If icon should be interactive, the
+ * function to get called on click and 'Enter' key down events. Should
+ * be null to make the icon non interactive.
+ */
+ setInteractive: function(callback) {
+ // Update tabIndex property if needed.
+ if (!!this.actionHandler_ != !!callback) {
+ if (callback) {
+ this.iconElement.setAttribute('tabIndex',
+ UserPodTabOrder.POD_CUSTOM_ICON);
+ } else {
+ this.iconElement.removeAttribute('tabIndex');
+ }
+ }
+
+ // Set the new action handler.
+ this.actionHandler_ = callback;
+ },
+
+ /**
+ * Hides the icon. Makes sure the tooltip is hidden and animation reset.
+ * @private
+ */
+ hide_: function() {
+ this.hideTooltip_(true);
+ this.hidden = true;
+ this.setAnimation(null);
+ this.setInteractive(null);
+ this.resetHideTransitionState_();
+ },
+
+ /**
+ * Ensures the icon's transition state potentially set by a call to
+ * {@code fadeOut} is cleared.
+ * @private
+ */
+ resetHideTransitionState_: function() {
+ if (this.hideTransitionListener_) {
+ this.iconElement.removeEventListener('webkitTransitionEnd',
+ this.hideTransitionListener_);
+ this.hideTransitionListener_ = null;
+ }
+ this.iconElement.classList.toggle('faded', false);
+ },
+
+ /**
+ * Handles click event on the icon element. No-op if
+ * {@code this.actionHandler_} is not set.
+ * @param {Event} e The click event.
+ * @private
+ */
+ handleClick_: function(e) {
+ if (!this.actionHandler_)
+ return;
+ this.actionHandler_();
+ stopEventPropagation(e);
+ },
+
+ /**
+ * Handles key down event on the icon element. Only 'Enter' key is handled.
+ * No-op if {@code this.actionHandler_} is not set.
+ * @param {Event} e The key down event.
+ * @private
+ */
+ handleKeyDown_: function(e) {
+ if (!this.actionHandler_ || e.keyIdentifier != 'Enter')
+ return;
+ this.actionHandler_(e);
+ stopEventPropagation(e);
+ },
+
+ /**
* Called when mouse enters the icon. It sets timeout for showing the
* tooltip.
* @private
@@ -415,7 +530,7 @@ cr.define('login', function() {
},
/**
- * Shows the current tooltip, if one is set.
+ * Shows the current tooltip if one is set.
* @private
*/
showTooltip_: function() {
@@ -973,7 +1088,8 @@ cr.define('login', function() {
* @type {bool}
*/
get isAuthTypePassword() {
- return this.authType_ == AUTH_TYPE.OFFLINE_PASSWORD;
+ return this.authType_ == AUTH_TYPE.OFFLINE_PASSWORD ||
+ this.authType_ == AUTH_TYPE.FORCE_OFFLINE_PASSWORD;
},
/**
@@ -2199,6 +2315,12 @@ cr.define('login', function() {
pod.customIconElement.setSize(icon.size || {width: 0, height: 0});
pod.customIconElement.setAnimation(icon.animation || null);
pod.customIconElement.setOpacity(icon.opacity || 100);
+ if (icon.hardlockOnClick) {
+ pod.customIconElement.setInteractive(
+ this.hardlockUserPod_.bind(this, username));
+ } else {
+ pod.customIconElement.setInteractive(null);
+ }
pod.customIconElement.show();
// This has to be called after |show| in case the tooltip should be shown
// immediatelly.
@@ -2207,6 +2329,17 @@ cr.define('login', function() {
},
/**
+ * Hard-locks user pod for the user. If user pod is hard-locked, it can be
+ * only unlocked using password, and the authentication type cannot be
+ * changed.
+ * @param {!string} username The user's username.
+ * @private
+ */
+ hardlockUserPod_: function(username) {
+ chrome.send('hardlockPod', [username]);
+ },
+
+ /**
* Hides the custom icon in the user pod added by showUserPodCustomIcon().
* @param {string} username Username of pod to remove button
*/
@@ -2218,7 +2351,7 @@ cr.define('login', function() {
return;
}
- pod.customIconElement.hide();
+ pod.customIconElement.fadeOut();
},
/**