output_protection_delegate.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Copyright 2013 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 "ash/display/output_protection_delegate.h"
  5. #include "ash/capture_mode/capture_mode_controller.h"
  6. #include "ash/shell.h"
  7. #include "base/callback_helpers.h"
  8. #include "ui/display/display.h"
  9. #include "ui/display/manager/content_protection_manager.h"
  10. #include "ui/display/manager/display_configurator.h"
  11. #include "ui/display/screen.h"
  12. #include "ui/display/types/display_constants.h"
  13. namespace ash {
  14. namespace {
  15. display::ContentProtectionManager* manager() {
  16. return Shell::Get()->display_configurator()->content_protection_manager();
  17. }
  18. void MaybeSetCaptureModeWindowProtection(aura::Window* window,
  19. uint32_t protection_mask) {
  20. CaptureModeController::Get()->SetWindowProtectionMask(window,
  21. protection_mask);
  22. }
  23. } // namespace
  24. struct OutputProtectionDelegate::ClientIdHolder {
  25. ClientIdHolder() : id(manager()->RegisterClient()) {}
  26. ~ClientIdHolder() { manager()->UnregisterClient(id); }
  27. const display::ContentProtectionManager::ClientId id;
  28. };
  29. OutputProtectionDelegate::OutputProtectionDelegate(aura::Window* window)
  30. : window_(window),
  31. display_id_(
  32. display::Screen::GetScreen()->GetDisplayNearestWindow(window).id()) {
  33. // TODO(domlaskowski): OutputProtectionImpl passes null if the RenderFrameHost
  34. // no longer exists. Investigate removing this check in crbug.com/997270.
  35. if (!window_)
  36. return;
  37. window_->AddObserver(this);
  38. }
  39. OutputProtectionDelegate::~OutputProtectionDelegate() {
  40. if (!window_)
  41. return;
  42. window_->RemoveObserver(this);
  43. MaybeSetCaptureModeWindowProtection(window_,
  44. display::CONTENT_PROTECTION_METHOD_NONE);
  45. }
  46. void OutputProtectionDelegate::OnDisplayMetricsChanged(
  47. const display::Display& display,
  48. uint32_t changed_metrics) {
  49. // Switching the primary display (either by user or by going into docked
  50. // mode), as well as changing mirror mode may change the display on which
  51. // the window resides without actually changing the window hierarchy (i.e.
  52. // the root window is still the same). Hence we need to watch out for these
  53. // situations and update |display_id_| if needed.
  54. if (!(changed_metrics &
  55. (display::DisplayObserver::DISPLAY_METRIC_PRIMARY |
  56. display::DisplayObserver::DISPLAY_METRIC_MIRROR_STATE))) {
  57. return;
  58. }
  59. OnWindowMayHaveMovedToAnotherDisplay();
  60. }
  61. void OutputProtectionDelegate::OnWindowHierarchyChanged(
  62. const aura::WindowObserver::HierarchyChangeParams& params) {
  63. OnWindowMayHaveMovedToAnotherDisplay();
  64. }
  65. void OutputProtectionDelegate::OnWindowDestroying(aura::Window* window) {
  66. DCHECK_EQ(window, window_);
  67. display_observer_.reset();
  68. window_->RemoveObserver(this);
  69. MaybeSetCaptureModeWindowProtection(window_,
  70. display::CONTENT_PROTECTION_METHOD_NONE);
  71. window_ = nullptr;
  72. }
  73. void OutputProtectionDelegate::QueryStatus(QueryStatusCallback callback) {
  74. if (!RegisterClientIfNecessary()) {
  75. std::move(callback).Run(/*success=*/false,
  76. display::DISPLAY_CONNECTION_TYPE_NONE,
  77. display::CONTENT_PROTECTION_METHOD_NONE);
  78. return;
  79. }
  80. manager()->QueryContentProtection(client_->id, display_id_,
  81. std::move(callback));
  82. }
  83. void OutputProtectionDelegate::SetProtection(uint32_t protection_mask,
  84. SetProtectionCallback callback) {
  85. protection_mask_ = protection_mask;
  86. // Capture mode screen recording doesn't rely on display protection, and hence
  87. // must be informed with the new window's protection.
  88. if (window_)
  89. MaybeSetCaptureModeWindowProtection(window_, protection_mask);
  90. if (!RegisterClientIfNecessary()) {
  91. std::move(callback).Run(/*success=*/false);
  92. return;
  93. }
  94. manager()->ApplyContentProtection(client_->id, display_id_, protection_mask,
  95. std::move(callback));
  96. }
  97. void OutputProtectionDelegate::OnWindowMayHaveMovedToAnotherDisplay() {
  98. DCHECK(window_);
  99. int64_t new_display_id =
  100. display::Screen::GetScreen()->GetDisplayNearestWindow(window_).id();
  101. if (display_id_ == new_display_id)
  102. return;
  103. if (protection_mask_ != display::CONTENT_PROTECTION_METHOD_NONE) {
  104. DCHECK(client_);
  105. manager()->ApplyContentProtection(client_->id, new_display_id,
  106. protection_mask_, base::DoNothing());
  107. manager()->ApplyContentProtection(client_->id, display_id_,
  108. display::CONTENT_PROTECTION_METHOD_NONE,
  109. base::DoNothing());
  110. // The window may have moved to a display that is currently being recorded,
  111. // so we need to refresh Capture Mode's content protection.
  112. CaptureModeController::Get()->RefreshContentProtection();
  113. }
  114. display_id_ = new_display_id;
  115. }
  116. bool OutputProtectionDelegate::RegisterClientIfNecessary() {
  117. if (!window_)
  118. return false;
  119. if (!client_)
  120. client_ = std::make_unique<ClientIdHolder>();
  121. return true;
  122. }
  123. } // namespace ash