Commit a791670e authored by Tomasz Moniuszko's avatar Tomasz Moniuszko Committed by Commit Bot

Delete NativeWindowOcclusionTrackerWin instance between tests

Fixes crash in WebContentsViewAuraTest on Windows.

TEST=content_unittests.exe --gtest_filter=WebContentsViewAuraTest.*

Bug: 1014395
Change-Id: Ied84d4569ab20ac82da6d082dd1004fb08a43ef7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1862459
Commit-Queue: Tomasz Moniuszko <tmoniuszko@opera.com>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709925}
parent 3c5f5046
......@@ -90,6 +90,11 @@ void NativeWindowOcclusionTrackerWin::OnWindowDestroying(Window* window) {
Disable(window);
}
NativeWindowOcclusionTrackerWin**
NativeWindowOcclusionTrackerWin::GetInstanceForTesting() {
return &g_tracker;
}
NativeWindowOcclusionTrackerWin::NativeWindowOcclusionTrackerWin()
: // Use a COMSTATaskRunner so that registering and unregistering
// event hooks will happen on the same thread, as required by Windows,
......@@ -111,10 +116,10 @@ NativeWindowOcclusionTrackerWin::NativeWindowOcclusionTrackerWin()
}
NativeWindowOcclusionTrackerWin::~NativeWindowOcclusionTrackerWin() {
// This shouldn't be reached, because if it is, |occlusion_calculator_| will
// be deleted on the ui thread, which is problematic if there tasks scheduled
// on the background thread.
NOTREACHED();
// This shouldn't be reached in production code, because if it is,
// |occlusion_calculator_| will be deleted on the ui thread, which is
// problematic if there tasks scheduled on the background thread.
// Tests are allowed to delete the instance after running all pending tasks.
}
// static
......
......@@ -25,6 +25,11 @@
namespace aura {
// Required to declare a friend class.
namespace test {
class AuraTestHelper;
}
// This class keeps track of whether any HWNDs are occluding any app windows.
// It notifies the host of any app window whose occlusion state changes. Most
// code should not need to use this; it's an implementation detail.
......@@ -48,11 +53,15 @@ class AURA_EXPORT NativeWindowOcclusionTrackerWin : public WindowObserver {
private:
friend class NativeWindowOcclusionTrackerTest;
friend class test::AuraTestHelper;
// Returns a pointer to global instance.
static NativeWindowOcclusionTrackerWin** GetInstanceForTesting();
// This class computes the occlusion state of the tracked windows.
// It runs on a separate thread, and notifies the main thread of
// the occlusion state of the tracked windows.
class WindowOcclusionCalculator {
class AURA_EXPORT WindowOcclusionCalculator {
public:
WindowOcclusionCalculator(
scoped_refptr<base::SequencedTaskRunner> task_runner,
......@@ -67,6 +76,8 @@ class AURA_EXPORT NativeWindowOcclusionTrackerWin : public WindowObserver {
private:
friend class NativeWindowOcclusionTrackerTest;
friend class test::AuraTestHelper;
struct NativeWindowOcclusionState {
// The region of the native window that is not occluded by other windows.
SkRegion unoccluded_region;
......
......@@ -32,6 +32,13 @@
#include "ui/platform_window/common/platform_window_defaults.h" // nogncheck
#endif
#if defined(OS_WIN)
#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/bind_test_util.h"
#include "ui/aura/native_window_occlusion_tracker_win.h"
#endif
#if defined(USE_X11)
#include "ui/base/x/x11_util.h" // nogncheck
#endif
......@@ -155,6 +162,14 @@ void AuraTestHelper::TearDown() {
ui::test::EventGeneratorDelegate::SetFactoryFunction(
ui::test::EventGeneratorDelegate::FactoryFunction());
#if defined(OS_WIN)
// NativeWindowOcclusionTrackerWin is a global instance which creates its own
// task runner. Since ThreadPool is destroyed together with TaskEnvironment,
// NativeWindowOcclusionTrackerWin instance must be deleted as well and
// recreated on demand in other test.
DeleteNativeWindowOcclusionTrackerWin();
#endif
}
void AuraTestHelper::RunAllPendingInMessageLoop() {
......@@ -172,5 +187,32 @@ Env* AuraTestHelper::GetEnv() {
return env_ ? env_.get() : Env::HasInstance() ? Env::GetInstance() : nullptr;
}
#if defined(OS_WIN)
void AuraTestHelper::DeleteNativeWindowOcclusionTrackerWin() {
NativeWindowOcclusionTrackerWin** global_ptr =
NativeWindowOcclusionTrackerWin::GetInstanceForTesting();
if (NativeWindowOcclusionTrackerWin* tracker = *global_ptr) {
// WindowOcclusionCalculator must be deleted on its sequence. Wait until
// it's deleted and then delete the tracker.
base::WaitableEvent waitable_event;
DCHECK(
!tracker->update_occlusion_task_runner_->RunsTasksInCurrentSequence());
tracker->update_occlusion_task_runner_->PostTask(
FROM_HERE, base::BindLambdaForTesting([tracker, &waitable_event]() {
if (tracker->occlusion_calculator_) {
tracker->occlusion_calculator_->root_window_hwnds_occlusion_state_
.clear();
tracker->occlusion_calculator_->UnregisterEventHooks();
tracker->occlusion_calculator_.reset();
}
waitable_event.Signal();
}));
waitable_event.Wait();
delete tracker;
*global_ptr = nullptr;
}
}
#endif // defined(OS_WIN)
} // namespace test
} // namespace aura
......@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
#include "build/build_config.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
......@@ -69,6 +70,11 @@ class AuraTestHelper {
Env* GetEnv();
private:
#if defined(OS_WIN)
// Deletes existing NativeWindowOcclusionTrackerWin instance.
void DeleteNativeWindowOcclusionTrackerWin();
#endif // defined(OS_WIN)
bool setup_called_ = false;
bool teardown_called_ = false;
ui::ContextFactory* context_factory_to_restore_ = nullptr;
......
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