1 /*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/desktop_capture/win/window_capture_utils.h"
12
13 #include <winuser.h>
14
15 #include <algorithm>
16 #include <memory>
17 #include <mutex>
18
19 #include "modules/desktop_capture/desktop_capturer.h"
20 #include "modules/desktop_capture/win/test_support/test_window.h"
21 #include "rtc_base/task_queue_for_test.h"
22 #include "rtc_base/thread.h"
23 #include "test/gtest.h"
24
25 namespace webrtc {
26 namespace {
27
28 const char kWindowThreadName[] = "window_capture_utils_test_thread";
29 const WCHAR kWindowTitle[] = L"Window Capture Utils Test";
30
SetUpUnresponsiveWindow(std::mutex & mtx,WindowInfo & info)31 std::unique_ptr<rtc::Thread> SetUpUnresponsiveWindow(std::mutex& mtx,
32 WindowInfo& info) {
33 std::unique_ptr<rtc::Thread> window_thread;
34 window_thread = rtc::Thread::Create();
35 window_thread->SetName(kWindowThreadName, nullptr);
36 window_thread->Start();
37
38 SendTask(window_thread.get(), [&] { info = CreateTestWindow(kWindowTitle); });
39
40 // Intentionally create a deadlock to cause the window to become unresponsive.
41 mtx.lock();
42 window_thread->PostTask([&mtx]() {
43 mtx.lock();
44 mtx.unlock();
45 });
46
47 return window_thread;
48 }
49
50 } // namespace
51
TEST(WindowCaptureUtilsTest,GetWindowList)52 TEST(WindowCaptureUtilsTest, GetWindowList) {
53 WindowInfo info = CreateTestWindow(kWindowTitle);
54 DesktopCapturer::SourceList window_list;
55 ASSERT_TRUE(GetWindowList(GetWindowListFlags::kNone, &window_list));
56 EXPECT_GT(window_list.size(), 0ULL);
57 EXPECT_NE(std::find_if(window_list.begin(), window_list.end(),
58 [&info](DesktopCapturer::Source window) {
59 return reinterpret_cast<HWND>(window.id) ==
60 info.hwnd;
61 }),
62 window_list.end());
63 DestroyTestWindow(info);
64 }
65
TEST(WindowCaptureUtilsTest,IncludeUnresponsiveWindows)66 TEST(WindowCaptureUtilsTest, IncludeUnresponsiveWindows) {
67 std::mutex mtx;
68 WindowInfo info;
69 std::unique_ptr<rtc::Thread> window_thread =
70 SetUpUnresponsiveWindow(mtx, info);
71
72 EXPECT_FALSE(IsWindowResponding(info.hwnd));
73
74 DesktopCapturer::SourceList window_list;
75 ASSERT_TRUE(GetWindowList(GetWindowListFlags::kNone, &window_list));
76 EXPECT_GT(window_list.size(), 0ULL);
77 EXPECT_NE(std::find_if(window_list.begin(), window_list.end(),
78 [&info](DesktopCapturer::Source window) {
79 return reinterpret_cast<HWND>(window.id) ==
80 info.hwnd;
81 }),
82 window_list.end());
83
84 mtx.unlock();
85 SendTask(window_thread.get(), [&info]() { DestroyTestWindow(info); });
86 window_thread->Stop();
87 }
88
TEST(WindowCaptureUtilsTest,IgnoreUnresponsiveWindows)89 TEST(WindowCaptureUtilsTest, IgnoreUnresponsiveWindows) {
90 std::mutex mtx;
91 WindowInfo info;
92 std::unique_ptr<rtc::Thread> window_thread =
93 SetUpUnresponsiveWindow(mtx, info);
94
95 EXPECT_FALSE(IsWindowResponding(info.hwnd));
96
97 DesktopCapturer::SourceList window_list;
98 ASSERT_TRUE(
99 GetWindowList(GetWindowListFlags::kIgnoreUnresponsive, &window_list));
100 EXPECT_EQ(std::find_if(window_list.begin(), window_list.end(),
101 [&info](DesktopCapturer::Source window) {
102 return reinterpret_cast<HWND>(window.id) ==
103 info.hwnd;
104 }),
105 window_list.end());
106
107 mtx.unlock();
108 SendTask(window_thread.get(), [&info]() { DestroyTestWindow(info); });
109 window_thread->Stop();
110 }
111
TEST(WindowCaptureUtilsTest,IncludeUntitledWindows)112 TEST(WindowCaptureUtilsTest, IncludeUntitledWindows) {
113 WindowInfo info = CreateTestWindow(L"");
114 DesktopCapturer::SourceList window_list;
115 ASSERT_TRUE(GetWindowList(GetWindowListFlags::kNone, &window_list));
116 EXPECT_GT(window_list.size(), 0ULL);
117 EXPECT_NE(std::find_if(window_list.begin(), window_list.end(),
118 [&info](DesktopCapturer::Source window) {
119 return reinterpret_cast<HWND>(window.id) ==
120 info.hwnd;
121 }),
122 window_list.end());
123 DestroyTestWindow(info);
124 }
125
TEST(WindowCaptureUtilsTest,IgnoreUntitledWindows)126 TEST(WindowCaptureUtilsTest, IgnoreUntitledWindows) {
127 WindowInfo info = CreateTestWindow(L"");
128 DesktopCapturer::SourceList window_list;
129 ASSERT_TRUE(GetWindowList(GetWindowListFlags::kIgnoreUntitled, &window_list));
130 EXPECT_EQ(std::find_if(window_list.begin(), window_list.end(),
131 [&info](DesktopCapturer::Source window) {
132 return reinterpret_cast<HWND>(window.id) ==
133 info.hwnd;
134 }),
135 window_list.end());
136 DestroyTestWindow(info);
137 }
138
TEST(WindowCaptureUtilsTest,IgnoreCurrentProcessWindows)139 TEST(WindowCaptureUtilsTest, IgnoreCurrentProcessWindows) {
140 WindowInfo info = CreateTestWindow(kWindowTitle);
141 DesktopCapturer::SourceList window_list;
142 ASSERT_TRUE(GetWindowList(GetWindowListFlags::kIgnoreCurrentProcessWindows,
143 &window_list));
144 EXPECT_EQ(std::find_if(window_list.begin(), window_list.end(),
145 [&info](DesktopCapturer::Source window) {
146 return reinterpret_cast<HWND>(window.id) ==
147 info.hwnd;
148 }),
149 window_list.end());
150 DestroyTestWindow(info);
151 }
152
153 } // namespace webrtc
154