Skip to content

Commit

Permalink
Desks: Add autotestPrivate APIs to interact with Virtual Desks
Browse files Browse the repository at this point in the history
Expose a limited API through autotest private to interact with
Virtual Desks, so that we can later invoke those APIs from Tast
tests.

BUG=1016994
TEST=Added new tests

Change-Id: I43d0f4d8c85f95c1b2bfb4aa97107bdc2f24623c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1895742
Commit-Queue: Ahmed Fakhry <afakhry@chromium.org>
Reviewed-by: Steven Bennetts <stevenjb@chromium.org>
Reviewed-by: James Cook <jamescook@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712868}
  • Loading branch information
Ahmed Fakhry authored and Commit Bot committed Nov 6, 2019
1 parent a363ca2 commit ce18042
Show file tree
Hide file tree
Showing 9 changed files with 366 additions and 0 deletions.
3 changes: 3 additions & 0 deletions ash/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ component("ash") {
"public/cpp/arc_custom_tab.h",
"public/cpp/ash_prefs.h",
"public/cpp/assistant/assistant_settings.h",
"public/cpp/autotest_desks_api.h",
"public/cpp/autotest_private_api_utils.h",
"public/cpp/docked_magnifier_controller.h",
"public/cpp/event_rewriter_controller.h",
Expand Down Expand Up @@ -1123,6 +1124,7 @@ component("ash") {
"wm/default_state.h",
"wm/default_window_resizer.cc",
"wm/default_window_resizer.h",
"wm/desks/autotest_desks_api.cc",
"wm/desks/close_desk_button.cc",
"wm/desks/close_desk_button.h",
"wm/desks/desk.cc",
Expand Down Expand Up @@ -1931,6 +1933,7 @@ test("ash_unittests") {
"wm/collision_detection/collision_detection_utils_unittest.cc",
"wm/container_finder_unittest.cc",
"wm/default_window_resizer_unittest.cc",
"wm/desks/autotest_desks_api_unittests.cc",
"wm/desks/desks_unittests.cc",
"wm/drag_window_resizer_unittest.cc",
"wm/fullscreen_window_finder_unittest.cc",
Expand Down
41 changes: 41 additions & 0 deletions ash/public/cpp/autotest_desks_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2019 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_PUBLIC_CPP_AUTOTEST_DESKS_API_H_
#define ASH_PUBLIC_CPP_AUTOTEST_DESKS_API_H_

#include "ash/ash_export.h"
#include "base/callback_forward.h"

namespace ash {

// Exposes limited APIs for the autotest private APIs to interact with Virtual
// Desks.
class ASH_EXPORT AutotestDesksApi {
public:
AutotestDesksApi();
~AutotestDesksApi();

AutotestDesksApi(const AutotestDesksApi& other) = delete;
AutotestDesksApi& operator=(const AutotestDesksApi& rhs) = delete;

// Creates a new desk if the maximum number of desks has not been reached, and
// returns true if succeeded, false otherwise.
bool CreateNewDesk();

// Activates the desk at the given |index| and invokes |on_complete| when the
// switch-desks animation completes. Returns false if |index| is invalid, or
// the desk at |index| is already the active desk; true otherwise.
bool ActivateDeskAtIndex(int index, base::OnceClosure on_complete);

// Removes the currently active desk and triggers the remove-desk animation.
// |on_complete| will be invoked when the remove-desks animation completes.
// Returns false if the active desk is the last available desk which cannot be
// removed; true otherwise.
bool RemoveActiveDesk(base::OnceClosure on_complete);
};

} // namespace ash

#endif // ASH_PUBLIC_CPP_AUTOTEST_DESKS_API_H_
92 changes: 92 additions & 0 deletions ash/wm/desks/autotest_desks_api.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2019 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/public/cpp/autotest_desks_api.h"

#include "ash/wm/desks/desks_controller.h"
#include "ash/wm/desks/desks_histogram_enums.h"
#include "base/callback.h"
#include "base/logging.h"

namespace ash {

namespace {

class DeskAnimationObserver : public DesksController::Observer {
public:
DeskAnimationObserver(base::OnceClosure on_desk_animation_complete)
: on_desk_animation_complete_(std::move(on_desk_animation_complete)) {
DesksController::Get()->AddObserver(this);
}

~DeskAnimationObserver() override {
DesksController::Get()->RemoveObserver(this);
}

DeskAnimationObserver(const DeskAnimationObserver& other) = delete;
DeskAnimationObserver& operator=(const DeskAnimationObserver& rhs) = delete;

// DesksController::Observer:
void OnDeskAdded(const Desk* desk) override {}
void OnDeskRemoved(const Desk* desk) override {}
void OnDeskActivationChanged(const Desk* activated,
const Desk* deactivated) override {}
void OnDeskSwitchAnimationLaunching() override {}
void OnDeskSwitchAnimationFinished() override {
std::move(on_desk_animation_complete_).Run();
delete this;
}

private:
base::OnceClosure on_desk_animation_complete_;
};

} // namespace

AutotestDesksApi::AutotestDesksApi() = default;

AutotestDesksApi::~AutotestDesksApi() = default;

bool AutotestDesksApi::CreateNewDesk() {
if (!DesksController::Get()->CanCreateDesks())
return false;

DesksController::Get()->NewDesk(DesksCreationRemovalSource::kButton);
return true;
}

bool AutotestDesksApi::ActivateDeskAtIndex(int index,
base::OnceClosure on_complete) {
DCHECK(!on_complete.is_null());

if (index < 0)
return false;

auto* controller = DesksController::Get();
if (index >= int{controller->desks().size()})
return false;

const Desk* target_desk = controller->desks()[index].get();
if (target_desk == controller->active_desk())
return false;

new DeskAnimationObserver(std::move(on_complete));
controller->ActivateDesk(target_desk, DesksSwitchSource::kMiniViewButton);
return true;
}

bool AutotestDesksApi::RemoveActiveDesk(base::OnceClosure on_complete) {
DCHECK(!on_complete.is_null());

auto* controller = DesksController::Get();
if (!controller->CanRemoveDesks())
return false;

new DeskAnimationObserver(std::move(on_complete));
controller->RemoveDesk(controller->active_desk(),
DesksCreationRemovalSource::kButton);
return true;
}

} // namespace ash
94 changes: 94 additions & 0 deletions ash/wm/desks/autotest_desks_api_unittests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright 2019 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/public/cpp/autotest_desks_api.h"

#include "ash/public/cpp/ash_features.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/desks/desks_controller.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"

namespace ash {

class AutotestDesksApiTest : public AshTestBase {
public:
AutotestDesksApiTest() = default;
~AutotestDesksApiTest() override = default;

AutotestDesksApiTest(const AutotestDesksApiTest& other) = delete;
AutotestDesksApiTest& operator=(const AutotestDesksApiTest& rhs) = delete;

// AshTestBase:
void SetUp() override {
scoped_feature_list_.InitAndEnableFeature(features::kVirtualDesks);

AshTestBase::SetUp();
}

private:
base::test::ScopedFeatureList scoped_feature_list_;
};

TEST_F(AutotestDesksApiTest, CreateNewDesk) {
AutotestDesksApi test_api;
auto* controller = DesksController::Get();
while (controller->CanCreateDesks())
EXPECT_TRUE(test_api.CreateNewDesk());
EXPECT_FALSE(test_api.CreateNewDesk());
}

TEST_F(AutotestDesksApiTest, ActivateDeskAtIndex) {
AutotestDesksApi test_api;
EXPECT_FALSE(test_api.ActivateDeskAtIndex(-1, base::DoNothing()));
EXPECT_FALSE(test_api.ActivateDeskAtIndex(4, base::DoNothing()));

// Activating already active desk does nothing.
EXPECT_FALSE(test_api.ActivateDeskAtIndex(0, base::DoNothing()));

// Create 4 desks and switch between all of them.
auto* controller = DesksController::Get();
while (controller->CanCreateDesks())
EXPECT_TRUE(test_api.CreateNewDesk());
EXPECT_EQ(4u, controller->desks().size());
constexpr int kIndices[] = {1, 2, 3, 0};
for (const int index : kIndices) {
base::RunLoop run_loop;
EXPECT_TRUE(test_api.ActivateDeskAtIndex(index, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(controller->active_desk(), controller->desks()[index].get());
}
}

TEST_F(AutotestDesksApiTest, RemoveActiveDesk) {
AutotestDesksApi test_api;
EXPECT_FALSE(test_api.RemoveActiveDesk(base::DoNothing()));

auto* controller = DesksController::Get();
while (controller->CanCreateDesks())
EXPECT_TRUE(test_api.CreateNewDesk());
EXPECT_EQ(4u, controller->desks().size());
EXPECT_EQ(controller->active_desk(), controller->desks()[0].get());

// List of desks that will be activated after each time we invoke
// RemoveActiveDesk().
const Desk* desks_after_removal[] = {
controller->desks()[1].get(),
controller->desks()[2].get(),
controller->desks()[3].get(),
};

for (const Desk* desk : desks_after_removal) {
base::RunLoop run_loop;
EXPECT_TRUE(test_api.RemoveActiveDesk(run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(controller->active_desk(), desk);
}

// Can no longer remove desks.
EXPECT_FALSE(test_api.RemoveActiveDesk(base::DoNothing()));
}

} // namespace ash
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "ash/public/cpp/app_list/app_list_types.h"
#include "ash/public/cpp/app_types.h"
#include "ash/public/cpp/ash_pref_names.h"
#include "ash/public/cpp/autotest_desks_api.h"
#include "ash/public/cpp/autotest_private_api_utils.h"
#include "ash/public/cpp/default_frame_header.h"
#include "ash/public/cpp/desks_helper.h"
Expand Down Expand Up @@ -3363,6 +3364,79 @@ void AutotestPrivateWaitForLauncherStateFunction::Done() {
Respond(NoArguments());
}

///////////////////////////////////////////////////////////////////////////////
// AutotestPrivateCreateNewDeskFunction
///////////////////////////////////////////////////////////////////////////////

AutotestPrivateCreateNewDeskFunction::AutotestPrivateCreateNewDeskFunction() =
default;
AutotestPrivateCreateNewDeskFunction::~AutotestPrivateCreateNewDeskFunction() =
default;

ExtensionFunction::ResponseAction AutotestPrivateCreateNewDeskFunction::Run() {
const bool success = ash::AutotestDesksApi().CreateNewDesk();
return RespondNow(OneArgument(
api::autotest_private::CreateNewDesk::Results::Create(success)));
}

///////////////////////////////////////////////////////////////////////////////
// AutotestPrivateActivateDeskAtIndexFunction
///////////////////////////////////////////////////////////////////////////////

AutotestPrivateActivateDeskAtIndexFunction::
AutotestPrivateActivateDeskAtIndexFunction() = default;
AutotestPrivateActivateDeskAtIndexFunction::
~AutotestPrivateActivateDeskAtIndexFunction() = default;

ExtensionFunction::ResponseAction
AutotestPrivateActivateDeskAtIndexFunction::Run() {
std::unique_ptr<api::autotest_private::ActivateDeskAtIndex::Params> params(
api::autotest_private::ActivateDeskAtIndex::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);

if (!ash::AutotestDesksApi().ActivateDeskAtIndex(
params->index,
base::BindOnce(
&AutotestPrivateActivateDeskAtIndexFunction::OnAnimationComplete,
this))) {
return RespondNow(OneArgument(
api::autotest_private::ActivateDeskAtIndex::Results::Create(false)));
}

return RespondLater();
}

void AutotestPrivateActivateDeskAtIndexFunction::OnAnimationComplete() {
Respond(OneArgument(
api::autotest_private::ActivateDeskAtIndex::Results::Create(true)));
}

///////////////////////////////////////////////////////////////////////////////
// AutotestPrivateRemoveActiveDeskFunction
///////////////////////////////////////////////////////////////////////////////

AutotestPrivateRemoveActiveDeskFunction::
AutotestPrivateRemoveActiveDeskFunction() = default;
AutotestPrivateRemoveActiveDeskFunction::
~AutotestPrivateRemoveActiveDeskFunction() = default;

ExtensionFunction::ResponseAction
AutotestPrivateRemoveActiveDeskFunction::Run() {
if (!ash::AutotestDesksApi().RemoveActiveDesk(base::BindOnce(
&AutotestPrivateRemoveActiveDeskFunction::OnAnimationComplete,
this))) {
return RespondNow(OneArgument(
api::autotest_private::RemoveActiveDesk::Results::Create(false)));
}

return RespondLater();
}

void AutotestPrivateRemoveActiveDeskFunction::OnAnimationComplete() {
Respond(OneArgument(
api::autotest_private::RemoveActiveDesk::Results::Create(true)));
}

///////////////////////////////////////////////////////////////////////////////
// AutotestPrivateAPI
///////////////////////////////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,43 @@ class AutotestPrivateWaitForLauncherStateFunction : public ExtensionFunction {
void Done();
};

class AutotestPrivateCreateNewDeskFunction : public ExtensionFunction {
public:
AutotestPrivateCreateNewDeskFunction();
DECLARE_EXTENSION_FUNCTION("autotestPrivate.createNewDesk",
AUTOTESTPRIVATE_CREATENEWDESK)

private:
~AutotestPrivateCreateNewDeskFunction() override;
ResponseAction Run() override;
};

class AutotestPrivateActivateDeskAtIndexFunction : public ExtensionFunction {
public:
AutotestPrivateActivateDeskAtIndexFunction();
DECLARE_EXTENSION_FUNCTION("autotestPrivate.activateDeskAtIndex",
AUTOTESTPRIVATE_ACTIVATEDESKATINDEX)

private:
~AutotestPrivateActivateDeskAtIndexFunction() override;
ResponseAction Run() override;

void OnAnimationComplete();
};

class AutotestPrivateRemoveActiveDeskFunction : public ExtensionFunction {
public:
AutotestPrivateRemoveActiveDeskFunction();
DECLARE_EXTENSION_FUNCTION("autotestPrivate.removeActiveDesk",
AUTOTESTPRIVATE_REMOVEACTIVEDESK)

private:
~AutotestPrivateRemoveActiveDeskFunction() override;
ResponseAction Run() override;

void OnAnimationComplete();
};

template <>
KeyedService*
BrowserContextKeyedAPIFactory<AutotestPrivateAPI>::BuildServiceInstanceFor(
Expand Down
Loading

0 comments on commit ce18042

Please sign in to comment.