tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

window_finder_unittest.cc (6379B)


      1 /*
      2 *  Copyright (c) 2017 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/window_finder.h"
     12 
     13 #include <cstdint>
     14 #include <memory>
     15 
     16 #include "api/scoped_refptr.h"
     17 #include "modules/desktop_capture/desktop_capture_types.h"
     18 #include "modules/desktop_capture/desktop_geometry.h"
     19 #include "modules/desktop_capture/screen_drawer.h"
     20 #include "rtc_base/logging.h"
     21 #include "test/gtest.h"
     22 
     23 #if defined(WEBRTC_USE_X11)
     24 #include "modules/desktop_capture/linux/x11/shared_x_display.h"
     25 #include "modules/desktop_capture/linux/x11/x_atom_cache.h"
     26 #endif
     27 
     28 #if defined(WEBRTC_WIN)
     29 #include <windows.h>
     30 
     31 #include "modules/desktop_capture/win/window_capture_utils.h"
     32 #include "modules/desktop_capture/window_finder_win.h"
     33 #endif
     34 
     35 namespace webrtc {
     36 
     37 namespace {
     38 
     39 #if defined(WEBRTC_WIN)
     40 // ScreenDrawerWin does not have a message loop, so it's unresponsive to user
     41 // inputs. WindowFinderWin cannot detect this kind of unresponsive windows.
     42 // Instead, console window is used to test WindowFinderWin.
     43 // TODO(b/373792116): Reenable once flakiness is fixed.
     44 TEST(WindowFinderTest, DISABLED_FindConsoleWindow) {
     45  // Creates a ScreenDrawer to avoid this test from conflicting with
     46  // ScreenCapturerIntegrationTest: both tests require its window to be in
     47  // foreground.
     48  //
     49  // In ScreenCapturer related tests, this is controlled by
     50  // ScreenDrawer, which has a global lock to ensure only one ScreenDrawer
     51  // window is active. So even we do not use ScreenDrawer for Windows test,
     52  // creating an instance can block ScreenCapturer related tests until this test
     53  // finishes.
     54  //
     55  // Usually the test framework should take care of this "isolated test"
     56  // requirement, but unfortunately WebRTC trybots do not support this.
     57  std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
     58  const int kMaxSize = 10000;
     59  // Enlarges current console window.
     60  system("mode 1000,1000");
     61  const HWND console_window = GetConsoleWindow();
     62  // Ensures that current console window is visible.
     63  ShowWindow(console_window, SW_MAXIMIZE);
     64  // Moves the window to the top-left of the display.
     65  if (!MoveWindow(console_window, 0, 0, kMaxSize, kMaxSize, true)) {
     66    FAIL() << "Failed to move window. Error code: " << GetLastError();
     67  }
     68 
     69  bool should_restore_notopmost =
     70      (GetWindowLong(console_window, GWL_EXSTYLE) & WS_EX_TOPMOST) == 0;
     71 
     72  // Brings console window to top.
     73  if (!SetWindowPos(console_window, HWND_TOPMOST, 0, 0, 0, 0,
     74                    SWP_NOMOVE | SWP_NOSIZE)) {
     75    FAIL() << "Failed to bring window to top. Error code: " << GetLastError();
     76  }
     77  if (!BringWindowToTop(console_window)) {
     78    FAIL() << "Failed second attempt to bring window to top. Error code: "
     79           << GetLastError();
     80  }
     81 
     82  bool success = false;
     83  WindowFinderWin finder;
     84  for (int i = 0; i < kMaxSize; i++) {
     85    const DesktopVector spot(i, i);
     86    const HWND id = reinterpret_cast<HWND>(finder.GetWindowUnderPoint(spot));
     87 
     88    if (id == console_window) {
     89      success = true;
     90      break;
     91    }
     92    RTC_LOG(LS_INFO) << "Expected window " << console_window
     93                     << ". Found window " << id;
     94  }
     95  if (should_restore_notopmost)
     96    SetWindowPos(console_window, HWND_NOTOPMOST, 0, 0, 0, 0,
     97                 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
     98 
     99  if (!success)
    100    FAIL();
    101 }
    102 
    103 #else
    104 TEST(WindowFinderTest, FindDrawerWindow) {
    105  WindowFinder::Options options;
    106 #if defined(WEBRTC_USE_X11)
    107  std::unique_ptr<XAtomCache> cache;
    108  const auto shared_x_display = SharedXDisplay::CreateDefault();
    109  if (shared_x_display) {
    110    cache = std::make_unique<XAtomCache>(shared_x_display->display());
    111    options.cache = cache.get();
    112  }
    113 #endif
    114  std::unique_ptr<WindowFinder> finder = WindowFinder::Create(options);
    115  if (!finder) {
    116    RTC_LOG(LS_WARNING)
    117        << "No WindowFinder implementation for current platform.";
    118    return;
    119  }
    120 
    121  std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
    122  if (!drawer) {
    123    RTC_LOG(LS_WARNING)
    124        << "No ScreenDrawer implementation for current platform.";
    125    return;
    126  }
    127 
    128  if (drawer->window_id() == kNullWindowId) {
    129    // TODO(zijiehe): WindowFinderTest can use a dedicated window without
    130    // relying on ScreenDrawer.
    131    RTC_LOG(LS_WARNING)
    132        << "ScreenDrawer implementation for current platform does "
    133           "create a window.";
    134    return;
    135  }
    136 
    137  // ScreenDrawer may not be able to bring the window to the top. So we test
    138  // several spots, at least one of them should succeed.
    139  const DesktopRect region = drawer->DrawableRegion();
    140  if (region.is_empty()) {
    141    RTC_LOG(LS_WARNING)
    142        << "ScreenDrawer::DrawableRegion() is too small for the "
    143           "WindowFinderTest.";
    144    return;
    145  }
    146 
    147  for (int i = 0; i < region.width(); i++) {
    148    const DesktopVector spot(
    149        region.left() + i, region.top() + i * region.height() / region.width());
    150    const WindowId id = finder->GetWindowUnderPoint(spot);
    151    if (id == drawer->window_id()) {
    152      return;
    153    }
    154  }
    155 
    156  FAIL();
    157 }
    158 #endif
    159 
    160 TEST(WindowFinderTest, ShouldReturnNullWindowIfSpotIsOutOfScreen) {
    161  WindowFinder::Options options;
    162 #if defined(WEBRTC_USE_X11)
    163  std::unique_ptr<XAtomCache> cache;
    164  const auto shared_x_display = SharedXDisplay::CreateDefault();
    165  if (shared_x_display) {
    166    cache = std::make_unique<XAtomCache>(shared_x_display->display());
    167    options.cache = cache.get();
    168  }
    169 #endif
    170  std::unique_ptr<WindowFinder> finder = WindowFinder::Create(options);
    171  if (!finder) {
    172    RTC_LOG(LS_WARNING)
    173        << "No WindowFinder implementation for current platform.";
    174    return;
    175  }
    176 
    177  ASSERT_EQ(kNullWindowId,
    178            finder->GetWindowUnderPoint(DesktopVector(INT16_MAX, INT16_MAX)));
    179  ASSERT_EQ(kNullWindowId,
    180            finder->GetWindowUnderPoint(DesktopVector(INT16_MAX, INT16_MIN)));
    181  ASSERT_EQ(kNullWindowId,
    182            finder->GetWindowUnderPoint(DesktopVector(INT16_MIN, INT16_MAX)));
    183  ASSERT_EQ(kNullWindowId,
    184            finder->GetWindowUnderPoint(DesktopVector(INT16_MIN, INT16_MIN)));
    185 }
    186 
    187 }  // namespace
    188 
    189 }  // namespace webrtc