aura_desktop_capturer_unittest.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "remoting/host/chromeos/aura_desktop_capturer.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <memory>
  8. #include <utility>
  9. #include "base/logging.h"
  10. #include "base/test/scoped_feature_list.h"
  11. #include "base/test/task_environment.h"
  12. #include "base/test/test_future.h"
  13. #include "remoting/host/chromeos/ash_display_util.h"
  14. #include "remoting/host/chromeos/features.h"
  15. #include "remoting/host/chromeos/scoped_fake_ash_display_util.h"
  16. #include "testing/gmock/include/gmock/gmock.h"
  17. #include "testing/gtest/include/gtest/gtest.h"
  18. #include "third_party/skia/include/core/SkBitmap.h"
  19. #include "third_party/skia/include/core/SkColorSpace.h"
  20. #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
  21. #include "ui/display/display.h"
  22. using testing::_;
  23. using testing::Eq;
  24. using testing::IsNull;
  25. using testing::NotNull;
  26. namespace remoting {
  27. namespace {
  28. struct CaptureResult {
  29. webrtc::DesktopCapturer::Result result;
  30. std::unique_ptr<webrtc::DesktopFrame> frame;
  31. };
  32. // Test frame data.
  33. const unsigned char expected_frame[] = {
  34. 0x00, 0x00, 0x00, 0x9a, 0x65, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
  35. 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x90,
  36. 0x24, 0x71, 0xf8, 0xf2, 0xe5, 0xdf, 0x7f, 0x81, 0xc7, 0x49, 0xc4, 0xa3,
  37. 0x58, 0x5c, 0xf6, 0xcc, 0x40, 0x14, 0x28, 0x0c, 0xa0, 0xfa, 0x03, 0x18,
  38. 0x38, 0xd8, 0x7d, 0x77, 0x2b, 0x3a, 0x00, 0x00, 0x00, 0x20, 0x64, 0x46,
  39. 0x47, 0x2f, 0xdf, 0x6e, 0xed, 0x7b, 0xf3, 0xc3, 0x37, 0x20, 0xf2, 0x36,
  40. 0x67, 0x6c, 0x36, 0xe1, 0xb4, 0x5e, 0xbe, 0x04, 0x85, 0xdb, 0x89, 0xa3,
  41. 0xcd, 0xfd, 0xd2, 0x4b, 0xd6, 0x9f, 0x00, 0x00, 0x00, 0x40, 0x38, 0x35,
  42. 0x05, 0x75, 0x1d, 0x13, 0x6e, 0xb3, 0x6b, 0x1d, 0x29, 0xae, 0xd3, 0x43,
  43. 0xe6, 0x84, 0x8f, 0xa3, 0x9d, 0x65, 0x4e, 0x2f, 0x57, 0xe3, 0xf6, 0xe6,
  44. 0x20, 0x3c, 0x00, 0xc6, 0xe1, 0x73, 0x34, 0xe2, 0x23, 0x99, 0xc4, 0xfa,
  45. 0x91, 0xc2, 0xd5, 0x97, 0xc1, 0x8b, 0xd0, 0x3c, 0x13, 0xba, 0xf0, 0xd7};
  46. SkBitmap TestBitmap() {
  47. SkBitmap bitmap;
  48. const SkImageInfo& info =
  49. SkImageInfo::Make(3, 4, kBGRA_8888_SkColorType, kPremul_SkAlphaType,
  50. SkColorSpace::MakeSRGB());
  51. bitmap.installPixels(info, const_cast<unsigned char*>(expected_frame), 12);
  52. return bitmap;
  53. }
  54. SkBitmap CreateBitmap(int width, int height) {
  55. SkBitmap bitmap;
  56. const SkImageInfo& info =
  57. SkImageInfo::Make(width, height, kBGRA_8888_SkColorType,
  58. kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
  59. bitmap.setInfo(info);
  60. return bitmap;
  61. }
  62. ACTION_P(SaveUniquePtrArg, dest) {
  63. *dest = std::move(*arg1);
  64. }
  65. class DesktopCapturerCallback : public webrtc::DesktopCapturer::Callback {
  66. public:
  67. DesktopCapturerCallback() = default;
  68. DesktopCapturerCallback(const DesktopCapturerCallback&) = delete;
  69. DesktopCapturerCallback& operator=(const DesktopCapturerCallback&) = delete;
  70. ~DesktopCapturerCallback() override = default;
  71. CaptureResult WaitForResult() {
  72. EXPECT_TRUE(result_.Wait());
  73. return result_.Take();
  74. }
  75. // webrtc::DesktopCapturer::Callback implementation:
  76. void OnCaptureResult(webrtc::DesktopCapturer::Result result,
  77. std::unique_ptr<webrtc::DesktopFrame> frame) override {
  78. result_.SetValue(CaptureResult{result, std::move(frame)});
  79. }
  80. private:
  81. base::test::TestFuture<CaptureResult> result_;
  82. };
  83. } // namespace
  84. class AuraDesktopCapturerTest : public testing::Test {
  85. public:
  86. AuraDesktopCapturerTest() = default;
  87. test::ScopedFakeAshDisplayUtil& display_util() { return display_util_; }
  88. DesktopCapturerCallback& desktop_capturer_callback() { return callback_; }
  89. protected:
  90. base::test::SingleThreadTaskEnvironment environment_;
  91. test::ScopedFakeAshDisplayUtil display_util_;
  92. DesktopCapturerCallback callback_;
  93. AuraDesktopCapturer capturer_{display_util_};
  94. };
  95. TEST_F(AuraDesktopCapturerTest, ShouldSendScreenshotRequestForPrimaryDisplay) {
  96. display_util().AddPrimaryDisplay(111);
  97. capturer_.Start(&desktop_capturer_callback());
  98. capturer_.CaptureFrame();
  99. test::ScreenshotRequest request = display_util().WaitForScreenshotRequest();
  100. EXPECT_THAT(request.display, Eq(111));
  101. }
  102. TEST_F(AuraDesktopCapturerTest, ShouldSendScreenshotToCapturer) {
  103. display_util().AddPrimaryDisplay();
  104. capturer_.Start(&desktop_capturer_callback());
  105. capturer_.CaptureFrame();
  106. const SkBitmap expected_bitmap = TestBitmap();
  107. display_util().ReplyWithScreenshot(expected_bitmap);
  108. CaptureResult result = desktop_capturer_callback().WaitForResult();
  109. EXPECT_THAT(result.result, Eq(webrtc::DesktopCapturer::Result::SUCCESS));
  110. ASSERT_THAT(result.frame, NotNull());
  111. EXPECT_EQ(0, memcmp(expected_bitmap.getPixels(), result.frame->data(),
  112. expected_bitmap.computeByteSize()));
  113. }
  114. TEST_F(AuraDesktopCapturerTest, ShouldSetUpdatedRegion) {
  115. display_util().AddPrimaryDisplay();
  116. capturer_.Start(&desktop_capturer_callback());
  117. capturer_.CaptureFrame();
  118. display_util().ReplyWithScreenshot(TestBitmap());
  119. CaptureResult result = desktop_capturer_callback().WaitForResult();
  120. ASSERT_THAT(result.frame, NotNull());
  121. EXPECT_FALSE(result.frame->updated_region().is_empty());
  122. }
  123. TEST_F(AuraDesktopCapturerTest, ShouldSetDpi) {
  124. const float scale_factor = 2.5;
  125. // scale_factor = dpi / default_dpi (and default_dpi is 96).
  126. const int dpi = static_cast<int>(scale_factor * 96);
  127. display_util().AddPrimaryDisplay().set_device_scale_factor(scale_factor);
  128. capturer_.Start(&desktop_capturer_callback());
  129. capturer_.CaptureFrame();
  130. display_util().ReplyWithScreenshot(TestBitmap());
  131. CaptureResult result = desktop_capturer_callback().WaitForResult();
  132. ASSERT_THAT(result.frame, NotNull());
  133. EXPECT_THAT(result.frame->dpi().x(), Eq(dpi));
  134. EXPECT_THAT(result.frame->dpi().y(), Eq(dpi));
  135. }
  136. TEST_F(AuraDesktopCapturerTest, ShouldSetDisplayBounds) {
  137. const int left = 100;
  138. const int top = 200;
  139. const int width = 300;
  140. const int height = 400;
  141. display_util().AddPrimaryDisplay().set_bounds(
  142. gfx::Rect(left, top, width, height));
  143. capturer_.Start(&desktop_capturer_callback());
  144. capturer_.CaptureFrame();
  145. display_util().ReplyWithScreenshot(CreateBitmap(width, height));
  146. CaptureResult result = desktop_capturer_callback().WaitForResult();
  147. ASSERT_THAT(result.frame, NotNull());
  148. EXPECT_THAT(result.frame->rect().left(), Eq(left));
  149. EXPECT_THAT(result.frame->rect().top(), Eq(top));
  150. EXPECT_THAT(result.frame->rect().width(), Eq(width));
  151. EXPECT_THAT(result.frame->rect().height(), Eq(height));
  152. }
  153. TEST_F(AuraDesktopCapturerTest, ShouldNotCrashIfDisplayIsUnavailable) {
  154. capturer_.Start(&desktop_capturer_callback());
  155. display_util().AddDisplayWithId(111);
  156. capturer_.SelectSource(111);
  157. display_util().RemoveDisplay(111);
  158. capturer_.CaptureFrame();
  159. CaptureResult result = desktop_capturer_callback().WaitForResult();
  160. ASSERT_THAT(result.result,
  161. Eq(webrtc::DesktopCapturer::Result::ERROR_TEMPORARY));
  162. ASSERT_THAT(result.frame, IsNull());
  163. }
  164. TEST_F(AuraDesktopCapturerTest, ShouldReturnTemporaryErrorIfScreenshotFails) {
  165. display_util().AddPrimaryDisplay();
  166. capturer_.Start(&desktop_capturer_callback());
  167. capturer_.CaptureFrame();
  168. display_util().ReplyWithScreenshot(absl::nullopt);
  169. CaptureResult result = desktop_capturer_callback().WaitForResult();
  170. EXPECT_THAT(result.result,
  171. Eq(webrtc::DesktopCapturer::Result::ERROR_TEMPORARY));
  172. EXPECT_THAT(result.frame, IsNull());
  173. }
  174. TEST_F(AuraDesktopCapturerTest,
  175. ShouldNotAllowSwitchingToSecondaryMonitorIfFeatureFlagIsDisabled) {
  176. base::test::ScopedFeatureList features;
  177. features.InitAndDisableFeature(features::kEnableMultiMonitorsInCrd);
  178. display_util().AddDisplayWithId(111);
  179. capturer_.Start(&desktop_capturer_callback());
  180. EXPECT_FALSE(capturer_.SelectSource(111));
  181. }
  182. TEST_F(AuraDesktopCapturerTest,
  183. ShouldAllowSwitchingToSecondaryMonitorIfFeatureFlagIsEnabled) {
  184. base::test::ScopedFeatureList features{features::kEnableMultiMonitorsInCrd};
  185. // We're using a value bigger than 32 bit to ensure nothing gets truncated.
  186. constexpr int64_t display_id = 123456789123456789;
  187. display_util().AddPrimaryDisplay();
  188. display_util().AddDisplayWithId(display_id);
  189. capturer_.Start(&desktop_capturer_callback());
  190. capturer_.SelectSource(display_id);
  191. capturer_.CaptureFrame();
  192. test::ScreenshotRequest request = display_util().WaitForScreenshotRequest();
  193. EXPECT_THAT(request.display, Eq(display_id));
  194. }
  195. TEST_F(AuraDesktopCapturerTest, ShouldFailSwitchingToNonExistingMonitor) {
  196. base::test::ScopedFeatureList features{features::kEnableMultiMonitorsInCrd};
  197. capturer_.Start(&desktop_capturer_callback());
  198. EXPECT_FALSE(capturer_.SelectSource(222));
  199. }
  200. TEST_F(AuraDesktopCapturerTest, ShouldUseCorrectDisplayAfterSwitching) {
  201. base::test::ScopedFeatureList features{features::kEnableMultiMonitorsInCrd};
  202. display_util().AddPrimaryDisplay();
  203. display_util().AddDisplayWithId(222);
  204. display_util().AddDisplayWithId(333);
  205. capturer_.Start(&desktop_capturer_callback());
  206. capturer_.SelectSource(333);
  207. capturer_.CaptureFrame();
  208. test::ScreenshotRequest request = display_util().WaitForScreenshotRequest();
  209. EXPECT_THAT(request.display, Eq(333));
  210. }
  211. } // namespace remoting