Commit 92164ac3 authored by Jacob Dufault's avatar Jacob Dufault Committed by Commit Bot

cros: Views-login UI for removing a user.

Bug: 809637
Change-Id: Id06bf1b73bed7e2338488b68a1702f13582331f0
Reviewed-on: https://chromium-review.googlesource.com/930242
Commit-Queue: Jacob Dufault <jdufault@chromium.org>
Reviewed-by: default avatarXiaoyin Hu <xiaoyinh@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539519}
parent 43a5cd79
......@@ -1156,7 +1156,18 @@ This file contains the strings for ash.
<message name="IDS_ASH_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME" desc="Text to be spoken when the focus is set to the menu button of the user pod on the login screen.">
Options menu for <ph name="USER_EMAIL_ADDRESS">$1<ex>john.doe@example.com</ex></ph>
</message>
<message name="IDS_ASH_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME" desc="Text to be spoken when 'Remove user' item is selected on the pod menu.">
Remove this user
</message>
<message name="IDS_ASH_LOGIN_POD_LEGACY_SUPERVISED_USER_REMOVE_WARNING" desc="Text shown as a warning when attempting to remove legacy supervised user.">
All files and local data associated with the supervised user will be permanently deleted once this supervised user is removed. Visited websites and settings for this supervised user may still be visible by the manager at <ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph>.
</message>
<message name="IDS_ASH_LOGIN_POD_NON_OWNER_USER_REMOVE_WARNING_PART_1" desc="Text shown as a warning when attempting to remove non-owner user. Also see IDS_ASH_LOGIN_POD_NON_OWNER_USER_REMOVE_WARNING_PART_2.">
All files and local data associated with this user will be permanently deleted once this user is removed.
</message>
<message name="IDS_ASH_LOGIN_POD_NON_OWNER_USER_REMOVE_WARNING_PART_2" desc="Text shown as a warning when attempting to remove non-owner user. Also see IDS_ASH_LOGIN_POD_NON_OWNER_USER_REMOVE_WARNING_PART_1.">
$1 can still sign in later.
</message>
<!-- Multi-profiles intro dialog -->
<message name="IDS_ASH_MULTIPROFILES_INTRO_HEADLINE" desc="Describes which feature multi-profiles intro dialog presents.">
......
......@@ -17,6 +17,7 @@ class View;
namespace ash {
// Runs a callback whenever a view has gained or lost mouse hover.
// TODO(jdufault): see if we can replace this class with views::MouseWatcher.
class HoverNotifier : public ui::EventHandler {
public:
using OnHover = base::RepeatingCallback<void(bool has_hover)>;
......
......@@ -9,9 +9,6 @@
namespace ash {
namespace {
// Spacing between the child view inside the bubble view.
constexpr int kBubbleBetweenChildSpacing = 6;
// Total width of the bubble view.
constexpr int kBubbleTotalWidthDp = 178;
......@@ -28,9 +25,6 @@ constexpr int kBubbleBottomMarginDp = 18;
LoginBaseBubbleView::LoginBaseBubbleView(views::View* anchor_view)
: BubbleDialogDelegateView(anchor_view, views::BubbleBorder::NONE) {
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::kVertical, gfx::Insets(), kBubbleBetweenChildSpacing));
set_margins(gfx::Insets(kBubbleTopMarginDp, kBubbleHorizontalMarginDp,
kBubbleBottomMarginDp, kBubbleHorizontalMarginDp));
set_color(SK_ColorBLACK);
......@@ -49,7 +43,7 @@ int LoginBaseBubbleView::GetDialogButtons() const {
}
gfx::Size LoginBaseBubbleView::CalculatePreferredSize() const {
gfx::Size size = views::View::CalculatePreferredSize();
gfx::Size size = views::BubbleDialogDelegateView::CalculatePreferredSize();
size.set_width(kBubbleTotalWidthDp);
return size;
}
......
......@@ -20,10 +20,10 @@ class ASH_EXPORT LoginBaseBubbleView : public views::BubbleDialogDelegateView {
// views::BubbleDialogDelegateView:
int GetDialogButtons() const override;
private:
// views::View:
gfx::Size CalculatePreferredSize() const override;
private:
DISALLOW_COPY_AND_ASSIGN(LoginBaseBubbleView);
};
......
This diff is collapsed.
......@@ -8,6 +8,7 @@
#include "ash/ash_export.h"
#include "ash/login/ui/login_base_bubble_view.h"
#include "base/strings/string16.h"
#include "components/user_manager/user_type.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget_observer.h"
......@@ -26,6 +27,8 @@ class ASH_EXPORT LoginBubble : public views::WidgetObserver,
public ui::EventHandler,
public ui::LayerAnimationObserver {
public:
static const int kUserMenuRemoveUserButtonIdForTest;
LoginBubble();
~LoginBubble() override;
......@@ -38,11 +41,14 @@ class ASH_EXPORT LoginBubble : public views::WidgetObserver,
// |bubble_opener| is a view that could open/close the bubble.
// |show_remove_user| indicate whether or not we show the
// "Remove this user" action.
void ShowUserMenu(const base::string16& message,
const base::string16& sub_message,
void ShowUserMenu(const base::string16& username,
const base::string16& email,
user_manager::UserType type,
bool is_owner,
views::View* anchor_view,
LoginButton* bubble_opener,
bool show_remove_user);
bool show_remove_user,
base::OnceClosure do_remove_user);
// Shows a tooltip.
void ShowTooltip(const base::string16& message, views::View* anchor_view);
......
......@@ -66,6 +66,14 @@ class LoginBubbleTest : public LoginTestBase {
LoginTestBase::TearDown();
}
void ShowUserMenu(base::OnceClosure on_remove) {
bool show_remove_user = !on_remove.is_null();
bubble_->ShowUserMenu(
base::string16() /*username*/, base::string16() /*email*/,
user_manager::UserType::USER_TYPE_REGULAR, false /*is_owner*/,
container_, bubble_opener_, show_remove_user, std::move(on_remove));
}
// Owned by test widget view hierarchy.
views::View* container_ = nullptr;
// Owned by test widget view hierarchy.
......@@ -83,8 +91,7 @@ class LoginBubbleTest : public LoginTestBase {
// Verifies the base bubble settings.
TEST_F(LoginBubbleTest, BaseBubbleSettings) {
bubble_->ShowUserMenu(base::string16(), base::string16(), container_,
bubble_opener_, false /*show_remove_user*/);
bubble_->ShowTooltip(base::string16(), bubble_opener_);
EXPECT_TRUE(bubble_->IsVisible());
LoginBaseBubbleView* bubble_view = bubble_->bubble_view_for_test();
......@@ -108,8 +115,7 @@ TEST_F(LoginBubbleTest, BubbleKeyEventHandling) {
EXPECT_FALSE(bubble_->IsVisible());
// Verifies that key event on the bubble opener view won't close the bubble.
bubble_->ShowUserMenu(base::string16(), base::string16(), container_,
bubble_opener_, false /*show_remove_user*/);
ShowUserMenu(base::OnceClosure());
EXPECT_TRUE(bubble_->IsVisible());
bubble_opener_->RequestFocus();
generator.PressKey(ui::KeyboardCode::VKEY_A, ui::EF_NONE);
......@@ -132,8 +138,7 @@ TEST_F(LoginBubbleTest, BubbleMouseEventHandling) {
EXPECT_FALSE(bubble_->IsVisible());
// Verifies that mouse event on the bubble opener view won't close the bubble.
bubble_->ShowUserMenu(base::string16(), base::string16(), container_,
bubble_opener_, false /*show_remove_user*/);
ShowUserMenu(base::OnceClosure());
EXPECT_TRUE(bubble_->IsVisible());
generator.MoveMouseTo(bubble_opener_->GetBoundsInScreen().CenterPoint());
generator.ClickLeftButton();
......@@ -162,8 +167,7 @@ TEST_F(LoginBubbleTest, BubbleGestureEventHandling) {
// Verifies that gesture event on the bubble opener view won't close the
// bubble.
bubble_->ShowUserMenu(base::string16(), base::string16(), container_,
bubble_opener_, false /*show_remove_user*/);
ShowUserMenu(base::OnceClosure());
EXPECT_TRUE(bubble_->IsVisible());
generator.GestureTapAt(bubble_opener_->GetBoundsInScreen().CenterPoint());
EXPECT_TRUE(bubble_->IsVisible());
......@@ -185,8 +189,7 @@ TEST_F(LoginBubbleTest, LoginButtonRipple) {
views::InkDropHostView::InkDropMode::ON);
// Show the bubble to activate the ripple effect.
bubble_->ShowUserMenu(base::string16(), base::string16(), container_,
bubble_opener_, false /*show_remove_user*/);
ShowUserMenu(base::OnceClosure());
EXPECT_TRUE(bubble_->IsVisible());
EXPECT_TRUE(ink_drop_api.HasInkDrop());
EXPECT_EQ(ink_drop_api.GetInkDrop()->GetTargetInkDropState(),
......@@ -206,4 +209,31 @@ TEST_F(LoginBubbleTest, LoginButtonRipple) {
EXPECT_FALSE(ink_drop_api.GetInkDrop()->IsHighlightFadingInOrVisible());
}
// Verifies that clicking remove user requires two clicks before firing the
// callback.
TEST_F(LoginBubbleTest, RemoveUserRequiresTwoActivations) {
// Show the user menu.
bool remove_called = false;
ShowUserMenu(base::BindOnce(
[](bool* remove_called) { *remove_called = true; }, &remove_called));
EXPECT_TRUE(bubble_->IsVisible());
// Focus the remove user button.
views::View* remove_user_button =
bubble_->bubble_view_for_test()->GetViewByID(
LoginBubble::kUserMenuRemoveUserButtonIdForTest);
remove_user_button->RequestFocus();
EXPECT_TRUE(remove_user_button->HasFocus());
// Click it twice. Verify only the second click fires the callback.
auto click = [&]() {
EXPECT_TRUE(remove_user_button->HasFocus());
GetEventGenerator().PressKey(ui::KeyboardCode::VKEY_RETURN, 0);
};
EXPECT_NO_FATAL_FAILURE(click());
EXPECT_FALSE(remove_called);
EXPECT_NO_FATAL_FAILURE(click());
EXPECT_TRUE(remove_called);
}
} // namespace ash
......@@ -405,17 +405,13 @@ void LoginUserView::ButtonPressed(views::Button* sender,
if (sender == user_dropdown_) {
DCHECK(user_dropdown_);
if (!user_menu_->IsVisible()) {
base::string16 display_name =
base::UTF8ToUTF16(current_user_->basic_user_info->display_name);
user_menu_->ShowUserMenu(
current_user_->is_device_owner
? l10n_util::GetStringFUTF16(IDS_ASH_LOGIN_POD_OWNER_USER,
display_name)
: display_name,
base::UTF8ToUTF16(current_user_->basic_user_info->display_name),
base::UTF8ToUTF16(current_user_->basic_user_info->display_email),
current_user_->basic_user_info->type, current_user_->is_device_owner,
user_dropdown_ /*anchor_view*/, user_dropdown_ /*bubble_opener*/,
false /*show_remove_user*/);
current_user_->can_remove /*show_remove_user*/,
base::OnceClosure() /*do_remove_user*/);
} else {
user_menu_->Close();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment