blob: 524f10be2d4deff9e4d4c93f4730125d9a1a7eaf [file] [log] [blame]
// Copyright 2018 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/message_center/ash_message_center_lock_screen_controller.h"
#include "ash/login/ui/lock_screen.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/ash_pref_names.h"
#include "ash/session/session_controller.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/toast/toast_data.h"
#include "ash/system/toast/toast_manager.h"
#include "ash/system/unified/unified_system_tray.h"
#include "base/strings/utf_string_conversions.h"
#include "components/prefs/pref_service.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/widget/widget.h"
namespace ash {
// static private
base::Optional<AshMessageCenterLockScreenController::Mode>
AshMessageCenterLockScreenController::overridden_mode_for_testing_;
// static
bool AshMessageCenterLockScreenController::IsEnabled() {
auto mode = GetMode();
bool is_showing = (mode == Mode::SHOW || mode == Mode::HIDE_SENSITIVE);
// If |isAllowed()| is false, must return false;
DCHECK(!is_showing || IsAllowed());
return is_showing;
}
// static
bool AshMessageCenterLockScreenController::IsAllowed() {
return GetMode() != Mode::PROHIBITED;
}
// static, private
AshMessageCenterLockScreenController::Mode
AshMessageCenterLockScreenController::GetMode() {
if (overridden_mode_for_testing_.has_value())
return *overridden_mode_for_testing_;
if (!features::IsLockScreenNotificationsEnabled())
return Mode::PROHIBITED;
// User prefs may be null in some tests.
PrefService* user_prefs =
Shell::Get()->session_controller()->GetLastActiveUserPrefService();
if (!user_prefs)
return Mode::PROHIBITED;
const std::string& mode =
user_prefs->GetString(prefs::kMessageCenterLockScreenMode);
if (mode == prefs::kMessageCenterLockScreenModeShow)
return Mode::SHOW;
if (mode == prefs::kMessageCenterLockScreenModeHideSensitive &&
features::IsLockScreenHideSensitiveNotificationsSupported())
return Mode::HIDE_SENSITIVE;
return Mode::HIDE;
}
// static, only for testing
void AshMessageCenterLockScreenController::OverrideModeForTest(
base::Optional<AshMessageCenterLockScreenController::Mode> new_mode) {
overridden_mode_for_testing_ = new_mode;
}
namespace {
const char kToastId[] = "ash-lock-screen-manager";
} // anonymous namespace
AshMessageCenterLockScreenController::AshMessageCenterLockScreenController()
: locked_(Shell::Get()->session_controller()->IsScreenLocked()) {}
AshMessageCenterLockScreenController::~AshMessageCenterLockScreenController() {
// Invokes the cancel task if any.
if (cancel_task_)
std::move(cancel_task_).Run();
}
void AshMessageCenterLockScreenController::DismissLockScreenThenExecute(
base::OnceClosure pending_callback,
base::OnceClosure cancel_callback) {
if (locked_) {
// Invokes the previous cancel task if any.
if (cancel_task_)
std::move(cancel_task_).Run();
// Stores the new pending/cancel tasks.
pending_task_ = std::move(pending_callback);
cancel_task_ = std::move(cancel_callback);
EncourageUserToUnlock();
} else {
DCHECK(pending_task_.is_null());
DCHECK(cancel_task_.is_null());
if (pending_callback)
std::move(pending_callback).Run();
}
}
bool AshMessageCenterLockScreenController::IsScreenLocked() const {
return locked_;
}
void AshMessageCenterLockScreenController::EncourageUserToUnlock() {
DCHECK(locked_);
DCHECK(LockScreen::Get());
DCHECK(LockScreen::Get()->widget());
auto* unified_system_tray =
Shelf::ForWindow(LockScreen::Get()->widget()->GetNativeWindow())
->GetStatusAreaWidget()
->unified_system_tray();
if (unified_system_tray) {
// Lockscreen notification works only with the unified system tray.
unified_system_tray->CloseBubble();
}
// TODO(yoshiki): Update UI after the UX finalizes.
Shell::Get()->toast_manager()->Show(ToastData(
kToastId,
(Shell::Get()->session_controller()->NumberOfLoggedInUsers() == 1 ||
active_account_id_.empty())
? l10n_util::GetStringUTF16(
IDS_ASH_MESSAGE_CENTER_UNLOCK_TO_PERFORM_ACTION)
: l10n_util::GetStringFUTF16(
IDS_ASH_MESSAGE_CENTER_UNLOCK_TO_PERFORM_ACTION_WITH_USER_ID,
base::UTF8ToUTF16(active_account_id_.GetUserEmail())),
ToastData::kInfiniteDuration, base::nullopt,
/*visible_on_lock_screen=*/true));
}
void AshMessageCenterLockScreenController::OnLockStateChanged(bool locked) {
if (locked_ == locked)
return;
locked_ = locked;
if (!locked) {
Shell::Get()->toast_manager()->Cancel(kToastId);
// Invokes the pending task and resets the cancel task.
if (pending_task_)
std::move(pending_task_).Run();
std::move(cancel_task_).Reset();
} else {
DCHECK(pending_task_.is_null());
DCHECK(cancel_task_.is_null());
}
}
void AshMessageCenterLockScreenController::OnActiveUserSessionChanged(
const AccountId& account_id) {
if (active_account_id_ == account_id)
return;
active_account_id_ = account_id;
if (locked_) {
// Cancels the current callbacks, if the user switches the active account
// on the lock screen.
DCHECK(Shell::Get());
DCHECK(Shell::Get()->toast_manager());
Shell::Get()->toast_manager()->Cancel(kToastId);
std::move(pending_task_).Reset();
if (cancel_task_)
std::move(cancel_task_).Run();
}
}
} // namespace ash