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
);
22 gfx::NativeView native_view
= rfh
->GetNativeView();
23 gfx::Screen
* screen
= gfx::Screen::GetScreenFor(native_view
);
26 gfx::Display display
= screen
->GetDisplayNearestWindow(native_view
);
27 *display_id
= display
.id();
31 void DoNothing(bool status
) {
36 OutputProtectionDelegate::OutputProtectionDelegate(int render_process_id
,
38 : render_process_id_(render_process_id
),
39 render_frame_id_(render_frame_id
),
41 client_id_(ui::DisplayConfigurator::kInvalidClientId
),
43 weak_ptr_factory_(this) {
44 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
47 OutputProtectionDelegate::~OutputProtectionDelegate() {
48 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
50 ui::DisplayConfigurator
* configurator
=
51 ash::Shell::GetInstance()->display_configurator();
52 configurator
->UnregisterContentProtectionClient(client_id_
);
55 window_
->RemoveObserver(this);
58 ui::DisplayConfigurator::ContentProtectionClientId
59 OutputProtectionDelegate::GetClientId() {
60 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
61 if (client_id_
== ui::DisplayConfigurator::kInvalidClientId
) {
62 content::RenderFrameHost
* rfh
=
63 content::RenderFrameHost::FromID(render_process_id_
, render_frame_id_
);
64 if (!GetCurrentDisplayId(rfh
, &display_id_
))
65 return ui::DisplayConfigurator::kInvalidClientId
;
67 window_
= rfh
->GetNativeView();
69 return ui::DisplayConfigurator::kInvalidClientId
;
71 ui::DisplayConfigurator
* configurator
=
72 ash::Shell::GetInstance()->display_configurator();
73 client_id_
= configurator
->RegisterContentProtectionClient();
75 if (client_id_
!= ui::DisplayConfigurator::kInvalidClientId
)
76 window_
->AddObserver(this);
81 void OutputProtectionDelegate::QueryStatus(
82 const QueryStatusCallback
& callback
) {
83 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
85 content::RenderFrameHost
* rfh
=
86 content::RenderFrameHost::FromID(render_process_id_
, render_frame_id_
);
88 LOG(WARNING
) << "RenderFrameHost is not alive.";
89 callback
.Run(false, 0, 0);
93 ui::DisplayConfigurator
* configurator
=
94 ash::Shell::GetInstance()->display_configurator();
95 configurator
->QueryContentProtectionStatus(
96 GetClientId(), display_id_
,
97 base::Bind(&OutputProtectionDelegate::QueryStatusComplete
,
98 weak_ptr_factory_
.GetWeakPtr(), callback
));
101 void OutputProtectionDelegate::EnableProtection(
102 uint32_t desired_method_mask
,
103 const EnableProtectionCallback
& callback
) {
104 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
106 ui::DisplayConfigurator
* configurator
=
107 ash::Shell::GetInstance()->display_configurator();
108 configurator
->EnableContentProtection(
109 GetClientId(), display_id_
, desired_method_mask
,
110 base::Bind(&OutputProtectionDelegate::EnableProtectionComplete
,
111 weak_ptr_factory_
.GetWeakPtr(), callback
));
112 desired_method_mask_
= desired_method_mask
;
115 void OutputProtectionDelegate::QueryStatusComplete(
116 const QueryStatusCallback
& callback
,
117 const ui::DisplayConfigurator::QueryProtectionResponse
& response
) {
118 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
120 content::RenderFrameHost
* rfh
=
121 content::RenderFrameHost::FromID(render_process_id_
, render_frame_id_
);
123 LOG(WARNING
) << "RenderFrameHost is not alive.";
124 callback
.Run(false, 0, 0);
128 uint32_t link_mask
= response
.link_mask
;
129 // If we successfully retrieved the device level status, check for capturers.
130 if (response
.success
) {
131 const bool capture_detected
=
132 // Check for tab capture on the current tab.
133 content::WebContents::FromRenderFrameHost(rfh
)->GetCapturerCount() >
135 // Check for desktop capture.
136 MediaCaptureDevicesDispatcher::GetInstance()
137 ->IsDesktopCaptureInProgress();
138 if (capture_detected
)
139 link_mask
|= ui::DISPLAY_CONNECTION_TYPE_NETWORK
;
142 callback
.Run(response
.success
, link_mask
, response
.protection_mask
);
145 void OutputProtectionDelegate::EnableProtectionComplete(
146 const EnableProtectionCallback
& callback
,
148 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
150 callback
.Run(success
);
153 void OutputProtectionDelegate::OnWindowHierarchyChanged(
154 const aura::WindowObserver::HierarchyChangeParams
& params
) {
155 content::RenderFrameHost
* rfh
=
156 content::RenderFrameHost::FromID(render_process_id_
, render_frame_id_
);
158 LOG(WARNING
) << "RenderFrameHost is not alive.";
162 int64 new_display_id
= 0;
163 if (!GetCurrentDisplayId(rfh
, &new_display_id
))
165 if (display_id_
== new_display_id
)
168 if (desired_method_mask_
!= ui::CONTENT_PROTECTION_METHOD_NONE
) {
169 // Display changed and should enable output protections on new display.
170 ui::DisplayConfigurator
* configurator
=
171 ash::Shell::GetInstance()->display_configurator();
172 configurator
->EnableContentProtection(GetClientId(), new_display_id
,
173 desired_method_mask_
,
174 base::Bind(&DoNothing
));
175 configurator
->EnableContentProtection(GetClientId(), display_id_
,
176 ui::CONTENT_PROTECTION_METHOD_NONE
,
177 base::Bind(&DoNothing
));
179 display_id_
= new_display_id
;
182 void OutputProtectionDelegate::OnWindowDestroying(aura::Window
* window
) {
183 DCHECK_EQ(window
, window_
);
184 window_
->RemoveObserver(this);
188 } // namespace chromeos