Commit d31967e4 authored by binjin@chromium.org's avatar binjin@chromium.org

Implements the dialog view for logout confirmation dialog in public sessions.

Implements ash::internal::LogoutConfirmationDialogView which is supposed
to be used by ash::internal::LogoutButtonTray.

BUG=223846
TEST=new unit test

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=242286

Review URL: https://codereview.chromium.org/40053002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243530 0039d316-1c4b-4281-b951-d872f2087c98
parent d1634c26
......@@ -332,6 +332,8 @@
'system/logout_button/logout_button_observer.h',
'system/logout_button/logout_button_tray.cc',
'system/logout_button/logout_button_tray.h',
'system/logout_button/logout_confirmation_dialog_view.cc',
'system/logout_button/logout_confirmation_dialog_view.h',
'system/monitor/tray_monitor.cc',
'system/monitor/tray_monitor.h',
'system/session_length_limit/session_length_limit_observer.h',
......@@ -828,6 +830,7 @@
'system/chromeos/screen_security/screen_tray_item_unittest.cc',
'system/chromeos/tray_display_unittest.cc',
'system/date/date_view_unittest.cc',
'system/logout_button/logout_button_tray_unittest.cc',
'system/session_length_limit/tray_session_length_limit_unittest.cc',
'system/tray/system_tray_unittest.cc',
'system/tray/tray_details_view_unittest.cc',
......
......@@ -585,6 +585,19 @@ Press Shift + Alt to switch.
Press Control Shift Q twice to quit.
</message>
<message name="IDS_ASH_LOGOUT_CONFIRMATION_TITLE" desc="Dialog title for the logout confirmation dialog.">
Exiting Session
</message>
<message name="IDS_ASH_LOGOUT_CONFIRMATION_WARNING" desc="The text for the logout confirmation dialog.">
You will automatically be signed out in <ph name="LOGOUT_TIME_LEFT">$1<ex>5 seconds</ex></ph>.
</message>
<message name="IDS_ASH_LOGOUT_CONFIRMATION_WARNING_NOW" desc="The text for the logout confirmation dialog with no time left.">
You will be signed out now.
</message>
<message name="IDS_ASH_LOGOUT_CONFIRMATION_BUTTON" desc="The text for okay button of the logout confirmation dialog.">
Sign out now
</message>
<!-- ChromeOS-specific strings -->
<if expr="pp_ifdef('chromeos')">
<part file="ash_chromeos_strings.grdp" />
......
......@@ -5,16 +5,24 @@
#ifndef ASH_SYSTEM_LOGOUT_BUTTON_LOGOUT_BUTTON_OBSERVER_H_
#define ASH_SYSTEM_LOGOUT_BUTTON_LOGOUT_BUTTON_OBSERVER_H_
#include "ash/ash_export.h"
#include "base/time/time.h"
namespace ash {
// Observer for the value of the kShowLogoutButtonInTray pref that determines
// whether a logout button should be shown in the system tray during a session.
class LogoutButtonObserver {
class ASH_EXPORT LogoutButtonObserver {
public:
virtual ~LogoutButtonObserver() {}
// Called when the value of the kShowLogoutButtonInTray pref changes.
// Called when the value of the kShowLogoutButtonInTray pref changes, which
// determines whether a logout button should be shown in the system tray
// during a session.
virtual void OnShowLogoutButtonInTrayChanged(bool show) = 0;
// Called when the value of the kLogoutDialogDurationMs pref changes.
// |duration| is the duration for which the logout confirmation dialog is
// shown after the user has pressed the logout button.
virtual void OnLogoutDialogDurationChanged(base::TimeDelta duration) = 0;
};
} // namespace ash
......
......@@ -24,7 +24,6 @@
#include "ui/views/painter.h"
namespace ash {
namespace internal {
namespace {
......@@ -64,6 +63,21 @@ class LogoutButton : public views::LabelButton {
DISALLOW_COPY_AND_ASSIGN(LogoutButton);
};
class LogoutConfirmationDialogDelegate
: public LogoutConfirmationDialogView::Delegate {
public:
LogoutConfirmationDialogDelegate() {}
virtual ~LogoutConfirmationDialogDelegate() {}
virtual void LogoutCurrentUser() OVERRIDE;
virtual base::TimeTicks GetCurrentTime() const OVERRIDE;
virtual void ShowDialog(views::DialogDelegate* dialog) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationDialogDelegate);
};
} // namespace
LogoutButton::LogoutButton(views::ButtonListener* listener)
......@@ -95,20 +109,62 @@ LogoutButton::LogoutButton(views::ButtonListener* listener)
LogoutButton::~LogoutButton() {
}
void LogoutConfirmationDialogDelegate::LogoutCurrentUser() {
Shell::GetInstance()->system_tray_delegate()->SignOut();
}
base::TimeTicks LogoutConfirmationDialogDelegate::GetCurrentTime() const {
return base::TimeTicks::Now();
}
void LogoutConfirmationDialogDelegate::ShowDialog(
views::DialogDelegate *dialog) {
views::DialogDelegate::CreateDialogWidget(
dialog, ash::Shell::GetPrimaryRootWindow(), NULL);
dialog->GetWidget()->Show();
}
LogoutButtonTray::LogoutButtonTray(StatusAreaWidget* status_area_widget)
: TrayBackgroundView(status_area_widget),
button_(NULL),
login_status_(user::LOGGED_IN_NONE),
show_logout_button_in_tray_(false) {
show_logout_button_in_tray_(false),
confirmation_dialog_(NULL),
confirmation_delegate_(new LogoutConfirmationDialogDelegate) {
button_ = new LogoutButton(this);
tray_container()->AddChildView(button_);
tray_container()->set_border(NULL);
Shell::GetInstance()->system_tray_notifier()->AddLogoutButtonObserver(this);
// The Shell may not exist in some unit tests.
if (Shell::HasInstance()) {
Shell::GetInstance()->system_tray_notifier()->
AddLogoutButtonObserver(this);
}
}
LogoutButtonTray::~LogoutButtonTray() {
Shell::GetInstance()->system_tray_notifier()->
RemoveLogoutButtonObserver(this);
EnsureConfirmationDialogIsClosed();
// The Shell may not exist in some unit tests.
if (Shell::HasInstance()) {
Shell::GetInstance()->system_tray_notifier()->
RemoveLogoutButtonObserver(this);
}
}
bool LogoutButtonTray::IsConfirmationDialogShowing() const {
return confirmation_dialog_ != NULL;
}
void LogoutButtonTray::EnsureConfirmationDialogIsShowing() {
if (!confirmation_dialog_) {
confirmation_dialog_ = new LogoutConfirmationDialogView(
this, confirmation_delegate_.get());
confirmation_dialog_->Show(dialog_duration_);
}
}
void LogoutButtonTray::EnsureConfirmationDialogIsClosed() {
if (confirmation_dialog_)
confirmation_dialog_->Close();
}
void LogoutButtonTray::SetShelfAlignment(ShelfAlignment alignment) {
......@@ -133,10 +189,20 @@ void LogoutButtonTray::OnShowLogoutButtonInTrayChanged(bool show) {
UpdateVisibility();
}
void LogoutButtonTray::OnLogoutDialogDurationChanged(base::TimeDelta duration) {
dialog_duration_ = duration;
if (confirmation_dialog_)
confirmation_dialog_->UpdateDialogDuration(dialog_duration_);
}
void LogoutButtonTray::ButtonPressed(views::Button* sender,
const ui::Event& event) {
DCHECK_EQ(sender, button_);
Shell::GetInstance()->system_tray_delegate()->SignOut();
// Sign out immediately if |dialog_duration_| is non-positive.
if (dialog_duration_ <= base::TimeDelta())
confirmation_delegate_->LogoutCurrentUser();
else
EnsureConfirmationDialogIsShowing();
}
void LogoutButtonTray::UpdateAfterLoginStatusChange(
......@@ -149,10 +215,21 @@ void LogoutButtonTray::UpdateAfterLoginStatusChange(
UpdateVisibility();
}
void LogoutButtonTray::ReleaseConfirmationDialog() {
confirmation_dialog_ = NULL;
}
void LogoutButtonTray::SetDelegateForTest(
scoped_ptr<LogoutConfirmationDialogView::Delegate> delegate) {
confirmation_delegate_ = delegate.Pass();
}
void LogoutButtonTray::UpdateVisibility() {
SetVisible(show_logout_button_in_tray_ &&
login_status_ != user::LOGGED_IN_NONE &&
login_status_ != user::LOGGED_IN_LOCKED);
if (!show_logout_button_in_tray_)
EnsureConfirmationDialogIsClosed();
}
} // namespace internal
......
......@@ -5,11 +5,15 @@
#ifndef ASH_SYSTEM_LOGOUT_BUTTON_LOGOUT_BUTTON_TRAY_H_
#define ASH_SYSTEM_LOGOUT_BUTTON_LOGOUT_BUTTON_TRAY_H_
#include "ash/ash_export.h"
#include "ash/system/logout_button/logout_button_observer.h"
#include "ash/system/logout_button/logout_confirmation_dialog_view.h"
#include "ash/system/tray/tray_background_view.h"
#include "ash/system/user/login_status.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "ui/views/controls/button/button.h"
namespace views {
......@@ -23,9 +27,9 @@ class StatusAreaWidget;
// Adds a logout button to the launcher's status area if enabled by the
// kShowLogoutButtonInTray pref.
class LogoutButtonTray : public TrayBackgroundView,
public LogoutButtonObserver,
public views::ButtonListener {
class ASH_EXPORT LogoutButtonTray : public TrayBackgroundView,
public LogoutButtonObserver,
public views::ButtonListener {
public:
explicit LogoutButtonTray(StatusAreaWidget* status_area_widget);
virtual ~LogoutButtonTray();
......@@ -39,6 +43,7 @@ class LogoutButtonTray : public TrayBackgroundView,
// LogoutButtonObserver:
virtual void OnShowLogoutButtonInTrayChanged(bool show) OVERRIDE;
virtual void OnLogoutDialogDurationChanged(base::TimeDelta duration) OVERRIDE;
// views::ButtonListener:
virtual void ButtonPressed(views::Button* sender,
......@@ -46,12 +51,30 @@ class LogoutButtonTray : public TrayBackgroundView,
void UpdateAfterLoginStatusChange(user::LoginStatus login_status);
// Nullify the pointer to confirmation dialog, this is expected to be called
// when the confirmation dialog is going to be destroyed.
// Note: the confirmation dialog is not owned by LogoutButtonTray.
void ReleaseConfirmationDialog();
void SetDelegateForTest(
scoped_ptr<LogoutConfirmationDialogView::Delegate> delegate);
private:
friend class LogoutConfirmationDialogTest;
bool IsConfirmationDialogShowing() const;
void EnsureConfirmationDialogIsShowing();
void EnsureConfirmationDialogIsClosed();
void UpdateVisibility();
views::LabelButton* button_; // Not owned.
user::LoginStatus login_status_;
bool show_logout_button_in_tray_;
base::TimeDelta dialog_duration_;
LogoutConfirmationDialogView* confirmation_dialog_; // Not owned.
scoped_ptr<LogoutConfirmationDialogView::Delegate> confirmation_delegate_;
DISALLOW_COPY_AND_ASSIGN(LogoutButtonTray);
};
......
This diff is collapsed.
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/logout_button/logout_confirmation_dialog_view.h"
#include "ash/shell.h"
#include "ash/system/logout_button/logout_button_tray.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/tray_constants.h"
#include "base/location.h"
#include "grit/ash_strings.h"
#include "ui/aura/root_window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/time_format.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace internal {
namespace {
const int kCountdownUpdateIntervalMs = 1000; // 1 second.
inline int Round(double x) {
return static_cast<int>(x + 0.5);
}
} // namespace
LogoutConfirmationDialogView::LogoutConfirmationDialogView(
LogoutButtonTray* owner, Delegate* delegate) : owner_(owner),
delegate_(delegate) {
text_label_ = new views::Label;
text_label_->set_border(
views::Border::CreateEmptyBorder(0, kTrayPopupPaddingHorizontal,
0, kTrayPopupPaddingHorizontal));
text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
text_label_->SetMultiLine(true);
SetLayoutManager(new views::FillLayout());
AddChildView(text_label_);
}
LogoutConfirmationDialogView::~LogoutConfirmationDialogView() {
}
bool LogoutConfirmationDialogView::Accept() {
LogoutCurrentUser();
return true;
}
ui::ModalType LogoutConfirmationDialogView::GetModalType() const {
return ui::MODAL_TYPE_SYSTEM;
}
base::string16 LogoutConfirmationDialogView::GetWindowTitle() const {
return l10n_util::GetStringUTF16(IDS_ASH_LOGOUT_CONFIRMATION_TITLE);
}
base::string16 LogoutConfirmationDialogView::GetDialogButtonLabel(
ui::DialogButton button) const {
if (button == ui::DIALOG_BUTTON_OK)
return l10n_util::GetStringUTF16(IDS_ASH_LOGOUT_CONFIRMATION_BUTTON);
return views::DialogDelegateView::GetDialogButtonLabel(button);
}
void LogoutConfirmationDialogView::OnClosed() {
owner_->ReleaseConfirmationDialog();
owner_ = NULL;
timer_.Stop();
// Nullify the delegate to prevent future activities of the dialog.
delegate_ = NULL;
}
void LogoutConfirmationDialogView::DeleteDelegate() {
if (owner_)
owner_->ReleaseConfirmationDialog();
delete this;
}
void LogoutConfirmationDialogView::Show(base::TimeDelta duration) {
if (!delegate_)
return;
countdown_start_time_ = delegate_->GetCurrentTime();
duration_ = duration;
UpdateCountdown();
delegate_->ShowDialog(this);
timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(kCountdownUpdateIntervalMs),
this,
&LogoutConfirmationDialogView::UpdateCountdown);
}
void LogoutConfirmationDialogView::UpdateDialogDuration(
base::TimeDelta duration) {
duration_ = duration;
UpdateCountdown();
}
void LogoutConfirmationDialogView::LogoutCurrentUser() {
if (!delegate_)
return;
delegate_->LogoutCurrentUser();
}
void LogoutConfirmationDialogView::UpdateCountdown() {
if (!delegate_)
return;
const base::TimeDelta time_remaining = countdown_start_time_ +
duration_ - delegate_->GetCurrentTime();
// Round the remaining time to nearest second, and use this value for
// the countdown display and actual enforcement.
int seconds_remaining = Round(time_remaining.InSecondsF());
if (seconds_remaining > 0) {
text_label_->SetText(l10n_util::GetStringFUTF16(
IDS_ASH_LOGOUT_CONFIRMATION_WARNING,
ui::TimeFormat::TimeDurationLong(base::TimeDelta::FromSeconds(
seconds_remaining))));
} else {
text_label_->SetText(l10n_util::GetStringUTF16(
IDS_ASH_LOGOUT_CONFIRMATION_WARNING_NOW));
timer_.Stop();
LogoutCurrentUser();
}
}
} // namespace internal
} // namespace ash
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_SYSTEM_LOGOUT_BUTTON_LOGOUT_CONFIRMATION_DIALOG_VIEW_H_
#define ASH_SYSTEM_LOGOUT_BUTTON_LOGOUT_CONFIRMATION_DIALOG_VIEW_H_
#include "ash/ash_export.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/views/window/dialog_delegate.h"
namespace views {
class Label;
}
namespace ash {
namespace internal {
class LogoutButtonTray;
// This class implements dialog view for logout confirmation.
class ASH_EXPORT LogoutConfirmationDialogView
: public views::DialogDelegateView {
public:
class ASH_EXPORT Delegate {
public:
virtual ~Delegate() {}
virtual void LogoutCurrentUser() = 0;
virtual base::TimeTicks GetCurrentTime() const = 0;
virtual void ShowDialog(views::DialogDelegate* dialog) = 0;
};
LogoutConfirmationDialogView(LogoutButtonTray* owner, Delegate* delegate);
virtual ~LogoutConfirmationDialogView();
// views::DialogDelegateView:
virtual bool Accept() OVERRIDE;
virtual ui::ModalType GetModalType() const OVERRIDE;
virtual base::string16 GetWindowTitle() const OVERRIDE;
virtual base::string16
GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
virtual void OnClosed() OVERRIDE;
virtual void DeleteDelegate() OVERRIDE;
void Show(base::TimeDelta duration);
// The duration of the confirmation dialog can be changed while the dialog
// is still showing. This method is only expected to be called when the
// preference for confirmation dialog duration has changed.
void UpdateDialogDuration(base::TimeDelta duration);
private:
void LogoutCurrentUser();
void UpdateCountdown();
views::Label* text_label_;
base::TimeTicks countdown_start_time_;
base::TimeDelta duration_;
base::RepeatingTimer<LogoutConfirmationDialogView> timer_;
LogoutButtonTray* owner_;
Delegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationDialogView);
};
} // namespace internal
} // namespace ash
#endif // ASH_SYSTEM_LOGOUT_BUTTON_LOGOUT_CONFIRMATION_DIALOG_VIEW_H_
......@@ -232,6 +232,13 @@ void SystemTrayNotifier::NotifyShowLoginButtonChanged(bool show_login_button) {
OnShowLogoutButtonInTrayChanged(show_login_button));
}
void SystemTrayNotifier::NotifyLogoutDialogDurationChanged(
base::TimeDelta duration) {
FOR_EACH_OBSERVER(LogoutButtonObserver,
logout_button_observers_,
OnLogoutDialogDurationChanged(duration));
}
void SystemTrayNotifier::NotifyLocaleChanged(
LocaleObserver::Delegate* delegate,
const std::string& cur_locale,
......
......@@ -22,6 +22,7 @@
#include "ash/system/user/update_observer.h"
#include "ash/system/user/user_observer.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#if defined(OS_CHROMEOS)
#include "ash/system/chromeos/enterprise/enterprise_domain_observer.h"
......@@ -103,6 +104,7 @@ public:
void NotifyDriveJobUpdated(const DriveOperationStatus& status);
void NotifyRefreshIME(bool show_message);
void NotifyShowLoginButtonChanged(bool show_login_button);
void NotifyLogoutDialogDurationChanged(base::TimeDelta duration);
void NotifyLocaleChanged(LocaleObserver::Delegate* delegate,
const std::string& cur_locale,
const std::string& from_locale,
......
......@@ -68,13 +68,17 @@ void RegisterChromeLauncherUserPrefs(
prefs::kShelfAlignmentLocal,
std::string(),
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
registry->RegisterDictionaryPref(
prefs::kShelfPreferences,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
registry->RegisterIntegerPref(
prefs::kLogoutDialogDurationMs,
20000,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
registry->RegisterBooleanPref(
prefs::kShowLogoutButtonInTray,
false,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
registry->RegisterDictionaryPref(
prefs::kShelfPreferences,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}
base::DictionaryValue* CreateAppDict(const std::string& app_id) {
......
......@@ -908,6 +908,10 @@ class SystemTrayDelegate : public ash::SystemTrayDelegate,
prefs::kShowLogoutButtonInTray,
base::Bind(&SystemTrayDelegate::UpdateShowLogoutButtonInTray,
base::Unretained(this)));
user_pref_registrar_->Add(
prefs::kLogoutDialogDurationMs,
base::Bind(&SystemTrayDelegate::UpdateLogoutDialogDuration,
base::Unretained(this)));
user_pref_registrar_->Add(
prefs::kLargeCursorEnabled,
base::Bind(&SystemTrayDelegate::OnAccessibilityModeChanged,
......@@ -930,6 +934,7 @@ class SystemTrayDelegate : public ash::SystemTrayDelegate,
UpdateClockType();
UpdateShowLogoutButtonInTray();
UpdateLogoutDialogDuration();
UpdatePerformanceTracing();
search_key_mapped_to_ =
profile->GetPrefs()->GetInteger(prefs::kLanguageRemapSearchKeyTo);
......@@ -1001,6 +1006,13 @@ class SystemTrayDelegate : public ash::SystemTrayDelegate,
prefs::kShowLogoutButtonInTray));
}
void UpdateLogoutDialogDuration() {
const int duration_ms = user_pref_registrar_->prefs()->GetInteger(
prefs::kLogoutDialogDurationMs);
GetSystemTrayNotifier()->NotifyLogoutDialogDurationChanged(
base::TimeDelta::FromMilliseconds(duration_ms));
}
void UpdateSessionStartTime() {
const PrefService* local_state = local_state_registrar_->prefs();
if (local_state->HasPrefPath(prefs::kSessionStartTime)) {
......
......@@ -2464,15 +2464,20 @@ const char kShelfAutoHideBehaviorLocal[] = "auto_hide_behavior_local";
// index is also stored in the |kPinnedLauncherApp| pref. It may causes
// creating two chrome icons.
const char kShelfChromeIconIndex[] = "shelf_chrome_icon_index";
const char kPinnedLauncherApps[] = "pinned_launcher_apps";
// Boolean value indicating whether to show a logout button in the ash tray.
const char kShowLogoutButtonInTray[] = "show_logout_button_in_tray";
// Dictionary value that holds per-display preference of shelf alignment and
// auto-hide behavior. Key of the dictionary is the id of the display, and
// its value is a dictionary whose keys are kShelfAlignment and
// kShelfAutoHideBehavior.
const char kShelfPreferences[] = "shelf_preferences";
// Integer value in milliseconds indicating the length of time for which a
// confirmation dialog should be shown when the user presses the logout button.
// A value of 0 indicates that logout should happen immediately, without showing
// a confirmation dialog.
const char kLogoutDialogDurationMs[] = "logout_dialog_duration_ms";
const char kPinnedLauncherApps[] = "pinned_launcher_apps";
// Boolean value indicating whether to show a logout button in the ash tray.
const char kShowLogoutButtonInTray[] = "show_logout_button_in_tray";
#endif
#if defined(USE_AURA)
......
......@@ -851,9 +851,11 @@ extern const char kShelfAlignmentLocal[];
extern const char kShelfAutoHideBehavior[];
extern const char kShelfAutoHideBehaviorLocal[];
extern const char kShelfChromeIconIndex[];
extern const char kShelfPreferences[];
extern const char kLogoutDialogDurationMs[];
extern const char kPinnedLauncherApps[];
extern const char kShowLogoutButtonInTray[];
extern const char kShelfPreferences[];
#endif
#if defined(USE_AURA)
......
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