tor-browser

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

screen_capturer_mac_unittest.cc (5899B)


      1 /*
      2 *  Copyright (c) 2013 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 <ApplicationServices/ApplicationServices.h>
     12 
     13 #include <chrono>
     14 #include <memory>
     15 #include <thread>
     16 
     17 #include "modules/desktop_capture/desktop_capture_options.h"
     18 #include "modules/desktop_capture/desktop_capturer.h"
     19 #include "modules/desktop_capture/desktop_frame.h"
     20 #include "modules/desktop_capture/desktop_geometry.h"
     21 #include "modules/desktop_capture/desktop_region.h"
     22 #include "modules/desktop_capture/mac/desktop_configuration.h"
     23 #include "modules/desktop_capture/mock_desktop_capturer_callback.h"
     24 #include "test/gtest.h"
     25 
     26 using ::testing::_;
     27 using ::testing::AnyNumber;
     28 using ::testing::AnyOf;
     29 using ::testing::InSequence;
     30 
     31 namespace webrtc {
     32 
     33 class ScreenCapturerMacTest : public ::testing::Test {
     34 public:
     35  // Verifies that the whole screen is initially dirty.
     36  void CaptureDoneCallback1(DesktopCapturer::Result result,
     37                            std::unique_ptr<DesktopFrame>* frame);
     38 
     39  // Verifies that a rectangle explicitly marked as dirty is propagated
     40  // correctly.
     41  void CaptureDoneCallback2(DesktopCapturer::Result result,
     42                            std::unique_ptr<DesktopFrame>* frame);
     43 
     44 protected:
     45  void SetUp() override {
     46    capturer_ = DesktopCapturer::CreateScreenCapturer(
     47        DesktopCaptureOptions::CreateDefault());
     48  }
     49 
     50  std::unique_ptr<DesktopCapturer> capturer_;
     51  MockDesktopCapturerCallback callback_;
     52 };
     53 
     54 class ScreenCapturerSckTest : public ScreenCapturerMacTest {
     55 protected:
     56  void SetUp() override {
     57    auto options = DesktopCaptureOptions::CreateDefault();
     58    options.set_allow_sck_capturer(true);
     59    capturer_ = DesktopCapturer::CreateScreenCapturer(options);
     60  }
     61 
     62  std::unique_ptr<DesktopCapturer> capturer_;
     63  MockDesktopCapturerCallback callback_;
     64 };
     65 
     66 void ScreenCapturerMacTest::CaptureDoneCallback1(
     67    DesktopCapturer::Result result,
     68    std::unique_ptr<DesktopFrame>* frame) {
     69  EXPECT_EQ(result, DesktopCapturer::Result::SUCCESS);
     70 
     71  MacDesktopConfiguration config = MacDesktopConfiguration::GetCurrent(
     72      MacDesktopConfiguration::BottomLeftOrigin);
     73 
     74  // Verify that the region contains full frame.
     75  DesktopRegion::Iterator it((*frame)->updated_region());
     76  EXPECT_TRUE(!it.IsAtEnd() && it.rect().equals(config.pixel_bounds));
     77 }
     78 
     79 void ScreenCapturerMacTest::CaptureDoneCallback2(
     80    DesktopCapturer::Result result,
     81    std::unique_ptr<DesktopFrame>* frame) {
     82  EXPECT_EQ(result, DesktopCapturer::Result::SUCCESS);
     83 
     84  MacDesktopConfiguration config = MacDesktopConfiguration::GetCurrent(
     85      MacDesktopConfiguration::BottomLeftOrigin);
     86  int width = config.pixel_bounds.width();
     87  int height = config.pixel_bounds.height();
     88 
     89  EXPECT_EQ(width, (*frame)->size().width());
     90  EXPECT_EQ(height, (*frame)->size().height());
     91  EXPECT_TRUE((*frame)->data() != NULL);
     92  // Depending on the capture method, the screen may be flipped or not, so
     93  // the stride may be positive or negative.
     94  // The stride may in theory be larger than the width due to alignment, but in
     95  // other cases, like window capture, the stride normally matches the monitor
     96  // resolution whereas the width matches the window region on said monitor.
     97  // Make no assumptions.
     98  EXPECT_LE(static_cast<int>(sizeof(uint32_t) * width),
     99            abs((*frame)->stride()));
    100 }
    101 
    102 TEST_F(ScreenCapturerMacTest, Capture) {
    103  EXPECT_CALL(callback_,
    104              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
    105      .Times(2)
    106      .WillOnce(Invoke(this, &ScreenCapturerMacTest::CaptureDoneCallback1))
    107      .WillOnce(Invoke(this, &ScreenCapturerMacTest::CaptureDoneCallback2));
    108 
    109  SCOPED_TRACE("");
    110  capturer_->Start(&callback_);
    111 
    112  // Check that we get an initial full-screen updated.
    113  capturer_->CaptureFrame();
    114 
    115  // Check that subsequent dirty rects are propagated correctly.
    116  capturer_->CaptureFrame();
    117 }
    118 
    119 TEST_F(ScreenCapturerSckTest, Capture) {
    120  if (!CGPreflightScreenCaptureAccess()) {
    121    GTEST_SKIP()
    122        << "ScreenCapturerSckTest needs TCC ScreenCapture authorization";
    123  }
    124 
    125  std::atomic<bool> done{false};
    126  std::atomic<DesktopCapturer::Result> result{
    127      DesktopCapturer::Result::ERROR_TEMPORARY};
    128  InSequence s;
    129  EXPECT_CALL(callback_,
    130              OnCaptureResultPtr(DesktopCapturer::Result::ERROR_TEMPORARY, _))
    131      .Times(AnyNumber());
    132  EXPECT_CALL(callback_,
    133              OnCaptureResultPtr(AnyOf(DesktopCapturer::Result::ERROR_PERMANENT,
    134                                       DesktopCapturer::Result::SUCCESS),
    135                                 _))
    136      .WillOnce([this, &result](DesktopCapturer::Result res,
    137                                std::unique_ptr<DesktopFrame>* frame) {
    138        result = res;
    139        if (res == DesktopCapturer::Result::SUCCESS) {
    140          CaptureDoneCallback1(res, frame);
    141        }
    142      });
    143  SCOPED_TRACE("");
    144  capturer_->Start(&callback_);
    145 
    146  while (result == DesktopCapturer::Result::ERROR_TEMPORARY) {
    147    // Check that we get an initial full-screen updated.
    148    capturer_->CaptureFrame();
    149    std::this_thread::sleep_for(std::chrono::milliseconds(1));
    150  }
    151  ASSERT_NE(result, DesktopCapturer::Result::ERROR_PERMANENT);
    152 
    153  EXPECT_CALL(callback_,
    154              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
    155      .Times(1)
    156      .WillOnce([this, &done](auto res, auto frame) {
    157        CaptureDoneCallback2(res, frame);
    158        done = true;
    159      });
    160 
    161  while (!done) {
    162    // Check that we get an initial full-screen updated.
    163    capturer_->CaptureFrame();
    164    std::this_thread::sleep_for(std::chrono::milliseconds(1));
    165  }
    166 }
    167 
    168 }  // namespace webrtc