#include <algorithm>
#include "ash/accessibility/accessibility_controller.h"
#include "ash/accessibility/autoclick/autoclick_controller.h"
#include "ash/capture_mode/capture_mode_bar_view.h"
#include "ash/capture_mode/capture_mode_camera_controller.h"
#include "ash/capture_mode/capture_mode_camera_preview_view.h"
#include "ash/capture_mode/capture_mode_constants.h"
#include "ash/capture_mode/capture_mode_controller.h"
#include "ash/capture_mode/capture_mode_menu_group.h"
#include "ash/capture_mode/capture_mode_metrics.h"
#include "ash/capture_mode/capture_mode_session.h"
#include "ash/capture_mode/capture_mode_session_focus_cycler.h"
#include "ash/capture_mode/capture_mode_session_test_api.h"
#include "ash/capture_mode/capture_mode_settings_test_api.h"
#include "ash/capture_mode/capture_mode_settings_view.h"
#include "ash/capture_mode/capture_mode_test_util.h"
#include "ash/capture_mode/capture_mode_toast_controller.h"
#include "ash/capture_mode/capture_mode_types.h"
#include "ash/capture_mode/capture_mode_util.h"
#include "ash/capture_mode/fake_camera_device.h"
#include "ash/capture_mode/fake_folder_selection_dialog_factory.h"
#include "ash/capture_mode/fake_video_source_provider.h"
#include "ash/capture_mode/test_capture_mode_delegate.h"
#include "ash/display/window_tree_host_manager.h"
#include "ash/public/cpp/capture_mode/capture_mode_test_api.h"
#include "ash/public/cpp/holding_space/holding_space_controller.h"
#include "ash/public/cpp/holding_space/holding_space_model.h"
#include "ash/public/cpp/holding_space/holding_space_prefs.h"
#include "ash/public/cpp/holding_space/holding_space_test_api.h"
#include "ash/public/cpp/holding_space/holding_space_util.h"
#include "ash/public/cpp/holding_space/mock_holding_space_client.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_id.h"
#include "ash/style/tab_slider_button.h"
#include "ash/system/accessibility/autoclick_menu_bubble_controller.h"
#include "ash/system/notification_center/notification_center_test_api.h"
#include "ash/system/notification_center/notification_center_tray.h"
#include "ash/system/privacy/privacy_indicators_controller.h"
#include "ash/system/privacy/privacy_indicators_tray_item_view.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/ash_test_util.h"
#include "ash/wm/window_state.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/system_monitor.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/timer/timer.h"
#include "cc/paint/skia_paint_canvas.h"
#include "chromeos/ui/frame/frame_header.h"
#include "components/viz/test/test_in_process_context_provider.h"
#include "media/base/video_facing.h"
#include "media/base/video_frame.h"
#include "media/renderers/paint_canvas_video_renderer.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/scoped_animation_duration_scale_mode.h"
#include "ui/message_center/message_center.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/window_util.h"
namespace ash {
namespace {
constexpr char kTestUser[] = "user@test";
constexpr char kCaptureModePrivacyIndicatorId[] = "system-capture-mode";
constexpr int kMinRegionLengthForCameraToIntersectLabelButton =
capture_mode::kMinCaptureSurfaceShortSideLengthForVisibleCamera + 20;
CaptureModeCameraController* GetCameraController() {
return CaptureModeController::Get()->camera_controller();
}
aura::Window* GetCurrentRoot() {
auto* controller = CaptureModeController::Get();
if (controller->IsActive())
return controller->capture_mode_session()->current_root();
if (controller->is_recording_in_progress()) {
return controller->video_recording_watcher_for_testing()
->window_being_recorded()
->GetRootWindow();
}
return Shell::GetPrimaryRootWindow();
}
bool IsWindowStackedRightBelow(aura::Window* window, aura::Window* sibling) {
DCHECK_EQ(window->parent(), sibling->parent());
const auto& children = window->parent()->children();
const int sibling_index =
std::ranges::find(children, sibling) - children.begin();
return sibling_index > 0 && children[sibling_index - 1] == window;
}
gfx::Rect GetTooSmallToFitCameraRegion() {
return {100, 100,
capture_mode::kMinCaptureSurfaceShortSideLengthForVisibleCamera - 1,
capture_mode::kMinCaptureSurfaceShortSideLengthForVisibleCamera - 1};
}
}
class CaptureModeCameraTest : public AshTestBase {
public:
CaptureModeCameraTest()
: AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
CaptureModeCameraTest(const CaptureModeCameraTest&) = delete;
CaptureModeCameraTest& operator=(const CaptureModeCameraTest&) = delete;
~CaptureModeCameraTest() override = default;
void SetUp() override {
AshTestBase::SetUp();
FakeFolderSelectionDialogFactory::Start();
window_ = CreateTestWindow(gfx::Rect(30, 40, 600, 500));
}
void TearDown() override {
window_.reset();
FakeFolderSelectionDialogFactory::Stop();
AshTestBase::TearDown();
}
aura::Window* window() const { return window_.get(); }
void StartRecordingFromSource(CaptureModeSource source) {
auto* controller = CaptureModeController::Get();
controller->SetSource(source);
switch (source) {
case CaptureModeSource::kFullscreen:
case CaptureModeSource::kRegion:
break;
case CaptureModeSource::kWindow:
GetEventGenerator()->MoveMouseTo(
window_->GetBoundsInScreen().CenterPoint());
break;
}
CaptureModeTestApi().PerformCapture();
WaitForRecordingToStart();
EXPECT_TRUE(controller->is_recording_in_progress());
}
CaptureModeCameraController* AddAndRemoveCameraAndTriggerGracePeriod() {
AddDefaultCamera();
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
RemoveDefaultCamera();
return camera_controller;
}
void OpenSettingsView() {
BaseCaptureModeSession* session =
CaptureModeController::Get()->capture_mode_session();
DCHECK(session);
ClickOnView(CaptureModeSessionTestApi(session)
.GetCaptureModeBarView()
->settings_button(),
GetEventGenerator());
}
void DragPreviewToPoint(views::Widget* preview_widget,
const gfx::Point& screen_location,
bool by_touch_gestures = false,
bool drop = true) {
DCHECK(preview_widget);
auto* event_generator = GetEventGenerator();
event_generator->set_current_screen_location(
preview_widget->GetWindowBoundsInScreen().CenterPoint());
if (by_touch_gestures) {
event_generator->PressTouch();
event_generator->MoveTouchBy(50, 0);
event_generator->MoveTouch(screen_location);
if (drop)
event_generator->ReleaseTouch();
} else {
event_generator->PressLeftButton();
event_generator->MoveMouseTo(screen_location);
if (drop)
event_generator->ReleaseLeftButton();
}
}
CameraPreviewResizeButton* GetPreviewResizeButton() const {
return GetCameraController()->camera_preview_view()->resize_button();
}
void VerifyPreviewAlignment(const gfx::Rect& confine_bounds_in_screen) {
auto* camera_controller = GetCameraController();
const auto* preview_widget = camera_controller->camera_preview_widget();
DCHECK(preview_widget);
const gfx::Rect camera_preview_bounds =
preview_widget->GetWindowBoundsInScreen();
switch (camera_controller->camera_preview_snap_position()) {
case CameraPreviewSnapPosition::kTopLeft: {
gfx::Point expect_origin = confine_bounds_in_screen.origin();
expect_origin.Offset(capture_mode::kSpaceBetweenCameraPreviewAndEdges,
capture_mode::kSpaceBetweenCameraPreviewAndEdges);
EXPECT_EQ(expect_origin, camera_preview_bounds.origin());
break;
}
case CameraPreviewSnapPosition::kBottomLeft: {
const gfx::Point expect_bottom_left =
gfx::Point(confine_bounds_in_screen.x() +
capture_mode::kSpaceBetweenCameraPreviewAndEdges,
confine_bounds_in_screen.bottom() -
capture_mode::kSpaceBetweenCameraPreviewAndEdges);
EXPECT_EQ(expect_bottom_left, camera_preview_bounds.bottom_left());
break;
}
case CameraPreviewSnapPosition::kBottomRight: {
const gfx::Point expect_bottom_right =
gfx::Point(confine_bounds_in_screen.right() -
capture_mode::kSpaceBetweenCameraPreviewAndEdges,
confine_bounds_in_screen.bottom() -
capture_mode::kSpaceBetweenCameraPreviewAndEdges);
EXPECT_EQ(expect_bottom_right, camera_preview_bounds.bottom_right());
break;
}
case CameraPreviewSnapPosition::kTopRight: {
const gfx::Point expect_top_right =
gfx::Point(confine_bounds_in_screen.right() -
capture_mode::kSpaceBetweenCameraPreviewAndEdges,
confine_bounds_in_screen.y() +
capture_mode::kSpaceBetweenCameraPreviewAndEdges);
EXPECT_EQ(expect_top_right, camera_preview_bounds.top_right());
break;
}
}
}
void VerifyResizeButton(bool is_collapsed,
CameraPreviewResizeButton* resize_button) {
SkColor color =
resize_button->GetColorProvider()->GetColor(kColorAshIconColorPrimary);
const gfx::ImageSkia collapse_icon_image =
gfx::CreateVectorIcon(kCaptureModeCameraPreviewCollapseIcon, color);
const gfx::ImageSkia expand_icon_image =
gfx::CreateVectorIcon(kCaptureModeCameraPreviewExpandIcon, color);
const SkBitmap* expected_icon = is_collapsed ? expand_icon_image.bitmap()
: collapse_icon_image.bitmap();
const SkBitmap* actual_icon =
resize_button->GetImage(views::ImageButton::ButtonState::STATE_NORMAL)
.bitmap();
EXPECT_TRUE(gfx::test::AreBitmapsEqual(*actual_icon, *expected_icon));
const auto expected_tooltip_text = l10n_util::GetStringUTF16(
is_collapsed ? IDS_ASH_SCREEN_CAPTURE_TOOLTIP_EXPAND_SELFIE_CAMERA
: IDS_ASH_SCREEN_CAPTURE_TOOLTIP_COLLAPSE_SELFIE_CAMERA);
EXPECT_EQ(resize_button->GetTooltipText(), expected_tooltip_text);
}
void SelectCaptureRegion(const gfx::Rect& region, bool release_mouse = true) {
auto* controller = CaptureModeController::Get();
ASSERT_TRUE(controller->IsActive());
ASSERT_EQ(CaptureModeSource::kRegion, controller->source());
auto* event_generator = GetEventGenerator();
event_generator->set_current_screen_location(region.origin());
event_generator->PressLeftButton();
event_generator->MoveMouseTo(region.bottom_right());
if (release_mouse)
event_generator->ReleaseLeftButton();
EXPECT_EQ(region, controller->user_capture_region());
}
void ConvertToPipWindow(aura::Window* pip_window) {
WindowState* window_state = WindowState::Get(pip_window);
DCHECK(!window_state->IsPip());
views::Widget::GetWidgetForNativeWindow(pip_window)
->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
pip_window->SetProperty(kWindowPipTypeKey, true);
DCHECK(window_state->IsPip());
}
bool IsCameraIndicatorIconVisible() const {
auto* indicator_view = GetPrimaryDisplayPrivacyIndicatorsView();
return indicator_view && indicator_view->GetVisible() &&
PrivacyIndicatorsController::Get()->IsCameraUsed() &&
indicator_view->camera_icon()->GetVisible();
}
bool IsMicrophoneIndicatorIconVisible() const {
auto* indicator_view = GetPrimaryDisplayPrivacyIndicatorsView();
return indicator_view && indicator_view->GetVisible() &&
PrivacyIndicatorsController::Get()->IsMicrophoneUsed() &&
indicator_view->microphone_icon()->GetVisible();
}
PrivacyIndicatorsTrayItemView* GetPrimaryDisplayPrivacyIndicatorsView()
const {
return Shell::GetPrimaryRootWindowController()
->GetStatusAreaWidget()
->notification_center_tray()
->privacy_indicators_view();
}
private:
std::unique_ptr<aura::Window> window_;
};
TEST_F(CaptureModeCameraTest, SizeSpecsBigEnoughRegion) {
gfx::Size confine_bounds_size(800, 700);
{
auto specs = capture_mode_util::CalculateCameraPreviewSizeSpecs(
confine_bounds_size,
false);
EXPECT_TRUE(specs.is_collapsible);
EXPECT_TRUE(specs.should_be_visible);
EXPECT_EQ(specs.size.width(), specs.size.height());
EXPECT_EQ(specs.size.width(),
700 / capture_mode::kCaptureSurfaceShortSideDivider);
}
confine_bounds_size.Transpose();
{
auto specs = capture_mode_util::CalculateCameraPreviewSizeSpecs(
confine_bounds_size,
false);
EXPECT_TRUE(specs.is_collapsible);
EXPECT_TRUE(specs.should_be_visible);
EXPECT_EQ(specs.size.width(),
700 / capture_mode::kCaptureSurfaceShortSideDivider);
}
{
auto specs = capture_mode_util::CalculateCameraPreviewSizeSpecs(
confine_bounds_size,
true);
EXPECT_TRUE(specs.is_collapsible);
EXPECT_TRUE(specs.should_be_visible);
EXPECT_EQ(specs.size.width(), capture_mode::kMinCameraPreviewDiameter);
}
}
TEST_F(CaptureModeCameraTest, SizeSpecsNotCollapsible) {
gfx::Size confine_bounds_size(800, 500);
auto specs = capture_mode_util::CalculateCameraPreviewSizeSpecs(
confine_bounds_size,
false);
EXPECT_FALSE(specs.is_collapsible);
EXPECT_TRUE(specs.should_be_visible);
EXPECT_EQ(specs.size.width(), specs.size.height());
EXPECT_EQ(specs.size.width(),
500 / capture_mode::kCaptureSurfaceShortSideDivider);
EXPECT_FALSE(specs.is_surface_too_small);
}
TEST_F(CaptureModeCameraTest, SizeSpecsHiddenPreview) {
gfx::Size confine_bounds_size(800, 170);
auto specs = capture_mode_util::CalculateCameraPreviewSizeSpecs(
confine_bounds_size,
false);
EXPECT_FALSE(specs.is_collapsible);
EXPECT_FALSE(specs.should_be_visible);
EXPECT_EQ(specs.size.width(), specs.size.height());
EXPECT_EQ(specs.size.width(), capture_mode::kMinCameraPreviewDiameter);
EXPECT_TRUE(specs.is_surface_too_small);
}
TEST_F(CaptureModeCameraTest, CameraDevicesChanges) {
auto* camera_controller = GetCameraController();
ASSERT_TRUE(camera_controller);
EXPECT_TRUE(camera_controller->available_cameras().empty());
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
EXPECT_FALSE(camera_controller->should_show_preview());
EXPECT_FALSE(camera_controller->camera_preview_widget());
const std::string device_id = "/dev/video0";
const std::string display_name = "Integrated Webcam";
const std::string model_id = "0123:4567";
AddFakeCamera(device_id, display_name, model_id);
EXPECT_EQ(1u, camera_controller->available_cameras().size());
EXPECT_TRUE(camera_controller->available_cameras()[0].camera_id.is_valid());
EXPECT_EQ(model_id, camera_controller->available_cameras()[0]
.camera_id.model_id_or_display_name());
EXPECT_EQ(1, camera_controller->available_cameras()[0].camera_id.number());
EXPECT_EQ(device_id, camera_controller->available_cameras()[0].device_id);
EXPECT_EQ(display_name,
camera_controller->available_cameras()[0].display_name);
EXPECT_FALSE(camera_controller->should_show_preview());
EXPECT_FALSE(camera_controller->camera_preview_widget());
RemoveFakeCamera(device_id);
EXPECT_TRUE(camera_controller->available_cameras().empty());
EXPECT_FALSE(camera_controller->should_show_preview());
EXPECT_FALSE(camera_controller->camera_preview_widget());
}
TEST_F(CaptureModeCameraTest, CameraRemovedWhileWaitingForCameraDevices) {
auto* camera_controller = GetCameraController();
AddDefaultCamera();
EXPECT_EQ(1u, camera_controller->available_cameras().size());
auto* video_source_provider = GetTestDelegate()->video_source_provider();
{
base::RunLoop loop;
video_source_provider->set_on_replied_with_source_infos(
base::BindLambdaForTesting([&]() { loop.Quit(); }));
base::SystemMonitor::Get()->ProcessDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
loop.Run();
}
RemoveDefaultCamera();
EXPECT_TRUE(camera_controller->available_cameras().empty());
}
TEST_F(CaptureModeCameraTest, SelectingUnavailableCamera) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
EXPECT_FALSE(camera_controller->camera_preview_widget());
camera_controller->SetSelectedCamera(CameraId("model", 1));
EXPECT_FALSE(camera_controller->camera_preview_widget());
}
TEST_F(CaptureModeCameraTest, SelectingAvailableCamera) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
EXPECT_FALSE(camera_controller->camera_preview_widget());
AddDefaultCamera();
EXPECT_EQ(1u, camera_controller->available_cameras().size());
EXPECT_FALSE(camera_controller->camera_preview_widget());
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
EXPECT_TRUE(camera_controller->camera_preview_widget());
}
TEST_F(CaptureModeCameraTest, SelectedCameraBecomesAvailable) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
EXPECT_FALSE(camera_controller->camera_preview_widget());
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
EXPECT_FALSE(camera_controller->camera_preview_widget());
AddDefaultCamera();
EXPECT_TRUE(camera_controller->camera_preview_widget());
camera_controller->SetSelectedCamera(CameraId());
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
EXPECT_FALSE(camera_controller->camera_preview_widget());
}
TEST_F(CaptureModeCameraTest, SelectingDifferentCameraCreatesNewPreviewWidget) {
AddDefaultCamera();
const std::string device_id = "/dev/video0";
const std::string display_name = "Integrated Webcam";
const std::string model_id = "0123:4567";
AddFakeCamera(device_id, display_name, model_id);
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
EXPECT_FALSE(camera_controller->camera_preview_widget());
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* current_preview_widget = camera_controller->camera_preview_widget();
EXPECT_TRUE(current_preview_widget);
camera_controller->SetSelectedCamera(CameraId(model_id, 1));
EXPECT_TRUE(camera_controller->camera_preview_widget());
EXPECT_NE(current_preview_widget, camera_controller->camera_preview_widget());
}
TEST_F(CaptureModeCameraTest, MultipleCamerasOfTheSameModel) {
auto* camera_controller = GetCameraController();
const std::string device_id_1 = "/dev/video0";
const std::string display_name = "Integrated Webcam";
const std::string model_id = "0123:4567";
AddFakeCamera(device_id_1, display_name, model_id);
const auto& available_cameras = camera_controller->available_cameras();
EXPECT_EQ(1u, available_cameras.size());
EXPECT_EQ(1, available_cameras[0].camera_id.number());
EXPECT_EQ(model_id,
available_cameras[0].camera_id.model_id_or_display_name());
const std::string device_id_2 = "/dev/video1";
AddFakeCamera(device_id_2, display_name, model_id);
EXPECT_EQ(2u, available_cameras.size());
EXPECT_EQ(2, available_cameras[1].camera_id.number());
EXPECT_EQ(model_id,
available_cameras[1].camera_id.model_id_or_display_name());
EXPECT_NE(available_cameras[0].camera_id, available_cameras[1].camera_id);
}
TEST_F(CaptureModeCameraTest, MissingCameraModelId) {
auto* camera_controller = GetCameraController();
const std::string device_id = "/dev/video0";
const std::string display_name = "Integrated Webcam";
AddFakeCamera(device_id, display_name, "");
const auto& available_cameras = camera_controller->available_cameras();
EXPECT_EQ(1u, available_cameras.size());
EXPECT_TRUE(available_cameras[0].camera_id.is_valid());
EXPECT_EQ(1, available_cameras[0].camera_id.number());
EXPECT_EQ(display_name,
available_cameras[0].camera_id.model_id_or_display_name());
{
base::RunLoop loop;
camera_controller->SetOnCameraListReceivedForTesting(loop.QuitClosure());
CameraDevicesChangeWaiter observer;
base::SystemMonitor::Get()->ProcessDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
loop.Run();
EXPECT_EQ(0, observer.camera_change_event_count());
}
}
TEST_F(CaptureModeCameraTest, CameraFramesFlipping) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
int index = 0;
for (const auto facing_mode :
{media::MEDIA_VIDEO_FACING_NONE, media::MEDIA_VIDEO_FACING_USER,
media::MEDIA_VIDEO_FACING_ENVIRONMENT}) {
const std::string device_id = base::StringPrintf("/dev/video%d", index);
const std::string display_name = base::StringPrintf("Camera %d", index);
AddFakeCamera(device_id, display_name, display_name, facing_mode);
camera_controller->SetSelectedCamera(CameraId(display_name, 1));
EXPECT_TRUE(camera_controller->camera_preview_widget());
const bool should_be_flipped =
facing_mode != media::MEDIA_VIDEO_FACING_ENVIRONMENT;
EXPECT_EQ(should_be_flipped, camera_controller->camera_preview_view()
->should_flip_frames_horizontally())
<< "Failed for facing mode: " << facing_mode;
++index;
}
}
TEST_F(CaptureModeCameraTest, DisconnectSelectedCamera) {
AddDefaultCamera();
auto* camera_controller = GetCameraController();
const CameraId camera_id(kDefaultCameraModelId, 1);
camera_controller->SetSelectedCamera(camera_id);
RemoveDefaultCamera();
base::OneShotTimer* timer =
camera_controller->camera_reconnect_timer_for_test();
EXPECT_TRUE(timer->IsRunning());
EXPECT_EQ(camera_id, camera_controller->selected_camera());
timer->FireNow();
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
EXPECT_FALSE(timer->IsRunning());
}
TEST_F(CaptureModeCameraTest, SelectUnavailableCameraDuringGracePeriod) {
auto* camera_controller = AddAndRemoveCameraAndTriggerGracePeriod();
base::OneShotTimer* timer =
camera_controller->camera_reconnect_timer_for_test();
EXPECT_TRUE(timer->IsRunning());
const CameraId new_camera_id("Different Camera", 1);
camera_controller->SetSelectedCamera(new_camera_id);
EXPECT_TRUE(timer->IsRunning());
EXPECT_EQ(new_camera_id, camera_controller->selected_camera());
timer->FireNow();
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
EXPECT_FALSE(timer->IsRunning());
}
TEST_F(CaptureModeCameraTest, SelectAvailableCameraDuringGracePeriod) {
const std::string device_id = "/dev/video0";
const std::string display_name = "Integrated Webcam";
const CameraId available_camera_id(display_name, 1);
AddFakeCamera(device_id, display_name, "");
auto* camera_controller = AddAndRemoveCameraAndTriggerGracePeriod();
base::OneShotTimer* timer =
camera_controller->camera_reconnect_timer_for_test();
EXPECT_TRUE(timer->IsRunning());
camera_controller->SetSelectedCamera(available_camera_id);
EXPECT_FALSE(timer->IsRunning());
EXPECT_EQ(available_camera_id, camera_controller->selected_camera());
}
TEST_F(CaptureModeCameraTest, ReconnectDuringGracePeriod) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = AddAndRemoveCameraAndTriggerGracePeriod();
base::OneShotTimer* timer =
camera_controller->camera_reconnect_timer_for_test();
EXPECT_TRUE(timer->IsRunning());
EXPECT_FALSE(camera_controller->camera_preview_widget());
AddDefaultCamera();
EXPECT_FALSE(timer->IsRunning());
EXPECT_TRUE(camera_controller->camera_preview_widget());
}
TEST_F(CaptureModeCameraTest, ReconnectDuringGracePeriodAfterRecordingStarts) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = AddAndRemoveCameraAndTriggerGracePeriod();
base::OneShotTimer* timer =
camera_controller->camera_reconnect_timer_for_test();
EXPECT_TRUE(timer->IsRunning());
EXPECT_FALSE(camera_controller->camera_preview_widget());
EXPECT_TRUE(camera_controller->should_show_preview());
StartVideoRecordingImmediately();
EXPECT_FALSE(camera_controller->should_show_preview());
AddDefaultCamera();
EXPECT_FALSE(timer->IsRunning());
EXPECT_FALSE(camera_controller->camera_preview_widget());
}
TEST_F(CaptureModeCameraTest, SelectedCameraChangedObserver) {
AddDefaultCamera();
auto* camera_controller = GetCameraController();
const CameraId camera_id(kDefaultCameraModelId, 1);
CameraDevicesChangeWaiter observer;
camera_controller->SetSelectedCamera(camera_id);
EXPECT_EQ(1, observer.selected_camera_change_event_count());
camera_controller->SetSelectedCamera(camera_id);
EXPECT_EQ(1, observer.selected_camera_change_event_count());
camera_controller->SetSelectedCamera(CameraId());
EXPECT_EQ(2, observer.selected_camera_change_event_count());
}
TEST_F(CaptureModeCameraTest, ShouldShowPreviewTest) {
auto* controller = CaptureModeController::Get();
auto* camera_controller = GetCameraController();
controller->SetSource(CaptureModeSource::kFullscreen);
controller->SetType(CaptureModeType::kVideo);
controller->Start(CaptureModeEntryType::kQuickSettings);
EXPECT_TRUE(camera_controller->should_show_preview());
controller->SetType(CaptureModeType::kImage);
EXPECT_FALSE(camera_controller->should_show_preview());
controller->Stop();
EXPECT_FALSE(camera_controller->should_show_preview());
EXPECT_FALSE(controller->IsActive());
controller->SetType(CaptureModeType::kVideo);
controller->Start(CaptureModeEntryType::kQuickSettings);
EXPECT_TRUE(camera_controller->should_show_preview());
controller->StartVideoRecordingImmediatelyForTesting();
EXPECT_TRUE(camera_controller->should_show_preview());
controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
EXPECT_FALSE(camera_controller->should_show_preview());
}
TEST_F(CaptureModeCameraTest, ManagedByPolicyCameraOptions) {
GetTestDelegate()->set_is_camera_disabled_by_policy(true);
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
OpenSettingsView();
CaptureModeSettingsTestApi test_api;
CaptureModeMenuGroup* camera_menu_group = test_api.GetCameraMenuGroup();
ASSERT_TRUE(camera_menu_group);
EXPECT_FALSE(camera_menu_group->GetVisible());
AddDefaultCamera();
EXPECT_TRUE(camera_menu_group->GetVisible());
EXPECT_TRUE(camera_menu_group->IsOptionChecked(kCameraOff));
EXPECT_FALSE(camera_menu_group->IsOptionEnabled(kCameraOff));
EXPECT_FALSE(test_api.GetCameraOption(kCameraDevicesBegin));
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
EXPECT_TRUE(camera_menu_group->IsOptionChecked(kCameraOff));
EXPECT_FALSE(camera_controller->camera_preview_widget());
RemoveDefaultCamera();
EXPECT_FALSE(camera_menu_group->GetVisible());
EXPECT_FALSE(test_api.GetCameraOption(kCameraOff));
}
TEST_F(CaptureModeCameraTest, CheckCameraOptions) {
auto* camera_controller = GetCameraController();
const std::string device_id_1 = "/dev/video0";
const std::string display_name_1 = "Integrated Webcam";
const std::string device_id_2 = "/dev/video1";
const std::string display_name_2 = "Integrated Webcam 1";
AddFakeCamera(device_id_1, display_name_1, display_name_1);
AddFakeCamera(device_id_2, display_name_2, display_name_2);
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
OpenSettingsView();
CaptureModeSettingsTestApi test_api;
CaptureModeMenuGroup* camera_menu_group = test_api.GetCameraMenuGroup();
EXPECT_TRUE(camera_menu_group && camera_menu_group->GetVisible());
EXPECT_TRUE(camera_menu_group->IsOptionChecked(kCameraOff));
EXPECT_FALSE(camera_menu_group->IsOptionChecked(kCameraDevicesBegin));
EXPECT_FALSE(camera_menu_group->IsOptionChecked(kCameraDevicesBegin + 1));
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
ClickOnView(test_api.GetCameraOption(kCameraDevicesBegin),
GetEventGenerator());
EXPECT_FALSE(camera_menu_group->IsOptionChecked(kCameraOff));
EXPECT_EQ(base::UTF16ToUTF8(camera_menu_group->GetOptionLabelForTesting(
kCameraDevicesBegin)),
display_name_1);
EXPECT_TRUE(camera_menu_group->IsOptionChecked(kCameraDevicesBegin));
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
RemoveFakeCamera(device_id_1);
EXPECT_TRUE(test_api.GetCameraOption(kCameraDevicesBegin));
EXPECT_FALSE(test_api.GetCameraOption(kCameraDevicesBegin + 1));
EXPECT_EQ(base::UTF16ToUTF8(camera_menu_group->GetOptionLabelForTesting(
kCameraDevicesBegin)),
display_name_2);
EXPECT_FALSE(camera_menu_group->IsOptionChecked(kCameraOff));
EXPECT_FALSE(camera_menu_group->IsOptionChecked(kCameraDevicesBegin));
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
AddFakeCamera(device_id_1, display_name_1, display_name_1);
EXPECT_TRUE(test_api.GetCameraOption(kCameraDevicesBegin));
EXPECT_TRUE(test_api.GetCameraOption(kCameraDevicesBegin + 1));
EXPECT_FALSE(camera_menu_group->IsOptionChecked(kCameraOff));
EXPECT_TRUE(camera_menu_group->IsOptionChecked(kCameraDevicesBegin));
EXPECT_FALSE(camera_menu_group->IsOptionChecked(kCameraDevicesBegin + 1));
EXPECT_EQ(base::UTF16ToUTF8(camera_menu_group->GetOptionLabelForTesting(
kCameraDevicesBegin)),
display_name_1);
EXPECT_EQ(base::UTF16ToUTF8(camera_menu_group->GetOptionLabelForTesting(
kCameraDevicesBegin + 1)),
display_name_2);
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
}
TEST_F(CaptureModeCameraTest, CameraPreviewWidgetStackingInFullscreen) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
base::RunLoop().RunUntilIdle();
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
EXPECT_TRUE(camera_preview_widget);
auto* preview_window = camera_preview_widget->GetNativeWindow();
const auto* menu_container = preview_window->GetRootWindow()->GetChildById(
kShellWindowId_MenuContainer);
auto* parent = preview_window->parent();
EXPECT_EQ(parent, menu_container);
EXPECT_EQ(menu_container->children().front(), preview_window);
StartRecordingFromSource(CaptureModeSource::kFullscreen);
preview_window = camera_preview_widget->GetNativeWindow();
parent = preview_window->parent();
EXPECT_EQ(parent, menu_container);
EXPECT_EQ(menu_container->children().back(), preview_window);
}
TEST_F(CaptureModeCameraTest, CameraPreviewWidgetStackingInRegion) {
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
EXPECT_TRUE(camera_preview_widget);
auto* preview_window = camera_preview_widget->GetNativeWindow();
EXPECT_TRUE(controller->user_capture_region().IsEmpty());
EXPECT_EQ(preview_window->parent(),
preview_window->GetRootWindow()->GetChildById(
kShellWindowId_UnparentedContainer));
EXPECT_FALSE(camera_preview_widget->IsVisible());
controller->SetUserCaptureRegion(gfx::Rect(10, 20, 80, 60),
true);
StartRecordingFromSource(CaptureModeSource::kRegion);
const auto* menu_container = preview_window->GetRootWindow()->GetChildById(
kShellWindowId_MenuContainer);
ASSERT_EQ(preview_window->parent(), menu_container);
EXPECT_EQ(menu_container->children().back(), preview_window);
}
TEST_F(CaptureModeCameraTest, CameraPreviewWhileUpdatingCaptureRegion) {
UpdateDisplay("800x700");
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
auto* capture_session = controller->capture_mode_session();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
EXPECT_TRUE(camera_preview_widget);
auto* preview_window = camera_preview_widget->GetNativeWindow();
const int min_region_length =
capture_mode::kMinCaptureSurfaceShortSideLengthForVisibleCamera;
const gfx::Rect capture_region(10, 20, min_region_length, min_region_length);
controller->SetUserCaptureRegion(capture_region, true);
const auto* menu_container = preview_window->GetRootWindow()->GetChildById(
kShellWindowId_MenuContainer);
ASSERT_EQ(preview_window->parent(), menu_container);
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_TRUE(preview_window->IsVisible());
auto* event_generator = GetEventGenerator();
event_generator->set_current_screen_location(capture_region.bottom_right());
event_generator->PressLeftButton();
EXPECT_FALSE(camera_preview_widget->IsVisible());
EXPECT_FALSE(preview_window->IsVisible());
ASSERT_EQ(preview_window->parent(), menu_container);
const gfx::Vector2d delta(15, 20);
event_generator->MoveMouseTo(capture_region.bottom_right() + delta);
EXPECT_TRUE(capture_session->is_drag_in_progress());
EXPECT_FALSE(camera_preview_widget->IsVisible());
EXPECT_FALSE(preview_window->IsVisible());
ASSERT_EQ(preview_window->parent(), menu_container);
event_generator->ReleaseLeftButton();
EXPECT_FALSE(capture_session->is_drag_in_progress());
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_TRUE(preview_window->IsVisible());
EXPECT_EQ(preview_window->parent(), menu_container);
const gfx::Point current_position(capture_region.origin() + delta);
event_generator->set_current_screen_location(current_position);
event_generator->PressLeftButton();
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_EQ(preview_window->parent(), menu_container);
event_generator->MoveMouseTo(current_position + delta);
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_EQ(preview_window->parent(), menu_container);
event_generator->ReleaseLeftButton();
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_EQ(preview_window->parent(), menu_container);
}
TEST_F(CaptureModeCameraTest, CameraPreviewWidgetStackingInWindow) {
auto* controller =
StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
EXPECT_TRUE(camera_preview_widget);
auto* preview_window = camera_preview_widget->GetNativeWindow();
ASSERT_FALSE(controller->capture_mode_session()->GetSelectedWindow());
EXPECT_EQ(preview_window->parent(),
preview_window->GetRootWindow()->GetChildById(
kShellWindowId_UnparentedContainer));
EXPECT_FALSE(camera_preview_widget->IsVisible());
StartRecordingFromSource(CaptureModeSource::kWindow);
const auto* parent = preview_window->parent();
const auto* window_being_recorded =
controller->video_recording_watcher_for_testing()
->window_being_recorded();
ASSERT_EQ(parent, window_being_recorded);
EXPECT_EQ(window_being_recorded->children().back(), preview_window);
}
TEST_F(CaptureModeCameraTest, CheckCameraMenuVisibility) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
OpenSettingsView();
CaptureModeSettingsTestApi test_api;
CaptureModeMenuGroup* camera_menu_group = test_api.GetCameraMenuGroup();
EXPECT_TRUE(camera_menu_group && !camera_menu_group->GetVisible());
AddDefaultCamera();
camera_menu_group = test_api.GetCameraMenuGroup();
EXPECT_TRUE(camera_menu_group && camera_menu_group->GetVisible());
EXPECT_TRUE(test_api.GetCameraOption(kCameraOff));
EXPECT_TRUE(test_api.GetCameraOption(kCameraDevicesBegin));
RemoveDefaultCamera();
camera_menu_group = test_api.GetCameraMenuGroup();
EXPECT_TRUE(camera_menu_group && !camera_menu_group->GetVisible());
EXPECT_FALSE(test_api.GetCameraOption(kCameraOff));
EXPECT_FALSE(test_api.GetCameraOption(kCameraDevicesBegin));
}
TEST_F(CaptureModeCameraTest, CameraPreviewWidgetBounds) {
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
ASSERT_EQ(CameraPreviewSnapPosition::kBottomRight,
camera_controller->camera_preview_snap_position());
const auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_TRUE(preview_widget);
const auto* capture_mode_session = controller->capture_mode_session();
const gfx::Rect work_area =
display::Screen::Get()
->GetDisplayNearestWindow(capture_mode_session->current_root())
.work_area();
VerifyPreviewAlignment(work_area);
controller->SetSource(CaptureModeSource::kRegion);
EXPECT_TRUE(controller->user_capture_region().IsEmpty());
EXPECT_FALSE(preview_widget->IsVisible());
const gfx::Rect capture_region(10, 20, 300, 200);
controller->SetUserCaptureRegion(capture_region, true);
VerifyPreviewAlignment(capture_region);
controller->SetSource(CaptureModeSource::kFullscreen);
VerifyPreviewAlignment(work_area);
controller->SetSource(CaptureModeSource::kRegion);
camera_controller->SetCameraPreviewSnapPosition(
CameraPreviewSnapPosition::kBottomLeft);
VerifyPreviewAlignment(capture_region);
camera_controller->SetCameraPreviewSnapPosition(
CameraPreviewSnapPosition::kTopLeft);
VerifyPreviewAlignment(capture_region);
camera_controller->SetCameraPreviewSnapPosition(
CameraPreviewSnapPosition::kTopRight);
VerifyPreviewAlignment(capture_region);
controller->SetUserCaptureRegion(gfx::Rect(), true);
EXPECT_FALSE(preview_widget->IsVisible());
StartRecordingFromSource(CaptureModeSource::kWindow);
auto* window_being_recorded =
controller->video_recording_watcher_for_testing()
->window_being_recorded();
DCHECK(window_being_recorded);
auto window_confine_bounds =
capture_mode_util::GetCaptureWindowConfineBounds(window_being_recorded);
wm::ConvertRectToScreen(window_being_recorded, &window_confine_bounds);
VerifyPreviewAlignment(window_confine_bounds);
}
TEST_F(CaptureModeCameraTest, MultiDisplayCameraPreviewWidgetBounds) {
UpdateDisplay("800x700,801+0-800x700");
const gfx::Point point_in_second_display = gfx::Point(1000, 500);
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(point_in_second_display);
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const gfx::Rect second_display_bounds(801, 0, 800, 700);
const auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_TRUE(second_display_bounds.Contains(
preview_widget->GetWindowBoundsInScreen()));
event_generator->MoveMouseTo(gfx::Point(10, 20));
EXPECT_TRUE(gfx::Rect(0, 0, 800, 700)
.Contains(preview_widget->GetWindowBoundsInScreen()));
event_generator->MoveMouseTo(point_in_second_display);
controller->SetSource(CaptureModeSource::kRegion);
const gfx::Rect capture_region(100, 0, 400, 550);
controller->SetUserCaptureRegion(capture_region, true);
const gfx::Rect capture_region_in_screen(901, 0, 400, 550);
const gfx::Rect preview_bounds = preview_widget->GetWindowBoundsInScreen();
EXPECT_TRUE(second_display_bounds.Contains(preview_bounds));
EXPECT_TRUE(capture_region_in_screen.Contains(preview_bounds));
window()->SetBoundsInScreen(gfx::Rect(900, 0, 600, 500),
display::Screen::Get()->GetDisplayNearestWindow(
Shell::GetAllRootWindows()[1]));
StartRecordingFromSource(CaptureModeSource::kWindow);
const auto* window_being_recorded =
controller->video_recording_watcher_for_testing()
->window_being_recorded();
EXPECT_TRUE(window_being_recorded->GetBoundsInScreen().Contains(
preview_widget->GetWindowBoundsInScreen()));
}
TEST_F(CaptureModeCameraTest, CameraPreviewWidgetAfterTypeSwitched) {
auto* controller =
StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kImage);
auto* camera_controller = GetCameraController();
GetEventGenerator()->MoveMouseToCenterOf(window());
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
controller->SetType(CaptureModeType::kVideo);
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
EXPECT_TRUE(camera_preview_widget);
auto* camera_preview_window = camera_preview_widget->GetNativeWindow();
const auto* selected_window =
controller->capture_mode_session()->GetSelectedWindow();
ASSERT_EQ(camera_preview_window->parent(), selected_window);
VerifyPreviewAlignment(selected_window->GetBoundsInScreen());
EXPECT_FALSE(wm::GetTransientParent(camera_preview_window));
}
TEST_F(CaptureModeCameraTest,
AudioAndCameraMenuGroupsAreHiddenWhenVideoRecordingInProgress) {
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
auto* camera_controller = controller->camera_controller();
StartVideoRecordingImmediately();
EXPECT_TRUE(controller->is_recording_in_progress());
EXPECT_FALSE(camera_controller->camera_preview_widget());
EXPECT_FALSE(controller->IsActive());
controller->Start(CaptureModeEntryType::kQuickSettings);
EXPECT_EQ(CaptureModeType::kImage, controller->type());
EXPECT_FALSE(camera_controller->camera_preview_widget());
OpenSettingsView();
CaptureModeSettingsTestApi test_api_new;
EXPECT_FALSE(test_api_new.GetCameraMenuGroup());
EXPECT_FALSE(test_api_new.GetAudioInputMenuGroup());
EXPECT_TRUE(test_api_new.GetSaveToMenuGroup());
}
TEST_F(CaptureModeCameraTest,
CameraPreviewNotChangeWhenVideoRecordingInProgress) {
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
auto* camera_controller = controller->camera_controller();
AddDefaultCamera();
OpenSettingsView();
CaptureModeSettingsTestApi test_api;
ClickOnView(test_api.GetCameraOption(kCameraDevicesBegin),
GetEventGenerator());
StartVideoRecordingImmediately();
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
EXPECT_TRUE(camera_preview_widget);
auto* preview_window = camera_preview_widget->GetNativeWindow();
auto* parent = preview_window->parent();
controller->Start(CaptureModeEntryType::kQuickSettings);
controller->SetSource(CaptureModeSource::kFullscreen);
EXPECT_EQ(preview_window,
camera_controller->camera_preview_widget()->GetNativeWindow());
EXPECT_EQ(
parent,
camera_controller->camera_preview_widget()->GetNativeWindow()->parent());
controller->SetSource(CaptureModeSource::kRegion);
controller->SetUserCaptureRegion({100, 100, 200, 300}, true);
EXPECT_EQ(preview_window,
camera_controller->camera_preview_widget()->GetNativeWindow());
EXPECT_EQ(
parent,
camera_controller->camera_preview_widget()->GetNativeWindow()->parent());
controller->SetSource(CaptureModeSource::kWindow);
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseToCenterOf(window());
EXPECT_EQ(preview_window,
camera_controller->camera_preview_widget()->GetNativeWindow());
EXPECT_EQ(
parent,
camera_controller->camera_preview_widget()->GetNativeWindow()->parent());
}
TEST_F(CaptureModeCameraTest, ChangeFolderWhileVideoRecordingInProgress) {
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
StartVideoRecordingImmediately();
controller->Start(CaptureModeEntryType::kQuickSettings);
controller->SetCustomCaptureFolder(
CreateCustomFolderInUserDownloadsPath("test"));
controller->PerformCapture();
const base::FilePath& saved_image_file = WaitForCaptureFileToBeSaved();
EXPECT_EQ(controller->GetCustomCaptureFolder(), saved_image_file.DirName());
controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
const base::FilePath& saved_video_file = WaitForCaptureFileToBeSaved();
EXPECT_EQ(controller->delegate_for_testing()->GetUserDefaultDownloadsFolder(),
saved_video_file.DirName());
}
TEST_F(CaptureModeCameraTest,
UpdateSelectedWindowAtPositionWithCameraPreviewIgnored) {
auto* controller =
StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo);
AddDefaultCamera();
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseToCenterOf(window());
EXPECT_TRUE(camera_controller->camera_preview_widget());
controller->SetType(CaptureModeType::kImage);
event_generator->MoveMouseToCenterOf(window());
EXPECT_FALSE(camera_controller->camera_preview_widget());
controller->SetType(CaptureModeType::kVideo);
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
const auto* capture_mode_session = controller->capture_mode_session();
event_generator->MoveMouseToCenterOf(
camera_preview_widget->GetNativeWindow());
EXPECT_EQ(window(), capture_mode_session->GetSelectedWindow());
EXPECT_TRUE(window()->IsVisible());
EXPECT_TRUE(camera_preview_widget->IsVisible());
window()->Hide();
EXPECT_FALSE(window()->IsVisible());
EXPECT_FALSE(camera_preview_widget->IsVisible());
EXPECT_FALSE(capture_mode_session->GetSelectedWindow());
const auto* preview_native_window = camera_preview_widget->GetNativeWindow();
window()->Show();
EXPECT_TRUE(window()->IsVisible());
EXPECT_FALSE(camera_preview_widget->IsVisible());
EXPECT_FALSE(capture_mode_session->GetSelectedWindow());
EXPECT_EQ(preview_native_window->parent(),
preview_native_window->GetRootWindow()->GetChildById(
kShellWindowId_UnparentedContainer));
event_generator->MoveMouseToCenterOf(window());
EXPECT_EQ(preview_native_window->parent(),
capture_mode_session->GetSelectedWindow());
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_EQ(window(), capture_mode_session->GetSelectedWindow());
}
TEST_F(CaptureModeCameraTest,
CaptureLabelOpacityChangeWhenOverlappingWithCameraPreview) {
UpdateDisplay("900x800");
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
const auto* capture_label_widget = capture_session->capture_label_widget();
const ui::Layer* capture_label_layer = capture_label_widget->GetLayer();
const gfx::Rect capture_region(100, 100, 700, 700);
SelectCaptureRegion(capture_region);
EXPECT_FALSE(capture_label_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_label_layer->GetTargetOpacity(), 1.f);
const int delta_x =
kMinRegionLengthForCameraToIntersectLabelButton - capture_region.width();
const int delta_y =
kMinRegionLengthForCameraToIntersectLabelButton - capture_region.height();
const gfx::Vector2d delta(delta_x, delta_y);
auto* event_generator = GetEventGenerator();
event_generator->set_current_screen_location(capture_region.bottom_right());
event_generator->PressLeftButton();
event_generator->MoveMouseTo(capture_region.bottom_right() + delta);
event_generator->ReleaseLeftButton();
EXPECT_TRUE(capture_label_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_label_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
const gfx::Rect capture_lable_bounds =
capture_label_widget->GetWindowBoundsInScreen();
event_generator->MoveMouseTo(capture_lable_bounds.CenterPoint());
EXPECT_TRUE(capture_lable_bounds.Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_label_layer->GetTargetOpacity(), 1.0f);
const gfx::Vector2d delta1(50, 50);
event_generator->MoveMouseTo(capture_lable_bounds.bottom_right() + delta1);
EXPECT_EQ(capture_label_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
const gfx::Rect current_capture_region = controller->user_capture_region();
event_generator->MoveMouseTo(current_capture_region.bottom_right() + delta1);
event_generator->ClickLeftButton();
EXPECT_EQ(capture_label_layer->GetTargetOpacity(), 1.0f);
}
TEST_F(CaptureModeCameraTest,
CaptureBarOpacityChangeWhenOverlappingWithCameraPreview) {
UpdateDisplay("1366x768");
window()->SetBounds({0, 195, 903, 492});
auto* controller =
StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo);
auto* capture_session = controller->capture_mode_session();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
const auto* capture_bar_widget = capture_session->GetCaptureModeBarWidget();
const ui::Layer* capture_bar_layer = capture_bar_widget->GetLayer();
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(window()->GetBoundsInScreen().CenterPoint());
EXPECT_EQ(capture_session->GetSelectedWindow(), window());
EXPECT_TRUE(capture_bar_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
event_generator->MoveMouseTo(
capture_bar_widget->GetWindowBoundsInScreen().CenterPoint());
EXPECT_TRUE(capture_bar_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(), 1.0f);
const gfx::Point capture_bar_origin =
capture_bar_widget->GetWindowBoundsInScreen().origin();
event_generator->MoveMouseTo(capture_bar_origin.x() - 10,
capture_bar_origin.y() - 10);
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
}
TEST_F(CaptureModeCameraTest, CaptureBarOpacityChangeOnDisplayRotation) {
UpdateDisplay("1366x768");
window()->SetBounds({0, 195, 903, 492});
auto* controller =
StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo);
auto* capture_session = controller->capture_mode_session();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
const auto* capture_bar_widget = capture_session->GetCaptureModeBarWidget();
const ui::Layer* capture_bar_layer = capture_bar_widget->GetLayer();
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(window()->GetBoundsInScreen().CenterPoint());
EXPECT_EQ(capture_session->GetSelectedWindow(), window());
EXPECT_TRUE(capture_bar_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
Shell::Get()->display_manager()->SetDisplayRotation(
WindowTreeHostManager::GetPrimaryDisplayId(), display::Display::ROTATE_90,
display::Display::RotationSource::USER);
EXPECT_FALSE(capture_bar_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(), 1.0f);
Shell::Get()->display_manager()->SetDisplayRotation(
WindowTreeHostManager::GetPrimaryDisplayId(),
display::Display::ROTATE_180, display::Display::RotationSource::USER);
EXPECT_TRUE(capture_bar_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
}
TEST_F(CaptureModeCameraTest, CaptureLabelOpacityChangeOnCaptureSourceChange) {
UpdateDisplay("800x600");
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* camera_preview_widget = camera_controller->camera_preview_widget();
auto* capture_label_widget = capture_session->capture_label_widget();
ui::Layer* capture_label_layer = capture_label_widget->GetLayer();
const int min_region_length = kMinRegionLengthForCameraToIntersectLabelButton;
SelectCaptureRegion({100, 100, min_region_length, min_region_length});
EXPECT_TRUE(capture_label_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_label_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
controller->SetSource(CaptureModeSource::kFullscreen);
EXPECT_EQ(capture_label_layer->GetTargetOpacity(), 1.0f);
}
TEST_F(CaptureModeCameraTest,
CaptureLabelOpacityChangeWhileVideoRecordingInProgress) {
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* camera_preview_widget = camera_controller->camera_preview_widget();
const int min_region_length = kMinRegionLengthForCameraToIntersectLabelButton;
controller->SetUserCaptureRegion(
{100, 100, min_region_length, min_region_length}, true);
StartVideoRecordingImmediately();
EXPECT_FALSE(controller->IsActive());
controller->Start(CaptureModeEntryType::kQuickSettings);
EXPECT_EQ(CaptureModeSource::kRegion, controller->source());
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
const auto* capture_label_widget = capture_session->capture_label_widget();
EXPECT_TRUE(capture_label_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_label_widget->GetLayer()->GetTargetOpacity(), 1.0f);
}
TEST_F(CaptureModeCameraTest, FocusableCameraPreviewInFullscreen) {
UpdateDisplay("800x700");
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
AddDefaultCamera();
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
using FocusGroup = CaptureModeSessionFocusCycler::FocusGroup;
CaptureModeSessionTestApi test_api(controller->capture_mode_session());
auto* camera_preview_view = camera_controller->camera_preview_view();
auto* resize_button = GetPreviewResizeButton();
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 6);
EXPECT_EQ(FocusGroup::kCameraPreview, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->GetVisible());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(1u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(resize_button->has_focus());
EXPECT_TRUE(resize_button->GetVisible());
EXPECT_TRUE(resize_button->has_focus());
EXPECT_FALSE(camera_controller->is_camera_preview_collapsed());
SendKey(ui::VKEY_SPACE, event_generator);
EXPECT_TRUE(camera_controller->is_camera_preview_collapsed());
SendKey(ui::VKEY_SPACE, event_generator);
EXPECT_FALSE(camera_controller->is_camera_preview_collapsed());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kSettingsClose, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
base::OneShotTimer* hide_timer =
camera_preview_view->resize_button_hide_timer_for_test();
EXPECT_FALSE(resize_button->has_focus());
EXPECT_TRUE(hide_timer->IsRunning());
EXPECT_EQ(hide_timer->GetCurrentDelay(),
capture_mode::kResizeButtonShowDuration);
{
ViewVisibilityChangeWaiter waiter(resize_button);
EXPECT_TRUE(resize_button->GetVisible());
hide_timer->FireNow();
waiter.Wait();
EXPECT_FALSE(resize_button->GetVisible());
}
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(FocusGroup::kCameraPreview, test_api.GetCurrentFocusGroup());
EXPECT_EQ(1u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(resize_button->has_focus());
hide_timer = camera_preview_view->resize_button_hide_timer_for_test();
EXPECT_TRUE(hide_timer->IsRunning());
EXPECT_TRUE(resize_button->GetVisible());
hide_timer->FireNow();
EXPECT_TRUE(resize_button->GetVisible());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(camera_preview_view->has_focus());
hide_timer = camera_preview_view->resize_button_hide_timer_for_test();
EXPECT_FALSE(resize_button->has_focus());
EXPECT_TRUE(hide_timer->IsRunning());
EXPECT_EQ(hide_timer->GetCurrentDelay(),
capture_mode::kResizeButtonShowDuration);
{
ViewVisibilityChangeWaiter waiter(resize_button);
EXPECT_TRUE(resize_button->GetVisible());
hide_timer->FireNow();
waiter.Wait();
EXPECT_FALSE(resize_button->GetVisible());
}
EXPECT_TRUE(camera_controller->camera_preview_view()->has_focus());
EXPECT_EQ(CameraPreviewSnapPosition::kBottomRight,
camera_controller->camera_preview_snap_position());
SendKey(ui::VKEY_RIGHT, event_generator, ui::EF_CONTROL_DOWN);
EXPECT_EQ(CameraPreviewSnapPosition::kBottomRight,
camera_controller->camera_preview_snap_position());
SendKey(ui::VKEY_DOWN, event_generator, ui::EF_CONTROL_DOWN);
EXPECT_EQ(CameraPreviewSnapPosition::kBottomRight,
camera_controller->camera_preview_snap_position());
SendKey(ui::VKEY_LEFT, event_generator, ui::EF_CONTROL_DOWN);
EXPECT_EQ(CameraPreviewSnapPosition::kBottomLeft,
camera_controller->camera_preview_snap_position());
SendKey(ui::VKEY_RIGHT, event_generator, ui::EF_CONTROL_DOWN);
EXPECT_EQ(CameraPreviewSnapPosition::kBottomRight,
camera_controller->camera_preview_snap_position());
SendKey(ui::VKEY_UP, event_generator, ui::EF_CONTROL_DOWN);
EXPECT_EQ(CameraPreviewSnapPosition::kTopRight,
camera_controller->camera_preview_snap_position());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(FocusGroup::kTypeSource, test_api.GetCurrentFocusGroup());
EXPECT_EQ(4u, test_api.GetCurrentFocusIndex());
}
TEST_F(CaptureModeCameraTest, FocusableCameraPreviewInRegion) {
UpdateDisplay("1366x768");
auto* controller = CaptureModeController::Get();
controller->SetUserCaptureRegion(gfx::Rect(10, 10, 800, 700),
true);
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
AddDefaultCamera();
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
using FocusGroup = CaptureModeSessionFocusCycler::FocusGroup;
CaptureModeSessionTestApi test_api(controller->capture_mode_session());
auto* camera_preview_view = camera_controller->camera_preview_view();
auto* resize_button = GetPreviewResizeButton();
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 15);
EXPECT_EQ(FocusGroup::kCameraPreview, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(1u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(resize_button->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kCaptureButton, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
while (FocusGroup::kSettingsClose != test_api.GetCurrentFocusGroup()) {
SendKey(ui::VKEY_TAB, event_generator);
}
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(FocusGroup::kCaptureButton, test_api.GetCurrentFocusGroup());
EXPECT_EQ(1u, test_api.GetCurrentFocusIndex());
while (FocusGroup::kCameraPreview != test_api.GetCurrentFocusGroup()) {
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
}
EXPECT_EQ(1u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(resize_button->has_focus());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN, 10);
EXPECT_EQ(FocusGroup::kTypeSource, test_api.GetCurrentFocusGroup());
EXPECT_EQ(4u, test_api.GetCurrentFocusIndex());
controller->SetUserCaptureRegion(gfx::Rect(10, 10, 400, 550),
true);
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 10);
EXPECT_EQ(FocusGroup::kCameraPreview, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(camera_preview_view->has_focus());
EXPECT_FALSE(camera_preview_view->is_collapsible());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kCaptureButton, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
}
TEST_F(CaptureModeCameraTest, FocusableCameraPreviewInWindow) {
UpdateDisplay("1366x768");
std::unique_ptr<aura::Window> window2(
CreateTestWindow(gfx::Rect(150, 50, 800, 700)));
window()->SetBounds(gfx::Rect(30, 40, 800, 700));
auto* controller =
StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo);
AddDefaultCamera();
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
using FocusGroup = CaptureModeSessionFocusCycler::FocusGroup;
auto* capture_mode_session = controller->capture_mode_session();
CaptureModeSessionTestApi test_api(capture_mode_session);
const auto* preview_window =
camera_controller->camera_preview_widget()->GetNativeWindow();
auto* camera_preview_view = camera_controller->camera_preview_view();
auto* resize_button = GetPreviewResizeButton();
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 6);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(test_api.GetHighlightableWindow(window2.get())->has_focus());
EXPECT_EQ(window2.get(), capture_mode_session->GetSelectedWindow());
EXPECT_EQ(window2.get(), preview_window->parent());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(1u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(2u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(resize_button->has_focus());
EXPECT_FALSE(camera_controller->camera_preview_view()->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(3u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(test_api.GetHighlightableWindow(window())->has_focus());
EXPECT_EQ(window(), capture_mode_session->GetSelectedWindow());
EXPECT_EQ(window(), preview_window->parent());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(4u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(5u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(resize_button->has_focus());
EXPECT_FALSE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kSettingsClose, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_FALSE(resize_button->has_focus());
EXPECT_FALSE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(5u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(resize_button->has_focus());
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_EQ(window(), capture_mode_session->GetSelectedWindow());
EXPECT_EQ(window(), preview_window->parent());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(4u, test_api.GetCurrentFocusIndex());
EXPECT_FALSE(resize_button->has_focus());
EXPECT_TRUE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(3u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(test_api.GetHighlightableWindow(window())->has_focus());
EXPECT_FALSE(resize_button->has_focus());
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_EQ(window(), capture_mode_session->GetSelectedWindow());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(2u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(resize_button->has_focus());
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_EQ(window2.get(), capture_mode_session->GetSelectedWindow());
EXPECT_EQ(window2.get(), preview_window->parent());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(1u, test_api.GetCurrentFocusIndex());
EXPECT_FALSE(resize_button->has_focus());
EXPECT_TRUE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(test_api.GetHighlightableWindow(window2.get())->has_focus());
EXPECT_FALSE(resize_button->has_focus());
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_EQ(window2.get(), capture_mode_session->GetSelectedWindow());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_EQ(FocusGroup::kTypeSource, test_api.GetCurrentFocusGroup());
EXPECT_EQ(4u, test_api.GetCurrentFocusIndex());
window2.reset();
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(test_api.GetHighlightableWindow(window())->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(1u, test_api.GetCurrentFocusIndex());
EXPECT_TRUE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(2u, test_api.GetCurrentFocusIndex());
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_TRUE(resize_button->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kSettingsClose, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
}
TEST_F(CaptureModeCameraTest,
FocusableCameraPreviewInVideoRecordingWithFullscreenCapture) {
UpdateDisplay("800x700");
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
AddDefaultCamera();
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
auto* camera_preview_view = camera_controller->camera_preview_view();
auto* resize_button = GetPreviewResizeButton();
StartVideoRecordingImmediately();
EXPECT_TRUE(camera_preview_view->is_collapsible());
EXPECT_FALSE(camera_controller->is_camera_preview_collapsed());
SendKey(ui::VKEY_S, event_generator, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
EXPECT_TRUE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
EXPECT_FALSE(resize_button->GetVisible());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_TRUE(resize_button->has_focus());
EXPECT_TRUE(resize_button->GetVisible());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_TRUE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
EXPECT_TRUE(resize_button->GetVisible());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_TRUE(resize_button->has_focus());
EXPECT_TRUE(resize_button->GetVisible());
SendKey(ui::VKEY_SPACE, event_generator);
EXPECT_TRUE(camera_controller->is_camera_preview_collapsed());
EXPECT_TRUE(resize_button->has_focus());
SendKey(ui::VKEY_SPACE, event_generator);
EXPECT_FALSE(camera_controller->is_camera_preview_collapsed());
EXPECT_TRUE(resize_button->has_focus());
SendKey(ui::VKEY_ESCAPE, event_generator);
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kImage);
EXPECT_TRUE(controller->IsActive());
EXPECT_TRUE(controller->is_recording_in_progress());
SendKey(ui::VKEY_S, event_generator, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
EXPECT_FALSE(camera_preview_view->has_focus());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 5);
EXPECT_TRUE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_TRUE(resize_button->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
CaptureModeSessionTestApi test_api(controller->capture_mode_session());
EXPECT_TRUE(CaptureModeSessionFocusCycler::HighlightHelper::Get(
test_api.GetCaptureModeBarView()->settings_button())
->has_focus());
}
TEST_F(CaptureModeCameraTest,
FocusableCameraPreviewInVideoRecordingWithRegionCapture) {
auto* controller = CaptureModeController::Get();
controller->SetUserCaptureRegion(gfx::Rect(10, 10, 400, 550),
true);
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
AddDefaultCamera();
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
auto* camera_preview_view = camera_controller->camera_preview_view();
auto* resize_button = GetPreviewResizeButton();
StartVideoRecordingImmediately();
EXPECT_FALSE(camera_controller->is_camera_preview_collapsed());
EXPECT_FALSE(camera_preview_view->is_collapsible());
SendKey(ui::VKEY_S, event_generator, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
EXPECT_TRUE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
EXPECT_FALSE(resize_button->GetVisible());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_TRUE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
EXPECT_FALSE(resize_button->GetVisible());
const gfx::Point origin = camera_preview_view->GetBoundsInScreen().origin();
const gfx::Vector2d delta(-50, -50);
event_generator->MoveMouseTo(origin + delta);
event_generator->ClickLeftButton();
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
}
TEST_F(CaptureModeCameraTest,
FocusableCameraPreviewInVideoRecordingWithWindowCapture) {
UpdateDisplay("1366x768");
window()->SetBounds(gfx::Rect(30, 40, 800, 700));
auto* controller =
StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo);
AddDefaultCamera();
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
auto* camera_preview_view = camera_controller->camera_preview_view();
auto* resize_button = GetPreviewResizeButton();
event_generator->MoveMouseTo(window()->GetBoundsInScreen().origin());
EXPECT_EQ(controller->capture_mode_session()->GetSelectedWindow(), window());
StartVideoRecordingImmediately();
EXPECT_FALSE(camera_controller->is_camera_preview_collapsed());
EXPECT_TRUE(camera_preview_view->is_collapsible());
SendKey(ui::VKEY_S, event_generator, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
EXPECT_TRUE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_FALSE(camera_preview_view->has_focus());
EXPECT_TRUE(resize_button->has_focus());
EXPECT_TRUE(resize_button->GetVisible());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_SHIFT_DOWN);
EXPECT_TRUE(camera_preview_view->has_focus());
EXPECT_FALSE(resize_button->has_focus());
}
TEST_F(CaptureModeCameraTest, CaptureBarOpacityChangeOnKeyboardNavigation) {
using FocusGroup = CaptureModeSessionFocusCycler::FocusGroup;
UpdateDisplay("1366x768");
window()->SetBounds({0, 0, 903, 700});
auto* controller =
StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo);
CaptureModeSessionTestApi test_api(controller->capture_mode_session());
auto* capture_session = controller->capture_mode_session();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const auto* camera_preview_widget =
camera_controller->camera_preview_widget();
const auto* capture_bar_widget = capture_session->GetCaptureModeBarWidget();
const ui::Layer* capture_bar_layer = capture_bar_widget->GetLayer();
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(window()->GetBoundsInScreen().CenterPoint());
EXPECT_EQ(capture_session->GetSelectedWindow(), window());
EXPECT_TRUE(capture_bar_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(), 1.0f);
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 4);
EXPECT_EQ(FocusGroup::kTypeSource, test_api.GetCurrentFocusGroup());
EXPECT_EQ(4u, test_api.GetCurrentFocusIndex());
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(), 1.0f);
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kCaptureWindow, test_api.GetCurrentFocusGroup());
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 3);
EXPECT_EQ(FocusGroup::kSettingsClose, test_api.GetCurrentFocusGroup());
EXPECT_EQ(0u, test_api.GetCurrentFocusIndex());
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(), 1.0f);
SendKey(ui::VKEY_SPACE, event_generator);
EXPECT_EQ(FocusGroup::kPendingSettings, test_api.GetCurrentFocusGroup());
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(), 1.0f);
SendKey(ui::VKEY_TAB, event_generator);
EXPECT_EQ(FocusGroup::kSettingsMenu, test_api.GetCurrentFocusGroup());
EXPECT_EQ(capture_bar_layer->GetTargetOpacity(), 1.0f);
}
TEST_F(CaptureModeCameraTest, CaptureLabelOpacityChangeOnKeyboardNavigation) {
UpdateDisplay("800x600");
using FocusGroup = CaptureModeSessionFocusCycler::FocusGroup;
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
CaptureModeSessionTestApi test_api(controller->capture_mode_session());
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* camera_preview_widget = camera_controller->camera_preview_widget();
auto* capture_label_widget = capture_session->capture_label_widget();
ui::Layer* capture_label_layer = capture_label_widget->GetLayer();
const int min_region_length = kMinRegionLengthForCameraToIntersectLabelButton;
SelectCaptureRegion({100, 100, min_region_length, min_region_length});
EXPECT_TRUE(capture_label_widget->GetWindowBoundsInScreen().Intersects(
camera_preview_widget->GetWindowBoundsInScreen()));
EXPECT_EQ(capture_label_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
auto* event_generator = GetEventGenerator();
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 4);
EXPECT_EQ(FocusGroup::kTypeSource, test_api.GetCurrentFocusGroup());
EXPECT_EQ(3u, test_api.GetCurrentFocusIndex());
EXPECT_EQ(capture_label_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 2);
EXPECT_EQ(FocusGroup::kSelection, test_api.GetCurrentFocusGroup());
EXPECT_EQ(capture_label_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
EXPECT_FALSE(camera_controller->camera_preview_view()->is_collapsible());
SendKey(ui::VKEY_TAB, event_generator, ui::EF_NONE, 10);
EXPECT_EQ(FocusGroup::kCaptureButton, test_api.GetCurrentFocusGroup());
EXPECT_EQ(capture_label_layer->GetTargetOpacity(), 1.0f);
while (FocusGroup::kSettingsClose != test_api.GetCurrentFocusGroup()) {
SendKey(ui::VKEY_TAB, event_generator);
}
EXPECT_EQ(capture_label_layer->GetTargetOpacity(),
capture_mode::kCaptureUiOverlapOpacity);
}
TEST_F(CaptureModeCameraTest, CameraPreviewVisibilityOnCaptureSourceChanged) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
AddDefaultCamera();
CaptureModeTestApi().SelectCameraAtIndex(0);
auto* camera_preview_widget = GetCameraController()->camera_preview_widget();
auto* preview_window = camera_preview_widget->GetNativeWindow();
EXPECT_EQ(preview_window->parent(),
preview_window->GetRootWindow()->GetChildById(
kShellWindowId_MenuContainer));
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_TRUE(preview_window->TargetVisibility());
auto* event_generator = GetEventGenerator();
ClickOnView(GetRegionToggleButton(), event_generator);
EXPECT_EQ(preview_window->parent(),
preview_window->GetRootWindow()->GetChildById(
kShellWindowId_UnparentedContainer));
EXPECT_FALSE(camera_preview_widget->IsVisible());
ClickOnView(GetFullscreenToggleButton(), event_generator);
EXPECT_EQ(preview_window->parent(),
preview_window->GetRootWindow()->GetChildById(
kShellWindowId_MenuContainer));
EXPECT_TRUE(preview_window->TargetVisibility());
EXPECT_TRUE(camera_preview_widget->IsVisible());
}
TEST_F(CaptureModeCameraTest, RecordingStartsWithCameraHistogramTest) {
base::HistogramTester histogram_tester;
constexpr char kHistogramNameBase[] = "RecordingStartsWithCamera";
AddDefaultCamera();
struct {
bool tablet_enabled;
bool camera_on;
} kTestCases[] = {
{false, false},
{false, true},
{true, false},
{true, true},
};
for (const auto test_case : kTestCases) {
if (test_case.tablet_enabled) {
SwitchToTabletMode();
EXPECT_TRUE(display::Screen::Get()->InTabletMode());
} else {
EXPECT_FALSE(display::Screen::Get()->InTabletMode());
}
const std::string histogram_name =
BuildHistogramName(kHistogramNameBase, nullptr,
true);
histogram_tester.ExpectBucketCount(histogram_name, test_case.camera_on, 0);
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(
test_case.camera_on ? CameraId(kDefaultCameraModelId, 1) : CameraId());
StartVideoRecordingImmediately();
EXPECT_TRUE(controller->is_recording_in_progress());
controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
WaitForCaptureFileToBeSaved();
histogram_tester.ExpectBucketCount(histogram_name, test_case.camera_on, 1);
}
}
TEST_F(CaptureModeCameraTest,
RecordCameraDisconnectionsDuringRecordingsHistogramTest) {
constexpr char kHistogramNameBase[] = "CameraDisconnectionsDuringRecordings";
base::HistogramTester histogram_tester;
auto* camera_controller = GetCameraController();
auto disconnect_and_reconnect_camera_n_times = [&](int n) {
for (int i = 0; i < n; i++) {
AddAndRemoveCameraAndTriggerGracePeriod();
camera_controller->camera_reconnect_timer_for_test()->FireNow();
}
};
for (const bool tablet_enabled : {false, true}) {
if (tablet_enabled) {
SwitchToTabletMode();
EXPECT_TRUE(display::Screen::Get()->InTabletMode());
} else {
EXPECT_FALSE(display::Screen::Get()->InTabletMode());
}
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
controller->StartVideoRecordingImmediatelyForTesting();
disconnect_and_reconnect_camera_n_times(3);
controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
WaitForCaptureFileToBeSaved();
histogram_tester.ExpectBucketCount(
BuildHistogramName(kHistogramNameBase, nullptr,
true),
3, 1);
}
}
TEST_F(CaptureModeCameraTest, RecordNumberOfConnectedCamerasHistogramTest) {
constexpr char kHistogramNameBase[] = "NumberOfConnectedCameras";
const std::string histogram_name =
BuildHistogramName(kHistogramNameBase, nullptr,
false);
base::HistogramTester histogram_tester;
{
base::RunLoop loop;
GetCameraController()->SetOnCameraListReceivedForTesting(
loop.QuitClosure());
base::SystemMonitor::Get()->ProcessDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
loop.Run();
}
histogram_tester.ExpectBucketCount(histogram_name, 0, 1);
AddFakeCamera("/dev/video", "fake cam ", "model 1");
histogram_tester.ExpectBucketCount(histogram_name, 1, 1);
AddFakeCamera("/dev/video1", "fake cam 2", "model 2");
histogram_tester.ExpectBucketCount(histogram_name, 2, 1);
RemoveFakeCamera("/dev/video1");
histogram_tester.ExpectBucketCount(histogram_name, 1, 2);
AddFakeCamera("/dev/video2", "fake cam 3", "model 3");
histogram_tester.ExpectBucketCount(histogram_name, 2, 2);
}
TEST_F(CaptureModeCameraTest,
DISABLED_RecordCameraReconnectDurationHistogramTest) {
constexpr char kHistogramNameBase[] = "CameraReconnectDuration";
base::HistogramTester histogram_tester;
for (const bool tablet_enabled : {false, true}) {
if (tablet_enabled) {
SwitchToTabletMode();
EXPECT_TRUE(display::Screen::Get()->InTabletMode());
} else {
EXPECT_FALSE(display::Screen::Get()->InTabletMode());
}
AddAndRemoveCameraAndTriggerGracePeriod();
WaitForSeconds(1);
AddDefaultCamera();
histogram_tester.ExpectBucketCount(
BuildHistogramName(kHistogramNameBase, nullptr,
true),
1, 1);
RemoveDefaultCamera();
}
}
TEST_F(CaptureModeCameraTest, RecordingCameraSizeOnStartHistogramTest) {
UpdateDisplay("1366x768");
constexpr char kHistogramNameBase[] = "RecordingCameraSizeOnStart";
base::HistogramTester histogram_tester;
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
for (const bool tablet_enabled : {false, true}) {
if (tablet_enabled) {
SwitchToTabletMode();
EXPECT_TRUE(display::Screen::Get()->InTabletMode());
} else {
EXPECT_FALSE(display::Screen::Get()->InTabletMode());
}
const std::string histogram_name =
BuildHistogramName(kHistogramNameBase, nullptr,
true);
for (const bool collapsed : {false, true}) {
const auto sample = collapsed ? CaptureModeCameraSize::kCollapsed
: CaptureModeCameraSize::kExpanded;
histogram_tester.ExpectBucketCount(histogram_name, sample, 0);
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
auto* event_generator = GetEventGenerator();
ClickOrTapView(camera_controller->camera_preview_view(), tablet_enabled,
event_generator);
auto* resize_button = GetPreviewResizeButton();
DCHECK(resize_button);
if (collapsed) {
if (!camera_controller->is_camera_preview_collapsed())
ClickOrTapView(resize_button, tablet_enabled, event_generator);
EXPECT_TRUE(camera_controller->is_camera_preview_collapsed());
} else {
if (camera_controller->is_camera_preview_collapsed())
ClickOrTapView(resize_button, tablet_enabled, event_generator);
EXPECT_FALSE(camera_controller->is_camera_preview_collapsed());
}
StartVideoRecordingImmediately();
controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
WaitForCaptureFileToBeSaved();
histogram_tester.ExpectBucketCount(histogram_name, sample, 1);
}
}
}
TEST_F(CaptureModeCameraTest, RecordingCameraPositionOnStartHistogramTest) {
constexpr char kHistogramName[] = "RecordingCameraPositionOnStart";
base::HistogramTester histogram_tester;
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
AddDefaultCamera();
auto* camera_controller = GetCameraController();
const CameraId camera_id(kDefaultCameraModelId, 1);
camera_controller->SetSelectedCamera(camera_id);
const CameraPreviewSnapPosition kCameraPositionTestCases[]{
CameraPreviewSnapPosition::kTopLeft,
CameraPreviewSnapPosition::kBottomLeft,
CameraPreviewSnapPosition::kTopRight,
CameraPreviewSnapPosition::kBottomRight};
for (const bool tablet_enabled : {false, true}) {
if (tablet_enabled) {
SwitchToTabletMode();
EXPECT_TRUE(display::Screen::Get()->InTabletMode());
} else {
EXPECT_FALSE(display::Screen::Get()->InTabletMode());
}
const std::string histogram_name = BuildHistogramName(
kHistogramName, nullptr, true);
for (const auto camera_position : kCameraPositionTestCases) {
histogram_tester.ExpectBucketCount(histogram_name, camera_position, 0);
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
DCHECK(camera_controller->camera_preview_widget());
camera_controller->SetCameraPreviewSnapPosition(camera_position);
StartVideoRecordingImmediately();
controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
WaitForCaptureFileToBeSaved();
histogram_tester.ExpectBucketCount(histogram_name, camera_position, 1);
}
}
}
TEST_F(CaptureModeCameraTest, ToastVisibilityChangeOnCaptureRegionUpdated) {
UpdateDisplay("800x600");
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* camera_controller = GetCameraController();
auto* capture_toast_controller = capture_session->capture_toast_controller();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const gfx::Rect capture_region(100, 100, 300, 300);
SelectCaptureRegion(capture_region);
auto* capture_toast_widget = capture_toast_controller->capture_toast_widget();
EXPECT_TRUE(capture_toast_widget);
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kUserNudge);
const int delta_x =
capture_mode::kMinCaptureSurfaceShortSideLengthForVisibleCamera - 30 -
capture_region.width();
const int delta_y =
capture_mode::kMinCaptureSurfaceShortSideLengthForVisibleCamera - 30 -
capture_region.height();
const gfx::Vector2d delta(delta_x, delta_y);
auto* event_generator = GetEventGenerator();
event_generator->set_current_screen_location(capture_region.bottom_right());
event_generator->PressLeftButton();
EXPECT_FALSE(capture_toast_widget->IsVisible());
event_generator->MoveMouseTo(capture_region.bottom_right() + delta);
event_generator->ReleaseLeftButton();
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
EXPECT_TRUE(capture_toast_widget->IsVisible());
EXPECT_FALSE(GetUserNudgeController());
const gfx::Vector2d delta1(delta_x + 10, delta_y + 10);
event_generator->set_current_screen_location(capture_region.bottom_right());
event_generator->PressLeftButton();
EXPECT_FALSE(capture_toast_widget->IsVisible());
event_generator->MoveMouseTo(capture_region.bottom_right() + delta1);
event_generator->ReleaseLeftButton();
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
EXPECT_TRUE(capture_toast_widget->IsVisible());
event_generator->set_current_screen_location(capture_region.origin());
event_generator->PressLeftButton();
EXPECT_FALSE(capture_toast_widget->IsVisible());
event_generator->MoveMouseTo(capture_region.bottom_right());
event_generator->ReleaseLeftButton();
EXPECT_FALSE(capture_toast_controller->current_toast_type());
EXPECT_FALSE(capture_toast_widget->IsVisible());
}
TEST_F(CaptureModeCameraTest, ToastVisibilityChangeOnTimeOut) {
UpdateDisplay("800x600");
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* camera_controller = GetCameraController();
auto* capture_toast_controller = capture_session->capture_toast_controller();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const gfx::Rect capture_region = GetTooSmallToFitCameraRegion();
SelectCaptureRegion(capture_region);
auto* capture_toast_widget = capture_toast_controller->capture_toast_widget();
EXPECT_TRUE(capture_toast_widget->IsVisible());
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
base::OneShotTimer* timer =
capture_toast_controller->capture_toast_dismiss_timer_for_test();
EXPECT_TRUE(timer->IsRunning());
timer->FireNow();
EXPECT_FALSE(capture_toast_widget->IsVisible());
}
TEST_F(CaptureModeCameraTest, ToastVisibilityChangeOnSettingsMenuOpen) {
UpdateDisplay("800x600");
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* camera_controller = GetCameraController();
auto* capture_toast_controller = capture_session->capture_toast_controller();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const gfx::Rect capture_region = GetTooSmallToFitCameraRegion();
SelectCaptureRegion(capture_region);
auto* capture_toast_widget = capture_toast_controller->capture_toast_widget();
EXPECT_TRUE(capture_toast_widget->IsVisible());
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
OpenSettingsView();
EXPECT_FALSE(capture_toast_widget->IsVisible());
}
TEST_F(CaptureModeCameraTest, ToastVisibilityChangeOnCaptureRegionMoved) {
UpdateDisplay("800x600");
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* camera_controller = GetCameraController();
auto* capture_toast_controller = capture_session->capture_toast_controller();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const gfx::Rect capture_region = GetTooSmallToFitCameraRegion();
SelectCaptureRegion(capture_region);
auto* capture_toast_widget = capture_toast_controller->capture_toast_widget();
EXPECT_TRUE(capture_toast_widget->IsVisible());
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
const gfx::Vector2d delta(20, 20);
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(capture_region.origin() + delta);
event_generator->PressLeftButton();
EXPECT_FALSE(capture_toast_widget->IsVisible());
event_generator->MoveMouseTo(capture_region.CenterPoint());
event_generator->ReleaseLeftButton();
EXPECT_TRUE(capture_toast_widget->IsVisible());
}
TEST_F(CaptureModeCameraTest, ToastVisibilityChangeOnCaptureModeTurnedOn) {
UpdateDisplay("800x600");
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* camera_controller = GetCameraController();
auto* capture_toast_controller = capture_session->capture_toast_controller();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const gfx::Rect capture_region = GetTooSmallToFitCameraRegion();
SelectCaptureRegion(capture_region);
auto* capture_toast_widget = capture_toast_controller->capture_toast_widget();
EXPECT_TRUE(capture_toast_widget->IsVisible());
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
controller->Stop();
controller->Start(CaptureModeEntryType::kQuickSettings);
capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
capture_toast_controller = capture_session->capture_toast_controller();
EXPECT_TRUE(capture_toast_controller->capture_toast_widget()->IsVisible());
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
}
TEST_F(CaptureModeCameraTest, ToastStackingOrderChangeOnCaptureModeTurnedOn) {
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const gfx::Rect capture_region = GetTooSmallToFitCameraRegion();
SelectCaptureRegion(capture_region);
controller->Stop();
controller->Start(CaptureModeEntryType::kQuickSettings);
base::RunLoop().RunUntilIdle();
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* capture_toast_controller = capture_session->capture_toast_controller();
auto* capture_toast_widget = capture_toast_controller->capture_toast_widget();
auto* capture_toast_window = capture_toast_widget->GetNativeWindow();
auto* capture_label_window =
capture_session->capture_label_widget()->GetNativeWindow();
auto* capture_bar_window =
capture_session->GetCaptureModeBarWidget()->GetNativeWindow();
auto* camera_preview_window =
camera_controller->camera_preview_widget()->GetNativeWindow();
EXPECT_TRUE(
IsWindowStackedRightBelow(capture_label_window, capture_bar_window));
EXPECT_TRUE(
IsWindowStackedRightBelow(capture_toast_window, capture_label_window));
EXPECT_TRUE(
IsWindowStackedRightBelow(camera_preview_window, capture_toast_window));
EXPECT_TRUE(IsLayerStackedRightBelow(capture_session->layer(),
camera_preview_window->layer()));
}
TEST_F(CaptureModeCameraTest, ToastVisibilityChangeOnPerformingCapture) {
UpdateDisplay("800x600");
auto* controller =
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* camera_controller = GetCameraController();
auto* capture_toast_controller = capture_session->capture_toast_controller();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
const gfx::Rect capture_region = GetTooSmallToFitCameraRegion();
SelectCaptureRegion(capture_region);
auto* capture_toast_widget = capture_toast_controller->capture_toast_widget();
EXPECT_TRUE(capture_toast_widget->IsVisible());
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
controller->PerformCapture();
EXPECT_EQ(capture_toast_widget->GetLayer()->GetTargetOpacity(), 0.f);
}
TEST_F(CaptureModeCameraTest, ToastVisibilityChangeOnMultiDisplays) {
UpdateDisplay("800x700,801+0-800x700");
const gfx::Rect first_display_bounds(0, 0, 800, 700);
const gfx::Rect second_display_bounds(801, 0, 800, 700);
window()->SetBoundsInScreen(gfx::Rect(600, 500, 100, 100),
display::Screen::Get()->GetDisplayNearestWindow(
Shell::GetAllRootWindows()[0]));
std::unique_ptr<aura::Window> window1(CreateTestWindow());
window1->SetBoundsInScreen(gfx::Rect(1400, 500, 100, 100),
display::Screen::Get()->GetDisplayNearestWindow(
Shell::GetAllRootWindows()[1]));
auto* controller =
StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
auto* capture_session =
static_cast<CaptureModeSession*>(controller->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
auto* capture_toast_controller = capture_session->capture_toast_controller();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(window()->GetBoundsInScreen().CenterPoint());
EXPECT_EQ(capture_session->GetSelectedWindow(), window());
auto* capture_toast_widget = capture_toast_controller->capture_toast_widget();
EXPECT_TRUE(capture_toast_widget->IsVisible());
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
first_display_bounds.Contains(
capture_toast_widget->GetWindowBoundsInScreen());
event_generator->MoveMouseTo(window1->GetBoundsInScreen().CenterPoint());
EXPECT_EQ(capture_session->GetSelectedWindow(), window1.get());
EXPECT_TRUE(capture_toast_widget->IsVisible());
ASSERT_TRUE(capture_toast_controller->current_toast_type());
EXPECT_EQ(*(capture_toast_controller->current_toast_type()),
CaptureToastType::kCameraPreview);
second_display_bounds.Contains(
capture_toast_widget->GetWindowBoundsInScreen());
event_generator->MoveMouseTo({1300, 500});
EXPECT_FALSE(capture_toast_widget->IsVisible());
window()->SetBoundsInScreen(gfx::Rect(100, 200, 300, 300),
display::Screen::Get()->GetDisplayNearestWindow(
Shell::GetAllRootWindows()[0]));
event_generator->MoveMouseTo(window()->GetBoundsInScreen().CenterPoint());
EXPECT_EQ(capture_session->GetSelectedWindow(), window());
EXPECT_FALSE(capture_toast_widget->IsVisible());
}
class CaptureModeCameraPreviewTest
: public CaptureModeCameraTest,
public testing::WithParamInterface<CaptureModeSource> {
public:
enum class CameraPreviewState {
kCollapsible,
kNotCollapsible,
kHidden,
};
CaptureModeCameraPreviewTest() = default;
CaptureModeCameraPreviewTest(const CaptureModeCameraPreviewTest&) = delete;
CaptureModeCameraPreviewTest& operator=(const CaptureModeCameraPreviewTest&) =
delete;
~CaptureModeCameraPreviewTest() override = default;
void StartCaptureSessionWithParam() {
auto* controller = CaptureModeController::Get();
const gfx::Rect capture_region(10, 20, 1300, 750);
controller->SetUserCaptureRegion(capture_region, true);
window()->SetBounds({30, 40, 1300, 750});
StartCaptureSession(GetParam(), CaptureModeType::kVideo);
if (GetParam() == CaptureModeSource::kWindow)
GetEventGenerator()->MoveMouseToCenterOf(window());
}
gfx::Size GetMinSurfaceSizeForCollapsibleCamera() const {
const int min_length = capture_mode::kMinCollapsibleCameraPreviewDiameter *
capture_mode::kCaptureSurfaceShortSideDivider;
return gfx::Size(min_length, min_length);
}
gfx::Size GetMinSurfaceSizeSoCameraBecomes(
CameraPreviewState preview_state) const {
gfx::Size min_size = GetMinSurfaceSizeForCollapsibleCamera();
switch (preview_state) {
case CameraPreviewState::kCollapsible:
min_size.Enlarge(10, 20);
break;
case CameraPreviewState::kNotCollapsible:
min_size.Enlarge(-10, -20);
break;
case CameraPreviewState::kHidden:
const int length_for_hidden =
capture_mode::kMinCaptureSurfaceShortSideLengthForVisibleCamera - 5;
min_size.SetSize(length_for_hidden, length_for_hidden - 5);
break;
}
return min_size;
}
void ResizeDisplaySoCameraPreviewBecomes(CameraPreviewState preview_state) {
gfx::Size min_size = GetMinSurfaceSizeSoCameraBecomes(preview_state);
const int shelf_size = ShelfConfig::Get()->shelf_size();
min_size.Enlarge(shelf_size, shelf_size);
UpdateDisplay(min_size.ToString());
}
void ResizeRegionSoCameraPreviewBecomes(CameraPreviewState preview_state) {
CaptureModeController::Get()->SetUserCaptureRegion(
gfx::Rect(GetMinSurfaceSizeSoCameraBecomes(preview_state)),
true);
}
void ResizeWindowSoCameraPreviewBecomes(CameraPreviewState preview_state) {
auto size = GetMinSurfaceSizeSoCameraBecomes(preview_state);
if (auto* frame_header =
capture_mode_util::GetWindowFrameHeader(window())) {
size.Enlarge(0, frame_header->GetHeaderHeight());
}
window()->SetBounds(gfx::Rect(size));
}
void ResizeSurfaceSoCameraPreviewBecomes(CameraPreviewState preview_state) {
switch (GetParam()) {
case CaptureModeSource::kFullscreen:
ResizeDisplaySoCameraPreviewBecomes(preview_state);
break;
case CaptureModeSource::kRegion:
ResizeRegionSoCameraPreviewBecomes(preview_state);
break;
case CaptureModeSource::kWindow:
ResizeWindowSoCameraPreviewBecomes(preview_state);
break;
}
}
gfx::Rect GetCaptureBoundsInScreen() const {
auto* controller = CaptureModeController::Get();
auto* root = GetCurrentRoot();
switch (GetParam()) {
case CaptureModeSource::kFullscreen:
return display::Screen::Get()
->GetDisplayNearestWindow(root)
.work_area();
case CaptureModeSource::kRegion: {
auto* recording_watcher =
controller->video_recording_watcher_for_testing();
gfx::Rect capture_region =
controller->is_recording_in_progress()
? recording_watcher->GetEffectivePartialRegionBounds()
: controller->user_capture_region();
wm::ConvertRectToScreen(root, &capture_region);
return capture_region;
}
case CaptureModeSource::kWindow:
auto bounds =
capture_mode_util::GetCaptureWindowConfineBounds(window());
wm::ConvertRectToScreen(window(), &bounds);
return bounds;
}
}
gfx::Size GetExpectedPreviewSize(bool collapsed) const {
return capture_mode_util::CalculateCameraPreviewSizeSpecs(
GetCaptureBoundsInScreen().size(), collapsed)
.size;
}
ui::mojom::CursorType GetCursorTypeOnCaptureSurface() const {
DCHECK(CaptureModeController::Get()->IsActive());
switch (GetParam()) {
case CaptureModeSource::kFullscreen:
case CaptureModeSource::kWindow:
return ui::mojom::CursorType::kCustom;
case CaptureModeSource::kRegion:
return ui::mojom::CursorType::kMove;
}
}
};
TEST_P(CaptureModeCameraPreviewTest, PreviewVisibilityWhileFolderSelection) {
AddDefaultCamera();
StartCaptureSessionWithParam();
CaptureModeTestApi().SelectCameraAtIndex(0);
auto* controller = CaptureModeController::Get();
ASSERT_TRUE(controller->IsActive());
auto* preview_widget = GetCameraController()->camera_preview_widget();
ASSERT_TRUE(preview_widget);
EXPECT_TRUE(preview_widget->IsVisible());
CaptureModeSessionTestApi session_test_api(
controller->capture_mode_session());
auto* settings_button =
session_test_api.GetCaptureModeBarView()->settings_button();
auto* event_generator = GetEventGenerator();
ClickOnView(settings_button, event_generator);
ASSERT_TRUE(session_test_api.GetCaptureModeSettingsWidget());
EXPECT_TRUE(preview_widget->IsVisible());
CaptureModeSettingsTestApi settings_test_api;
ClickOnView(settings_test_api.GetSelectFolderMenuItem(), event_generator);
EXPECT_TRUE(session_test_api.IsFolderSelectionDialogShown());
EXPECT_FALSE(session_test_api.AreAllUisVisible());
EXPECT_FALSE(preview_widget->IsVisible());
FakeFolderSelectionDialogFactory::Get()->CancelDialog();
EXPECT_FALSE(session_test_api.IsFolderSelectionDialogShown());
EXPECT_TRUE(session_test_api.AreAllUisVisible());
EXPECT_TRUE(preview_widget->IsVisible());
}
TEST_P(CaptureModeCameraPreviewTest, DisplayRotation) {
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
Shell::Get()->display_manager()->SetDisplayRotation(
WindowTreeHostManager::GetPrimaryDisplayId(), display::Display::ROTATE_90,
display::Display::RotationSource::USER);
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
StartVideoRecordingImmediately();
EXPECT_FALSE(CaptureModeController::Get()->IsActive());
Shell::Get()->display_manager()->SetDisplayRotation(
WindowTreeHostManager::GetPrimaryDisplayId(),
display::Display::ROTATE_180, display::Display::RotationSource::USER);
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
Shell::Get()->display_manager()->SetDisplayRotation(
WindowTreeHostManager::GetPrimaryDisplayId(),
display::Display::ROTATE_270, display::Display::RotationSource::USER);
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
}
TEST_P(CaptureModeCameraPreviewTest, CameraPreviewDragToSnap) {
UpdateDisplay("1600x800");
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
const gfx::Point capture_bounds_center_point =
GetCaptureBoundsInScreen().CenterPoint();
EXPECT_EQ(CameraPreviewSnapPosition::kBottomRight,
camera_controller->camera_preview_snap_position());
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
DragPreviewToPoint(preview_widget, {capture_bounds_center_point.x() + 20,
capture_bounds_center_point.y() + 20});
EXPECT_EQ(CameraPreviewSnapPosition::kBottomRight,
camera_controller->camera_preview_snap_position());
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
DragPreviewToPoint(preview_widget, {capture_bounds_center_point.x() + 20,
capture_bounds_center_point.y() - 20});
EXPECT_EQ(CameraPreviewSnapPosition::kTopRight,
camera_controller->camera_preview_snap_position());
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
DragPreviewToPoint(preview_widget,
{capture_bounds_center_point.x() - 20,
capture_bounds_center_point.y() - 20},
true);
EXPECT_EQ(CameraPreviewSnapPosition::kTopLeft,
camera_controller->camera_preview_snap_position());
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
StartVideoRecordingImmediately();
EXPECT_FALSE(CaptureModeController::Get()->IsActive());
DragPreviewToPoint(preview_widget, {capture_bounds_center_point.x() - 20,
capture_bounds_center_point.y() + 20});
EXPECT_EQ(CameraPreviewSnapPosition::kBottomLeft,
camera_controller->camera_preview_snap_position());
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
DragPreviewToPoint(preview_widget,
{capture_bounds_center_point.x() + 20,
capture_bounds_center_point.y() + 20},
true);
EXPECT_EQ(CameraPreviewSnapPosition::kBottomRight,
camera_controller->camera_preview_snap_position());
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
}
TEST_P(CaptureModeCameraPreviewTest,
CameraPreviewDragToSnapAfterPressOnResizeButton) {
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
auto* resize_button = GetPreviewResizeButton();
const int camera_previw_width =
preview_widget->GetWindowBoundsInScreen().width();
const gfx::Point capture_bounds_center_point =
GetCaptureBoundsInScreen().CenterPoint();
const gfx::Point center_point_of_resize_button =
resize_button->GetBoundsInScreen().CenterPoint();
EXPECT_EQ(CameraPreviewSnapPosition::kBottomRight,
camera_controller->camera_preview_snap_position());
auto* event_generator = GetEventGenerator();
event_generator->set_current_screen_location(center_point_of_resize_button);
event_generator->PressLeftButton();
const gfx::Vector2d delta(-camera_previw_width, -camera_previw_width);
event_generator->MoveMouseTo(center_point_of_resize_button + delta);
event_generator->ReleaseLeftButton();
DragPreviewToPoint(preview_widget, capture_bounds_center_point + delta);
EXPECT_EQ(CameraPreviewSnapPosition::kTopLeft,
camera_controller->camera_preview_snap_position());
}
TEST_P(CaptureModeCameraPreviewTest, CaptureUisVisibilityChangeOnDragAndDrop) {
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
auto* capture_session = static_cast<CaptureModeSession*>(
CaptureModeController::Get()->capture_mode_session());
ASSERT_EQ(capture_session->session_type(), SessionType::kReal);
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
const gfx::Point center_point_of_preview_widget =
preview_widget->GetWindowBoundsInScreen().CenterPoint();
const auto* capture_bar_widget = capture_session->GetCaptureModeBarWidget();
const auto* capture_label_widget = capture_session->capture_label_widget();
auto* event_generator = GetEventGenerator();
event_generator->set_current_screen_location(center_point_of_preview_widget);
event_generator->PressLeftButton();
EXPECT_FALSE(capture_bar_widget->IsVisible());
EXPECT_FALSE(capture_label_widget->IsVisible());
const gfx::Vector2d delta(-50, -60);
event_generator->MoveMouseTo(center_point_of_preview_widget + delta);
EXPECT_FALSE(capture_bar_widget->IsVisible());
EXPECT_FALSE(capture_label_widget->IsVisible());
event_generator->ReleaseLeftButton();
EXPECT_TRUE(capture_bar_widget->IsVisible());
EXPECT_TRUE(capture_label_widget->IsVisible());
}
TEST_P(CaptureModeCameraPreviewTest, CameraPreviewDragToSnapOnMultipleDisplay) {
UpdateDisplay("800x700,801+0-800x700");
const gfx::Point point_in_second_display = gfx::Point(1000, 500);
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(point_in_second_display);
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
const gfx::Point capture_bounds_center_point =
GetCaptureBoundsInScreen().CenterPoint();
DragPreviewToPoint(preview_widget, {capture_bounds_center_point.x() + 20,
capture_bounds_center_point.y() - 20});
EXPECT_EQ(CameraPreviewSnapPosition::kTopRight,
camera_controller->camera_preview_snap_position());
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
}
TEST_P(CaptureModeCameraPreviewTest,
DragPreviewInNewCaptureSessionWhileVideoRecordingInProgress) {
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
const gfx::Point capture_bounds_center_point =
GetCaptureBoundsInScreen().CenterPoint();
StartVideoRecordingImmediately();
EXPECT_FALSE(CaptureModeController::Get()->IsActive());
auto* controller = CaptureModeController::Get();
controller->Start(CaptureModeEntryType::kQuickSettings);
const gfx::Rect preview_bounds_in_screen_before_drag =
preview_widget->GetWindowBoundsInScreen();
const auto snap_position_before_drag =
camera_controller->camera_preview_snap_position();
EXPECT_EQ(snap_position_before_drag, CameraPreviewSnapPosition::kBottomRight);
DragPreviewToPoint(preview_widget,
{preview_bounds_in_screen_before_drag.x() + 20,
preview_bounds_in_screen_before_drag.y() + 20},
false,
false);
EXPECT_EQ(preview_widget->GetWindowBoundsInScreen(),
preview_bounds_in_screen_before_drag);
DragPreviewToPoint(preview_widget,
{capture_bounds_center_point.x() - 20,
capture_bounds_center_point.y() - 20},
true);
EXPECT_EQ(preview_widget->GetWindowBoundsInScreen(),
preview_bounds_in_screen_before_drag);
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
snap_position_before_drag);
}
TEST_P(CaptureModeCameraPreviewTest,
PreviewWidgetIsConstrainedByConfineBounds) {
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
ASSERT_TRUE(preview_widget);
const auto confine_bounds = GetCaptureBoundsInScreen();
gfx::Rect outer_rect = confine_bounds;
outer_rect.Inset(-20);
for (const auto& release_point :
{outer_rect.origin(), outer_rect.top_right(), outer_rect.bottom_left(),
outer_rect.bottom_right()}) {
DragPreviewToPoint(preview_widget, release_point);
EXPECT_TRUE(
confine_bounds.Contains(preview_widget->GetWindowBoundsInScreen()));
}
}
TEST_P(CaptureModeCameraPreviewTest, DragPreviewOutsidePreviewCircle) {
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
const gfx::Point capture_bounds_center_point =
GetCaptureBoundsInScreen().CenterPoint();
const gfx::Rect preview_bounds_in_screen_before_drag =
preview_widget->GetWindowBoundsInScreen();
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(preview_bounds_in_screen_before_drag.origin());
event_generator->PressLeftButton();
event_generator->MoveMouseTo(capture_bounds_center_point);
EXPECT_EQ(preview_widget->GetWindowBoundsInScreen(),
preview_bounds_in_screen_before_drag);
}
TEST_P(CaptureModeCameraPreviewTest,
DragPreviewOutsidePreviewCircleWhileVideoRecordingInProgress) {
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
const gfx::Point capture_bounds_center_point =
GetCaptureBoundsInScreen().CenterPoint();
const gfx::Rect preview_bounds_in_screen_before_drag =
preview_widget->GetWindowBoundsInScreen();
const auto snap_position_before_drag =
camera_controller->camera_preview_snap_position();
EXPECT_EQ(snap_position_before_drag, CameraPreviewSnapPosition::kBottomRight);
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(preview_bounds_in_screen_before_drag.origin());
event_generator->PressLeftButton();
event_generator->MoveMouseTo(capture_bounds_center_point);
EXPECT_EQ(preview_widget->GetWindowBoundsInScreen(),
preview_bounds_in_screen_before_drag);
event_generator->ReleaseLeftButton();
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
snap_position_before_drag);
}
TEST_P(CaptureModeCameraPreviewTest, CursorTypeUpdates) {
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
const gfx::Rect preview_bounds_in_screen =
preview_widget->GetWindowBoundsInScreen();
const gfx::Point camera_preview_center_point =
preview_bounds_in_screen.CenterPoint();
const gfx::Point camera_preview_origin_point =
preview_bounds_in_screen.origin();
auto* event_generator = GetEventGenerator();
auto* cursor_manager = Shell::Get()->cursor_manager();
event_generator->MoveMouseTo(preview_bounds_in_screen.origin());
EXPECT_NE(cursor_manager->GetCursor(), ui::mojom::CursorType::kPointer);
event_generator->MoveMouseTo(camera_preview_center_point);
EXPECT_EQ(cursor_manager->GetCursor(), ui::mojom::CursorType::kPointer);
event_generator->MoveMouseTo({camera_preview_origin_point.x() - 10,
camera_preview_origin_point.y() - 10});
EXPECT_EQ(cursor_manager->GetCursor(), GetCursorTypeOnCaptureSurface());
DragPreviewToPoint(preview_widget,
{camera_preview_center_point.x() - 10,
camera_preview_center_point.y() - 10},
false,
false);
EXPECT_EQ(cursor_manager->GetCursor(), ui::mojom::CursorType::kPointer);
DragPreviewToPoint(preview_widget, {camera_preview_origin_point.x() - 20,
camera_preview_origin_point.y() - 20});
EXPECT_EQ(cursor_manager->GetCursor(), GetCursorTypeOnCaptureSurface());
}
TEST_P(CaptureModeCameraPreviewTest, ResizePreviewWidget) {
UpdateDisplay("800x700");
StartCaptureSessionWithParam();
auto* controller = CaptureModeController::Get();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
views::Widget* preview_widget = camera_controller->camera_preview_widget();
DCHECK(preview_widget);
const auto default_preview_bounds = preview_widget->GetWindowBoundsInScreen();
EXPECT_EQ(default_preview_bounds.size(),
GetExpectedPreviewSize(false));
auto* resize_button = GetPreviewResizeButton();
auto* event_generator = GetEventGenerator();
VerifyResizeButton(camera_controller->is_camera_preview_collapsed(),
resize_button);
ClickOnView(resize_button, event_generator);
EXPECT_EQ(preview_widget->GetWindowBoundsInScreen().size(),
GetExpectedPreviewSize(true));
VerifyResizeButton(camera_controller->is_camera_preview_collapsed(),
resize_button);
ClickOnView(resize_button, event_generator);
EXPECT_EQ(preview_widget->GetWindowBoundsInScreen(), default_preview_bounds);
VerifyResizeButton(camera_controller->is_camera_preview_collapsed(),
resize_button);
ClickOnView(resize_button, event_generator);
EXPECT_EQ(preview_widget->GetWindowBoundsInScreen().size(),
GetExpectedPreviewSize(true));
VerifyResizeButton(camera_controller->is_camera_preview_collapsed(),
resize_button);
const auto collapsed_preview_bounds =
preview_widget->GetWindowBoundsInScreen();
controller->Stop();
StartCaptureSessionWithParam();
preview_widget = camera_controller->camera_preview_widget();
EXPECT_TRUE(preview_widget);
EXPECT_EQ(preview_widget->GetWindowBoundsInScreen(),
collapsed_preview_bounds);
resize_button = GetPreviewResizeButton();
EXPECT_TRUE(resize_button);
VerifyResizeButton(camera_controller->is_camera_preview_collapsed(),
resize_button);
}
TEST_P(CaptureModeCameraPreviewTest, MultiDisplayResize) {
UpdateDisplay("800x700,801+0-800x700");
ASSERT_EQ(2u, Shell::GetAllRootWindows().size());
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(gfx::Point(900, 500));
StartCaptureSessionWithParam();
auto* controller = CaptureModeController::Get();
auto* session = controller->capture_mode_session();
auto* display_2_root = Shell::GetAllRootWindows()[1].get();
if (GetParam() == CaptureModeSource::kWindow) {
views::Widget::GetWidgetForNativeWindow(window())->SetBounds(
{900, 10, 700, 650});
EXPECT_EQ(display_2_root, window()->GetRootWindow());
event_generator->MoveMouseToCenterOf(window());
}
EXPECT_EQ(display_2_root, session->current_root());
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
auto* resize_button = GetPreviewResizeButton();
ClickOnView(resize_button, event_generator);
VerifyPreviewAlignment(GetCaptureBoundsInScreen());
}
TEST_P(CaptureModeCameraPreviewTest, ResizeButtonVisibilityOnMouseEvents) {
UpdateDisplay("1366x768");
StartCaptureSessionWithParam();
CaptureModeCameraController* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
views::Widget* preview_widget = camera_controller->camera_preview_widget();
DCHECK(preview_widget);
const gfx::Rect default_preview_bounds =
preview_widget->GetWindowBoundsInScreen();
CameraPreviewResizeButton* resize_button = GetPreviewResizeButton();
auto* event_generator = GetEventGenerator();
EXPECT_FALSE(resize_button->GetVisible());
event_generator->MoveMouseTo(default_preview_bounds.CenterPoint());
EXPECT_TRUE(resize_button->GetVisible());
event_generator->MoveMouseTo(default_preview_bounds.top_center());
EXPECT_TRUE(resize_button->GetVisible());
auto outside_point = default_preview_bounds.origin();
outside_point.Offset(-1, -1);
event_generator->MoveMouseTo(outside_point);
base::OneShotTimer* timer = camera_controller->camera_preview_view()
->resize_button_hide_timer_for_test();
EXPECT_TRUE(timer->IsRunning());
EXPECT_EQ(timer->GetCurrentDelay(), capture_mode::kResizeButtonShowDuration);
{
ViewVisibilityChangeWaiter waiter(resize_button);
EXPECT_TRUE(resize_button->GetVisible());
timer->FireNow();
waiter.Wait();
EXPECT_FALSE(resize_button->GetVisible());
}
}
TEST_P(CaptureModeCameraPreviewTest, ResizeButtonVisibilityOnTapEvents) {
UpdateDisplay("800x700");
StartCaptureSessionWithParam();
CaptureModeCameraController* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
views::Widget* preview_widget = camera_controller->camera_preview_widget();
DCHECK(preview_widget);
const gfx::Rect default_preview_bounds =
preview_widget->GetWindowBoundsInScreen();
CameraPreviewResizeButton* resize_button = GetPreviewResizeButton();
auto* event_generator = GetEventGenerator();
EXPECT_FALSE(resize_button->GetVisible());
event_generator->GestureTapAt(default_preview_bounds.CenterPoint());
EXPECT_TRUE(resize_button->GetVisible());
base::OneShotTimer* timer = camera_controller->camera_preview_view()
->resize_button_hide_timer_for_test();
EXPECT_TRUE(timer->IsRunning());
EXPECT_EQ(timer->GetCurrentDelay(), capture_mode::kResizeButtonShowDuration);
{
ViewVisibilityChangeWaiter waiter(resize_button);
timer->FireNow();
waiter.Wait();
EXPECT_FALSE(resize_button->GetVisible());
}
}
TEST_P(CaptureModeCameraPreviewTest,
ResizeButtonVisibilityOnCameraPreviewDragToSnap) {
UpdateDisplay("1366x768");
StartCaptureSessionWithParam();
CaptureModeCameraController* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
views::Widget* preview_widget = camera_controller->camera_preview_widget();
const gfx::Rect preview_bounds = preview_widget->GetWindowBoundsInScreen();
CameraPreviewResizeButton* resize_button = GetPreviewResizeButton();
auto* event_generator = GetEventGenerator();
EXPECT_FALSE(resize_button->GetVisible());
event_generator->MoveMouseTo(preview_bounds.CenterPoint());
EXPECT_TRUE(resize_button->GetVisible());
event_generator->PressLeftButton();
EXPECT_FALSE(resize_button->GetVisible());
event_generator->MoveMouseBy(-300, -300);
EXPECT_FALSE(resize_button->GetVisible());
event_generator->ReleaseLeftButton();
EXPECT_FALSE(resize_button->GetVisible());
const gfx::Vector2d delta(-30, -30);
DragPreviewToPoint(preview_widget, preview_bounds.CenterPoint() + delta);
EXPECT_TRUE(resize_button->GetVisible());
}
TEST_P(CaptureModeCameraPreviewTest, CameraPreviewDeintersectsWithSystemTray) {
UpdateDisplay("1366x768");
ui::test::EventGenerator* event_generator = GetEventGenerator();
auto* system_tray = GetPrimaryUnifiedSystemTray();
event_generator->MoveMouseTo(system_tray->GetBoundsInScreen().CenterPoint());
event_generator->ClickLeftButton();
EXPECT_TRUE(system_tray->IsBubbleShown());
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_TRUE(system_tray->IsBubbleShown());
EXPECT_FALSE(system_tray->GetBubbleBoundsInScreen().Intersects(
preview_widget->GetWindowBoundsInScreen()));
EXPECT_NE(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
}
TEST_P(CaptureModeCameraPreviewTest,
CameraPreviewDeintersectsWithSystemTrayWhileVideoRecordingInProgress) {
UpdateDisplay("1366x768");
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
const gfx::Point capture_bounds_center_point =
GetCaptureBoundsInScreen().CenterPoint();
StartVideoRecordingImmediately();
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
ui::test::EventGenerator* event_generator = GetEventGenerator();
auto* system_tray = GetPrimaryUnifiedSystemTray();
event_generator->MoveMouseTo(system_tray->GetBoundsInScreen().CenterPoint());
event_generator->ClickLeftButton();
EXPECT_TRUE(system_tray->IsBubbleShown());
EXPECT_NE(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
EXPECT_FALSE(system_tray->GetBubbleBoundsInScreen().Intersects(
preview_widget->GetWindowBoundsInScreen()));
const gfx::Vector2d delta(20, 20);
DragPreviewToPoint(preview_widget, capture_bounds_center_point + delta);
if (system_tray->IsBubbleShown()) {
EXPECT_NE(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
EXPECT_FALSE(system_tray->GetBubbleBoundsInScreen().Intersects(
preview_widget->GetWindowBoundsInScreen()));
} else {
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
}
}
TEST_P(CaptureModeCameraPreviewTest, CameraPreviewDeintersectsWithPipWindow) {
std::unique_ptr<aura::Window> pip_window(
CreateTestWindow(gfx::Rect(700, 450, 104, 100)));
ConvertToPipWindow(pip_window.get());
const gfx::Rect origin_pip_window_bounds = pip_window->GetBoundsInScreen();
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
const gfx::Rect current_pip_window_bounds = pip_window->GetBoundsInScreen();
EXPECT_NE(origin_pip_window_bounds, current_pip_window_bounds);
EXPECT_FALSE(current_pip_window_bounds.Intersects(
preview_widget->GetWindowBoundsInScreen()));
}
TEST_P(CaptureModeCameraPreviewTest,
CameraPreviewDeintersectsWithPipWindowDuringRecording) {
std::unique_ptr<aura::Window> pip_window(
CreateTestWindow(gfx::Rect(0, 0, 104, 100)));
ConvertToPipWindow(pip_window.get());
const gfx::Rect origin_pip_window_bounds = pip_window->GetBoundsInScreen();
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
const gfx::Point capture_bounds_center_point =
GetCaptureBoundsInScreen().CenterPoint();
EXPECT_TRUE(preview_widget);
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
EXPECT_EQ(origin_pip_window_bounds, pip_window->GetBoundsInScreen());
StartVideoRecordingImmediately();
const gfx::Vector2d delta(-20, -20);
DragPreviewToPoint(preview_widget, capture_bounds_center_point + delta);
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kTopLeft);
EXPECT_NE(origin_pip_window_bounds, pip_window->GetBoundsInScreen());
EXPECT_FALSE(preview_widget->GetWindowBoundsInScreen().Intersects(
pip_window->GetBoundsInScreen()));
}
TEST_P(CaptureModeCameraPreviewTest,
CameraPreviewDeintersectsWithAutoclickBar) {
UpdateDisplay("1366x768");
views::Widget* autoclick_bubble_widget = EnableAndGetAutoClickBubbleWidget();
EXPECT_TRUE(autoclick_bubble_widget->IsVisible());
const gfx::Rect origin_autoclick_bar_bounds =
autoclick_bubble_widget->GetWindowBoundsInScreen();
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
const gfx::Rect current_autoclick_bar_bounds =
autoclick_bubble_widget->GetWindowBoundsInScreen();
EXPECT_NE(origin_autoclick_bar_bounds, current_autoclick_bar_bounds);
EXPECT_FALSE(current_autoclick_bar_bounds.Intersects(
preview_widget->GetWindowBoundsInScreen()));
}
TEST_P(CaptureModeCameraPreviewTest,
CameraPreviewDeintersectsWithSystemTrayOnSizeChanged) {
UpdateDisplay("1366x950");
StartCaptureSessionWithParam();
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_TRUE(preview_widget);
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
auto* resize_button = GetPreviewResizeButton();
auto* event_generator = GetEventGenerator();
ClickOnView(resize_button, event_generator);
EXPECT_TRUE(camera_controller->is_camera_preview_collapsed());
StartVideoRecordingImmediately();
auto* system_tray = GetPrimaryUnifiedSystemTray();
event_generator->MoveMouseTo(system_tray->GetBoundsInScreen().CenterPoint());
event_generator->ClickLeftButton();
EXPECT_TRUE(system_tray->IsBubbleShown());
EXPECT_TRUE(system_tray->IsBubbleShown());
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kTopRight);
EXPECT_FALSE(preview_widget->GetWindowBoundsInScreen().Intersects(
system_tray->GetBoundsInScreen()));
ClickOnView(resize_button, event_generator);
EXPECT_FALSE(preview_widget->GetWindowBoundsInScreen().Intersects(
system_tray->GetBoundsInScreen()));
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kTopRight);
}
TEST_P(CaptureModeCameraPreviewTest, CameraPreviewSpecs) {
AddDefaultCamera();
CaptureModeTestApi().SelectCameraAtIndex(0);
auto* camera_controller = GetCameraController();
struct {
CameraPreviewState preview_state;
std::string scope_trace;
} kTestCases[] = {
{CameraPreviewState::kCollapsible, "Collapsible Preview"},
{CameraPreviewState::kNotCollapsible, "Not Collapsible Preview"},
{CameraPreviewState::kHidden, "Hidden Preview"},
};
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(test_case.scope_trace);
UpdateDisplay("1366x700");
StartCaptureSessionWithParam();
auto* camera_preview_widget = camera_controller->camera_preview_widget();
auto* camera_preview_view = camera_controller->camera_preview_view();
EXPECT_TRUE(camera_preview_widget);
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_TRUE(camera_preview_view->is_collapsible());
ResizeSurfaceSoCameraPreviewBecomes(test_case.preview_state);
const auto preview_screen_bounds =
camera_preview_widget->GetWindowBoundsInScreen();
switch (test_case.preview_state) {
case CameraPreviewState::kCollapsible:
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_TRUE(camera_preview_view->is_collapsible());
EXPECT_EQ(preview_screen_bounds.size(),
GetExpectedPreviewSize(false));
break;
case CameraPreviewState::kNotCollapsible:
EXPECT_TRUE(camera_preview_widget->IsVisible());
EXPECT_FALSE(camera_preview_view->is_collapsible());
EXPECT_EQ(preview_screen_bounds.size(),
GetExpectedPreviewSize(false));
break;
case CameraPreviewState::kHidden:
EXPECT_FALSE(camera_preview_widget->IsVisible());
EXPECT_FALSE(camera_preview_view->is_collapsible());
break;
}
}
}
TEST_P(CaptureModeCameraPreviewTest,
ResizeButtonSwitchAccessVisibilityTestOnMouseEvent) {
UpdateDisplay("1366x768");
CaptureModeCameraController* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
for (const bool switch_access_enabled : {false, true}) {
AccessibilityController* a11y_controller =
Shell::Get()->accessibility_controller();
a11y_controller->switch_access().SetEnabled(switch_access_enabled);
EXPECT_EQ(switch_access_enabled, a11y_controller->IsSwitchAccessRunning());
StartCaptureSessionWithParam();
views::Widget* preview_widget = camera_controller->camera_preview_widget();
DCHECK(preview_widget);
gfx::Rect preview_bounds = preview_widget->GetWindowBoundsInScreen();
CameraPreviewResizeButton* resize_button = GetPreviewResizeButton();
EXPECT_EQ(resize_button->GetVisible(),
switch_access_enabled ? true : false);
event_generator->MoveMouseTo(preview_bounds.CenterPoint());
EXPECT_TRUE(resize_button->GetVisible());
auto outside_point = preview_bounds.origin();
outside_point.Offset(-1, -1);
event_generator->MoveMouseTo(outside_point);
base::OneShotTimer* timer = camera_controller->camera_preview_view()
->resize_button_hide_timer_for_test();
timer->FireNow();
EXPECT_EQ(resize_button->GetVisible(),
switch_access_enabled ? true : false);
event_generator->MoveMouseTo(preview_bounds.CenterPoint());
EXPECT_TRUE(resize_button->GetVisible());
event_generator->PressLeftButton();
EXPECT_FALSE(resize_button->GetVisible());
event_generator->MoveMouseBy(-100, -100);
EXPECT_FALSE(resize_button->GetVisible());
event_generator->ReleaseLeftButton();
EXPECT_EQ(resize_button->GetVisible(),
switch_access_enabled ? true : false);
CaptureModeController::Get()->Stop();
}
}
TEST_P(CaptureModeCameraPreviewTest,
ResizeButtonSwitchAccessVisibilityTestOnTapEvent) {
UpdateDisplay("1366x768");
SwitchToTabletMode();
EXPECT_TRUE(display::Screen::Get()->InTabletMode());
CaptureModeCameraController* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* event_generator = GetEventGenerator();
for (const bool switch_access_enabled : {false, true}) {
AccessibilityController* a11y_controller =
Shell::Get()->accessibility_controller();
a11y_controller->switch_access().SetEnabled(switch_access_enabled);
EXPECT_EQ(switch_access_enabled, a11y_controller->IsSwitchAccessRunning());
StartCaptureSessionWithParam();
views::Widget* preview_widget = camera_controller->camera_preview_widget();
DCHECK(preview_widget);
gfx::Rect preview_bounds = preview_widget->GetWindowBoundsInScreen();
CameraPreviewResizeButton* resize_button = GetPreviewResizeButton();
EXPECT_EQ(resize_button->GetVisible(),
switch_access_enabled ? true : false);
event_generator->GestureTapAt(preview_bounds.CenterPoint());
EXPECT_TRUE(resize_button->GetVisible());
base::OneShotTimer* timer = camera_controller->camera_preview_view()
->resize_button_hide_timer_for_test();
if (timer->IsRunning())
timer->FireNow();
EXPECT_EQ(resize_button->GetVisible(),
switch_access_enabled ? true : false);
CaptureModeController::Get()->Stop();
}
}
INSTANTIATE_TEST_SUITE_P(All,
CaptureModeCameraPreviewTest,
testing::Values(CaptureModeSource::kFullscreen,
CaptureModeSource::kRegion,
CaptureModeSource::kWindow));
class CameraPreviewWithNotificationTest : public CaptureModeCameraTest {
public:
CameraPreviewWithNotificationTest() = default;
CameraPreviewWithNotificationTest(const CameraPreviewWithNotificationTest&) =
delete;
CameraPreviewWithNotificationTest& operator=(
const CameraPreviewWithNotificationTest&) = delete;
~CameraPreviewWithNotificationTest() override = default;
void SetUp() override {
CaptureModeCameraTest::SetUp();
auto test_api = std::make_unique<NotificationCenterTestApi>();
test_api->AddNotification();
ASSERT_TRUE(test_api->IsTrayShown());
}
};
TEST_F(CameraPreviewWithNotificationTest,
AvoidCollisionWithNotificationBubbleShownFirst) {
NotificationCenterTray* notification_center_tray =
GetPrimaryNotificationCenterTray();
LeftClickOn(notification_center_tray);
EXPECT_TRUE(notification_center_tray->IsBubbleShown());
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
EXPECT_TRUE(notification_center_tray->IsBubbleShown());
auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_FALSE(
notification_center_tray->GetBubbleView()->GetBoundsInScreen().Intersects(
preview_widget->GetWindowBoundsInScreen()));
EXPECT_NE(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
}
TEST_F(CameraPreviewWithNotificationTest,
AvoidCollisionWithCameraPreviewShownFirst) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
StartVideoRecordingImmediately();
NotificationCenterTray* notification_center_tray =
GetPrimaryNotificationCenterTray();
EXPECT_FALSE(notification_center_tray->IsBubbleShown());
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
LeftClickOn(notification_center_tray);
EXPECT_TRUE(notification_center_tray->IsBubbleShown());
auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_FALSE(
notification_center_tray->GetBubbleView()->GetBoundsInScreen().Intersects(
preview_widget->GetWindowBoundsInScreen()));
EXPECT_NE(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
}
class CameraPreviewWithHoldingSpaceTest : public CaptureModeCameraTest {
public:
CameraPreviewWithHoldingSpaceTest() { set_start_session(false); }
CameraPreviewWithHoldingSpaceTest(const CameraPreviewWithHoldingSpaceTest&) =
delete;
CameraPreviewWithHoldingSpaceTest& operator=(
const CameraPreviewWithHoldingSpaceTest&) = delete;
~CameraPreviewWithHoldingSpaceTest() override = default;
HoldingSpaceModel* model() { return &model_; }
testing::NiceMock<MockHoldingSpaceClient>* client() {
return &holding_space_client_;
}
HoldingSpaceTestApi* holding_space_test_api() {
return holding_space_test_api_.get();
}
void SetUp() override {
CaptureModeCameraTest::SetUp();
holding_space_test_api_ = std::make_unique<HoldingSpaceTestApi>();
AccountId user_account = AccountId::FromUserEmail(kTestUser);
HoldingSpaceController::Get()->RegisterClientAndModelForUser(
user_account, client(), model());
auto pref_service = TestPrefServiceProvider::CreateUserPrefServiceSimple();
holding_space_prefs::MarkTimeOfFirstAvailability(pref_service.get());
holding_space_prefs::MarkTimeOfFirstAdd(pref_service.get());
SimulateUserLogin({}, user_account, std::move(pref_service));
}
void TearDown() override {
holding_space_test_api_.reset();
CaptureModeCameraTest::TearDown();
}
private:
std::unique_ptr<HoldingSpaceTestApi> holding_space_test_api_;
testing::NiceMock<MockHoldingSpaceClient> holding_space_client_;
HoldingSpaceModel model_;
};
TEST_F(CameraPreviewWithHoldingSpaceTest,
AvoidCollisionWithHoldingSpaceBubbleShownFirst) {
EXPECT_TRUE(holding_space_test_api()->IsShowingInShelf());
holding_space_test_api()->Show();
EXPECT_TRUE(holding_space_test_api()->IsShowing());
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
EXPECT_TRUE(holding_space_test_api()->IsShowing());
auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_FALSE(
holding_space_test_api()->GetBubble()->GetBoundsInScreen().Intersects(
preview_widget->GetWindowBoundsInScreen()));
EXPECT_NE(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
}
TEST_F(CameraPreviewWithHoldingSpaceTest,
AvoidCollisionWithCameraPreviewShownFirst) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
AddDefaultCamera();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
StartVideoRecordingImmediately();
EXPECT_TRUE(holding_space_test_api()->IsShowingInShelf());
EXPECT_FALSE(holding_space_test_api()->IsShowing());
EXPECT_EQ(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
holding_space_test_api()->Show();
EXPECT_TRUE(holding_space_test_api()->IsShowing());
auto* preview_widget = camera_controller->camera_preview_widget();
EXPECT_FALSE(
holding_space_test_api()->GetBubble()->GetBoundsInScreen().Intersects(
preview_widget->GetWindowBoundsInScreen()));
EXPECT_NE(camera_controller->camera_preview_snap_position(),
CameraPreviewSnapPosition::kBottomRight);
}
class ProjectorCaptureModeCameraTest : public CaptureModeCameraTest {
public:
ProjectorCaptureModeCameraTest() = default;
~ProjectorCaptureModeCameraTest() override = default;
void SetUp() override {
CaptureModeCameraTest::SetUp();
projector_helper_.SetUp();
}
void StartProjectorModeSession() {
projector_helper_.StartProjectorModeSession();
}
private:
ProjectorCaptureModeIntegrationHelper projector_helper_;
};
TEST_F(ProjectorCaptureModeCameraTest, NoAvailableCameras) {
auto* camera_controller = GetCameraController();
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
StartProjectorModeSession();
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
EXPECT_FALSE(camera_controller->camera_preview_widget());
}
TEST_F(ProjectorCaptureModeCameraTest, FirstCamSelectedByDefault) {
AddDefaultCamera();
auto* camera_controller = GetCameraController();
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
StartProjectorModeSession();
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
EXPECT_TRUE(camera_controller->camera_preview_widget());
}
TEST_F(ProjectorCaptureModeCameraTest,
DefaultCaptureSessionWhileProjectorRecording) {
AddDefaultCamera();
StartProjectorModeSession();
auto* camera_controller = GetCameraController();
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
EXPECT_TRUE(camera_controller->camera_preview_widget());
CaptureModeTestApi test_api;
test_api.PerformCapture();
WaitForRecordingToStart();
auto* controller = CaptureModeController::Get();
EXPECT_TRUE(controller->is_recording_in_progress());
EXPECT_TRUE(camera_controller->camera_preview_widget());
test_api.StartForFullscreen(false);
controller->Stop();
EXPECT_TRUE(controller->is_recording_in_progress());
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
EXPECT_TRUE(camera_controller->camera_preview_widget());
}
TEST_F(ProjectorCaptureModeCameraTest,
SessionStartsWithAnAlreadySelectedCamera) {
const std::string model_id_1 = "model1";
const std::string model_id_2 = "model2";
AddFakeCamera("/dev/video0", "fake cam 1", model_id_1);
AddFakeCamera("/dev/video1", "fake cam 2", model_id_2);
auto* camera_controller = GetCameraController();
CameraId cam_id_1(model_id_1, 1);
CameraId cam_id_2(model_id_2, 1);
EXPECT_EQ(cam_id_1, camera_controller->available_cameras()[0].camera_id);
EXPECT_EQ(cam_id_2, camera_controller->available_cameras()[1].camera_id);
camera_controller->SetSelectedCamera(cam_id_2);
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
StartProjectorModeSession();
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
EXPECT_EQ(cam_id_2, camera_controller->selected_camera());
EXPECT_TRUE(camera_controller->camera_preview_widget());
CaptureModeController::Get()->Stop();
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
EXPECT_EQ(cam_id_2, camera_controller->selected_camera());
EXPECT_TRUE(camera_controller->camera_preview_widget());
}
TEST_F(ProjectorCaptureModeCameraTest,
ProjectorRecordingStartsWithCameraHistogramTest) {
base::HistogramTester histogram_tester;
constexpr char kHistogramNameBase[] = "RecordingStartsWithCamera";
AddDefaultCamera();
struct {
bool tablet_enabled;
bool camera_on;
} kTestCases[] = {
{false, false},
{false, true},
{true, false},
{true, true},
};
for (const auto test_case : kTestCases) {
if (test_case.tablet_enabled) {
SwitchToTabletMode();
EXPECT_TRUE(display::Screen::Get()->InTabletMode());
} else {
EXPECT_FALSE(display::Screen::Get()->InTabletMode());
}
const std::string histogram_name = BuildHistogramName(
kHistogramNameBase,
CaptureModeTestApi().GetBehavior(BehaviorType::kProjector),
true);
histogram_tester.ExpectBucketCount(histogram_name, test_case.camera_on, 0);
auto* controller = CaptureModeController::Get();
controller->SetType(CaptureModeType::kVideo);
controller->SetSource(CaptureModeSource::kFullscreen);
StartProjectorModeSession();
EXPECT_TRUE(controller->IsActive());
auto* session = controller->capture_mode_session();
ASSERT_TRUE(session);
GetCameraController()->SetSelectedCamera(
test_case.camera_on ? CameraId(kDefaultCameraModelId, 1) : CameraId());
StartVideoRecordingImmediately();
EXPECT_TRUE(controller->is_recording_in_progress());
WaitForSeconds(1);
controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
WaitForCaptureFileToBeSaved();
histogram_tester.ExpectBucketCount(histogram_name, test_case.camera_on, 1);
}
}
TEST_F(ProjectorCaptureModeCameraTest,
DoNotRememberProjectorCameraSelectionBeforeVideoRecording) {
AddDefaultCamera();
auto* controller = CaptureModeController::Get();
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
controller->Stop();
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
StartProjectorModeSession();
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
controller->Stop();
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
}
TEST_F(ProjectorCaptureModeCameraTest,
DoNotRememberProjectorCameraSelectionAfterVideoRecording) {
AddDefaultCamera();
auto* controller = CaptureModeController::Get();
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
controller->Stop();
StartProjectorModeSession();
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
StartVideoRecordingImmediately();
controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
WaitForCaptureFileToBeSaved();
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
EXPECT_FALSE(camera_controller->selected_camera().is_valid());
}
class CaptureModeCameraFramesTest : public CaptureModeCameraTest,
public testing::WithParamInterface<bool> {
public:
CaptureModeCameraFramesTest() {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
::switches::kEnablePixelOutputInTests);
}
CaptureModeCameraFramesTest(const CaptureModeCameraFramesTest&) = delete;
CaptureModeCameraFramesTest& operator=(const CaptureModeCameraFramesTest&) =
delete;
~CaptureModeCameraFramesTest() override = default;
bool ShouldUseGpuMemoryBuffers() const { return GetParam(); }
void SetUp() override {
CaptureModeCameraTest::SetUp();
CaptureModeTestApi test_api;
test_api.SetForceUseGpuMemoryBufferForCameraFrames(
ShouldUseGpuMemoryBuffers());
AddDefaultCamera();
ASSERT_EQ(1u, test_api.GetNumberOfAvailableCameras());
test_api.SelectCameraAtIndex(0);
const CameraId camera_id(kDefaultCameraModelId, 1);
EXPECT_EQ(camera_id, GetCameraController()->selected_camera());
}
void TearDown() override {
CaptureModeTestApi().SetForceUseGpuMemoryBufferForCameraFrames(false);
CaptureModeCameraTest::TearDown();
}
};
namespace {
void WaitForAndVerifyRenderedVideoFrame() {
auto context_provider =
base::MakeRefCounted<viz::TestInProcessContextProvider>(
viz::TestContextType::kGpuRaster, false);
auto result = context_provider->BindToCurrentSequence();
CHECK_EQ(result, gpu::ContextResult::kSuccess);
for (size_t i = 0; i < 3 * FakeCameraDevice::kMaxBufferCount; ++i) {
base::RunLoop loop;
CaptureModeTestApi().SetOnCameraVideoFrameRendered(
base::BindLambdaForTesting([&loop, &context_provider](
scoped_refptr<media::VideoFrame> frame) {
ASSERT_TRUE(frame);
const gfx::Size frame_size = frame->visible_rect().size();
const auto produced_frame_bitmap =
FakeCameraDevice::GetProducedFrameAsBitmap(frame_size);
media::PaintCanvasVideoRenderer renderer;
SkBitmap received_frame_bitmap;
received_frame_bitmap.allocN32Pixels(frame_size.width(),
frame_size.height());
cc::SkiaPaintCanvas canvas(received_frame_bitmap);
renderer.Copy(frame, &canvas, context_provider.get());
EXPECT_TRUE(gfx::test::AreBitmapsEqual(produced_frame_bitmap,
received_frame_bitmap));
loop.Quit();
}));
loop.Run();
}
}
}
TEST_P(CaptureModeCameraFramesTest, VerifyFrames) {
CaptureModeTestApi().StartForFullscreen(true);
EXPECT_TRUE(GetCameraController()->camera_preview_widget());
WaitForAndVerifyRenderedVideoFrame();
}
TEST_P(CaptureModeCameraFramesTest, TurnOffCameraWhileRendering) {
CaptureModeTestApi test_api;
test_api.StartForFullscreen(true);
auto* camera_controller = GetCameraController();
EXPECT_TRUE(camera_controller->camera_preview_widget());
WaitForAndVerifyRenderedVideoFrame();
test_api.TurnCameraOff();
EXPECT_FALSE(camera_controller->camera_preview_widget());
}
TEST_P(CaptureModeCameraFramesTest, DisconnectCameraWhileRendering) {
CaptureModeTestApi test_api;
test_api.StartForFullscreen(true);
auto* camera_controller = GetCameraController();
EXPECT_TRUE(camera_controller->camera_preview_widget());
WaitForAndVerifyRenderedVideoFrame();
RemoveDefaultCamera();
EXPECT_FALSE(camera_controller->camera_preview_widget());
}
TEST_P(CaptureModeCameraFramesTest, SelectAnotherCameraWhileRendering) {
CaptureModeTestApi test_api;
test_api.StartForFullscreen(true);
auto* camera_controller = GetCameraController();
EXPECT_TRUE(camera_controller->camera_preview_widget());
auto* preview_view = camera_controller->camera_preview_view();
ASSERT_TRUE(preview_view);
EXPECT_EQ(preview_view->camera_id(), camera_controller->selected_camera());
WaitForAndVerifyRenderedVideoFrame();
const std::string device_id = "/dev/video0";
const std::string display_name = "Integrated Webcam";
const std::string model_id = "0123:4567";
AddFakeCamera(device_id, display_name, model_id);
EXPECT_EQ(preview_view, camera_controller->camera_preview_view());
const CameraId second_camera_id(model_id, 1);
camera_controller->SetSelectedCamera(second_camera_id);
EXPECT_TRUE(camera_controller->camera_preview_widget());
EXPECT_NE(preview_view, camera_controller->camera_preview_view());
preview_view = camera_controller->camera_preview_view();
EXPECT_EQ(preview_view->camera_id(), second_camera_id);
WaitForAndVerifyRenderedVideoFrame();
}
TEST_P(CaptureModeCameraFramesTest, CameraFatalErrors) {
CaptureModeTestApi().StartForFullscreen(true);
auto* camera_controller = GetCameraController();
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
EXPECT_TRUE(camera_controller->camera_preview_widget());
WaitForAndVerifyRenderedVideoFrame();
auto* video_source_provider = GetTestDelegate()->video_source_provider();
video_source_provider->TriggerFatalErrorOnCamera(kDefaultCameraDeviceId);
CameraDevicesChangeWaiter().Wait();
EXPECT_FALSE(camera_controller->camera_preview_widget());
EXPECT_TRUE(camera_controller->selected_camera().is_valid());
CameraDevicesChangeWaiter().Wait();
EXPECT_TRUE(camera_controller->camera_preview_widget());
WaitForAndVerifyRenderedVideoFrame();
}
INSTANTIATE_TEST_SUITE_P(All, CaptureModeCameraFramesTest, testing::Bool());
using NoSessionCaptureModeCameraTest = NoSessionAshTestBase;
TEST_F(NoSessionCaptureModeCameraTest, RequestCameraInfoAfterUserLogsIn) {
auto* camera_controller = GetCameraController();
GetTestDelegate()->video_source_provider()->AddFakeCameraWithoutNotifying(
"/dev/video0", "Integrated Webcam", "0123:4567",
media::MEDIA_VIDEO_FACING_NONE);
EXPECT_TRUE(camera_controller->available_cameras().empty());
{
base::RunLoop loop;
camera_controller->SetOnCameraListReceivedForTesting(loop.QuitClosure());
SimulateUserLogin({"example@gmail.com"});
loop.Run();
}
EXPECT_EQ(camera_controller->available_cameras().size(), 1u);
}
TEST_F(CaptureModeCameraTest, CameraPrivacyIndicators) {
gfx::ScopedAnimationDurationScaleMode animation_scale(
gfx::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
auto* message_center = message_center::MessageCenter::Get();
auto capture_mode_privacy_notification_id =
GetPrivacyIndicatorsNotificationId(kCaptureModePrivacyIndicatorId);
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
EXPECT_FALSE(camera_controller->camera_preview_widget());
EXPECT_FALSE(IsCameraIndicatorIconVisible());
EXPECT_FALSE(IsMicrophoneIndicatorIconVisible());
EXPECT_FALSE(message_center->FindNotificationById(
capture_mode_privacy_notification_id));
AddDefaultCamera();
EXPECT_TRUE(camera_controller->camera_preview_widget());
EXPECT_TRUE(IsCameraIndicatorIconVisible());
EXPECT_FALSE(IsMicrophoneIndicatorIconVisible());
EXPECT_TRUE(message_center->FindNotificationById(
capture_mode_privacy_notification_id));
RemoveDefaultCamera();
EXPECT_FALSE(camera_controller->camera_preview_widget());
base::RunLoop().RunUntilIdle();
task_environment()->FastForwardBy(
PrivacyIndicatorsController::kPrivacyIndicatorsMinimumHoldDuration);
EXPECT_FALSE(IsCameraIndicatorIconVisible());
EXPECT_FALSE(IsMicrophoneIndicatorIconVisible());
EXPECT_FALSE(message_center->FindNotificationById(
capture_mode_privacy_notification_id));
AddDefaultCamera();
EXPECT_TRUE(camera_controller->camera_preview_widget());
EXPECT_TRUE(IsCameraIndicatorIconVisible());
EXPECT_FALSE(IsMicrophoneIndicatorIconVisible());
EXPECT_TRUE(message_center->FindNotificationById(
capture_mode_privacy_notification_id));
}
TEST_F(CaptureModeCameraTest, DuringRecordingPrivacyIndicators) {
gfx::ScopedAnimationDurationScaleMode animation_scale(
gfx::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
auto* message_center = message_center::MessageCenter::Get();
auto capture_mode_privacy_notification_id =
GetPrivacyIndicatorsNotificationId(kCaptureModePrivacyIndicatorId);
auto* camera_controller = GetCameraController();
camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
AddDefaultCamera();
EXPECT_FALSE(camera_controller->camera_preview_widget());
EXPECT_FALSE(IsCameraIndicatorIconVisible());
EXPECT_FALSE(IsMicrophoneIndicatorIconVisible());
EXPECT_FALSE(message_center->FindNotificationById(
capture_mode_privacy_notification_id));
auto* capture_controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kVideo);
EXPECT_TRUE(camera_controller->camera_preview_widget());
EXPECT_TRUE(IsCameraIndicatorIconVisible());
EXPECT_FALSE(IsMicrophoneIndicatorIconVisible());
EXPECT_TRUE(message_center->FindNotificationById(
capture_mode_privacy_notification_id));
capture_controller->SetAudioRecordingMode(AudioRecordingMode::kMicrophone);
EXPECT_FALSE(IsMicrophoneIndicatorIconVisible());
StartRecordingFromSource(CaptureModeSource::kFullscreen);
EXPECT_TRUE(IsMicrophoneIndicatorIconVisible());
EXPECT_TRUE(message_center->FindNotificationById(
capture_mode_privacy_notification_id));
capture_controller->EndVideoRecording(
EndRecordingReason::kStopRecordingButton);
WaitForCaptureFileToBeSaved();
task_environment()->FastForwardBy(
PrivacyIndicatorsController::kPrivacyIndicatorsMinimumHoldDuration);
EXPECT_FALSE(IsCameraIndicatorIconVisible());
EXPECT_FALSE(IsMicrophoneIndicatorIconVisible());
EXPECT_FALSE(message_center->FindNotificationById(
capture_mode_privacy_notification_id));
}
TEST_F(CaptureModeCameraTest, CameraPreviewViewAccessibleProperties) {
StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kVideo);
AddDefaultCamera();
GetCameraController()->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1));
auto* camera_preview_view = GetCameraController()->camera_preview_view();
ui::AXNodeData data;
camera_preview_view->GetViewAccessibility().GetAccessibleNodeData(&data);
EXPECT_EQ(data.role, ax::mojom::Role::kVideo);
EXPECT_EQ(
data.GetString16Attribute(ax::mojom::StringAttribute::kName),
l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_CAMERA_PREVIEW_FOCUSED));
}
TEST_F(CaptureModeCameraTest, CaptureModeMenuHeaderAccessibleProperties) {
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
OpenSettingsView();
CaptureModeSettingsTestApi test_api;
AddDefaultCamera();
auto* menu_header = test_api.GetCameraMenuHeader();
ui::AXNodeData data;
menu_header->GetViewAccessibility().GetAccessibleNodeData(&data);
EXPECT_EQ(data.role, ax::mojom::Role::kHeader);
}
}