diff options
author | kcwu@chromium.org <kcwu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-28 13:49:54 +0000 |
---|---|---|
committer | kcwu@chromium.org <kcwu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-28 13:49:54 +0000 |
commit | a1ab6d8994a202ce7fd45fb72edbf67e51657746 (patch) | |
tree | faa5855b40b36e70992a1191fc6f1077a6f0f4c5 | |
parent | 633b1ea1cd6e46531f45cc087cd6e280f322daaa (diff) | |
download | chromium_src-a1ab6d8994a202ce7fd45fb72edbf67e51657746.zip chromium_src-a1ab6d8994a202ce7fd45fb72edbf67e51657746.tar.gz chromium_src-a1ab6d8994a202ce7fd45fb72edbf67e51657746.tar.bz2 |
Pepper API implementation for output protection.
BUG=256538
R=cpu@chromium.org, dalecurtis@chromium.org, dmichael@chromium.org, marcheu@chromium.org, wuchengli@chromium.org
Review URL: https://codereview.chromium.org/24039002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225849 0039d316-1c4b-4281-b951-d872f2087c98
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; |