summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkcwu@chromium.org <kcwu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-31 10:00:41 +0000
committerkcwu@chromium.org <kcwu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-31 10:00:41 +0000
commit67e6a68b14d311eb758ac8a569695a141dcd6627 (patch)
tree1d41b918b40a754c82cea0810e0a1bc6b6840331
parent7ac8dcbec919514520a95b421da0ea53907703d1 (diff)
downloadchromium_src-67e6a68b14d311eb758ac8a569695a141dcd6627.zip
chromium_src-67e6a68b14d311eb758ac8a569695a141dcd6627.tar.gz
chromium_src-67e6a68b14d311eb758ac8a569695a141dcd6627.tar.bz2
Only enable HDCP on monitors displaying the protected video
BUG=305643 R=derat@chromium.org, dmichael@chromium.org Review URL: https://codereview.chromium.org/49513002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@232075 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc240
-rw-r--r--chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h14
-rw-r--r--chromeos/display/output_configurator.cc114
-rw-r--r--chromeos/display/output_configurator.h14
-rw-r--r--chromeos/display/output_configurator_unittest.cc45
5 files changed, 307 insertions, 120 deletions
diff --git a/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc b/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc
index 10dc050..ef7a27e 100644
--- a/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc
+++ b/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc
@@ -8,6 +8,7 @@
#include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_output_protection_private.h"
@@ -16,10 +17,12 @@
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
-#if defined(USE_ASH) && defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS)
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "chromeos/display/output_configurator.h"
+#include "ui/aura/window.h"
+#include "ui/gfx/screen.h"
#endif
namespace chrome {
@@ -67,40 +70,193 @@ COMPILE_ASSERT(
static_cast<int>(PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP) ==
static_cast<int>(chromeos::OUTPUT_PROTECTION_METHOD_HDCP),
PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP);
+
+bool GetCurrentDisplayId(content::RenderViewHost* rvh, int64* display_id) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ content::RenderWidgetHostView* view = rvh->GetView();
+ if (!view)
+ return false;
+ gfx::NativeView native_view = view->GetNativeView();
+ gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view);
+ if (!screen)
+ return false;
+ gfx::Display display = screen->GetDisplayNearestWindow(native_view);
+ *display_id = display.id();
+ return true;
+}
#endif
-#if defined(OS_CHROMEOS) && defined(USE_ASH)
-void UnregisterClientOnUIThread(
- chromeos::OutputConfigurator::OutputProtectionClientId client_id) {
+} // namespace
+
+#if defined(OS_CHROMEOS)
+// Output protection delegate. All methods except constructor should be
+// invoked in UI thread.
+class PepperOutputProtectionMessageFilter::Delegate
+ : public aura::WindowObserver {
+ public:
+ Delegate(int render_process_id, int render_view_id);
+ virtual ~Delegate();
+
+ // aura::WindowObserver overrides.
+ virtual void OnWindowHierarchyChanged(
+ const aura::WindowObserver::HierarchyChangeParams& params) OVERRIDE;
+
+ int32_t OnQueryStatus(uint32_t* link_mask, uint32_t* protection_mask);
+ int32_t OnEnableProtection(uint32_t desired_method_mask);
+
+ private:
+ chromeos::OutputConfigurator::OutputProtectionClientId GetClientId();
+
+ // Used to lookup the WebContents associated with this PP_Instance.
+ int render_process_id_;
+ int render_view_id_;
+
+ chromeos::OutputConfigurator::OutputProtectionClientId client_id_;
+ // The display id which the renderer currently uses.
+ int64 display_id_;
+ // The last desired method mask. Will enable this mask on new display if
+ // renderer changes display.
+ uint32_t desired_method_mask_;
+};
+
+PepperOutputProtectionMessageFilter::Delegate::Delegate(int render_process_id,
+ int render_view_id)
+ : render_process_id_(render_process_id),
+ render_view_id_(render_view_id),
+ client_id_(chromeos::OutputConfigurator::kInvalidClientId),
+ display_id_(0) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+
+}
+
+PepperOutputProtectionMessageFilter::Delegate::~Delegate() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
chromeos::OutputConfigurator* configurator =
ash::Shell::GetInstance()->output_configurator();
- configurator->UnregisterOutputProtectionClient(client_id);
+ configurator->UnregisterOutputProtectionClient(client_id_);
+
+ content::RenderViewHost* rvh =
+ content::RenderViewHost::FromID(render_process_id_, render_view_id_);
+ if (rvh) {
+ content::RenderWidgetHostView* view = rvh->GetView();
+ if (view) {
+ gfx::NativeView native_view = view->GetNativeView();
+ native_view->RemoveObserver(this);
+ }
+ }
}
-#endif
-} // namespace
+chromeos::OutputConfigurator::OutputProtectionClientId
+PepperOutputProtectionMessageFilter::Delegate::GetClientId() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (client_id_ == chromeos::OutputConfigurator::kInvalidClientId) {
+ content::RenderViewHost* rvh =
+ content::RenderViewHost::FromID(render_process_id_, render_view_id_);
+ if (!GetCurrentDisplayId(rvh, &display_id_))
+ return chromeos::OutputConfigurator::kInvalidClientId;
+ content::RenderWidgetHostView* view = rvh->GetView();
+ if (!view)
+ return chromeos::OutputConfigurator::kInvalidClientId;
+ gfx::NativeView native_view = view->GetNativeView();
+ if (!view)
+ return chromeos::OutputConfigurator::kInvalidClientId;
+ native_view->AddObserver(this);
+
+ chromeos::OutputConfigurator* configurator =
+ ash::Shell::GetInstance()->output_configurator();
+ client_id_ = configurator->RegisterOutputProtectionClient();
+ }
+ return client_id_;
+}
+
+int32_t PepperOutputProtectionMessageFilter::Delegate::OnQueryStatus(
+ uint32_t* link_mask, uint32_t* protection_mask) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ content::RenderViewHost* rvh =
+ content::RenderViewHost::FromID(render_process_id_, render_view_id_);
+ if (!rvh) {
+ LOG(WARNING) << "RenderViewHost is not alive.";
+ return PP_ERROR_FAILED;
+ }
+
+ chromeos::OutputConfigurator* configurator =
+ ash::Shell::GetInstance()->output_configurator();
+ bool result = configurator->QueryOutputProtectionStatus(
+ GetClientId(), display_id_, link_mask, protection_mask);
+
+ // If we successfully retrieved the device level status, check for capturers.
+ if (result) {
+ if (content::WebContents::FromRenderViewHost(rvh)->GetCapturerCount() > 0)
+ *link_mask |= chromeos::OUTPUT_TYPE_NETWORK;
+ }
+
+ return PP_OK;
+}
+
+int32_t PepperOutputProtectionMessageFilter::Delegate::OnEnableProtection(
+ uint32_t desired_method_mask) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ chromeos::OutputConfigurator* configurator =
+ ash::Shell::GetInstance()->output_configurator();
+ bool result = configurator->EnableOutputProtection(
+ GetClientId(), display_id_, desired_method_mask);
+ desired_method_mask_ = desired_method_mask;
+ return result ? PP_OK : PP_ERROR_FAILED;
+}
+
+void PepperOutputProtectionMessageFilter::Delegate::OnWindowHierarchyChanged(
+ const aura::WindowObserver::HierarchyChangeParams& params) {
+ content::RenderViewHost* rvh =
+ content::RenderViewHost::FromID(render_process_id_, render_view_id_);
+ if (!rvh) {
+ LOG(WARNING) << "RenderViewHost is not alive.";
+ return;
+ }
+
+ int64 new_display_id = 0;
+ if (!GetCurrentDisplayId(rvh, &new_display_id))
+ return;
+ if (display_id_ == new_display_id)
+ return;
+
+ if (desired_method_mask_ != chromeos::OUTPUT_PROTECTION_METHOD_NONE) {
+ // Display changed and should enable output protections on new display.
+ chromeos::OutputConfigurator* configurator =
+ ash::Shell::GetInstance()->output_configurator();
+ configurator->EnableOutputProtection(GetClientId(), new_display_id,
+ desired_method_mask_);
+ configurator->EnableOutputProtection(
+ GetClientId(),
+ display_id_,
+ chromeos::OUTPUT_PROTECTION_METHOD_NONE);
+ }
+ display_id_ = new_display_id;
+}
+#endif
PepperOutputProtectionMessageFilter::PepperOutputProtectionMessageFilter(
content::BrowserPpapiHost* host,
PP_Instance instance) {
-#if defined(OS_CHROMEOS) && defined(USE_ASH) && defined(USE_X11)
- client_id_ = 0;
+#if defined(OS_CHROMEOS)
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ int render_process_id = 0;
+ int render_view_id = 0;
host->GetRenderViewIDsForInstance(
- instance, &render_process_id_, &render_view_id_);
+ instance, &render_process_id, &render_view_id);
+ delegate_ = new Delegate(render_process_id, render_view_id);
#else
NOTIMPLEMENTED();
#endif
}
PepperOutputProtectionMessageFilter::~PepperOutputProtectionMessageFilter() {
-#if defined(OS_CHROMEOS) && defined(USE_ASH)
- if (client_id_ != 0) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI,
- FROM_HERE,
- base::Bind(&UnregisterClientOnUIThread, client_id_));
- }
+#if defined(OS_CHROMEOS)
+ content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE,
+ delegate_);
+ delegate_ = NULL;
#endif
}
@@ -125,46 +281,15 @@ int32_t PepperOutputProtectionMessageFilter::OnResourceMessageReceived(
return PP_ERROR_FAILED;
}
-#if defined(OS_CHROMEOS)
-chromeos::OutputConfigurator::OutputProtectionClientId
-PepperOutputProtectionMessageFilter::GetClientId() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- if (client_id_ == 0) {
-#if defined(USE_ASH) && defined(USE_X11)
- chromeos::OutputConfigurator* configurator =
- ash::Shell::GetInstance()->output_configurator();
- client_id_ = configurator->RegisterOutputProtectionClient();
-#endif
- }
- return client_id_;
-}
-#endif
-
int32_t PepperOutputProtectionMessageFilter::OnQueryStatus(
ppapi::host::HostMessageContext* context) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+#if defined(OS_CHROMEOS)
+ uint32_t link_mask = 0, protection_mask = 0;
+ int32_t result = delegate_->OnQueryStatus(&link_mask, &protection_mask);
-#if defined(OS_CHROMEOS) && defined(USE_ASH) && defined(USE_X11)
ppapi::host::ReplyMessageContext reply_context =
context->MakeReplyMessageContext();
- uint32_t link_mask = 0, protection_mask = 0;
- chromeos::OutputConfigurator* configurator =
- ash::Shell::GetInstance()->output_configurator();
- bool result = configurator->QueryOutputProtectionStatus(
- GetClientId(), &link_mask, &protection_mask);
-
- // If we successfully retrieved the device level status, check for capturers.
- if (result) {
- // Ensure the RenderViewHost is still alive.
- content::RenderViewHost* rvh =
- content::RenderViewHost::FromID(render_process_id_, render_view_id_);
- if (rvh) {
- if (content::WebContents::FromRenderViewHost(rvh)->GetCapturerCount() > 0)
- link_mask |= chromeos::OUTPUT_TYPE_NETWORK;
- }
- }
-
- reply_context.params.set_result(result ? PP_OK : PP_ERROR_FAILED);
+ reply_context.params.set_result(result);
SendReply(
reply_context,
PpapiPluginMsg_OutputProtection_QueryStatusReply(
@@ -179,16 +304,11 @@ int32_t PepperOutputProtectionMessageFilter::OnQueryStatus(
int32_t PepperOutputProtectionMessageFilter::OnEnableProtection(
ppapi::host::HostMessageContext* context,
uint32_t desired_method_mask) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-#if defined(OS_CHROMEOS) && defined(USE_ASH) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
ppapi::host::ReplyMessageContext reply_context =
context->MakeReplyMessageContext();
- chromeos::OutputConfigurator* configurator =
- ash::Shell::GetInstance()->output_configurator();
- bool result = configurator->EnableOutputProtection(
- GetClientId(), desired_method_mask);
- reply_context.params.set_result(result ? PP_OK : PP_ERROR_FAILED);
+ int32_t result = delegate_->OnEnableProtection(desired_method_mask);
+ reply_context.params.set_result(result);
SendReply(
reply_context,
PpapiPluginMsg_OutputProtection_EnableProtectionReply());
diff --git a/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h b/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h
index be5ef16..6994d85 100644
--- a/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h
+++ b/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h
@@ -31,6 +31,10 @@ class PepperOutputProtectionMessageFilter
PP_Instance instance);
private:
+#if defined(OS_CHROMEOS)
+ class Delegate;
+#endif
+
// ppapi::host::ResourceMessageFilter overrides.
virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
const IPC::Message& msg) OVERRIDE;
@@ -40,19 +44,13 @@ class PepperOutputProtectionMessageFilter
virtual ~PepperOutputProtectionMessageFilter();
-#if defined(OS_CHROMEOS)
- chromeos::OutputConfigurator::OutputProtectionClientId GetClientId();
-#endif
int32_t OnQueryStatus(ppapi::host::HostMessageContext* context);
int32_t OnEnableProtection(ppapi::host::HostMessageContext* context,
uint32_t desired_method_mask);
#if defined(OS_CHROMEOS)
- chromeos::OutputConfigurator::OutputProtectionClientId client_id_;
-
- // Used to lookup the WebContents associated with this PP_Instance.
- int render_process_id_;
- int render_view_id_;
+ // Delegator. Should be deleted in UI thread.
+ Delegate* delegate_;
#endif
DISALLOW_COPY_AND_ASSIGN(PepperOutputProtectionMessageFilter);
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index 4676246..1a3cc31 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -299,21 +299,72 @@ void OutputConfigurator::Start(uint32 background_color_argb) {
NotifyObservers(success, new_state);
}
+bool OutputConfigurator::ApplyProtections(const DisplayProtections& requests) {
+ for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin();
+ it != cached_outputs_.end(); ++it) {
+ RROutput this_id = it->output;
+ uint32_t all_desired = 0;
+ DisplayProtections::const_iterator request_it = requests.find(
+ it->display_id);
+ if (request_it != requests.end())
+ all_desired = request_it->second;
+ switch (it->type) {
+ case OUTPUT_TYPE_UNKNOWN:
+ return false;
+ // DisplayPort, DVI, and HDMI all support HDCP.
+ case OUTPUT_TYPE_DISPLAYPORT:
+ case OUTPUT_TYPE_DVI:
+ case OUTPUT_TYPE_HDMI: {
+ HDCPState new_desired_state =
+ (all_desired & OUTPUT_PROTECTION_METHOD_HDCP) ?
+ HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED;
+ if (!delegate_->SetHDCPState(this_id, new_desired_state))
+ return false;
+ break;
+ }
+ case OUTPUT_TYPE_INTERNAL:
+ case OUTPUT_TYPE_VGA:
+ case OUTPUT_TYPE_NETWORK:
+ // No protections for these types. Do nothing.
+ break;
+ case OUTPUT_TYPE_NONE:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ return true;
+}
+
OutputConfigurator::OutputProtectionClientId
OutputConfigurator::RegisterOutputProtectionClient() {
if (!configure_display_)
- return 0;
+ return kInvalidClientId;
return next_output_protection_client_id_++;
}
void OutputConfigurator::UnregisterOutputProtectionClient(
OutputProtectionClientId client_id) {
- EnableOutputProtection(client_id, OUTPUT_PROTECTION_METHOD_NONE);
+ client_protection_requests_.erase(client_id);
+
+ DisplayProtections protections;
+ for (ProtectionRequests::const_iterator it =
+ client_protection_requests_.begin();
+ it != client_protection_requests_.end();
+ ++it) {
+ for (DisplayProtections::const_iterator it2 = it->second.begin();
+ it2 != it->second.end(); ++it2) {
+ protections[it2->first] |= it2->second;
+ }
+ }
+
+ ApplyProtections(protections);
}
bool OutputConfigurator::QueryOutputProtectionStatus(
OutputProtectionClientId client_id,
+ int64 display_id,
uint32_t* link_mask,
uint32_t* protection_mask) {
if (!configure_display_)
@@ -325,6 +376,8 @@ bool OutputConfigurator::QueryOutputProtectionStatus(
for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin();
it != cached_outputs_.end(); ++it) {
RROutput this_id = it->output;
+ if (it->display_id != display_id)
+ continue;
*link_mask |= it->type;
switch (it->type) {
case OUTPUT_TYPE_UNKNOWN:
@@ -356,7 +409,9 @@ bool OutputConfigurator::QueryOutputProtectionStatus(
// Don't reveal protections requested by other clients.
ProtectionRequests::iterator it = client_protection_requests_.find(client_id);
if (it != client_protection_requests_.end()) {
- uint32_t requested_mask = it->second;
+ uint32_t requested_mask = 0;
+ if (it->second.find(display_id) != it->second.end())
+ requested_mask = it->second[display_id];
*protection_mask = enabled & ~unfulfilled & requested_mask;
} else {
*protection_mask = 0;
@@ -366,52 +421,39 @@ bool OutputConfigurator::QueryOutputProtectionStatus(
bool OutputConfigurator::EnableOutputProtection(
OutputProtectionClientId client_id,
+ int64 display_id,
uint32_t desired_method_mask) {
if (!configure_display_)
return false;
- uint32_t all_desired = desired_method_mask;
+ DisplayProtections protections;
for (ProtectionRequests::const_iterator it =
client_protection_requests_.begin();
it != client_protection_requests_.end();
++it) {
- if (it->first != client_id)
- all_desired |= it->second;
+ for (DisplayProtections::const_iterator it2 = it->second.begin();
+ it2 != it->second.end(); ++it2) {
+ if (it->first == client_id && it2->first == display_id)
+ continue;
+ protections[it2->first] |= it2->second;
+ }
}
+ protections[display_id] |= desired_method_mask;
- for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin();
- it != cached_outputs_.end(); ++it) {
- RROutput this_id = it->output;
- switch (it->type) {
- case OUTPUT_TYPE_UNKNOWN:
- return false;
- // DisplayPort, DVI, and HDMI all support HDCP.
- case OUTPUT_TYPE_DISPLAYPORT:
- case OUTPUT_TYPE_DVI:
- case OUTPUT_TYPE_HDMI: {
- HDCPState new_desired_state =
- (all_desired & OUTPUT_PROTECTION_METHOD_HDCP) ?
- HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED;
- if (!delegate_->SetHDCPState(this_id, new_desired_state))
- return false;
- break;
- }
- case OUTPUT_TYPE_INTERNAL:
- case OUTPUT_TYPE_VGA:
- case OUTPUT_TYPE_NETWORK:
- // No protections for these types. Do nothing.
- break;
- case OUTPUT_TYPE_NONE:
- NOTREACHED();
- break;
+ if (!ApplyProtections(protections))
+ return false;
+
+ if (desired_method_mask == OUTPUT_PROTECTION_METHOD_NONE) {
+ if (client_protection_requests_.find(client_id) !=
+ client_protection_requests_.end()) {
+ client_protection_requests_[client_id].erase(display_id);
+ if (client_protection_requests_[client_id].size() == 0)
+ client_protection_requests_.erase(client_id);
}
+ } else {
+ client_protection_requests_[client_id][display_id] = desired_method_mask;
}
- if (desired_method_mask == OUTPUT_PROTECTION_METHOD_NONE)
- client_protection_requests_.erase(client_id);
- else
- client_protection_requests_[client_id] = desired_method_mask;
-
return true;
}
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
index 3491344..ef5085e 100644
--- a/chromeos/display/output_configurator.h
+++ b/chromeos/display/output_configurator.h
@@ -68,6 +68,7 @@ class CHROMEOS_EXPORT OutputConfigurator
public base::MessagePumpObserver {
public:
typedef uint64_t OutputProtectionClientId;
+ static const OutputProtectionClientId kInvalidClientId = 0;
struct ModeInfo {
ModeInfo();
@@ -413,6 +414,7 @@ class CHROMEOS_EXPORT OutputConfigurator
// Returns true on success.
bool QueryOutputProtectionStatus(
OutputProtectionClientId client_id,
+ int64 display_id,
uint32_t* link_mask,
uint32_t* protection_mask);
@@ -422,12 +424,15 @@ class CHROMEOS_EXPORT OutputConfigurator
// Returns true when the protection request has been made.
bool EnableOutputProtection(
OutputProtectionClientId client_id,
+ int64 display_id,
uint32_t desired_protection_mask);
private:
- // Mapping a client to its protection request bitmask.
- typedef std::map<chromeos::OutputConfigurator::OutputProtectionClientId,
- uint32_t> ProtectionRequests;
+ // Mapping a display_id to a protection request bitmask.
+ typedef std::map<int64, uint32_t> DisplayProtections;
+ // Mapping a client to its protection request.
+ typedef std::map<OutputProtectionClientId,
+ DisplayProtections> ProtectionRequests;
// Updates |cached_outputs_| to contain currently-connected outputs. Calls
// |delegate_->GetOutputs()| and then does additional work, like finding the
@@ -487,6 +492,9 @@ class CHROMEOS_EXPORT OutputConfigurator
float GetMirroredDisplayAreaRatio(
const OutputConfigurator::OutputSnapshot& output);
+ // Applies output protections according to requests.
+ bool ApplyProtections(const DisplayProtections& requests);
+
StateController* state_controller_;
SoftwareMirroringController* mirroring_controller_;
scoped_ptr<Delegate> delegate_;
diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc
index 4e23345..28f0553 100644
--- a/chromeos/display/output_configurator_unittest.cc
+++ b/chromeos/display/output_configurator_unittest.cc
@@ -358,6 +358,7 @@ class OutputConfiguratorTest : public testing::Test {
o->is_aspect_preserving_scaling = true;
o->mode_infos[kSmallModeId] = small_mode_info;
o->has_display_id = true;
+ o->display_id = 123;
o->index = 0;
o = &outputs_[1];
@@ -371,6 +372,7 @@ class OutputConfiguratorTest : public testing::Test {
o->mode_infos[kSmallModeId] = small_mode_info;
o->mode_infos[kBigModeId] = big_mode_info;
o->has_display_id = true;
+ o->display_id = 456;
o->index = 1;
UpdateOutputs(2, false);
@@ -1120,7 +1122,9 @@ TEST_F(OutputConfiguratorTest, OutputProtection) {
EXPECT_NE(kNoActions, delegate_->GetActionsAndClear());
uint32_t link_mask = 0;
uint32_t protection_mask = 0;
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id,
+ outputs_[0].display_id,
+ &link_mask,
&protection_mask));
EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL), link_mask);
EXPECT_EQ(static_cast<uint32_t>(OUTPUT_PROTECTION_METHOD_NONE),
@@ -1130,28 +1134,38 @@ TEST_F(OutputConfiguratorTest, OutputProtection) {
// Two outputs.
UpdateOutputs(2, true);
EXPECT_NE(kNoActions, delegate_->GetActionsAndClear());
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id,
+ outputs_[1].display_id,
+ &link_mask,
&protection_mask));
- EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL | OUTPUT_TYPE_HDMI),
+ EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI),
link_mask);
EXPECT_EQ(static_cast<uint32_t>(OUTPUT_PROTECTION_METHOD_NONE),
protection_mask);
EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
EXPECT_TRUE(
- configurator_.EnableOutputProtection(id, OUTPUT_PROTECTION_METHOD_HDCP));
+ configurator_.EnableOutputProtection(id,
+ outputs_[1].display_id,
+ OUTPUT_PROTECTION_METHOD_HDCP));
EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output, HDCP_STATE_DESIRED),
delegate_->GetActionsAndClear());
// Enable protection.
delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id,
+ outputs_[1].display_id,
+ &link_mask,
&protection_mask));
- EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL | OUTPUT_TYPE_HDMI),
- link_mask);
+ EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI), link_mask);
EXPECT_EQ(static_cast<uint32_t>(OUTPUT_PROTECTION_METHOD_HDCP),
protection_mask);
EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
+
+ // Protections should be disabled after unregister.
+ configurator_.UnregisterOutputProtectionClient(id);
+ EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output, HDCP_STATE_UNDESIRED),
+ delegate_->GetActionsAndClear());
}
TEST_F(OutputConfiguratorTest, OutputProtectionTwoClients) {
@@ -1169,6 +1183,7 @@ TEST_F(OutputConfiguratorTest, OutputProtectionTwoClients) {
// Clients never know state enableness for methods that they didn't request.
EXPECT_TRUE(
configurator_.EnableOutputProtection(client1,
+ outputs_[1].display_id,
OUTPUT_PROTECTION_METHOD_HDCP));
EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output,
HDCP_STATE_DESIRED).c_str(),
@@ -1177,27 +1192,31 @@ TEST_F(OutputConfiguratorTest, OutputProtectionTwoClients) {
uint32_t link_mask = 0;
uint32_t protection_mask = 0;
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client1, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client1,
+ outputs_[1].display_id,
+ &link_mask,
&protection_mask));
- EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL | OUTPUT_TYPE_HDMI),
- link_mask);
+ EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI), link_mask);
EXPECT_EQ(OUTPUT_PROTECTION_METHOD_HDCP, protection_mask);
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client2, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client2,
+ outputs_[1].display_id,
+ &link_mask,
&protection_mask));
- EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL | OUTPUT_TYPE_HDMI),
- link_mask);
+ EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI), link_mask);
EXPECT_EQ(OUTPUT_PROTECTION_METHOD_NONE, protection_mask);
// Protections will be disabled only if no more clients request them.
EXPECT_TRUE(
configurator_.EnableOutputProtection(client2,
+ outputs_[1].display_id,
OUTPUT_PROTECTION_METHOD_NONE));
EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output,
HDCP_STATE_DESIRED).c_str(),
delegate_->GetActionsAndClear());
EXPECT_TRUE(
configurator_.EnableOutputProtection(client1,
+ outputs_[1].display_id,
OUTPUT_PROTECTION_METHOD_NONE));
EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output,
HDCP_STATE_UNDESIRED).c_str(),