Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(478)

Unified Diff: media/cdm/ppapi/cdm_wrapper.cc

Issue 23546014: Plumb PPAPI PlatformVerification into CDM.h (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add DEPS roll. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « DEPS ('k') | media/cdm/ppapi/clear_key_cdm.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/cdm/ppapi/cdm_wrapper.cc
diff --git a/media/cdm/ppapi/cdm_wrapper.cc b/media/cdm/ppapi/cdm_wrapper.cc
index 66ae43d4d65917ab4ac609a75ef5fc70f986db19..1edb67eb35845352cac41d50d0dd0c273ebfe528 100644
--- a/media/cdm/ppapi/cdm_wrapper.cc
+++ b/media/cdm/ppapi/cdm_wrapper.cc
@@ -10,8 +10,10 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "build/build_config.h"
#include "media/cdm/ppapi/api/content_decryption_module.h"
#include "media/cdm/ppapi/linked_ptr.h"
+#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/private/pp_content_decryptor.h"
@@ -33,6 +35,11 @@
#include "ppapi/cpp/instance_handle.h"
#endif // defined(CHECK_DOCUMENT_URL)
+#if defined(OS_CHROMEOS)
+#include "ppapi/cpp/private/output_protection_private.h"
+#include "ppapi/cpp/private/platform_verification.h"
+#endif
+
namespace {
bool IsMainThread() {
@@ -456,9 +463,10 @@ VideoFrameImpl::~VideoFrameImpl() {
frame_buffer_->Destroy();
}
-class AudioFramesImpl : public cdm::AudioFrames {
+class AudioFramesImpl : public cdm::AudioFrames_1,
+ public cdm::AudioFrames_2 {
public:
- AudioFramesImpl() : buffer_(NULL) {}
+ AudioFramesImpl() : buffer_(NULL), format_(cdm::kAudioFormatS16) {}
virtual ~AudioFramesImpl() {
if (buffer_)
buffer_->Destroy();
@@ -471,9 +479,16 @@ class AudioFramesImpl : public cdm::AudioFrames {
virtual cdm::Buffer* FrameBuffer() OVERRIDE {
return buffer_;
}
+ virtual void SetFormat(cdm::AudioFormat format) OVERRIDE {
+ format_ = format;
+ }
+ virtual cdm::AudioFormat Format() const OVERRIDE {
+ return format_;
+ }
private:
PpbBuffer* buffer_;
+ cdm::AudioFormat format_;
DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl);
};
@@ -485,7 +500,8 @@ void* GetCdmHost(int host_interface_version, void* user_data);
// Content Decryption Module (CDM).
class CdmWrapper : public pp::Instance,
public pp::ContentDecryptor_Private,
- public cdm::Host {
+ public cdm::Host_1,
+ public cdm::Host_2 {
public:
CdmWrapper(PP_Instance instance, pp::Module* module);
virtual ~CdmWrapper();
@@ -524,7 +540,7 @@ class CdmWrapper : public pp::Instance,
pp::Buffer_Dev encrypted_buffer,
const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
- // cdm::Host implementation.
+ // cdm::Host_1 implementation.
virtual cdm::Buffer* Allocate(int32_t capacity) OVERRIDE;
virtual void SetTimer(int64_t delay_ms, void* context) OVERRIDE;
virtual double GetCurrentWallTimeInSeconds() OVERRIDE;
@@ -539,6 +555,15 @@ class CdmWrapper : public pp::Instance,
virtual void GetPrivateData(int32_t* instance,
GetPrivateInterface* get_interface) OVERRIDE;
+ // cdm::Host_2 implementation.
+ virtual bool CanChallengePlatform() OVERRIDE;
+ virtual void SendPlatformChallenge(
+ const char* service_id, int32_t service_id_length,
+ const char* challenge, int32_t challenge_length) OVERRIDE;
+ virtual void EnableOutputProtection(
+ uint32_t desired_protection_mask) OVERRIDE;
+ virtual void QueryOutputProtectionStatus() OVERRIDE;
+
private:
struct SessionInfo {
SessionInfo(const std::string& key_system_in,
@@ -606,6 +631,35 @@ class CdmWrapper : public pp::Instance,
bool IsValidVideoFrame(const LinkedVideoFrame& video_frame);
+#if defined(OS_CHROMEOS)
+ void CanChallengePlatformDone(int32_t result, bool can_challenge_platform);
+ void SendPlatformChallengeDone(int32_t result);
+ void EnableProtectionDone(int32_t result);
+ void QueryOutputProtectionStatusDone(int32_t result);
+
+ pp::OutputProtection_Private output_protection_;
+ pp::PlatformVerification platform_verification_;
+
+ // |can_challenge_platform_| is currently set asynchronously, return the value
+ // if we have it, otherwise guess "true" for the most common case...
+ // TODO(jrummell): This stinks. The value should be delivered via the
+ // Initialize() method once plumbed.
+ bool can_challenge_platform_;
+
+ // Since PPAPI doesn't provide handlers for CompletionCallbacks w/ more than
+ // one output we need to manage our own. These values are only read by
+ // SendPlatformChallengeDone().
+ pp::Var signed_data_output_;
+ pp::Var signed_data_signature_output_;
+ pp::Var platform_key_certificate_output_;
+ bool challenge_in_progress_;
+
+ // Same as above, these are only read by QueryOutputProtectionStatusDone().
+ uint32_t link_mask_;
+ uint32_t output_protection_mask_;
+ bool query_in_progress_;
+#endif
+
PpbBufferAllocator allocator_;
pp::CompletionCallbackFactory<CdmWrapper> callback_factory_;
cdm::ContentDecryptionModule* cdm_;
@@ -617,9 +671,25 @@ class CdmWrapper : public pp::Instance,
CdmWrapper::CdmWrapper(PP_Instance instance, pp::Module* module)
: pp::Instance(instance),
pp::ContentDecryptor_Private(this),
+#if defined(OS_CHROMEOS)
+ output_protection_(this),
+ platform_verification_(this),
+ // Err on the side of the most common case...
+ can_challenge_platform_(true),
+ challenge_in_progress_(false),
+ link_mask_(0),
ddorwin 2013/10/05 21:39:36 output_... ?
DaleCurtis 2013/10/07 22:15:59 Done.
+ output_protection_mask_(0),
+ query_in_progress_(false),
ddorwin 2013/10/05 21:39:36 nit: query is not very specific. query_output_prot
DaleCurtis 2013/10/07 22:15:59 Done.
+#endif
allocator_(this),
cdm_(NULL) {
callback_factory_.Initialize(this);
+#if defined(OS_CHROMEOS)
+ // Preemptively retrieve the platform challenge status. It will not change.
+ platform_verification_.CanChallengePlatform(
+ callback_factory_.NewCallbackWithOutput(
+ &CdmWrapper::CanChallengePlatformDone));
+#endif
}
CdmWrapper::~CdmWrapper() {
@@ -936,7 +1006,7 @@ void CdmWrapper::SendKeyError(const char* session_id,
}
void CdmWrapper::GetPrivateData(int32_t* instance,
- cdm::Host::GetPrivateInterface* get_interface) {
+ GetPrivateInterface* get_interface) {
*instance = pp_instance();
*get_interface = pp::Module::Get()->get_browser_interface();
}
@@ -1155,15 +1225,147 @@ bool CdmWrapper::IsValidVideoFrame(const LinkedVideoFrame& video_frame) {
return true;
}
+bool CdmWrapper::CanChallengePlatform() {
+#if defined(OS_CHROMEOS)
+ return can_challenge_platform_;
+#else
+ return false;
+#endif
+}
+
+void CdmWrapper::SendPlatformChallenge(
+ const char* service_id, int32_t service_id_length,
+ const char* challenge, int32_t challenge_length) {
+#if defined(OS_CHROMEOS)
+ PP_DCHECK(!challenge_in_progress_);
+
+ // Ensure member variables set by the callback are in a clean state.
ddorwin 2013/10/05 21:39:36 Do we need to do the same for output protection?
DaleCurtis 2013/10/07 22:15:59 No, not since the outputs are simple types. We ne
+ signed_data_output_ = pp::Var();
+ signed_data_signature_output_ = pp::Var();
+ platform_key_certificate_output_ = pp::Var();
+
+ pp::VarArrayBuffer challenge_var(challenge_length);
+ uint8_t* var_data = static_cast<uint8_t*>(challenge_var.Map());
+ memcpy(var_data, challenge, challenge_length);
+
+ std::string service_id_str(service_id, service_id_length);
+ int32_t result = platform_verification_.ChallengePlatform(
+ pp::Var(service_id_str), challenge_var, &signed_data_output_,
+ &signed_data_signature_output_, &platform_key_certificate_output_,
+ callback_factory_.NewCallback(&CdmWrapper::SendPlatformChallengeDone));
+ challenge_var.Unmap();
+ if (result == PP_OK_COMPLETIONPENDING) {
+ challenge_in_progress_ = true;
+ return;
+ }
+
+ // Fall through on error and issue an empty OnPlatformChallengeResponse().
+ PP_DCHECK(result != PP_OK);
+#endif
+
+ cdm::PlatformChallengeResponse response = {};
+ cdm_->OnPlatformChallengeResponse(response);
+}
+
+void CdmWrapper::EnableOutputProtection(uint32_t desired_protection_mask) {
+#if defined(OS_CHROMEOS)
+ output_protection_.EnableProtection(
+ desired_protection_mask, callback_factory_.NewCallback(
+ &CdmWrapper::EnableProtectionDone));
+
+ // Errors are ignored since clients must call QueryOutputProtectionStatus() to
+ // inspect the protection status on a regular basis.
+ // TODO(dalecurtis): It'd be nice to log a message or non-fatal error here...
ddorwin 2013/10/05 21:39:36 Won't we always get PENDING since we're OOP?
DaleCurtis 2013/10/07 22:15:59 Not if there's an error that prevents the call fro
+#endif
+}
+
+void CdmWrapper::QueryOutputProtectionStatus() {
+#if defined(OS_CHROMEOS)
+ PP_DCHECK(!query_in_progress_);
+
+ link_mask_ = output_protection_mask_ = 0;
+ int32_t result = output_protection_.QueryStatus(
+ &link_mask_, &output_protection_mask_, callback_factory_.NewCallback(
+ &CdmWrapper::QueryOutputProtectionStatusDone));
+ if (result == PP_OK_COMPLETIONPENDING) {
+ query_in_progress_ = true;
+ return;
+ }
+
+ // Fall through on error and issue an empty OnQueryOutputProtectionStatus().
+ PP_DCHECK(result != PP_OK);
+#endif
+
+ cdm_->OnQueryOutputProtectionStatus(0, 0);
+}
+
+#if defined(OS_CHROMEOS)
+void CdmWrapper::CanChallengePlatformDone(int32_t result,
+ bool can_challenge_platform) {
+ can_challenge_platform_ = (result == PP_OK) ? can_challenge_platform : false;
+}
+
+void CdmWrapper::SendPlatformChallengeDone(int32_t result) {
+ challenge_in_progress_ = false;
+
+ if (result != PP_OK) {
+ cdm::PlatformChallengeResponse response = {};
+ cdm_->OnPlatformChallengeResponse(response);
+ return;
+ }
+
+ pp::VarArrayBuffer signed_data_var(signed_data_output_);
+ pp::VarArrayBuffer signed_data_signature_var(signed_data_signature_output_);
+ std::string platform_key_certificate_string =
+ platform_key_certificate_output_.AsString();
+
+ cdm::PlatformChallengeResponse response = {
+ static_cast<uint8_t*>(signed_data_var.Map()),
+ signed_data_var.ByteLength(),
+
+ static_cast<uint8_t*>(signed_data_signature_var.Map()),
+ signed_data_signature_var.ByteLength(),
+
+ reinterpret_cast<const uint8_t*>(platform_key_certificate_string.c_str()),
+ platform_key_certificate_string.length()
+ };
+ cdm_->OnPlatformChallengeResponse(response);
+
+ signed_data_var.Unmap();
+ signed_data_signature_var.Unmap();
+}
+
+void CdmWrapper::EnableProtectionDone(int32_t result) {
+ // Does nothing since clients must call QueryOutputProtectionStatus() to
+ // inspect the protection status on a regular basis.
+ // TODO(dalecurtis): It'd be nice to log a message or non-fatal error here...
+}
+
+void CdmWrapper::QueryOutputProtectionStatusDone(int32_t result) {
+ query_in_progress_ = false;
ddorwin 2013/10/05 21:39:36 Should we add DCHECK(query_in_progress_); ?
DaleCurtis 2013/10/07 22:15:59 Done.
+
+ // Return a protection status of none on error.
+ if (result != PP_OK)
+ link_mask_ = output_protection_mask_ = 0;
+
+ cdm_->OnQueryOutputProtectionStatus(link_mask_, output_protection_mask_);
+}
+#endif
+
void* GetCdmHost(int host_interface_version, void* user_data) {
if (!host_interface_version || !user_data)
return NULL;
- if (host_interface_version != cdm::kHostInterfaceVersion)
- return NULL;
-
CdmWrapper* cdm_wrapper = static_cast<CdmWrapper*>(user_data);
- return static_cast<cdm::Host*>(cdm_wrapper);
+ switch (host_interface_version) {
+ case cdm::kHostInterfaceVersion_1:
+ return static_cast<cdm::Host_1*>(cdm_wrapper);
+ case cdm::kHostInterfaceVersion_2:
+ return static_cast<cdm::Host_2*>(cdm_wrapper);
+ default:
+ PP_NOTREACHED();
+ return NULL;
+ }
}
// This object is the global object representing this plugin library as long
« no previous file with comments | « DEPS ('k') | media/cdm/ppapi/clear_key_cdm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698