summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/component_updater/ppapi_utils.cc1
-rw-r--r--chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc10
-rw-r--r--chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc180
-rw-r--r--chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h56
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/test/ppapi/ppapi_browsertest.cc4
-rw-r--r--chromeos/display/output_configurator.cc118
-rw-r--r--chromeos/display/output_configurator.h71
-rw-r--r--chromeos/display/output_configurator_unittest.cc8
-rw-r--r--chromeos/display/real_output_configurator_delegate.cc104
-rw-r--r--chromeos/display/real_output_configurator_delegate.h2
-rw-r--r--content/renderer/pepper/plugin_module.cc1
-rw-r--r--content/renderer/pepper/resource_creation_impl.cc5
-rw-r--r--content/renderer/pepper/resource_creation_impl.h2
-rw-r--r--native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc6
-rw-r--r--ppapi/cpp/private/output_protection_private.cc59
-rw-r--r--ppapi/cpp/private/output_protection_private.h28
-rw-r--r--ppapi/ppapi_proxy.gypi2
-rw-r--r--ppapi/ppapi_shared.gypi2
-rw-r--r--ppapi/ppapi_sources.gypi5
-rw-r--r--ppapi/proxy/interface_list.cc1
-rw-r--r--ppapi/proxy/output_protection_resource.cc105
-rw-r--r--ppapi/proxy/output_protection_resource.h58
-rw-r--r--ppapi/proxy/ppapi_messages.h11
-rw-r--r--ppapi/proxy/resource_creation_proxy.cc7
-rw-r--r--ppapi/proxy/resource_creation_proxy.h2
-rw-r--r--ppapi/shared_impl/resource.h1
-rw-r--r--ppapi/tests/all_c_includes.h1
-rw-r--r--ppapi/tests/test_output_protection_private.cc60
-rw-r--r--ppapi/tests/test_output_protection_private.h29
-rw-r--r--ppapi/thunk/interfaces_ppb_private.h3
-rw-r--r--ppapi/thunk/ppb_output_protection_api.h32
-rw-r--r--ppapi/thunk/resource_creation_api.h1
33 files changed, 972 insertions, 5 deletions
diff --git a/chrome/browser/component_updater/ppapi_utils.cc b/chrome/browser/component_updater/ppapi_utils.cc
index 6f9638f..b1ce949 100644
--- a/chrome/browser/component_updater/ppapi_utils.cc
+++ b/chrome/browser/component_updater/ppapi_utils.cc
@@ -87,6 +87,7 @@
#include "ppapi/c/private/ppb_flash_message_loop.h"
#include "ppapi/c/private/ppb_flash_print.h"
#include "ppapi/c/private/ppb_host_resolver_private.h"
+#include "ppapi/c/private/ppb_output_protection_private.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/c/private/ppb_proxy_private.h"
#include "ppapi/c/private/ppb_talk_private.h"
diff --git a/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc b/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc
index 6887303..f634338 100644
--- a/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc
+++ b/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/renderer_host/pepper/pepper_flash_browser_host.h"
#include "chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h"
#include "chrome/browser/renderer_host/pepper/pepper_flash_drm_host.h"
+#include "chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h"
#include "chrome/browser/renderer_host/pepper/pepper_platform_verification_message_filter.h"
#include "chrome/browser/renderer_host/pepper/pepper_talk_host.h"
#include "content/public/browser/browser_ppapi_host.h"
@@ -83,6 +84,15 @@ scoped_ptr<ResourceHost> ChromeBrowserPepperHostFactory::CreateResourceHost(
case PpapiHostMsg_Talk_Create::ID:
return scoped_ptr<ResourceHost>(new PepperTalkHost(
host_, instance, params.pp_resource()));
+#if defined(OS_CHROMEOS)
+ case PpapiHostMsg_OutputProtection_Create::ID: {
+ scoped_refptr<ResourceMessageFilter> output_protection_filter(
+ new PepperOutputProtectionMessageFilter());
+ return scoped_ptr<ResourceHost>(new MessageFilterHost(
+ host_->GetPpapiHost(), instance, params.pp_resource(),
+ output_protection_filter));
+ }
+#endif
}
}
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
new file mode 100644
index 0000000..9167d3d
--- /dev/null
+++ b/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc
@@ -0,0 +1,180 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h"
+
+#include "build/build_config.h"
+#include "content/public/browser/browser_thread.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_output_protection_private.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+#if defined(USE_ASH) && defined(OS_CHROMEOS)
+#include "ash/shell.h"
+#include "ash/shell_delegate.h"
+#include "chromeos/display/output_configurator.h"
+#endif
+
+namespace chrome {
+
+namespace {
+
+#if defined(OS_CHROMEOS)
+COMPILE_ASSERT(
+ static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE) ==
+ static_cast<int>(chromeos::OUTPUT_TYPE_NONE),
+ PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE);
+COMPILE_ASSERT(
+ static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_UNKNOWN) ==
+ static_cast<int>(chromeos::OUTPUT_TYPE_UNKNOWN),
+ PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_UNKNOWN);
+COMPILE_ASSERT(
+ static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_INTERNAL) ==
+ static_cast<int>(chromeos::OUTPUT_TYPE_INTERNAL),
+ PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_INTERNAL);
+COMPILE_ASSERT(
+ static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA) ==
+ static_cast<int>(chromeos::OUTPUT_TYPE_VGA),
+ PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA);
+COMPILE_ASSERT(
+ static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI) ==
+ static_cast<int>(chromeos::OUTPUT_TYPE_HDMI),
+ PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI);
+COMPILE_ASSERT(
+ static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DVI) ==
+ static_cast<int>(chromeos::OUTPUT_TYPE_DVI),
+ PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DVI);
+COMPILE_ASSERT(
+ static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT) ==
+ static_cast<int>(chromeos::OUTPUT_TYPE_DISPLAYPORT),
+ PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT);
+COMPILE_ASSERT(
+ static_cast<int>(PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE) ==
+ static_cast<int>(chromeos::OUTPUT_PROTECTION_METHOD_NONE),
+ PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE);
+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);
+#endif
+
+#if defined(OS_CHROMEOS) && defined(USE_ASH) && defined(USE_X11)
+void UnregisterClientOnUIThread(
+ chromeos::OutputConfigurator::OutputProtectionClientId client_id) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ chromeos::OutputConfigurator* configurator =
+ ash::Shell::GetInstance()->output_configurator();
+ configurator->UnregisterOutputProtectionClient(client_id);
+}
+#endif
+
+} // namespace
+
+PepperOutputProtectionMessageFilter::PepperOutputProtectionMessageFilter() {
+#if defined(OS_CHROMEOS) && defined(USE_ASH) && defined(USE_X11)
+ client_id_ = 0;
+#else
+ NOTIMPLEMENTED();
+#endif
+}
+
+PepperOutputProtectionMessageFilter::~PepperOutputProtectionMessageFilter() {
+#if defined(OS_CHROMEOS)
+ if (client_id_ != 0) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&UnregisterClientOnUIThread, client_id_));
+ }
+#endif
+}
+
+scoped_refptr<base::TaskRunner>
+PepperOutputProtectionMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& message) {
+ return content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::UI);
+}
+
+int32_t PepperOutputProtectionMessageFilter::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) {
+ IPC_BEGIN_MESSAGE_MAP(PepperOutputProtectionMessageFilter, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+ PpapiHostMsg_OutputProtection_QueryStatus,
+ OnQueryStatus);
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+ PpapiHostMsg_OutputProtection_EnableProtection,
+ OnEnableProtection);
+ IPC_END_MESSAGE_MAP()
+ 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) && 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);
+ reply_context.params.set_result(result ? PP_OK : PP_ERROR_FAILED);
+ SendReply(
+ reply_context,
+ PpapiPluginMsg_OutputProtection_QueryStatusReply(
+ link_mask, protection_mask));
+ return PP_OK_COMPLETIONPENDING;
+#else
+ NOTIMPLEMENTED();
+ return PP_ERROR_NOTSUPPORTED;
+#endif
+}
+
+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)
+ 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);
+ SendReply(
+ reply_context,
+ PpapiPluginMsg_OutputProtection_EnableProtectionReply());
+ return PP_OK_COMPLETIONPENDING;
+#else
+ NOTIMPLEMENTED();
+ return PP_ERROR_NOTSUPPORTED;
+#endif
+}
+
+} // namespace chrome
+
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
new file mode 100644
index 0000000..d64260f
--- /dev/null
+++ b/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_OUTPUT_PROTECTION_MESSAGE_FILTER_H_
+#define CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_OUTPUT_PROTECTION_MESSAGE_FILTER_H_
+
+#include "content/public/browser/browser_thread.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/resource_message_filter.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/display/output_configurator.h"
+#endif
+
+namespace ppapi {
+namespace host {
+class PpapiHost;
+}
+}
+
+namespace chrome {
+
+class PepperOutputProtectionMessageFilter
+ : public ppapi::host::ResourceMessageFilter {
+ public:
+ PepperOutputProtectionMessageFilter();
+
+ private:
+ // ppapi::host::ResourceMessageFilter overrides.
+ virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) OVERRIDE;
+ virtual int32_t OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) OVERRIDE;
+
+ 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_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(PepperOutputProtectionMessageFilter);
+};
+
+} // namespace chrome
+
+#endif // CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_OUTPUT_PROTECTION_MESSAGE_FILTER_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 0cf2924..c9dcfd0 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1805,6 +1805,8 @@
'browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h',
'browser/renderer_host/pepper/pepper_flash_drm_host.cc',
'browser/renderer_host/pepper/pepper_flash_drm_host.h',
+ 'browser/renderer_host/pepper/pepper_output_protection_message_filter.cc',
+ 'browser/renderer_host/pepper/pepper_output_protection_message_filter.h',
'browser/renderer_host/pepper/pepper_platform_verification_message_filter.cc',
'browser/renderer_host/pepper/pepper_platform_verification_message_filter.h',
'browser/renderer_host/pepper/pepper_talk_host.cc',
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index 67938819..162e4cc 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -1540,3 +1540,7 @@ IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, FlashDRM) {
TEST_PPAPI_IN_PROCESS(TalkPrivate)
TEST_PPAPI_OUT_OF_PROCESS(TalkPrivate)
+
+#if defined(OS_CHROMEOS)
+TEST_PPAPI_OUT_OF_PROCESS(OutputProtectionPrivate)
+#endif
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index 92637a6..44cf4d9 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -132,6 +132,7 @@ OutputConfigurator::OutputSnapshot::OutputSnapshot()
height_mm(0),
is_internal(false),
is_aspect_preserving_scaling(false),
+ type(OUTPUT_TYPE_UNKNOWN),
touch_device_id(0),
display_id(0),
has_display_id(false),
@@ -227,7 +228,8 @@ OutputConfigurator::OutputConfigurator()
configure_display_(base::SysInfo::IsRunningOnChromeOS()),
xrandr_event_base_(0),
output_state_(STATE_INVALID),
- power_state_(DISPLAY_POWER_ALL_ON) {
+ power_state_(DISPLAY_POWER_ALL_ON),
+ next_output_protection_client_id_(1) {
}
OutputConfigurator::~OutputConfigurator() {}
@@ -273,6 +275,120 @@ void OutputConfigurator::Start(uint32 background_color_argb) {
NotifyObservers(success, new_state);
}
+OutputConfigurator::OutputProtectionClientId
+OutputConfigurator::RegisterOutputProtectionClient() {
+ if (!configure_display_)
+ return 0;
+
+ return next_output_protection_client_id_++;
+}
+
+void OutputConfigurator::UnregisterOutputProtectionClient(
+ OutputProtectionClientId client_id) {
+ EnableOutputProtection(client_id, OUTPUT_PROTECTION_METHOD_NONE);
+}
+
+bool OutputConfigurator::QueryOutputProtectionStatus(
+ OutputProtectionClientId client_id,
+ uint32_t* link_mask,
+ uint32_t* protection_mask) {
+ if (!configure_display_)
+ return false;
+
+ uint32_t enabled = 0;
+ uint32_t unfulfilled = 0;
+ *link_mask = 0;
+ for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin();
+ it != cached_outputs_.end(); ++it) {
+ RROutput this_id = it->output;
+ *link_mask |= it->type;
+ switch (it->type) {
+ case OUTPUT_TYPE_UNKNOWN:
+ return false;
+ // HDMI and DisplayPort both support HDCP.
+ case OUTPUT_TYPE_HDMI:
+ case OUTPUT_TYPE_DISPLAYPORT: {
+ HDCPState state;
+ if (!delegate_->GetHDCPState(this_id, &state))
+ return false;
+ if (state == HDCP_STATE_ENABLED)
+ enabled |= OUTPUT_PROTECTION_METHOD_HDCP;
+ else
+ unfulfilled |= OUTPUT_PROTECTION_METHOD_HDCP;
+ break;
+ }
+ case OUTPUT_TYPE_INTERNAL:
+ case OUTPUT_TYPE_VGA:
+ case OUTPUT_TYPE_DVI:
+ // No protections for these types. Do nothing.
+ break;
+ case OUTPUT_TYPE_NONE:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ // 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;
+ *protection_mask = enabled & ~unfulfilled & requested_mask;
+ } else {
+ *protection_mask = 0;
+ }
+ return true;
+}
+
+bool OutputConfigurator::EnableOutputProtection(
+ OutputProtectionClientId client_id,
+ uint32_t desired_method_mask) {
+ if (!configure_display_)
+ return false;
+
+ uint32_t all_desired = desired_method_mask;
+ 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 (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;
+ // HDMI and DisplayPort both support HDCP.
+ case OUTPUT_TYPE_HDMI:
+ case OUTPUT_TYPE_DISPLAYPORT: {
+ 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_DVI:
+ // No protections for these types. Do nothing.
+ break;
+ case OUTPUT_TYPE_NONE:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ 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;
+}
+
void OutputConfigurator::Stop() {
configure_display_ = false;
}
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
index ec45fc9..87071c1 100644
--- a/chromeos/display/output_configurator.h
+++ b/chromeos/display/output_configurator.h
@@ -36,12 +36,38 @@ enum OutputState {
STATE_DUAL_EXTENDED,
};
+// Video output types.
+enum OutputType {
+ OUTPUT_TYPE_NONE = 0,
+ OUTPUT_TYPE_UNKNOWN = 1 << 0,
+ OUTPUT_TYPE_INTERNAL = 1 << 1,
+ OUTPUT_TYPE_VGA = 1 << 2,
+ OUTPUT_TYPE_HDMI = 1 << 3,
+ OUTPUT_TYPE_DVI = 1 << 4,
+ OUTPUT_TYPE_DISPLAYPORT = 1 << 5,
+};
+
+// Content protection methods applied on video output.
+enum OutputProtectionMethod {
+ OUTPUT_PROTECTION_METHOD_NONE = 0,
+ OUTPUT_PROTECTION_METHOD_HDCP = 1 << 0,
+};
+
+// HDCP protection state.
+enum HDCPState {
+ HDCP_STATE_UNDESIRED,
+ HDCP_STATE_DESIRED,
+ HDCP_STATE_ENABLED
+};
+
// This class interacts directly with the underlying Xrandr API to manipulate
// CTRCs and Outputs.
class CHROMEOS_EXPORT OutputConfigurator
: public base::MessageLoop::Dispatcher,
public base::MessagePumpObserver {
public:
+ typedef uint64_t OutputProtectionClientId;
+
struct ModeInfo {
ModeInfo();
ModeInfo(int width, int height, bool interlaced, float refresh_rate);
@@ -95,9 +121,13 @@ class CHROMEOS_EXPORT OutputConfigurator
uint64 width_mm;
uint64 height_mm;
+ // TODO(kcwu): Remove this. Check type == OUTPUT_TYPE_INTERNAL instead.
bool is_internal;
bool is_aspect_preserving_scaling;
+ // The type of output.
+ OutputType type;
+
// Map from mode IDs to details about the corresponding modes.
ModeInfoMap mode_infos;
@@ -223,6 +253,12 @@ class CHROMEOS_EXPORT OutputConfigurator
// Sends a D-Bus message to the power manager telling it that the
// machine is or is not projecting.
virtual void SendProjectingStateToPowerManager(bool projecting) = 0;
+
+ // Gets HDCP state of output.
+ virtual bool GetHDCPState(RROutput id, HDCPState* state) = 0;
+
+ // Sets HDCP state of output.
+ virtual bool SetHDCPState(RROutput id, HDCPState state) = 0;
};
// Helper class used by tests.
@@ -362,7 +398,36 @@ class CHROMEOS_EXPORT OutputConfigurator
// so that time-consuming ConfigureOutputs() won't be called multiple times.
void ScheduleConfigureOutputs();
+ // Registers a client for output protection and requests a client id. Returns
+ // 0 if requesting failed.
+ OutputProtectionClientId RegisterOutputProtectionClient();
+
+ // Unregisters the client.
+ void UnregisterOutputProtectionClient(OutputProtectionClientId client_id);
+
+ // Queries link status and protection status.
+ // |link_mask| is the type of connected output links, which is a bitmask of
+ // OutputType values. |protection_mask| is the desired protection methods,
+ // which is a bitmask of the OutputProtectionMethod values.
+ // Returns true on success.
+ bool QueryOutputProtectionStatus(
+ OutputProtectionClientId client_id,
+ uint32_t* link_mask,
+ uint32_t* protection_mask);
+
+ // Requests the desired protection methods.
+ // |protection_mask| is the desired protection methods, which is a bitmask
+ // of the OutputProtectionMethod values.
+ // Returns true when the protection request has been made.
+ bool EnableOutputProtection(
+ OutputProtectionClientId client_id,
+ uint32_t desired_protection_mask);
+
private:
+ // Mapping a client to its protection request bitmask.
+ typedef std::map<chromeos::OutputConfigurator::OutputProtectionClientId,
+ uint32_t> ProtectionRequests;
+
// Updates |cached_outputs_| to contain currently-connected outputs. Calls
// |delegate_->GetOutputs()| and then does additional work, like finding the
// mirror mode and setting user-preferred modes. Note that the server must be
@@ -463,6 +528,12 @@ class CHROMEOS_EXPORT OutputConfigurator
// Dispatch().
scoped_ptr<base::OneShotTimer<OutputConfigurator> > configure_timer_;
+ // Id for next output protection client.
+ OutputProtectionClientId next_output_protection_client_id_;
+
+ // Output protection requests of each client.
+ ProtectionRequests client_protection_requests_;
+
DISALLOW_COPY_AND_ASSIGN(OutputConfigurator);
};
diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc
index d7f844d..18b2bdc 100644
--- a/chromeos/display/output_configurator_unittest.cc
+++ b/chromeos/display/output_configurator_unittest.cc
@@ -167,6 +167,14 @@ class TestDelegate : public OutputConfigurator::Delegate {
AppendAction(projecting ? kProjectingOn : kProjectingOff);
}
+ virtual bool GetHDCPState(RROutput id, HDCPState* state) OVERRIDE {
+ return true;
+ }
+
+ virtual bool SetHDCPState(RROutput id, HDCPState state) OVERRIDE {
+ return true;
+ }
+
private:
struct ModeDetails {
ModeDetails() : width(0), height(0), interlaced(false) {}
diff --git a/chromeos/display/real_output_configurator_delegate.cc b/chromeos/display/real_output_configurator_delegate.cc
index fd7d7b0..5bb4757 100644
--- a/chromeos/display/real_output_configurator_delegate.cc
+++ b/chromeos/display/real_output_configurator_delegate.cc
@@ -18,6 +18,7 @@
#include "base/logging.h"
#include "base/message_loop/message_pump_x11.h"
#include "base/x11/edid_parser_x11.h"
+#include "base/x11/x11_error_tracker.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager_client.h"
#include "chromeos/display/output_util.h"
@@ -31,6 +32,17 @@ const float kMmInInch = 25.4;
const float kDpi96 = 96.0;
const float kPixelsToMmScale = kMmInInch / kDpi96;
+// Prefixes of output name
+const char kOutputName_VGA[] = "VGA";
+const char kOutputName_HDMI[] = "HDMI";
+const char kOutputName_DVI[] = "DVI";
+const char kOutputName_DisplayPort[] = "DP";
+
+const char kContentProtectionAtomName[] = "Content Protection";
+const char kProtectionUndesiredAtomName[] = "Undesired";
+const char kProtectionDesiredAtomName[] = "Desired";
+const char kProtectionEnabledAtomName[] = "Enabled";
+
bool IsInternalOutput(const XRROutputInfo* output_info) {
return IsInternalOutputName(std::string(output_info->name));
}
@@ -304,9 +316,101 @@ RealOutputConfiguratorDelegate::InitOutputSnapshot(
LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode;
}
+ std::string name(info->name);
+ if (output.is_internal) {
+ output.type = OUTPUT_TYPE_INTERNAL;
+ } else if (name.find(kOutputName_VGA) == 0) {
+ output.type = OUTPUT_TYPE_VGA;
+ } else if (name.find(kOutputName_HDMI) == 0) {
+ output.type = OUTPUT_TYPE_HDMI;
+ } else if (name.find(kOutputName_DVI) == 0) {
+ output.type = OUTPUT_TYPE_DVI;
+ } else if (name.find(kOutputName_DisplayPort) == 0) {
+ output.type = OUTPUT_TYPE_DISPLAYPORT;
+ } else {
+ LOG(ERROR) << "Unknown link type: " << name;
+ output.type = OUTPUT_TYPE_UNKNOWN;
+ }
+
return output;
}
+bool RealOutputConfiguratorDelegate::GetHDCPState(RROutput id,
+ HDCPState* state) {
+ unsigned char* values = NULL;
+ int actual_format = 0;
+ unsigned long nitems = 0;
+ unsigned long bytes_after = 0;
+ Atom actual_type = None;
+ int success = 0;
+ // TODO(kcwu): Use X11AtomCache to save round trip time of XInternAtom.
+ Atom prop = XInternAtom(display_, kContentProtectionAtomName, False);
+
+ bool ok = true;
+ // TODO(kcwu): Move this to x11_util (similar method calls in this file and
+ // output_util.cc)
+ success = XRRGetOutputProperty(display_, id, prop, 0, 100, False,
+ False, AnyPropertyType, &actual_type,
+ &actual_format, &nitems, &bytes_after,
+ &values);
+ if (actual_type == None) {
+ LOG(ERROR) << "Property '" << kContentProtectionAtomName
+ << "' does not exist";
+ ok = false;
+ } else if (success == Success && actual_type == XA_ATOM &&
+ actual_format == 32 && nitems == 1) {
+ Atom value = reinterpret_cast<Atom*>(values)[0];
+ if (value == XInternAtom(display_, kProtectionUndesiredAtomName, False)) {
+ *state = HDCP_STATE_UNDESIRED;
+ } else if (value == XInternAtom(display_, kProtectionDesiredAtomName,
+ False)) {
+ *state = HDCP_STATE_DESIRED;
+ } else if (value == XInternAtom(display_, kProtectionEnabledAtomName,
+ False)) {
+ *state = HDCP_STATE_ENABLED;
+ } else {
+ LOG(ERROR) << "Unknown " << kContentProtectionAtomName << " value: "
+ << value;
+ ok = false;
+ }
+ } else {
+ LOG(ERROR) << "XRRGetOutputProperty failed";
+ ok = false;
+ }
+ if (values)
+ XFree(values);
+
+ VLOG(3) << "HDCP state: " << ok << "," << *state;
+ return ok;
+}
+
+bool RealOutputConfiguratorDelegate::SetHDCPState(RROutput id,
+ HDCPState state) {
+ Atom name = XInternAtom(display_, kContentProtectionAtomName, False);
+ Atom value = None;
+ switch (state) {
+ case HDCP_STATE_UNDESIRED:
+ value = XInternAtom(display_, kProtectionUndesiredAtomName, False);
+ break;
+ case HDCP_STATE_DESIRED:
+ value = XInternAtom(display_, kProtectionDesiredAtomName, False);
+ break;
+ default:
+ NOTREACHED() << "Invalid HDCP state: " << state;
+ return false;
+ }
+ base::X11ErrorTracker err_tracker;
+ unsigned char* data = reinterpret_cast<unsigned char*>(&value);
+ XRRChangeOutputProperty(display_, id, name, XA_ATOM, 32,
+ PropModeReplace, data, 1);
+ if (err_tracker.FoundNewError()) {
+ LOG(ERROR) << "XRRChangeOutputProperty failed";
+ return false;
+ } else {
+ return true;
+ }
+}
+
void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
CHECK(screen_) << "Server not grabbed";
diff --git a/chromeos/display/real_output_configurator_delegate.h b/chromeos/display/real_output_configurator_delegate.h
index 66edfda..26940c4 100644
--- a/chromeos/display/real_output_configurator_delegate.h
+++ b/chromeos/display/real_output_configurator_delegate.h
@@ -52,6 +52,8 @@ class RealOutputConfiguratorDelegate : public OutputConfigurator::Delegate {
int touch_device_id,
const OutputConfigurator::CoordinateTransformation& ctm) OVERRIDE;
virtual void SendProjectingStateToPowerManager(bool projecting) OVERRIDE;
+ virtual bool GetHDCPState(RROutput id, HDCPState* state) OVERRIDE;
+ virtual bool SetHDCPState(RROutput id, HDCPState state) OVERRIDE;
private:
// Initializes |mode_info| to contain details corresponding to |mode|. Returns
diff --git a/content/renderer/pepper/plugin_module.cc b/content/renderer/pepper/plugin_module.cc
index d8c193c..3a2a749 100644
--- a/content/renderer/pepper/plugin_module.cc
+++ b/content/renderer/pepper/plugin_module.cc
@@ -111,6 +111,7 @@
#include "ppapi/c/private/ppb_flash_print.h"
#include "ppapi/c/private/ppb_host_resolver_private.h"
#include "ppapi/c/private/ppb_instance_private.h"
+#include "ppapi/c/private/ppb_output_protection_private.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/c/private/ppb_proxy_private.h"
#include "ppapi/c/private/ppb_talk_private.h"
diff --git a/content/renderer/pepper/resource_creation_impl.cc b/content/renderer/pepper/resource_creation_impl.cc
index 178236e..d9ed442 100644
--- a/content/renderer/pepper/resource_creation_impl.cc
+++ b/content/renderer/pepper/resource_creation_impl.cc
@@ -216,6 +216,11 @@ PP_Resource ResourceCreationImpl::CreateNetworkMonitor(PP_Instance instance) {
return 0; // Not supported in-process.
}
+PP_Resource ResourceCreationImpl::CreateOutputProtectionPrivate(
+ PP_Instance instance) {
+ return 0; // Not supported in-process.
+}
+
PP_Resource ResourceCreationImpl::CreatePlatformVerificationPrivate(
PP_Instance instance) {
return 0; // Not supported in-process.
diff --git a/content/renderer/pepper/resource_creation_impl.h b/content/renderer/pepper/resource_creation_impl.h
index d5b61b8..ac54b6b 100644
--- a/content/renderer/pepper/resource_creation_impl.h
+++ b/content/renderer/pepper/resource_creation_impl.h
@@ -110,6 +110,8 @@ class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
uint32_t size) OVERRIDE;
virtual PP_Resource CreateScrollbar(PP_Instance instance,
PP_Bool vertical) OVERRIDE;
+ virtual PP_Resource CreateOutputProtectionPrivate(
+ PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateTalk(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateTCPServerSocketPrivate(
PP_Instance instance) OVERRIDE;
diff --git a/native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc b/native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc
index 785eaac..c4fd361 100644
--- a/native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc
@@ -13,8 +13,7 @@
'file_io_private.cc',
'host_resolver_private.cc',
'net_address_private.cc',
- # TODO(binji): Remove comment when this file is added.
- # 'output_protection_private.cc',
+ 'output_protection_private.cc',
'pass_file_handle.cc',
'tcp_socket_private.cc',
'tcp_server_socket_private.cc',
@@ -49,8 +48,7 @@
'file_io_private.h',
'host_resolver_private.h',
'net_address_private.h',
- # TODO(binji): Remove comment when this file is added.
- # 'output_protection_private.h',
+ 'output_protection_private.h',
'pass_file_handle.h',
'tcp_server_socket_private.h',
'tcp_socket_private.h',
diff --git a/ppapi/cpp/private/output_protection_private.cc b/ppapi/cpp/private/output_protection_private.cc
new file mode 100644
index 0000000..9b244fe
--- /dev/null
+++ b/ppapi/cpp/private/output_protection_private.cc
@@ -0,0 +1,59 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/cpp/private/output_protection_private.h"
+
+#include <stdio.h>
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_output_protection_private.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/instance_handle.h"
+#include "ppapi/cpp/module_impl.h"
+
+namespace pp {
+
+namespace {
+
+template <> const char* interface_name<PPB_OutputProtection_Private_0_1>() {
+ return PPB_OUTPUTPROTECTION_PRIVATE_INTERFACE_0_1;
+}
+
+} // namespace
+
+OutputProtection_Private::OutputProtection_Private(
+ const InstanceHandle& instance) {
+ if (has_interface<PPB_OutputProtection_Private_0_1>()) {
+ PassRefFromConstructor(
+ get_interface<PPB_OutputProtection_Private_0_1>()->Create(
+ instance.pp_instance()));
+ }
+}
+
+OutputProtection_Private::~OutputProtection_Private() {
+}
+
+int32_t OutputProtection_Private::QueryStatus(
+ uint32_t* link_mask,
+ uint32_t* protection_mask,
+ const CompletionCallback& callback) {
+ if (has_interface<PPB_OutputProtection_Private_0_1>()) {
+ return get_interface<PPB_OutputProtection_Private_0_1>()->QueryStatus(
+ pp_resource(), link_mask, protection_mask,
+ callback.pp_completion_callback());
+ }
+ return callback.MayForce(PP_ERROR_NOINTERFACE);
+}
+
+int32_t OutputProtection_Private::EnableProtection(
+ uint32_t desired_method_mask,
+ const CompletionCallback& callback) {
+ if (has_interface<PPB_OutputProtection_Private_0_1>()) {
+ return get_interface<PPB_OutputProtection_Private_0_1>()->EnableProtection(
+ pp_resource(), desired_method_mask,
+ callback.pp_completion_callback());
+ }
+ return callback.MayForce(PP_ERROR_NOINTERFACE);
+}
+
+} // namespace pp
diff --git a/ppapi/cpp/private/output_protection_private.h b/ppapi/cpp/private/output_protection_private.h
new file mode 100644
index 0000000..6b543ea
--- /dev/null
+++ b/ppapi/cpp/private/output_protection_private.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_CPP_PRIVATE_OUTPUT_PROTECTION_PRIVATE_H_
+#define PPAPI_CPP_PRIVATE_OUTPUT_PROTECTION_PRIVATE_H_
+
+#include "ppapi/c/private/ppb_output_protection_private.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/cpp/resource.h"
+
+namespace pp {
+
+class OutputProtection_Private : public Resource {
+ public:
+ explicit OutputProtection_Private(const InstanceHandle& instance);
+ virtual ~OutputProtection_Private();
+
+ // PPB_OutputProtection_Private implementation.
+ int32_t QueryStatus(uint32_t* link_mask, uint32_t* protection_mask,
+ const CompletionCallback& callback);
+ int32_t EnableProtection(uint32_t desired_method_mask,
+ const CompletionCallback& callback);
+};
+
+} // namespace pp
+
+#endif // PPAPI_CPP_PRIVATE_OUTPUT_PROTECTION_PRIVATE_H_
diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi
index 267402d..c078ef1 100644
--- a/ppapi/ppapi_proxy.gypi
+++ b/ppapi/ppapi_proxy.gypi
@@ -88,6 +88,8 @@
'proxy/network_monitor_resource.h',
'proxy/network_proxy_resource.cc',
'proxy/network_proxy_resource.h',
+ 'proxy/output_protection_resource.cc',
+ 'proxy/output_protection_resource.h',
'proxy/pdf_resource.cc',
'proxy/pdf_resource.h',
'proxy/platform_verification_private_resource.cc',
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index 7edeb2f..b861a34 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -213,6 +213,8 @@
'thunk/ppb_network_monitor_thunk.cc',
'thunk/ppb_network_proxy_api.h',
'thunk/ppb_network_proxy_thunk.cc',
+ 'thunk/ppb_output_protection_api.h',
+ 'thunk/ppb_output_protection_private_thunk.cc',
'thunk/ppb_pdf_api.h',
'thunk/ppb_pdf_thunk.cc',
'thunk/ppb_platform_verification_api.h',
diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi
index 6ec54b7..64219de 100644
--- a/ppapi/ppapi_sources.gypi
+++ b/ppapi/ppapi_sources.gypi
@@ -115,6 +115,7 @@
'c/private/ppb_instance_private.h',
'c/private/ppb_nacl_private.h',
'c/private/ppb_net_address_private.h',
+ 'c/private/ppb_output_protection_private.h',
'c/private/ppb_pdf.h',
'c/private/ppb_platform_verification_private.h',
'c/private/ppb_proxy_private.h',
@@ -321,6 +322,8 @@
'cpp/private/instance_private.h',
'cpp/private/net_address_private.cc',
'cpp/private/net_address_private.h',
+ 'cpp/private/output_protection_private.cc',
+ 'cpp/private/output_protection_private.h',
'cpp/private/pass_file_handle.cc',
'cpp/private/pass_file_handle.h',
'cpp/private/pdf.cc',
@@ -450,6 +453,8 @@
'tests/test_network_monitor.h',
'tests/test_network_proxy.cc',
'tests/test_network_proxy.h',
+ 'tests/test_output_protection_private.cc',
+ 'tests/test_output_protection_private.h',
'tests/test_paint_aggregator.cc',
'tests/test_paint_aggregator.h',
'tests/test_post_message.cc',
diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc
index 9c810a3..447d025f 100644
--- a/ppapi/proxy/interface_list.cc
+++ b/ppapi/proxy/interface_list.cc
@@ -81,6 +81,7 @@
#include "ppapi/c/private/ppb_flash_print.h"
#include "ppapi/c/private/ppb_host_resolver_private.h"
#include "ppapi/c/private/ppb_net_address_private.h"
+#include "ppapi/c/private/ppb_output_protection_private.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/c/private/ppb_platform_verification_private.h"
#include "ppapi/c/private/ppb_talk_private.h"
diff --git a/ppapi/proxy/output_protection_resource.cc b/ppapi/proxy/output_protection_resource.cc
new file mode 100644
index 0000000..8f601de
--- /dev/null
+++ b/ppapi/proxy/output_protection_resource.cc
@@ -0,0 +1,105 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/output_protection_resource.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_resource_tracker.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_output_protection_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+OutputProtectionResource::OutputProtectionResource(
+ Connection connection,
+ PP_Instance instance)
+ : PluginResource(connection, instance) {
+ SendCreate(BROWSER, PpapiHostMsg_OutputProtection_Create());
+}
+
+OutputProtectionResource::~OutputProtectionResource() {
+ if (TrackedCallback::IsPending(query_status_callback_))
+ query_status_callback_->PostAbort();
+ if (TrackedCallback::IsPending(enable_protection_callback_))
+ enable_protection_callback_->PostAbort();
+}
+
+thunk::PPB_OutputProtection_API*
+ OutputProtectionResource::AsPPB_OutputProtection_API() {
+ return this;
+}
+
+int32_t OutputProtectionResource::QueryStatus(
+ uint32_t* link_mask,
+ uint32_t* protection_mask,
+ const scoped_refptr<TrackedCallback>& callback) {
+ if (!link_mask || !protection_mask)
+ return PP_ERROR_BADARGUMENT;
+ if (TrackedCallback::IsPending(query_status_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ query_status_callback_ = callback;
+
+ Call<PpapiPluginMsg_OutputProtection_QueryStatusReply>(
+ BROWSER,
+ PpapiHostMsg_OutputProtection_QueryStatus(),
+ base::Bind(&OutputProtectionResource::OnPluginMsgQueryStatusReply,
+ base::Unretained(this),
+ link_mask,
+ protection_mask));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void OutputProtectionResource::OnPluginMsgQueryStatusReply(
+ uint32_t* out_link_mask,
+ uint32_t* out_protection_mask,
+ const ResourceMessageReplyParams& params,
+ uint32_t link_mask,
+ uint32_t protection_mask) {
+ // The callback may have been aborted.
+ if (!TrackedCallback::IsPending(query_status_callback_))
+ return;
+
+ int32_t result = params.result();
+
+ if (result == PP_OK) {
+ DCHECK(out_link_mask);
+ DCHECK(out_protection_mask);
+ *out_link_mask = link_mask;
+ *out_protection_mask = protection_mask;
+ }
+ query_status_callback_->Run(result);
+}
+
+int32_t OutputProtectionResource::EnableProtection(
+ uint32_t desired_method_mask,
+ const scoped_refptr<TrackedCallback>& callback) {
+ if (TrackedCallback::IsPending(enable_protection_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ enable_protection_callback_ = callback;
+
+ Call<PpapiPluginMsg_OutputProtection_EnableProtectionReply>(
+ BROWSER,
+ PpapiHostMsg_OutputProtection_EnableProtection(desired_method_mask),
+ base::Bind(&OutputProtectionResource::OnPluginMsgEnableProtectionReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void OutputProtectionResource::OnPluginMsgEnableProtectionReply(
+ const ResourceMessageReplyParams& params) {
+ // The callback may have been aborted.
+ if (TrackedCallback::IsPending(enable_protection_callback_))
+ enable_protection_callback_->Run(params.result());
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/ppapi/proxy/output_protection_resource.h b/ppapi/proxy/output_protection_resource.h
new file mode 100644
index 0000000..b56a33d
--- /dev/null
+++ b/ppapi/proxy/output_protection_resource.h
@@ -0,0 +1,58 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_OUTPUT_PROTECTION_RESOURCE_H_
+#define PPAPI_PROXY_OUTPUT_PROTECTION_RESOURCE_H_
+
+#include "base/compiler_specific.h"
+#include "ppapi/c/private/ppb_output_protection_private.h"
+#include "ppapi/proxy/device_enumeration_resource_helper.h"
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/thunk/ppb_output_protection_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class OutputProtectionResource
+ : public PluginResource,
+ public ::ppapi::thunk::PPB_OutputProtection_API {
+ public:
+ OutputProtectionResource(Connection connection,
+ PP_Instance instance);
+
+ private:
+ virtual ~OutputProtectionResource();
+
+ // PluginResource overrides.
+ virtual thunk::PPB_OutputProtection_API* AsPPB_OutputProtection_API()
+ OVERRIDE;
+
+ // PPB_OutputProtection_API implementation.
+ virtual int32_t QueryStatus(
+ uint32_t* link_mask,
+ uint32_t* protection_mask,
+ const scoped_refptr<TrackedCallback>& callback) OVERRIDE;
+ virtual int32_t EnableProtection(
+ uint32_t desired_method_mask,
+ const scoped_refptr<TrackedCallback>& callback) OVERRIDE;
+
+ void OnPluginMsgQueryStatusReply(
+ uint32_t* out_link_mask,
+ uint32_t* out_protection_mask,
+ const ResourceMessageReplyParams& params,
+ uint32_t link_mask,
+ uint32_t protection_mask);
+ void OnPluginMsgEnableProtectionReply(
+ const ResourceMessageReplyParams& params);
+
+ scoped_refptr<TrackedCallback> query_status_callback_;
+ scoped_refptr<TrackedCallback> enable_protection_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(OutputProtectionResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_OUTPUT_PROTECTION_RESOURCE_H_
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index c308873..046dbea 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -1702,6 +1702,17 @@ IPC_MESSAGE_CONTROL4(PpapiPluginMsg_WebSocket_ClosedReply,
uint16_t /* code */,
std::string /* reason */)
+// OutputProtection -----------------------------------------------------------
+
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_OutputProtection_Create)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_OutputProtection_EnableProtection,
+ uint32_t /* desired_method_mask */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_OutputProtection_EnableProtectionReply)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_OutputProtection_QueryStatus)
+IPC_MESSAGE_CONTROL2(PpapiPluginMsg_OutputProtection_QueryStatusReply,
+ uint32_t /* link_mask */,
+ uint32_t /* protection_mask */)
+
#if !defined(OS_NACL) && !defined(NACL_WIN64)
// Audio input.
diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc
index d1b99ec..7ee761b 100644
--- a/ppapi/proxy/resource_creation_proxy.cc
+++ b/ppapi/proxy/resource_creation_proxy.cc
@@ -21,6 +21,7 @@
#include "ppapi/proxy/host_resolver_resource.h"
#include "ppapi/proxy/net_address_resource.h"
#include "ppapi/proxy/network_monitor_resource.h"
+#include "ppapi/proxy/output_protection_resource.h"
#include "ppapi/proxy/platform_verification_private_resource.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_globals.h"
@@ -313,6 +314,12 @@ PP_Resource ResourceCreationProxy::CreateNetworkMonitor(
GetReference();
}
+PP_Resource ResourceCreationProxy::CreateOutputProtectionPrivate(
+ PP_Instance instance) {
+ return (new OutputProtectionResource(GetConnection(), instance))->
+ GetReference();
+}
+
PP_Resource ResourceCreationProxy::CreatePrinting(PP_Instance instance) {
return (new PrintingResource(GetConnection(), instance))->GetReference();
}
diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h
index 1507dc8..df564da 100644
--- a/ppapi/proxy/resource_creation_proxy.h
+++ b/ppapi/proxy/resource_creation_proxy.h
@@ -134,6 +134,8 @@ class ResourceCreationProxy : public InterfaceProxy,
PP_Instance instance,
const PP_NetAddress_Private& private_addr) OVERRIDE;
virtual PP_Resource CreateNetworkMonitor(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateOutputProtectionPrivate(
+ PP_Instance instance) OVERRIDE;
virtual PP_Resource CreatePrinting(PP_Instance) OVERRIDE;
virtual PP_Resource CreateTCPServerSocketPrivate(
PP_Instance instance) OVERRIDE;
diff --git a/ppapi/shared_impl/resource.h b/ppapi/shared_impl/resource.h
index 15ce142..d364b44 100644
--- a/ppapi/shared_impl/resource.h
+++ b/ppapi/shared_impl/resource.h
@@ -57,6 +57,7 @@
F(PPB_NetworkList_API) \
F(PPB_NetworkMonitor_API) \
F(PPB_NetworkProxy_API) \
+ F(PPB_OutputProtection_API) \
F(PPB_PDF_API) \
F(PPB_PlatformVerification_API) \
F(PPB_Printing_API) \
diff --git a/ppapi/tests/all_c_includes.h b/ppapi/tests/all_c_includes.h
index f6e3de0..be825ac 100644
--- a/ppapi/tests/all_c_includes.h
+++ b/ppapi/tests/all_c_includes.h
@@ -117,6 +117,7 @@
#include "ppapi/c/private/ppb_instance_private.h"
#include "ppapi/c/private/ppb_nacl_private.h"
#include "ppapi/c/private/ppb_net_address_private.h"
+#include "ppapi/c/private/ppb_output_protection_private.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/c/private/ppb_platform_verification_private.h"
#include "ppapi/c/private/ppb_proxy_private.h"
diff --git a/ppapi/tests/test_output_protection_private.cc b/ppapi/tests/test_output_protection_private.cc
new file mode 100644
index 0000000..49a44ae
--- /dev/null
+++ b/ppapi/tests/test_output_protection_private.cc
@@ -0,0 +1,60 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/tests/test_output_protection_private.h"
+
+#include "ppapi/tests/testing_instance.h"
+
+REGISTER_TEST_CASE(OutputProtectionPrivate);
+
+TestOutputProtectionPrivate::TestOutputProtectionPrivate(
+ TestingInstance* instance)
+ : TestCase(instance) {
+}
+
+bool TestOutputProtectionPrivate::Init() {
+ output_protection_interface_ =
+ static_cast<const PPB_OutputProtection_Private*>(
+ pp::Module::Get()->GetBrowserInterface(
+ PPB_OUTPUTPROTECTION_PRIVATE_INTERFACE_0_1));
+ return output_protection_interface_ && CheckTestingInterface();
+}
+
+void TestOutputProtectionPrivate::RunTests(const std::string& filter) {
+ RUN_TEST(QueryStatus, filter);
+ RUN_TEST(EnableProtection, filter);
+}
+
+std::string TestOutputProtectionPrivate::TestQueryStatus() {
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
+
+ PP_Resource output_protection_resource = output_protection_interface_->
+ Create(instance_->pp_instance());
+ uint32_t link_mask;
+ uint32_t protection_mask;
+ callback.WaitForResult(
+ output_protection_interface_->QueryStatus(
+ output_protection_resource,
+ &link_mask,
+ &protection_mask,
+ callback.GetCallback().pp_completion_callback()));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+
+ PASS();
+}
+
+std::string TestOutputProtectionPrivate::TestEnableProtection() {
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
+
+ PP_Resource output_protection_resource = output_protection_interface_->
+ Create(instance_->pp_instance());
+ callback.WaitForResult(
+ output_protection_interface_->EnableProtection(
+ output_protection_resource,
+ PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE,
+ callback.GetCallback().pp_completion_callback()));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+
+ PASS();
+}
diff --git a/ppapi/tests/test_output_protection_private.h b/ppapi/tests/test_output_protection_private.h
new file mode 100644
index 0000000..a7a341e
--- /dev/null
+++ b/ppapi/tests/test_output_protection_private.h
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_TESTS_TEST_OUTPUT_PROTECTION_PRIVATE_H_
+#define PPAPI_TESTS_TEST_OUTPUT_PROTECTION_PRIVATE_H_
+
+#include <string>
+
+#include "ppapi/cpp/private/output_protection_private.h"
+#include "ppapi/tests/test_case.h"
+#include "ppapi/tests/test_utils.h"
+
+class TestOutputProtectionPrivate: public TestCase {
+ public:
+ explicit TestOutputProtectionPrivate(TestingInstance* instance);
+
+ private:
+ // TestCase implementation.
+ virtual bool Init();
+ virtual void RunTests(const std::string& filter);
+
+ std::string TestQueryStatus();
+ std::string TestEnableProtection();
+
+ const PPB_OutputProtection_Private* output_protection_interface_;
+};
+
+#endif // PPAPI_TESTS_TEST_OUTPUT_PROTECTION_PRIVATE_H_
diff --git a/ppapi/thunk/interfaces_ppb_private.h b/ppapi/thunk/interfaces_ppb_private.h
index 038d5c5..94a1793 100644
--- a/ppapi/thunk/interfaces_ppb_private.h
+++ b/ppapi/thunk/interfaces_ppb_private.h
@@ -58,6 +58,9 @@ PROXIED_IFACE(NoAPIName, PPB_FILEIOTRUSTED_INTERFACE_0_4, PPB_FileIOTrusted_0_4)
PROXIED_IFACE(NoAPIName, PPB_URLLOADERTRUSTED_INTERFACE_0_3,
PPB_URLLoaderTrusted_0_3)
+PROXIED_IFACE(NoAPIName, PPB_OUTPUTPROTECTION_PRIVATE_INTERFACE_0_1,
+ PPB_OutputProtection_Private_0_1)
+
// Hack to keep font working. The Font 0.6 API is binary compatible with
// BrowserFont 1.0, so just map the string to the same thing.
// TODO(brettw) remove support for the old Font API.
diff --git a/ppapi/thunk/ppb_output_protection_api.h b/ppapi/thunk/ppb_output_protection_api.h
new file mode 100644
index 0000000..8a12090
--- /dev/null
+++ b/ppapi/thunk/ppb_output_protection_api.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_THUNK_OUTPUT_PROTECTION_API_H_
+#define PPAPI_THUNK_OUTPUT_PROTECTION_API_H_
+
+#include "ppapi/c/private/ppb_output_protection_private.h"
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace thunk {
+
+class PPB_OutputProtection_API {
+ public:
+ virtual ~PPB_OutputProtection_API() {}
+
+ virtual int32_t QueryStatus(
+ uint32_t* link_mask,
+ uint32_t* protection_mask,
+ const scoped_refptr<TrackedCallback>& callback) = 0;
+ virtual int32_t EnableProtection(
+ uint32_t desired_method_mask,
+ const scoped_refptr<TrackedCallback>& callback) = 0;
+};
+
+} // namespace thunk
+} // namespace ppapi
+
+#endif // PPAPI_THUNK_OUTPUT_PROTECTION_API_H_
diff --git a/ppapi/thunk/resource_creation_api.h b/ppapi/thunk/resource_creation_api.h
index aa731cf..61eaa97 100644
--- a/ppapi/thunk/resource_creation_api.h
+++ b/ppapi/thunk/resource_creation_api.h
@@ -146,6 +146,7 @@ class ResourceCreationAPI {
PP_Instance instance,
const PP_NetAddress_Private& private_addr) = 0;
virtual PP_Resource CreateNetworkMonitor(PP_Instance instance) = 0;
+ virtual PP_Resource CreateOutputProtectionPrivate(PP_Instance instance) = 0;
virtual PP_Resource CreatePrinting(PP_Instance instance) = 0;
virtual PP_Resource CreateTCPServerSocketPrivate(PP_Instance instance) = 0;
virtual PP_Resource CreateTCPSocket1_0(PP_Instance instace) = 0;