blob: 91999dd1ff7e97683ea18a0a1dd7395c884d47ab [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/assistant/assistant_screen_context_controller_impl.h"
#include <memory>
#include "ash/assistant/assistant_controller_impl.h"
#include "ash/assistant/test/assistant_ash_test_base.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/wm/desks/desks_util.h"
#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/ui/base/window_properties.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_tree_owner.h"
#include "ui/compositor/layer_type.h"
namespace ash {
namespace {
ui::Layer* FindLayerWithClosure(
ui::Layer* root,
const base::RepeatingCallback<bool(ui::Layer*)>& callback) {
if (callback.Run(root))
return root;
for (ui::Layer* child : root->children()) {
ui::Layer* result = FindLayerWithClosure(child, callback);
if (result)
return result;
}
return nullptr;
}
} // namespace
class AssistantScreenContextControllerTest : public AssistantAshTestBase {
protected:
AssistantScreenContextControllerTest()
: AssistantAshTestBase(
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
~AssistantScreenContextControllerTest() override = default;
void SetUp() override {
AssistantAshTestBase::SetUp();
controller_ =
Shell::Get()->assistant_controller()->screen_context_controller();
DCHECK(controller_);
}
AssistantScreenContextControllerImpl* controller() { return controller_; }
AssistantScreenContextModel* model() { return &controller_->model_; }
void WaitAndAssertAssistantStructure() {
base::RunLoop run_loop;
model()->assistant_structure()->GetValueAsync(base::BindOnce(
[](base::RunLoop* run_loop,
const ax::mojom::AssistantStructure& structure) {
run_loop->Quit();
},
&run_loop));
run_loop.Run();
EXPECT_TRUE(model()->assistant_structure()->HasValue());
}
void WaitAndAssertScreenContext(bool include_assistant_structure) {
base::RunLoop run_loop;
controller()->RequestScreenContext(
include_assistant_structure,
/*region=*/gfx::Rect(),
base::BindOnce(
[](base::RunLoop* run_loop, bool include_assistant_structure,
ax::mojom::AssistantStructurePtr assistant_structure,
const std::vector<uint8_t>& screenshot) {
if (include_assistant_structure)
EXPECT_TRUE(assistant_structure);
else
EXPECT_FALSE(assistant_structure);
run_loop->Quit();
},
&run_loop, include_assistant_structure));
run_loop.Run();
}
private:
AssistantScreenContextControllerImpl* controller_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(AssistantScreenContextControllerTest);
};
// Verify that incognito windows are blocked in screenshot.
TEST_F(AssistantScreenContextControllerTest, Screenshot) {
std::unique_ptr<aura::Window> window1 = CreateToplevelTestWindow(
gfx::Rect(0, 0, 200, 200), desks_util::GetActiveDeskContainerId());
std::unique_ptr<aura::Window> window2 = CreateToplevelTestWindow(
gfx::Rect(30, 30, 100, 100), desks_util::GetActiveDeskContainerId());
ui::Layer* window1_layer = window1->layer();
ui::Layer* window2_layer = window2->layer();
window1->SetProperty(chromeos::kBlockedForAssistantSnapshotKey, true);
std::unique_ptr<ui::LayerTreeOwner> layer_owner =
controller()->CreateLayerForAssistantSnapshotForTest();
// Test that windows marked as blocked for assistant snapshot is not included.
EXPECT_FALSE(FindLayerWithClosure(
layer_owner->root(), base::BindRepeating(
[](ui::Layer* layer, ui::Layer* mirror) {
return layer->ContainsMirrorForTest(mirror);
},
window1_layer)));
EXPECT_TRUE(FindLayerWithClosure(
layer_owner->root(), base::BindRepeating(
[](ui::Layer* layer, ui::Layer* mirror) {
return layer->ContainsMirrorForTest(mirror);
},
window2_layer)));
// Test that a solid black layer is inserted.
EXPECT_TRUE(FindLayerWithClosure(
layer_owner->root(), base::BindRepeating([](ui::Layer* layer) {
return layer->type() == ui::LayerType::LAYER_SOLID_COLOR;
})));
}
// Verify that, in Clamshell mode, opening Launcher will request and cache the
// Assistant structure.
TEST_F(AssistantScreenContextControllerTest,
ShouldCacheAssistantStructureFutureByOpeningLauncher) {
OpenLauncher();
WaitAndAssertAssistantStructure();
}
// Verify that, in Clamshell mode, opening Launcher with Assistant UI will
// request and cache the Assistant structure.
TEST_F(AssistantScreenContextControllerTest,
ShouldCacheAssistantStructureFutureByOpeningLauncherWithAssistantUi) {
ShowAssistantUi(AssistantEntryPoint::kLongPressLauncher);
WaitAndAssertAssistantStructure();
}
// Verify that, in Clamshell mode, closing Launcher will clear the cached
// Assistant structure.
TEST_F(AssistantScreenContextControllerTest,
ShouldClearAssistantStructureFutureByClosinggLauncher) {
ShowAssistantUi(AssistantEntryPoint::kLongPressLauncher);
WaitAndAssertAssistantStructure();
CloseLauncher();
EXPECT_FALSE(model()->assistant_structure()->HasValue());
}
// Verify that, in Clamshell mode, closing Assistant UI will not clear the
// Assistant structure.
TEST_F(AssistantScreenContextControllerTest,
ShouldNotClearAssistantStructureFutureByClosingAssistantUi) {
OpenLauncher();
WaitAndAssertAssistantStructure();
// Open Assistant UI will not change the cache of Assistant structure.
ShowAssistantUi(AssistantEntryPoint::kLauncherSearchResult);
EXPECT_TRUE(model()->assistant_structure()->HasValue());
// Close Assistant UI will not change the cache of Assistant structure.
CloseAssistantUi(AssistantExitPoint::kBackInLauncher);
EXPECT_TRUE(model()->assistant_structure()->HasValue());
}
// Verify that, in Tablet mode, opening Assistant UI will request and cache the
// Assistant structure.
TEST_F(AssistantScreenContextControllerTest,
ShouldCacheAssistantStructureFutureByOpeningAssistantUiInTabletMode) {
SetTabletMode(/*enable=*/true);
ShowAssistantUi(AssistantEntryPoint::kUnspecified);
WaitAndAssertAssistantStructure();
}
// Verify that, in Tablet mode, closing Assistant UI will clear the Assistant
// structure.
TEST_F(AssistantScreenContextControllerTest,
ShouldClearAssistantStructureFutureByClosingAssistantUiInTabletMode) {
SetTabletMode(/*enable=*/true);
ShowAssistantUi(AssistantEntryPoint::kUnspecified);
WaitAndAssertAssistantStructure();
CloseAssistantUi();
EXPECT_FALSE(model()->assistant_structure()->HasValue());
}
// Verify that screen context request without Assistant structure is returned.
TEST_F(AssistantScreenContextControllerTest,
ShouldCallCallbackForRequestScreenContextWithoutAssistantStructure) {
ShowAssistantUi(AssistantEntryPoint::kLongPressLauncher);
WaitAndAssertScreenContext(/*include_assistant_structure=*/false);
}
// Verify that screen context request with non-cached Assistant structure is
// returned.
TEST_F(
AssistantScreenContextControllerTest,
ShouldCallCallbackForRequestScreenContextWithNonCachedAssistantStructure) {
ShowAssistantUi(AssistantEntryPoint::kLongPressLauncher);
WaitAndAssertScreenContext(/*include_assistant_structure=*/true);
}
// Verify that screen context request with cached Assistant structure is
// returned.
TEST_F(AssistantScreenContextControllerTest,
ShouldCallCallbackForRequestScreenContextWithCachedAssistantStructure) {
ShowAssistantUi(AssistantEntryPoint::kLongPressLauncher);
WaitAndAssertAssistantStructure();
WaitAndAssertScreenContext(/*include_assistant_structure=*/true);
}
} // namespace ash