text: // Copyright (c) 2012 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_TEST_ASH_TEST_BASE_H_
  #define ASH_TEST_ASH_TEST_BASE_H_
  
  #include <stdint.h>
  
  #include <memory>
  #include <string>
  #include <utility>
  
  #include "ash/constants/app_types.h"
  #include "ash/public/cpp/shell_window_ids.h"
  #include "ash/session/test_session_controller_client.h"
  #include "ash/wm/desks/desks_util.h"
  #include "ash/wm/overview/overview_types.h"
  #include "base/compiler_specific.h"
  #include "base/test/task_environment.h"
  #include "base/threading/thread.h"
  #include "base/traits_bag.h"
  #include "components/prefs/testing_pref_service.h"
  #include "components/user_manager/user_type.h"
  #include "testing/gtest/include/gtest/gtest.h"
  #include "third_party/skia/include/core/SkColor.h"
  #include "ui/aura/client/window_types.h"
  #include "ui/aura/env.h"
  #include "ui/display/display.h"
  #include "ui/events/event_constants.h"
  #include "ui/events/test/event_generator.h"
  
  namespace aura {
  class Window;
  class WindowDelegate;
  }  // namespace aura
  
  namespace base {
  namespace test {
  class TaskEnvironment;
  }
  }  // namespace base
  
  namespace chromeos {
  class FakePowerManagerClient;
  }
  
  namespace display {
  class Display;
  class DisplayManager;
  
  namespace test {
  class DisplayManagerTestApi;
  }  // namespace test
  }  // namespace display
  
  namespace gfx {
  class Rect;
  }
  
  namespace views {
  class View;
  class Widget;
  class WidgetDelegate;
  }  // namespace views
  
  namespace ash {
  
  class AmbientAshTestHelper;
  class AppListTestHelper;
  class AshTestHelper;
  class Shelf;
  class TestAppListClient;
  class TestShellDelegate;
  class TestSystemTrayClient;
  class UnifiedSystemTray;
  class WorkAreaInsets;
  
  // Base class for most tests in //ash. Constructs ash::Shell and all its
  // dependencies. Provides a user login session (use NoSessionAshTestBase for
  // tests that start at the login screen or need unusual user types). Sets
  // animation durations to zero via AshTestHelper/AuraTestHelper.
  class AshTestBase : public testing::Test {
   public:
    // Constructs an AshTestBase with |traits| being forwarded to its
    // TaskEnvironment. MainThreadType always defaults to UI and must not be
    // specified.
    template <typename... TaskEnvironmentTraits>
    NOINLINE explicit AshTestBase(TaskEnvironmentTraits&&... traits)
        : AshTestBase(std::make_unique<base::test::TaskEnvironment>(
              base::test::TaskEnvironment::MainThreadType::UI,
              std::forward<TaskEnvironmentTraits>(traits)...)) {}
  
    // Alternatively a subclass may pass a TaskEnvironment directly.
    explicit AshTestBase(
        std::unique_ptr<base::test::TaskEnvironment> task_environment);
  
    AshTestBase(const AshTestBase&) = delete;
    AshTestBase& operator=(const AshTestBase&) = delete;
  
    ~AshTestBase() override;
  
    // testing::Test:
    void SetUp() override;
    void SetUp(std::unique_ptr<TestShellDelegate> delegate);
    void TearDown() override;
  
    // Returns the Shelf for the primary display.
    static Shelf* GetPrimaryShelf();
  
    // Returns the unified system tray on the primary display.
    static UnifiedSystemTray* GetPrimaryUnifiedSystemTray();
  
    // Returns WorkAreaInsets for the primary display.
    static WorkAreaInsets* GetPrimaryWorkAreaInsets();
  
    // Update the display configuration as given in |display_specs|.
    // See ash::DisplayManagerTestApi::UpdateDisplay for more details.
    void UpdateDisplay(const std::string& display_specs);
  
    // Returns a root Window. Usually this is the active root Window, but that
    // method can return NULL sometimes, and in those cases, we fall back on the
    // primary root Window.
    aura::Window* GetContext();
  
    // Creates and shows a widget. See ash/public/cpp/shell_window_ids.h for
    // values for |container_id|.
    static std::unique_ptr<views::Widget> CreateTestWidget(
        views::WidgetDelegate* delegate = nullptr,
        int container_id = desks_util::GetActiveDeskContainerId(),
        const gfx::Rect& bounds = gfx::Rect(),
        bool show = true);
  
    // Creates a frameless widget for testing.
    static std::unique_ptr<views::Widget> CreateFramelessTestWidget();
  
    // Creates a widget with a visible WINDOW_TYPE_NORMAL window with the given
    // |app_type|. If |app_type| is AppType::NON_APP, this window is considered a
    // non-app window.
    // If |bounds_in_screen| is empty the window is added to the primary root
    // window, otherwise the window is added to the display matching
    // |bounds_in_screen|. |shell_window_id| is the shell window id to give to
    // the new window.
    std::unique_ptr<aura::Window> CreateAppWindow(
        const gfx::Rect& bounds_in_screen = gfx::Rect(),
        AppType app_type = AppType::SYSTEM_APP,
        int shell_window_id = kShellWindowId_Invalid);
  
    // Creates a visible window in the appropriate container. If
    // |bounds_in_screen| is empty the window is added to the primary root
    // window, otherwise the window is added to the display matching
    // |bounds_in_screen|. |shell_window_id| is the shell window id to give to
    // the new window.
    // If |type| is WINDOW_TYPE_NORMAL this creates a views::Widget, otherwise
    // this creates an aura::Window.
    std::unique_ptr<aura::Window> CreateTestWindow(
        const gfx::Rect& bounds_in_screen = gfx::Rect(),
        aura::client::WindowType type = aura::client::WINDOW_TYPE_NORMAL,
        int shell_window_id = kShellWindowId_Invalid);
  
    // Creates a visible top-level window with a delegate.
    std::unique_ptr<aura::Window> CreateToplevelTestWindow(
        const gfx::Rect& bounds_in_screen = gfx::Rect(),
        int shell_window_id = kShellWindowId_Invalid);
  
    // Versions of the functions in aura::test:: that go through our shell
    // StackingController instead of taking a parent.
    aura::Window* CreateTestWindowInShellWithId(int id);
    aura::Window* CreateTestWindowInShellWithBounds(const gfx::Rect& bounds);
    aura::Window* CreateTestWindowInShellWithDelegate(
        aura::WindowDelegate* delegate,
        int id,
        const gfx::Rect& bounds);
    aura::Window* CreateTestWindowInShellWithDelegateAndType(
        aura::WindowDelegate* delegate,
        aura::client::WindowType type,
        int id,
        const gfx::Rect& bounds);
  
    // Attach |window| to the current shell's root window.
    void ParentWindowInPrimaryRootWindow(aura::Window* window);
  
    // Returns the EventGenerator that uses screen coordinates and works
    // across multiple displays. It creates a new generator if it
    // hasn't been created yet.
    ui::test::EventGenerator* GetEventGenerator();
  
    // Convenience method to return the DisplayManager.
    display::DisplayManager* display_manager();
  
    // Convenience method to return the FakePowerManagerClient.
    chromeos::FakePowerManagerClient* power_manager_client() const;
  
    // Test if moving a mouse to |point_in_screen| warps it to another
    // display.
    bool TestIfMouseWarpsAt(ui::test::EventGenerator* event_generator,
                            const gfx::Point& point_in_screen);
  
    // Presses and releases a key to simulate typing one character.
    void PressAndReleaseKey(ui::KeyboardCode key_code, int flags = ui::EF_NONE);
  
    // Moves the mouse to the center of the view and generates a left button click
    // event.
    void SimulateMouseClickAt(ui::test::EventGenerator* event_generator,
                              const views::View* target_view);
  
    // Enters/Exits overview mode with the given animation type `type`.
    bool EnterOverview(
        OverviewEnterExitType type = OverviewEnterExitType::kNormal);
    bool ExitOverview(
        OverviewEnterExitType type = OverviewEnterExitType::kNormal);
  
   protected:
    enum UserSessionBlockReason {
      FIRST_BLOCK_REASON,
      BLOCKED_BY_LOCK_SCREEN = FIRST_BLOCK_REASON,
      BLOCKED_BY_LOGIN_SCREEN,
      BLOCKED_BY_USER_ADDING_SCREEN,
      NUMBER_OF_BLOCK_REASONS
    };
  
    // Returns the rotation currentl active for the display |id|.
    static display::Display::Rotation GetActiveDisplayRotation(int64_t id);
  
    // Returns the rotation currently active for the internal display.
    static display::Display::Rotation GetCurrentInternalDisplayRotation();
  
    void set_start_session(bool start_session) { start_session_ = start_session; }
  
    base::test::TaskEnvironment* task_environment() {
      return task_environment_.get();
    }
    TestingPrefServiceSimple* local_state() { return &local_state_; }
    AshTestHelper* ash_test_helper() { return ash_test_helper_.get(); }
  
    void SetUserPref(const std::string& user_email,
                     const std::string& path,
                     const base::Value& value);
  
    TestSessionControllerClient* GetSessionControllerClient();
  
    TestSystemTrayClient* GetSystemTrayClient();
  
    AppListTestHelper* GetAppListTestHelper();
  
    TestAppListClient* GetTestAppListClient();
  
    AmbientAshTestHelper* GetAmbientAshTestHelper();
  
    // Emulates an ash session that have |session_count| user sessions running.
    // Note that existing user sessions will be cleared.
    void CreateUserSessions(int session_count);
  
    // Simulates a user sign-in. It creates a new user session, adds it to
    // existing user sessions and makes it the active user session.
    //
    // For convenience |user_email| is used to create an |AccountId|. For testing
    // behavior where |AccountId|s are compared, prefer the method of the same
    // name that takes an |AccountId| created with a valid storage key instead.
    // See the documentation for|AccountId::GetUserEmail| for discussion.
    void SimulateUserLogin(
        const std::string& user_email,
        user_manager::UserType user_type = user_manager::USER_TYPE_REGULAR);
  
    // Simulates a user sign-in. It creates a new user session, adds it to
    // existing user sessions and makes it the active user session.
    void SimulateUserLogin(
        const AccountId& account_id,
        user_manager::UserType user_type = user_manager::USER_TYPE_REGULAR);
  
    // Simular to SimulateUserLogin but for a newly created user first ever login.
    void SimulateNewUserFirstLogin(const std::string& user_email);
  
    // Similar to SimulateUserLogin but for a guest user.
    void SimulateGuestLogin();
  
    // Simulates kiosk mode. |user_type| must correlate to a kiosk type user.
    void SimulateKioskMode(user_manager::UserType user_type);
  
    // Simulates setting height of the accessibility panel.
    // Note: Accessibility panel widget needs to be setup first.
    void SetAccessibilityPanelHeight(int panel_height);
  
    // Clears all user sessions and resets to the primary login screen state.
    void ClearLogin();
  
    // Emulates whether the active user can lock screen.
    void SetCanLockScreen(bool can_lock);
  
    // Emulates whether the screen should be locked automatically.
    void SetShouldLockScreenAutomatically(bool should_lock);
  
    // Emulates whether the user adding screen is running.
    void SetUserAddingScreenRunning(bool user_adding_screen_running);
  
    // Methods to emulate blocking and unblocking user session with given
    // |block_reason|.
    void BlockUserSession(UserSessionBlockReason block_reason);
    void UnblockUserSession();
  
    // Enable or disable the virtual on-screen keyboard and run the message loop
    // to allow observer operations to complete.
    void SetVirtualKeyboardEnabled(bool enabled);
  
    void DisableIME();
  
    // Swap the primary display with the secondary.
    void SwapPrimaryDisplay();
  
    display::Display GetPrimaryDisplay() const;
    display::Display GetSecondaryDisplay() const;
  
   private:
    void CreateWindowTreeIfNecessary();
  
    bool setup_called_ = false;
    bool teardown_called_ = false;
  
    // SetUp() doesn't activate session if this is set to false.
    bool start_session_ = true;
  
    // |task_environment_| is initialized-once at construction time but
    // subclasses may elect to provide their own.
    std::unique_ptr<base::test::TaskEnvironment> task_environment_;
  
    // A pref service used for local state.
    TestingPrefServiceSimple local_state_;
  
    // Must be constructed after |task_environment_|.
    std::unique_ptr<AshTestHelper> ash_test_helper_;
  
    std::unique_ptr<ui::test::EventGenerator> event_generator_;
  };
  
  class NoSessionAshTestBase : public AshTestBase {
   public:
    NoSessionAshTestBase();
    explicit NoSessionAshTestBase(
        base::test::TaskEnvironment::TimeSource time_source);
  
    NoSessionAshTestBase(const NoSessionAshTestBase&) = delete;
    NoSessionAshTestBase& operator=(const NoSessionAshTestBase&) = delete;
  
    ~NoSessionAshTestBase() override;
  };
  
  }  // namespace ash
  
  #endif  // ASH_TEST_ASH_TEST_BASE_H_
  