123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- // Copyright 2017 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/shelf/shelf_controller.h"
- #include <string>
- #include "ash/constants/ash_pref_names.h"
- #include "ash/public/cpp/shelf_item_delegate.h"
- #include "ash/public/cpp/shelf_model.h"
- #include "ash/public/cpp/shelf_prefs.h"
- #include "ash/public/cpp/test/test_shelf_item_delegate.h"
- #include "ash/public/cpp/window_properties.h"
- #include "ash/root_window_controller.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/session/test_session_controller_client.h"
- #include "ash/shelf/shelf.h"
- #include "ash/shell.h"
- #include "ash/test/ash_test_base.h"
- #include "ash/test/ash_test_helper.h"
- #include "ash/test_shell_delegate.h"
- #include "ash/wm/tablet_mode/tablet_mode_controller.h"
- #include "ash/wm/window_util.h"
- #include "base/run_loop.h"
- #include "base/strings/utf_string_conversions.h"
- #include "components/account_id/account_id.h"
- #include "components/prefs/pref_service.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/gfx/image/image_unittest_util.h"
- #include "ui/message_center/message_center.h"
- #include "ui/message_center/public/cpp/notifier_id.h"
- namespace ash {
- Shelf* GetShelfForDisplay(int64_t display_id) {
- return Shell::GetRootWindowControllerWithDisplayId(display_id)->shelf();
- }
- using ShelfControllerTest = AshTestBase;
- TEST_F(ShelfControllerTest, Shutdown) {
- // Simulate a display change occurring during shutdown (e.g. due to a screen
- // rotation animation being canceled).
- Shell::Get()->shelf_controller()->Shutdown();
- display_manager()->SetDisplayRotation(
- display::Screen::GetScreen()->GetPrimaryDisplay().id(),
- display::Display::ROTATE_90, display::Display::RotationSource::ACTIVE);
- // Ash does not crash during cleanup.
- }
- TEST_F(ShelfControllerTest, ShelfIDUpdate) {
- ShelfModel* model = Shell::Get()->shelf_controller()->model();
- const ShelfID id1("id1");
- const ShelfID id2("id2");
- std::unique_ptr<aura::Window> window(
- CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
- window->SetProperty(kShelfIDKey, id1.Serialize());
- wm::ActivateWindow(window.get());
- EXPECT_EQ(id1, model->active_shelf_id());
- window->SetProperty(kShelfIDKey, id2.Serialize());
- EXPECT_EQ(id2, model->active_shelf_id());
- window->ClearProperty(kShelfIDKey);
- EXPECT_NE(id1, model->active_shelf_id());
- EXPECT_NE(id2, model->active_shelf_id());
- }
- class ShelfControllerNotificationIndicatorTest : public AshTestBase {
- public:
- ShelfControllerNotificationIndicatorTest() = default;
- ShelfControllerNotificationIndicatorTest(
- const ShelfControllerNotificationIndicatorTest&) = delete;
- ShelfControllerNotificationIndicatorTest& operator=(
- const ShelfControllerNotificationIndicatorTest&) = delete;
- ~ShelfControllerNotificationIndicatorTest() override = default;
- void SetUp() override {
- AshTestBase::SetUp();
- account_id_ = AccountId::FromUserEmail("test@gmail.com");
- }
- void SendAppUpdate(bool app_has_badge) {
- ShelfController* controller = Shell::Get()->shelf_controller();
- auto test_app = std::make_unique<apps::App>(apps::AppType::kArc, "app_id");
- test_app->has_badge = app_has_badge;
- apps::AppUpdate test_update(nullptr, /*delta=*/test_app.get(), account_id_);
- static_cast<apps::AppRegistryCache::Observer*>(controller)
- ->OnAppUpdate(test_update);
- }
- private:
- AccountId account_id_;
- };
- // Tests that the ShelfController keeps the ShelfModel updated on calls to
- // OnAppUpdate().
- TEST_F(ShelfControllerNotificationIndicatorTest, HasNotificationBasic) {
- ShelfController* controller = Shell::Get()->shelf_controller();
- const std::string app_id("app_id");
- ShelfItem item;
- item.type = TYPE_APP;
- item.id = ShelfID(app_id);
- const int index = controller->model()->Add(
- item, std::make_unique<TestShelfItemDelegate>(item.id));
- EXPECT_FALSE(controller->model()->items()[index].has_notification);
- // Send an app update to ShelfController for adding a notification badge.
- SendAppUpdate(true /* app_has_badge */);
- EXPECT_TRUE(controller->model()->items()[index].has_notification);
- // Send an app update to ShelfController for removing a notification badge.
- SendAppUpdate(false /* app_has_badge */);
- EXPECT_FALSE(controller->model()->items()[index].has_notification);
- }
- class ShelfControllerPrefsTest : public AshTestBase {
- public:
- ShelfControllerPrefsTest() = default;
- ShelfControllerPrefsTest(const ShelfControllerPrefsTest&) = delete;
- ShelfControllerPrefsTest& operator=(const ShelfControllerPrefsTest&) = delete;
- ~ShelfControllerPrefsTest() override = default;
- };
- // Ensure shelf settings are updated on preference changes.
- TEST_F(ShelfControllerPrefsTest, ShelfRespectsPrefs) {
- Shelf* shelf = GetPrimaryShelf();
- EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
- PrefService* prefs =
- Shell::Get()->session_controller()->GetLastActiveUserPrefService();
- prefs->SetString(prefs::kShelfAlignmentLocal, "Left");
- prefs->SetString(prefs::kShelfAutoHideBehaviorLocal, "Always");
- EXPECT_EQ(ShelfAlignment::kLeft, shelf->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
- }
- // Ensure shelf settings are updated on per-display preference changes.
- TEST_F(ShelfControllerPrefsTest, ShelfRespectsPerDisplayPrefs) {
- UpdateDisplay("1024x768,800x600");
- base::RunLoop().RunUntilIdle();
- const int64_t id1 = GetPrimaryDisplay().id();
- const int64_t id2 = GetSecondaryDisplay().id();
- Shelf* shelf1 = GetShelfForDisplay(id1);
- Shelf* shelf2 = GetShelfForDisplay(id2);
- EXPECT_EQ(ShelfAlignment::kBottom, shelf1->alignment());
- EXPECT_EQ(ShelfAlignment::kBottom, shelf2->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf1->auto_hide_behavior());
- EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf2->auto_hide_behavior());
- PrefService* prefs =
- Shell::Get()->session_controller()->GetLastActiveUserPrefService();
- SetShelfAlignmentPref(prefs, id1, ShelfAlignment::kLeft);
- SetShelfAlignmentPref(prefs, id2, ShelfAlignment::kRight);
- SetShelfAutoHideBehaviorPref(prefs, id1, ShelfAutoHideBehavior::kAlways);
- SetShelfAutoHideBehaviorPref(prefs, id2, ShelfAutoHideBehavior::kAlways);
- EXPECT_EQ(ShelfAlignment::kLeft, shelf1->alignment());
- EXPECT_EQ(ShelfAlignment::kRight, shelf2->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf1->auto_hide_behavior());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf2->auto_hide_behavior());
- }
- // Ensures that pre-Unified Mode per-display shelf settings don't prevent us
- // from changing the shelf settings in unified mode.
- TEST_F(ShelfControllerPrefsTest, ShelfRespectsPerDisplayPrefsUnified) {
- UpdateDisplay("1024x768,800x600");
- // Before enabling Unified Mode, set the shelf alignment for one of the two
- // displays, so that we have a per-display shelf alignment setting.
- ASSERT_FALSE(display_manager()->IsInUnifiedMode());
- const int64_t non_unified_primary_id = GetPrimaryDisplay().id();
- PrefService* prefs =
- Shell::Get()->session_controller()->GetLastActiveUserPrefService();
- Shelf* shelf = GetShelfForDisplay(non_unified_primary_id);
- EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
- SetShelfAlignmentPref(prefs, non_unified_primary_id, ShelfAlignment::kLeft);
- EXPECT_EQ(ShelfAlignment::kLeft, shelf->alignment());
- // Switch to Unified Mode, and expect to be able to change the shelf
- // alignment.
- display_manager()->SetUnifiedDesktopEnabled(true);
- ASSERT_TRUE(display_manager()->IsInUnifiedMode());
- const int64_t unified_id = display::kUnifiedDisplayId;
- ASSERT_EQ(unified_id, GetPrimaryDisplay().id());
- shelf = GetShelfForDisplay(unified_id);
- EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
- SetShelfAlignmentPref(prefs, unified_id, ShelfAlignment::kLeft);
- SetShelfAutoHideBehaviorPref(prefs, unified_id,
- ShelfAutoHideBehavior::kAlways);
- EXPECT_EQ(ShelfAlignment::kLeft, shelf->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
- SetShelfAlignmentPref(prefs, unified_id, ShelfAlignment::kRight);
- EXPECT_EQ(ShelfAlignment::kRight, shelf->alignment());
- }
- // Ensure shelf settings are correct after display swap at login screen, see
- // crbug.com/748291
- TEST_F(ShelfControllerPrefsTest,
- ShelfSettingsValidAfterDisplaySwapAtLoginScreen) {
- // Simulate adding an external display at the lock screen.
- GetSessionControllerClient()->RequestLockScreen();
- UpdateDisplay("1024x768,800x600");
- base::RunLoop().RunUntilIdle();
- const int64_t internal_display_id = GetPrimaryDisplay().id();
- const int64_t external_display_id = GetSecondaryDisplay().id();
- // The primary shelf should be on the internal display.
- EXPECT_EQ(GetPrimaryShelf(), GetShelfForDisplay(internal_display_id));
- EXPECT_NE(GetPrimaryShelf(), GetShelfForDisplay(external_display_id));
- PrefService* prefs =
- Shell::Get()->session_controller()->GetLastActiveUserPrefService();
- // Check for the default shelf preferences.
- EXPECT_EQ(ShelfAutoHideBehavior::kNever,
- GetShelfAutoHideBehaviorPref(prefs, internal_display_id));
- EXPECT_EQ(ShelfAutoHideBehavior::kNever,
- GetShelfAutoHideBehaviorPref(prefs, external_display_id));
- EXPECT_EQ(ShelfAlignment::kBottom,
- GetShelfAlignmentPref(prefs, internal_display_id));
- EXPECT_EQ(ShelfAlignment::kBottom,
- GetShelfAlignmentPref(prefs, external_display_id));
- // Check the current state; shelves have locked alignments in the lock screen.
- EXPECT_EQ(ShelfAutoHideBehavior::kNever,
- GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
- EXPECT_EQ(ShelfAutoHideBehavior::kNever,
- GetShelfForDisplay(external_display_id)->auto_hide_behavior());
- EXPECT_EQ(ShelfAlignment::kBottomLocked,
- GetShelfForDisplay(internal_display_id)->alignment());
- EXPECT_EQ(ShelfAlignment::kBottomLocked,
- GetShelfForDisplay(external_display_id)->alignment());
- // Set some shelf prefs to differentiate the two shelves, check state.
- SetShelfAlignmentPref(prefs, internal_display_id, ShelfAlignment::kLeft);
- SetShelfAlignmentPref(prefs, external_display_id, ShelfAlignment::kRight);
- EXPECT_EQ(ShelfAlignment::kBottomLocked,
- GetShelfForDisplay(internal_display_id)->alignment());
- EXPECT_EQ(ShelfAlignment::kBottomLocked,
- GetShelfForDisplay(external_display_id)->alignment());
- SetShelfAutoHideBehaviorPref(prefs, external_display_id,
- ShelfAutoHideBehavior::kAlways);
- EXPECT_EQ(ShelfAutoHideBehavior::kNever,
- GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways,
- GetShelfForDisplay(external_display_id)->auto_hide_behavior());
- // Simulate the external display becoming the primary display. The shelves are
- // swapped (each instance now has a different display id), check state.
- SwapPrimaryDisplay();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ShelfAlignment::kBottomLocked,
- GetShelfForDisplay(internal_display_id)->alignment());
- EXPECT_EQ(ShelfAlignment::kBottomLocked,
- GetShelfForDisplay(external_display_id)->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kNever,
- GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways,
- GetShelfForDisplay(external_display_id)->auto_hide_behavior());
- // After screen unlock the shelves should have the expected alignment values.
- GetSessionControllerClient()->UnlockScreen();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ShelfAlignment::kLeft,
- GetShelfForDisplay(internal_display_id)->alignment());
- EXPECT_EQ(ShelfAlignment::kRight,
- GetShelfForDisplay(external_display_id)->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kNever,
- GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways,
- GetShelfForDisplay(external_display_id)->auto_hide_behavior());
- }
- // Test display swap while logged in, which was causing a crash (see
- // crbug.com/1022852)
- TEST_F(ShelfControllerPrefsTest,
- ShelfSettingsValidAfterDisplaySwapWhileLoggedIn) {
- // Simulate adding an external display at the lock screen.
- GetSessionControllerClient()->RequestLockScreen();
- UpdateDisplay("1024x768,800x600");
- base::RunLoop().RunUntilIdle();
- const int64_t internal_display_id = GetPrimaryDisplay().id();
- const int64_t external_display_id = GetSecondaryDisplay().id();
- PrefService* prefs =
- Shell::Get()->session_controller()->GetLastActiveUserPrefService();
- // Set some shelf prefs to differentiate the two shelves.
- SetShelfAlignmentPref(prefs, internal_display_id, ShelfAlignment::kLeft);
- SetShelfAlignmentPref(prefs, external_display_id, ShelfAlignment::kRight);
- SetShelfAutoHideBehaviorPref(prefs, external_display_id,
- ShelfAutoHideBehavior::kAlways);
- // Unlock the screen.
- GetSessionControllerClient()->UnlockScreen();
- base::RunLoop().RunUntilIdle();
- // Simulate the external display becoming the primary display. The shelves are
- // swapped (each instance now has a different display id), check state.
- SwapPrimaryDisplay();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ShelfAlignment::kLeft,
- GetShelfForDisplay(internal_display_id)->alignment());
- EXPECT_EQ(ShelfAlignment::kRight,
- GetShelfForDisplay(external_display_id)->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kNever,
- GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways,
- GetShelfForDisplay(external_display_id)->auto_hide_behavior());
- }
- TEST_F(ShelfControllerPrefsTest, ShelfSettingsInTabletMode) {
- Shelf* shelf = GetPrimaryShelf();
- PrefService* prefs =
- Shell::Get()->session_controller()->GetLastActiveUserPrefService();
- SetShelfAlignmentPref(prefs, GetPrimaryDisplay().id(), ShelfAlignment::kLeft);
- SetShelfAutoHideBehaviorPref(prefs, GetPrimaryDisplay().id(),
- ShelfAutoHideBehavior::kAlways);
- ASSERT_EQ(ShelfAlignment::kLeft, shelf->alignment());
- ASSERT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
- // Verify after entering tablet mode, the shelf alignment is bottom and the
- // auto hide behavior has not changed.
- Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
- EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
- // Verify that screen rotation does not change alignment or auto-hide.
- display_manager()->SetDisplayRotation(
- display::Screen::GetScreen()->GetPrimaryDisplay().id(),
- display::Display::ROTATE_90, display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
- // Verify after exiting tablet mode, the shelf alignment and auto hide
- // behavior get their stored pref values.
- Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
- EXPECT_EQ(ShelfAlignment::kLeft, shelf->alignment());
- EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
- }
- using ShelfControllerAppModeTest = NoSessionAshTestBase;
- // Tests that shelf auto hide behavior is always hidden in app mode.
- TEST_F(ShelfControllerAppModeTest, AutoHideBehavior) {
- SimulateKioskMode(user_manager::USER_TYPE_KIOSK_APP);
- Shelf* shelf = GetPrimaryShelf();
- EXPECT_EQ(ShelfAutoHideBehavior::kAlwaysHidden, shelf->auto_hide_behavior());
- Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
- EXPECT_EQ(ShelfAutoHideBehavior::kAlwaysHidden, shelf->auto_hide_behavior());
- display_manager()->SetDisplayRotation(
- display::Screen::GetScreen()->GetPrimaryDisplay().id(),
- display::Display::ROTATE_90, display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(ShelfAutoHideBehavior::kAlwaysHidden, shelf->auto_hide_behavior());
- Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
- EXPECT_EQ(ShelfAutoHideBehavior::kAlwaysHidden, shelf->auto_hide_behavior());
- }
- using ShelfControllerShelfPartyTest = NoSessionAshTestBase;
- TEST_F(ShelfControllerShelfPartyTest, ShelfPartyEndedOnLockScreen) {
- auto* session_controller = GetSessionControllerClient();
- session_controller->SetSessionState(session_manager::SessionState::ACTIVE);
- ShelfModel* model = Shell::Get()->shelf_controller()->model();
- model->ToggleShelfParty();
- EXPECT_TRUE(model->in_shelf_party());
- session_controller->SetSessionState(session_manager::SessionState::LOCKED);
- EXPECT_FALSE(model->in_shelf_party());
- }
- TEST_F(ShelfControllerShelfPartyTest, ShelfPartyEndedOnSwitchUsers) {
- auto* session_controller = GetSessionControllerClient();
- constexpr char kEmail1[] = "user1@gmail.com";
- session_controller->AddUserSession(kEmail1);
- constexpr char kEmail2[] = "user2@gmail.com";
- session_controller->AddUserSession(kEmail2);
- session_controller->SwitchActiveUser(AccountId::FromUserEmail(kEmail1));
- session_controller->SetSessionState(session_manager::SessionState::ACTIVE);
- ShelfModel* model = Shell::Get()->shelf_controller()->model();
- model->ToggleShelfParty();
- EXPECT_TRUE(model->in_shelf_party());
- session_controller->SwitchActiveUser(AccountId::FromUserEmail(kEmail2));
- EXPECT_FALSE(model->in_shelf_party());
- }
- } // namespace ash
|