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.
5 #include "chrome/browser/chromeos/display/output_protection_delegate.h"
8 #include "ash/shell_delegate.h"
9 #include "build/build_config.h"
10 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/render_frame_host.h"
13 #include "content/public/browser/web_contents.h"
14 #include "ui/gfx/screen.h"
20 bool GetCurrentDisplayId(content::RenderFrameHost
* rfh
, int64
* display_id
) {
21 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
25 gfx::NativeView native_view
= rfh
->GetNativeView();
26 gfx::Screen
* screen
= gfx::Screen::GetScreenFor(native_view
);
29 gfx::Display display
= screen
->GetDisplayNearestWindow(native_view
);
30 *display_id
= display
.id();
34 void DoNothing(bool status
) {
39 OutputProtectionDelegate::OutputProtectionDelegate(int render_process_id
,
41 : render_process_id_(render_process_id
),
42 render_frame_id_(render_frame_id
),
44 client_id_(ui::DisplayConfigurator::kInvalidClientId
),
46 weak_ptr_factory_(this) {
47 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
50 OutputProtectionDelegate::~OutputProtectionDelegate() {
51 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
53 ui::DisplayConfigurator
* configurator
=
54 ash::Shell::GetInstance()->display_configurator();
55 configurator
->UnregisterContentProtectionClient(client_id_
);
58 window_
->RemoveObserver(this);
61 ui::DisplayConfigurator::ContentProtectionClientId
62 OutputProtectionDelegate::GetClientId() {
63 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
64 if (client_id_
== ui::DisplayConfigurator::kInvalidClientId
) {
65 content::RenderFrameHost
* rfh
=
66 content::RenderFrameHost::FromID(render_process_id_
, render_frame_id_
);
67 if (!rfh
|| !GetCurrentDisplayId(rfh
, &display_id_
))
68 return ui::DisplayConfigurator::kInvalidClientId
;
70 aura::Window
* window
= rfh
->GetNativeView();
72 return ui::DisplayConfigurator::kInvalidClientId
;
74 ui::DisplayConfigurator
* configurator
=
75 ash::Shell::GetInstance()->display_configurator();
76 client_id_
= configurator
->RegisterContentProtectionClient();
78 if (client_id_
!= ui::DisplayConfigurator::kInvalidClientId
) {
79 window
->AddObserver(this);
86 void OutputProtectionDelegate::QueryStatus(
87 const QueryStatusCallback
& callback
) {
88 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
90 content::RenderFrameHost
* rfh
=
91 content::RenderFrameHost::FromID(render_process_id_
, render_frame_id_
);
93 LOG(WARNING
) << "RenderFrameHost is not alive.";
94 callback
.Run(false, 0, 0);
98 ui::DisplayConfigurator
* configurator
=
99 ash::Shell::GetInstance()->display_configurator();
100 configurator
->QueryContentProtectionStatus(
101 GetClientId(), display_id_
,
102 base::Bind(&OutputProtectionDelegate::QueryStatusComplete
,
103 weak_ptr_factory_
.GetWeakPtr(), callback
));
106 void OutputProtectionDelegate::EnableProtection(
107 uint32_t desired_method_mask
,
108 const EnableProtectionCallback
& callback
) {
109 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
111 ui::DisplayConfigurator
* configurator
=
112 ash::Shell::GetInstance()->display_configurator();
113 configurator
->EnableContentProtection(
114 GetClientId(), display_id_
, desired_method_mask
,
115 base::Bind(&OutputProtectionDelegate::EnableProtectionComplete
,
116 weak_ptr_factory_
.GetWeakPtr(), callback
));
117 desired_method_mask_
= desired_method_mask
;
120 void OutputProtectionDelegate::QueryStatusComplete(
121 const QueryStatusCallback
& callback
,
122 const ui::DisplayConfigurator::QueryProtectionResponse
& response
) {
123 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
125 content::RenderFrameHost
* rfh
=
126 content::RenderFrameHost::FromID(render_process_id_
, render_frame_id_
);
128 LOG(WARNING
) << "RenderFrameHost is not alive.";
129 callback
.Run(false, 0, 0);
133 uint32_t link_mask
= response
.link_mask
;
134 // If we successfully retrieved the device level status, check for capturers.
135 if (response
.success
) {
136 const bool capture_detected
=
137 // Check for tab capture on the current tab.
138 content::WebContents::FromRenderFrameHost(rfh
)->GetCapturerCount() >
140 // Check for desktop capture.
141 MediaCaptureDevicesDispatcher::GetInstance()
142 ->IsDesktopCaptureInProgress();
143 if (capture_detected
)
144 link_mask
|= ui::DISPLAY_CONNECTION_TYPE_NETWORK
;
147 callback
.Run(response
.success
, link_mask
, response
.protection_mask
);
150 void OutputProtectionDelegate::EnableProtectionComplete(
151 const EnableProtectionCallback
& callback
,
153 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
155 callback
.Run(success
);
158 void OutputProtectionDelegate::OnWindowHierarchyChanged(
159 const aura::WindowObserver::HierarchyChangeParams
& params
) {
160 content::RenderFrameHost
* rfh
=
161 content::RenderFrameHost::FromID(render_process_id_
, render_frame_id_
);
163 LOG(WARNING
) << "RenderFrameHost is not alive.";
167 int64 new_display_id
= 0;
168 if (!GetCurrentDisplayId(rfh
, &new_display_id
))
170 if (display_id_
== new_display_id
)
173 if (desired_method_mask_
!= ui::CONTENT_PROTECTION_METHOD_NONE
) {
174 // Display changed and should enable output protections on new display.
175 ui::DisplayConfigurator
* configurator
=
176 ash::Shell::GetInstance()->display_configurator();
177 configurator
->EnableContentProtection(GetClientId(), new_display_id
,
178 desired_method_mask_
,
179 base::Bind(&DoNothing
));
180 configurator
->EnableContentProtection(GetClientId(), display_id_
,
181 ui::CONTENT_PROTECTION_METHOD_NONE
,
182 base::Bind(&DoNothing
));
184 display_id_
= new_display_id
;
187 void OutputProtectionDelegate::OnWindowDestroying(aura::Window
* window
) {
188 DCHECK_EQ(window
, window_
);
189 window_
->RemoveObserver(this);
193 } // namespace chromeos