Commit 11251422 authored by Xiyuan Xia's avatar Xiyuan Xia Committed by Commit Bot

SPM: Fix flaky AppWindowInteractiveTest.TestFullscreen

The test expects the bounds is synchronously set when the app
window contents is ready to be committed. This is not always
the case under single process mash because the window bounds
does not change synchronously when toggling fullscreen like in
the classic mode. The CL presets window bounds when fullscreen
state changes so that the bounds change happens synchronously.

Bug: 926007
Change-Id: If99e5946df1f9804c21202f075cbb1bf258f4bce
Reviewed-on: https://chromium-review.googlesource.com/c/1444431
Commit-Queue: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#629172}
parent e3a469e1
...@@ -235,6 +235,7 @@ source_set("unit_tests") { ...@@ -235,6 +235,7 @@ source_set("unit_tests") {
} }
source_set("test_support") { source_set("test_support") {
testonly = true
sources = [ sources = [
"immersive/immersive_fullscreen_controller_test_api.cc", "immersive/immersive_fullscreen_controller_test_api.cc",
"immersive/immersive_fullscreen_controller_test_api.h", "immersive/immersive_fullscreen_controller_test_api.h",
...@@ -247,6 +248,7 @@ source_set("test_support") { ...@@ -247,6 +248,7 @@ source_set("test_support") {
"//base", "//base",
"//services/service_manager/public/cpp", "//services/service_manager/public/cpp",
"//ui/aura", "//ui/aura",
"//ui/aura:test_support",
"//ui/gfx", "//ui/gfx",
"//ui/keyboard:mojom", "//ui/keyboard:mojom",
"//ui/views", "//ui/views",
......
...@@ -6,11 +6,44 @@ ...@@ -6,11 +6,44 @@
#include "ash/public/cpp/immersive/immersive_fullscreen_controller.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
#include "ash/public/cpp/immersive/immersive_fullscreen_controller_delegate.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller_delegate.h"
#include "base/run_loop.h"
#include "ui/aura/env.h" #include "ui/aura/env.h"
#include "ui/aura/event_injector.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
namespace {
// Update mouse location for |window|. For local window, update its aura::Env
// directly. For remote window, update aura::Env by injecting a mouse move
// event. EventInjector is used so that the Window Service side code under mash
// sees the updated mouse location as well.
void UpdateMouseLocation(aura::Window* window,
const gfx::Point& screen_location,
bool wait) {
if (window->env()->mode() == aura::Env::Mode::LOCAL) {
window->env()->SetLastMouseLocation(screen_location);
return;
}
ui::MouseEvent event(ui::ET_MOUSE_MOVED, screen_location, screen_location,
ui::EventTimeForNow(), ui::EF_NONE, 0);
if (!wait) {
aura::EventInjector().Inject(window->GetHost(), &event);
return;
}
// Ensure the mouse event goes through when |wait| is set.
aura::EventInjector event_injector;
base::RunLoop run_loop;
event_injector.Inject(window->GetHost(), &event, run_loop.QuitClosure());
run_loop.Run();
}
} // namespace
namespace ash { namespace ash {
ImmersiveFullscreenControllerTestApi::ImmersiveFullscreenControllerTestApi( ImmersiveFullscreenControllerTestApi::ImmersiveFullscreenControllerTestApi(
...@@ -20,7 +53,8 @@ ImmersiveFullscreenControllerTestApi::ImmersiveFullscreenControllerTestApi( ...@@ -20,7 +53,8 @@ ImmersiveFullscreenControllerTestApi::ImmersiveFullscreenControllerTestApi(
ImmersiveFullscreenControllerTestApi::~ImmersiveFullscreenControllerTestApi() = ImmersiveFullscreenControllerTestApi::~ImmersiveFullscreenControllerTestApi() =
default; default;
void ImmersiveFullscreenControllerTestApi::SetupForTest() { void ImmersiveFullscreenControllerTestApi::SetupForTest(
bool wait_for_mouse_event) {
immersive_fullscreen_controller_->animations_disabled_for_test_ = true; immersive_fullscreen_controller_->animations_disabled_for_test_ = true;
// Move the mouse off of the top-of-window views so that it does not keep the // Move the mouse off of the top-of-window views so that it does not keep the
...@@ -34,10 +68,9 @@ void ImmersiveFullscreenControllerTestApi::SetupForTest() { ...@@ -34,10 +68,9 @@ void ImmersiveFullscreenControllerTestApi::SetupForTest() {
bottommost_in_screen = bounds_in_screen[i].bottom(); bottommost_in_screen = bounds_in_screen[i].bottom();
} }
gfx::Point cursor_pos(0, bottommost_in_screen + 10); gfx::Point cursor_pos(0, bottommost_in_screen + 10);
immersive_fullscreen_controller_->widget() UpdateMouseLocation(
->GetNativeView() immersive_fullscreen_controller_->widget()->GetNativeView(), cursor_pos,
->env() wait_for_mouse_event);
->SetLastMouseLocation(cursor_pos);
immersive_fullscreen_controller_->UpdateLocatedEventRevealedLock(); immersive_fullscreen_controller_->UpdateLocatedEventRevealedLock();
} }
......
...@@ -30,8 +30,11 @@ class ImmersiveFullscreenControllerTestApi { ...@@ -30,8 +30,11 @@ class ImmersiveFullscreenControllerTestApi {
}; };
// Disables animations and moves the mouse so that it is not over the // Disables animations and moves the mouse so that it is not over the
// top-of-window views for the sake of testing. // top-of-window views for the sake of testing. |wait_for_mouse_move| should
void SetupForTest(); // normally be true to wait for the generated mouse events to go through under
// mash. It is provided for tests that call SetupForTest under the scope of
// TestMockTimeTaskRunner::ScopedContext that does not allow RunLoop::Run().
void SetupForTest(bool wait_for_mouse_event = true);
bool IsTopEdgeHoverTimerRunning() const; bool IsTopEdgeHoverTimerRunning() const;
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "extensions/browser/app_window/native_app_window.h" #include "extensions/browser/app_window/native_app_window.h"
#include "extensions/test/extension_test_message_listener.h" #include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h" #include "extensions/test/result_catcher.h"
#include "ui/base/ui_base_features.h"
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
#include "base/mac/mac_util.h" #include "base/mac/mac_util.h"
...@@ -458,9 +457,6 @@ IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, TestCreateHidden) { ...@@ -458,9 +457,6 @@ IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, TestCreateHidden) {
#define MAYBE_TestFullscreen TestFullscreen #define MAYBE_TestFullscreen TestFullscreen
#endif #endif
IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, MAYBE_TestFullscreen) { IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, MAYBE_TestFullscreen) {
// Flaky on CrOS + IsUsingWindowService. https://crbug.com/926007
if (features::IsUsingWindowService())
return;
ASSERT_TRUE(RunAppWindowInteractiveTest("testFullscreen")) << message_; ASSERT_TRUE(RunAppWindowInteractiveTest("testFullscreen")) << message_;
} }
......
...@@ -82,7 +82,6 @@ ...@@ -82,7 +82,6 @@
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
#include "services/ws/public/mojom/window_tree_constants.mojom.h" #include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "ui/aura/client/aura_constants.h" #include "ui/aura/client/aura_constants.h"
#include "ui/aura/event_injector.h"
#include "ui/aura/test/env_test_helper.h" #include "ui/aura/test/env_test_helper.h"
#include "ui/aura/test/mus/change_completion_waiter.h" #include "ui/aura/test/mus/change_completion_waiter.h"
#include "ui/base/class_property.h" #include "ui/base/class_property.h"
...@@ -267,15 +266,6 @@ class ImmersiveModeTester : public ImmersiveModeController::Observer { ...@@ -267,15 +266,6 @@ class ImmersiveModeTester : public ImmersiveModeController::Observer {
DISALLOW_COPY_AND_ASSIGN(ImmersiveModeTester); DISALLOW_COPY_AND_ASSIGN(ImmersiveModeTester);
}; };
// Update mouse location of aura::Env by injecting a mouse move event.
// EventInjector is used so that the Window Service side code under mash sees
// the updated mouse location as well.
void UpdateMouseLocation(aura::Window* window, const gfx::Point& location) {
ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location,
ui::EventTimeForNow(), ui::EF_NONE, 0);
aura::EventInjector().Inject(window->GetHost(), &event);
}
} // namespace } // namespace
using views::Widget; using views::Widget;
...@@ -448,10 +438,6 @@ class ImmersiveModeBrowserViewTest ...@@ -448,10 +438,6 @@ class ImmersiveModeBrowserViewTest
void PreRunTestOnMainThread() override { void PreRunTestOnMainThread() override {
InProcessBrowserTest::PreRunTestOnMainThread(); InProcessBrowserTest::PreRunTestOnMainThread();
// Move mouse cursor beyond immersive UI to avoid affecting tests.
UpdateMouseLocation(browser()->window()->GetNativeWindow(),
gfx::Point(0, 100));
BrowserView::SetDisableRevealerDelayForTesting(true); BrowserView::SetDisableRevealerDelayForTesting(true);
ash::ImmersiveFullscreenControllerTestApi( ash::ImmersiveFullscreenControllerTestApi(
......
...@@ -63,11 +63,11 @@ class ImmersiveModeControllerAshHostedAppBrowserTest ...@@ -63,11 +63,11 @@ class ImmersiveModeControllerAshHostedAppBrowserTest
GURL GetAppUrl() { return https_server_.GetURL("/simple.html"); } GURL GetAppUrl() { return https_server_.GetURL("/simple.html"); }
void LaunchAppBrowser(bool await_url_load = true) { void LaunchAppBrowser(bool wait = true) {
ui_test_utils::UrlLoadObserver url_observer( ui_test_utils::UrlLoadObserver url_observer(
GetAppUrl(), content::NotificationService::AllSources()); GetAppUrl(), content::NotificationService::AllSources());
browser_ = ExtensionBrowserTest::LaunchAppBrowser(app_); browser_ = ExtensionBrowserTest::LaunchAppBrowser(app_);
if (await_url_load) { if (wait) {
// Wait for the URL to load so that the location bar end-state stabilizes. // Wait for the URL to load so that the location bar end-state stabilizes.
url_observer.Wait(); url_observer.Wait();
} }
...@@ -77,7 +77,7 @@ class ImmersiveModeControllerAshHostedAppBrowserTest ...@@ -77,7 +77,7 @@ class ImmersiveModeControllerAshHostedAppBrowserTest
// which triggers an animation. // which triggers an animation.
ash::ImmersiveFullscreenControllerTestApi( ash::ImmersiveFullscreenControllerTestApi(
static_cast<ImmersiveModeControllerAsh*>(controller_)->controller()) static_cast<ImmersiveModeControllerAsh*>(controller_)->controller())
.SetupForTest(); .SetupForTest(/*wait_for_mouse_event=*/wait);
browser_->window()->Show(); browser_->window()->Show();
} }
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
#include "ui/aura/event_injector.h" #include "ui/aura/event_injector.h"
#include <utility>
#include "base/bind.h"
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
#include "services/ws/public/mojom/constants.mojom.h" #include "services/ws/public/mojom/constants.mojom.h"
#include "ui/aura/env.h" #include "ui/aura/env.h"
...@@ -15,19 +18,41 @@ ...@@ -15,19 +18,41 @@
namespace aura { namespace aura {
namespace {
void RunCallback(base::OnceClosure callback, bool processed) {
if (!callback)
return;
std::move(callback).Run();
}
} // namespace
EventInjector::EventInjector() {} EventInjector::EventInjector() {}
EventInjector::~EventInjector() {} EventInjector::~EventInjector() {
// |event_injector_| should not be waiting for responses. Otherwise, the
// pending callback would not happen because the mojo channel is closed.
DCHECK(!has_pending_callback_ || !event_injector_.IsExpectingResponse());
}
ui::EventDispatchDetails EventInjector::Inject(WindowTreeHost* host, ui::EventDispatchDetails EventInjector::Inject(WindowTreeHost* host,
ui::Event* event) { ui::Event* event,
base::OnceClosure callback) {
DCHECK(host); DCHECK(host);
Env* env = host->window()->env(); Env* env = host->window()->env();
DCHECK(env); DCHECK(env);
DCHECK(event); DCHECK(event);
if (env->mode() == Env::Mode::LOCAL) if (env->mode() == Env::Mode::LOCAL) {
return host->event_sink()->OnEventFromSource(event); ui::EventDispatchDetails details =
host->event_sink()->OnEventFromSource(event);
RunCallback(std::move(callback), /*processed=*/true);
return details;
}
has_pending_callback_ |= !callback.is_null();
if (event->IsLocatedEvent()) { if (event->IsLocatedEvent()) {
// The ui-service expects events coming in to have a location matching the // The ui-service expects events coming in to have a location matching the
...@@ -42,8 +67,9 @@ ui::EventDispatchDetails EventInjector::Inject(WindowTreeHost* host, ...@@ -42,8 +67,9 @@ ui::EventDispatchDetails EventInjector::Inject(WindowTreeHost* host,
env->window_tree_client_->connector()->BindInterface( env->window_tree_client_->connector()->BindInterface(
ws::mojom::kServiceName, &event_injector_); ws::mojom::kServiceName, &event_injector_);
} }
event_injector_->InjectEventNoAck(host->GetDisplayId(), event_injector_->InjectEvent(
ui::Event::Clone(*event)); host->GetDisplayId(), ui::Event::Clone(*event),
base::BindOnce(&RunCallback, std::move(callback)));
return ui::EventDispatchDetails(); return ui::EventDispatchDetails();
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef UI_AURA_EVENT_INJECTOR_H_ #ifndef UI_AURA_EVENT_INJECTOR_H_
#define UI_AURA_EVENT_INJECTOR_H_ #define UI_AURA_EVENT_INJECTOR_H_
#include "base/callback.h"
#include "services/ws/public/mojom/event_injector.mojom.h" #include "services/ws/public/mojom/event_injector.mojom.h"
#include "ui/aura/aura_export.h" #include "ui/aura/aura_export.h"
...@@ -25,10 +26,18 @@ class AURA_EXPORT EventInjector { ...@@ -25,10 +26,18 @@ class AURA_EXPORT EventInjector {
EventInjector(); EventInjector();
~EventInjector(); ~EventInjector();
ui::EventDispatchDetails Inject(WindowTreeHost* host, ui::Event* event); // Inject |event| to |host|. |callback| is optional that gets invoked after
// the event is processed by |host|. In LOCAL mode, |callback| is invoked
// synchronously. In MUS mode, it is invoked after a response is received
// from window-server (via mojo).
ui::EventDispatchDetails Inject(
WindowTreeHost* host,
ui::Event* event,
base::OnceClosure callback = base::OnceClosure());
private: private:
ws::mojom::EventInjectorPtr event_injector_; ws::mojom::EventInjectorPtr event_injector_;
bool has_pending_callback_ = false;
DISALLOW_COPY_AND_ASSIGN(EventInjector); DISALLOW_COPY_AND_ASSIGN(EventInjector);
}; };
......
...@@ -848,7 +848,23 @@ void DesktopWindowTreeHostMus::SetFullscreen(bool fullscreen) { ...@@ -848,7 +848,23 @@ void DesktopWindowTreeHostMus::SetFullscreen(bool fullscreen) {
if (IsFullscreen() == fullscreen) if (IsFullscreen() == fullscreen)
return; // Nothing to do. return; // Nothing to do.
// Retrieve restore bounds before leaving fullscreen.
gfx::Rect restore_bounds;
if (!fullscreen)
restore_bounds = GetRestoredBounds();
// Change the fullscreen state.
wm::SetWindowFullscreen(window(), fullscreen); wm::SetWindowFullscreen(window(), fullscreen);
// Preset bounds with heuristic size to provide synchronous bounds change
// after the switch to/from fullscreen.
if (fullscreen) {
window()->SetProperty(aura::client::kRestoreBoundsKey,
new gfx::Rect(GetWindowBoundsInScreen()));
SetBoundsInDIP(GetDisplay().bounds());
} else {
SetBoundsInDIP(restore_bounds);
}
} }
bool DesktopWindowTreeHostMus::IsFullscreen() const { bool DesktopWindowTreeHostMus::IsFullscreen() const {
......
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
#include <memory> #include <memory>
#include <set> #include <set>
#include "base/scoped_observer.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/scoped_observer.h"
#include "ui/aura/mus/focus_synchronizer_observer.h" #include "ui/aura/mus/focus_synchronizer_observer.h"
#include "ui/aura/mus/window_tree_host_mus.h" #include "ui/aura/mus/window_tree_host_mus.h"
#include "ui/aura/window_observer.h" #include "ui/aura/window_observer.h"
#include "ui/views/mus/mus_client_observer.h" #include "ui/views/mus/mus_client_observer.h"
#include "ui/views/view_observer.h"
#include "ui/views/mus/mus_export.h" #include "ui/views/mus/mus_export.h"
#include "ui/views/view_observer.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
......
...@@ -430,6 +430,37 @@ TEST_F(DesktopWindowTreeHostMusTest, CreateFullscreenWidget) { ...@@ -430,6 +430,37 @@ TEST_F(DesktopWindowTreeHostMusTest, CreateFullscreenWidget) {
} }
} }
TEST_F(DesktopWindowTreeHostMusTest, SynchronousBoundsWhenTogglingFullscreen) {
const gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
const Widget::InitParams::Type kWidgetTypes[] = {
Widget::InitParams::TYPE_WINDOW,
Widget::InitParams::TYPE_WINDOW_FRAMELESS,
};
for (auto widget_type : kWidgetTypes) {
Widget widget;
Widget::InitParams params = CreateParams(widget_type);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget.Init(params);
const gfx::Rect restore_bounds = widget.GetWindowBoundsInScreen();
// Entering fullscreen synchronously set show state and bounds.
widget.SetFullscreen(true);
EXPECT_TRUE(widget.IsFullscreen())
<< "Enter fullscreen failed for type=" << widget_type;
EXPECT_EQ(display_bounds, widget.GetWindowBoundsInScreen());
// Leaving fullscreen synchronously set show state and bounds.
widget.SetFullscreen(false);
EXPECT_FALSE(widget.IsFullscreen())
<< "Leave fullscreen failed for type=" << widget_type;
EXPECT_EQ(restore_bounds, widget.GetWindowBoundsInScreen());
}
}
TEST_F(DesktopWindowTreeHostMusTest, ClientWindowHasContent) { TEST_F(DesktopWindowTreeHostMusTest, ClientWindowHasContent) {
// Opaque window has content. // Opaque window has content.
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment