From 34db55b6bafbff86b637397af5001fbe2913dc42 Mon Sep 17 00:00:00 2001 From: Ahmed Fakhry Date: Wed, 13 Oct 2021 00:08:18 +0000 Subject: [PATCH] capture_mode_settings: Parent the folder selection dialog correctly |SelectFileDialogExtension| used to favor parenting the dialog window to an existing browser window (if one was available) ignoring the provided |owning_window| to the SelectFile() API. This is not the desired behavior, since in capture mode, the owning window must be respected, otherwise, the window will be below the capture mode shield (in terms of z-order), making it dimmed and preventing it from receiving any events. BUG=1258842 TEST=Manually, added a browser test that fails without the fix. Change-Id: I1de270c86151847299c6173b1f631c89918f52f0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3218405 Reviewed-by: Alex Danilo Reviewed-by: James Cook Commit-Queue: Ahmed Fakhry Cr-Commit-Position: refs/heads/main@{#930865} --- ash/capture_mode/capture_mode_api.cc | 4 -- ash/capture_mode/capture_mode_session.h | 1 + ash/capture_mode/capture_mode_test_api.cc | 28 ++++++++++++ .../folder_selection_dialog_controller.cc | 13 +++--- .../folder_selection_dialog_controller.h | 6 +++ .../cpp/capture_mode/capture_mode_api.h | 3 -- .../cpp/capture_mode/capture_mode_test_api.h | 12 +++++ ash/public/cpp/shell_window_ids.h | 11 ++--- ash/wm/window_state.cc | 6 +-- .../capture_mode/capture_mode_browsertest.cc | 44 +++++++++++++++++++ .../ui/views/select_file_dialog_extension.cc | 23 +++++++--- 11 files changed, 122 insertions(+), 29 deletions(-) diff --git a/ash/capture_mode/capture_mode_api.cc b/ash/capture_mode/capture_mode_api.cc index 8a4f34f60eebe7..b16ba24a999d62 100644 --- a/ash/capture_mode/capture_mode_api.cc +++ b/ash/capture_mode/capture_mode_api.cc @@ -12,8 +12,4 @@ void CaptureScreenshotsOfAllDisplays() { CaptureModeController::Get()->CaptureScreenshotsOfAllDisplays(); } -bool IsCaptureModeSessionActive() { - return CaptureModeController::Get()->IsActive(); -} - } // namespace ash diff --git a/ash/capture_mode/capture_mode_session.h b/ash/capture_mode/capture_mode_session.h index 684c23768df71a..0044d0b85a4650 100644 --- a/ash/capture_mode/capture_mode_session.h +++ b/ash/capture_mode/capture_mode_session.h @@ -172,6 +172,7 @@ class ASH_EXPORT CaptureModeSession friend class CaptureModeAdvancedSettingsTestApi; friend class CaptureModeSessionFocusCycler; friend class CaptureModeSessionTestApi; + friend class CaptureModeTestApi; class CursorSetter; class ScopedA11yOverrideWindowSetter; diff --git a/ash/capture_mode/capture_mode_test_api.cc b/ash/capture_mode/capture_mode_test_api.cc index 0e36e77987f6c8..cffe594a976d29 100644 --- a/ash/capture_mode/capture_mode_test_api.cc +++ b/ash/capture_mode/capture_mode_test_api.cc @@ -6,10 +6,12 @@ #include "ash/capture_mode/capture_mode_controller.h" #include "ash/capture_mode/capture_mode_metrics.h" +#include "ash/capture_mode/capture_mode_session.h" #include "ash/capture_mode/capture_mode_types.h" #include "ash/capture_mode/video_recording_watcher.h" #include "base/auto_reset.h" #include "base/check.h" +#include "base/run_loop.h" namespace ash { @@ -92,6 +94,32 @@ CaptureModeTestApi::GetRecordingOverlayController() { .get(); } +void CaptureModeTestApi::SimulateOpeningFolderSelectionDialog() { + DCHECK(controller_->IsActive()); + auto* session = controller_->capture_mode_session(); + DCHECK(!session->capture_mode_settings_widget_); + session->SetSettingsMenuShown(true); + DCHECK(session->capture_mode_settings_widget_); + session->OpenFolderSelectionDialog(); + + // In browser tests, the dialog creation is asynchronous, so we'll need to + // wait for it. + if (GetFolderSelectionDialogWindow()) + return; + + base::RunLoop loop; + session->folder_selection_dialog_controller_ + ->on_dialog_window_added_callback_for_test_ = loop.QuitClosure(); + loop.Run(); +} + +aura::Window* CaptureModeTestApi::GetFolderSelectionDialogWindow() { + DCHECK(controller_->IsActive()); + auto* session = controller_->capture_mode_session(); + auto* dialog_controller = session->folder_selection_dialog_controller_.get(); + return dialog_controller ? dialog_controller->dialog_window() : nullptr; +} + void CaptureModeTestApi::SetType(bool for_video) { controller_->SetType(for_video ? CaptureModeType::kVideo : CaptureModeType::kImage); diff --git a/ash/capture_mode/folder_selection_dialog_controller.cc b/ash/capture_mode/folder_selection_dialog_controller.cc index 2a0271641be745..8c345207a848ed 100644 --- a/ash/capture_mode/folder_selection_dialog_controller.cc +++ b/ash/capture_mode/folder_selection_dialog_controller.cc @@ -59,13 +59,14 @@ FolderSelectionDialogController::FolderSelectionDialogController( DCHECK(root); DCHECK(root->IsRootWindow()); - window_observation_.Observe(wm::TransientWindowManager::GetOrCreate( - dialog_background_dimmer_.window())); + auto* owner = dialog_background_dimmer_.window(); + owner->SetId(kShellWindowId_CaptureModeFolderSelectionDialogOwner); + window_observation_.Observe(wm::TransientWindowManager::GetOrCreate(owner)); dialog_background_dimmer_.SetDimColor( AshColorProvider::Get()->GetShieldLayerColor( AshColorProvider::ShieldLayerType::kShield40)); - dialog_background_dimmer_.window()->Show(); + owner->Show(); select_folder_dialog_->SelectFile( ui::SelectFileDialog::SELECT_FOLDER, @@ -74,7 +75,7 @@ FolderSelectionDialogController::FolderSelectionDialogController( /*file_types=*/nullptr, /*file_type_index=*/0, /*default_extension=*/base::FilePath::StringType(), - /*owning_window=*/dialog_background_dimmer_.window(), + /*owning_window=*/owner, /*params=*/nullptr); } @@ -104,7 +105,6 @@ void FolderSelectionDialogController::OnTransientChildAdded( DCHECK(!dialog_window_); dialog_window_ = transient; - dialog_window_->SetId(kShellWindowId_CaptureModeFolderSelectionDialog); // The dialog should never resize, minimize or maximize. auto* widget = views::Widget::GetWidgetForNativeWindow(dialog_window_); @@ -114,6 +114,9 @@ void FolderSelectionDialogController::OnTransientChildAdded( widget_delegate->SetCanResize(false); widget_delegate->SetCanMinimize(false); widget_delegate->SetCanMaximize(false); + + if (on_dialog_window_added_callback_for_test_) + std::move(on_dialog_window_added_callback_for_test_).Run(); } void FolderSelectionDialogController::OnTransientChildRemoved( diff --git a/ash/capture_mode/folder_selection_dialog_controller.h b/ash/capture_mode/folder_selection_dialog_controller.h index 5b7bd836b2bc24..9aef3950240197 100644 --- a/ash/capture_mode/folder_selection_dialog_controller.h +++ b/ash/capture_mode/folder_selection_dialog_controller.h @@ -6,6 +6,7 @@ #define ASH_CAPTURE_MODE_FOLDER_SELECTION_DIALOG_CONTROLLER_H_ #include "ash/wm/window_dimmer.h" +#include "base/callback_forward.h" #include "base/files/file_path.h" #include "base/memory/scoped_refptr.h" #include "base/scoped_observation.h" @@ -67,6 +68,8 @@ class FolderSelectionDialogController : public ui::SelectFileDialog::Listener, aura::Window* transient) override; private: + friend class CaptureModeTestApi; + Delegate* const delegate_; // Dims everything behind the dialog (including the capture bar, the settings @@ -81,6 +84,9 @@ class FolderSelectionDialogController : public ui::SelectFileDialog::Listener, // |select_folder_dialog_| as a transient child of the dimming window. aura::Window* dialog_window_ = nullptr; + // An optional callback that will be invoked when |dialog_window_| gets added. + base::OnceClosure on_dialog_window_added_callback_for_test_; + // We observe the transient window manager of the dimming window to know when // the dialog window is added or removed. base::ScopedObservation