Commit 22f8a43c authored by xhwang's avatar xhwang Committed by Commit bot

media: Add OutputProtectionProxy

This class handles output protection query and request in the browser
process on all platforms. On ChromeOS, it delegates the operations on
the hardware displays to OutputProtectionDelegate. On other platforms,
it does not check hardware displays. On all platforms, it checks
whether there is any network link and adds it to the existing link mask.

This class will also be used to implement mojo OutputProtection service
on all platforms.

This CL also updated PPAPI cdm adapter and PPAPI code to enable output
protection calls on all platforms. A unit test is added via external
clear key tests.

BUG=592122,589618
TEST=Added new tests.

Review-Url: https://codereview.chromium.org/2085063002
Cr-Commit-Position: refs/heads/master@{#401896}
parent c467abfd
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/shell_delegate.h" #include "ash/shell_delegate.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
...@@ -133,18 +132,7 @@ void OutputProtectionDelegate::QueryStatusComplete( ...@@ -133,18 +132,7 @@ void OutputProtectionDelegate::QueryStatusComplete(
return; return;
} }
uint32_t link_mask = response.link_mask; callback.Run(response.success, response.link_mask, response.protection_mask);
// If we successfully retrieved the device level status, check for capturers.
if (response.success) {
const bool insecure_capture_detected =
MediaCaptureDevicesDispatcher::GetInstance()
->IsInsecureCapturingInProgress(render_process_id_,
render_frame_id_);
if (insecure_capture_detected)
link_mask |= ui::DISPLAY_CONNECTION_TYPE_NETWORK;
}
callback.Run(response.success, link_mask, response.protection_mask);
} }
void OutputProtectionDelegate::EnableProtectionComplete( void OutputProtectionDelegate::EnableProtectionComplete(
......
...@@ -34,10 +34,18 @@ ...@@ -34,10 +34,18 @@
// Available key systems. // Available key systems.
const char kClearKeyKeySystem[] = "org.w3.clearkey"; const char kClearKeyKeySystem[] = "org.w3.clearkey";
const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey";
// Variants of External Clear Key key system to test different scenarios.
// To add a new variant, make sure you also update:
// - media/test/data/eme_player_js/globals.js
// - AddExternalClearKey() in chrome_key_systems.cc
// - CreateCdmInstance() in clear_key_cdm.cc
const char kExternalClearKeyFileIOTestKeySystem[] = const char kExternalClearKeyFileIOTestKeySystem[] =
"org.chromium.externalclearkey.fileiotest"; "org.chromium.externalclearkey.fileiotest";
const char kExternalClearKeyInitializeFailKeySystem[] = const char kExternalClearKeyInitializeFailKeySystem[] =
"org.chromium.externalclearkey.initializefail"; "org.chromium.externalclearkey.initializefail";
const char kExternalClearKeyOutputProtectionTestKeySystem[] =
"org.chromium.externalclearkey.outputprotectiontest";
const char kExternalClearKeyCrashKeySystem[] = const char kExternalClearKeyCrashKeySystem[] =
"org.chromium.externalclearkey.crash"; "org.chromium.externalclearkey.crash";
...@@ -57,7 +65,7 @@ const char kLoadableSession[] = "LoadableSession"; ...@@ -57,7 +65,7 @@ const char kLoadableSession[] = "LoadableSession";
const char kUnknownSession[] = "UnknownSession"; const char kUnknownSession[] = "UnknownSession";
// EME-specific test results and errors. // EME-specific test results and errors.
const char kFileIOTestSuccess[] = "FILE_IO_TEST_SUCCESS"; const char kUnitTestSuccess[] = "UNIT_TEST_SUCCESS";
const char kEmeNotSupportedError[] = "NOTSUPPORTEDERROR"; const char kEmeNotSupportedError[] = "NOTSUPPORTEDERROR";
const char kEmeGenerateRequestFailed[] = "EME_GENERATEREQUEST_FAILED"; const char kEmeGenerateRequestFailed[] = "EME_GENERATEREQUEST_FAILED";
const char kEmeSessionNotFound[] = "EME_SESSION_NOT_FOUND"; const char kEmeSessionNotFound[] = "EME_SESSION_NOT_FOUND";
...@@ -625,8 +633,14 @@ IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, CDMExpectedCrash) { ...@@ -625,8 +633,14 @@ IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, CDMExpectedCrash) {
} }
IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, FileIOTest) { IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, FileIOTest) {
TestNonPlaybackCases(kExternalClearKeyFileIOTestKeySystem, TestNonPlaybackCases(kExternalClearKeyFileIOTestKeySystem, kUnitTestSuccess);
kFileIOTestSuccess); }
// TODO(xhwang): Investigate how to fake capturing activities to test the
// network link detection logic in OutputProtectionProxy.
IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, OutputProtectionTest) {
TestNonPlaybackCases(kExternalClearKeyOutputProtectionTestKeySystem,
kUnitTestSuccess);
} }
IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, LoadLoadableSession) { IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, LoadLoadableSession) {
......
// Copyright 2016 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/media/output_protection_proxy.h"
#include "build/build_config.h"
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "ui/display/types/display_constants.h"
namespace chrome {
OutputProtectionProxy::OutputProtectionProxy(int render_process_id,
int render_frame_id)
: render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
#if defined(OS_CHROMEOS)
output_protection_delegate_(render_process_id, render_frame_id),
#endif // defined(OS_CHROMEOS)
weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
}
OutputProtectionProxy::~OutputProtectionProxy() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
void OutputProtectionProxy::QueryStatus(const QueryStatusCallback& callback) {
DVLOG(1) << __FUNCTION__;
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
#if defined(OS_CHROMEOS)
output_protection_delegate_.QueryStatus(
base::Bind(&OutputProtectionProxy::ProcessQueryStatusResult,
weak_ptr_factory_.GetWeakPtr(), callback));
#else // defined(OS_CHROMEOS)
ProcessQueryStatusResult(callback, true, 0, 0);
#endif // defined(OS_CHROMEOS)
}
void OutputProtectionProxy::EnableProtection(
uint32_t desired_method_mask,
const EnableProtectionCallback& callback) {
DVLOG(1) << __FUNCTION__;
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
#if defined(OS_CHROMEOS)
output_protection_delegate_.EnableProtection(desired_method_mask, callback);
#else // defined(OS_CHROMEOS)
NOTIMPLEMENTED();
callback.Run(false);
#endif // defined(OS_CHROMEOS)
}
void OutputProtectionProxy::ProcessQueryStatusResult(
const QueryStatusCallback& callback,
bool success,
uint32_t link_mask,
uint32_t protection_mask) {
DVLOG(1) << __FUNCTION__ << ": " << success << ", " << link_mask;
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::RenderFrameHost* rfh =
content::RenderFrameHost::FromID(render_process_id_, render_frame_id_);
// TODO(xjz): Investigate whether this check (and the checks in
// OutputProtectionDelegate) should be removed.
if (!rfh) {
LOG(WARNING) << "RenderFrameHost is not alive.";
callback.Run(false, 0, 0);
return;
}
uint32_t new_link_mask = link_mask;
// If we successfully retrieved the device level status, check for capturers.
if (success) {
const bool is_insecure_capture_detected =
MediaCaptureDevicesDispatcher::GetInstance()
->IsInsecureCapturingInProgress(render_process_id_,
render_frame_id_);
if (is_insecure_capture_detected)
new_link_mask |= ui::DISPLAY_CONNECTION_TYPE_NETWORK;
}
callback.Run(success, new_link_mask, protection_mask);
}
} // namespace chrome
// Copyright 2016 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_MEDIA_OUTPUT_PROTECTION_PROXY_H_
#define CHROME_BROWSER_MEDIA_OUTPUT_PROTECTION_PROXY_H_
#include <stdint.h>
#include "base/memory/weak_ptr.h"
#include "content/public/browser/browser_thread.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/display/output_protection_delegate.h"
#endif
namespace chrome {
// A class to query output protection status and/or enable output protection.
//
// On Chrome OS, operations on the physical displays are delegated to
// OutputProtectionDelegate. On other platforms, physical displays are not
// checked.
//
// On all platforms, in ProcessQueryStatusResult(), this class checks the
// network link and adds it to the existing link mask.
//
// All methods except constructor should be invoked in UI thread.
class OutputProtectionProxy {
public:
typedef base::Callback<void(bool /* success */,
uint32_t /* link_mask */,
uint32_t /* protection_mask*/)>
QueryStatusCallback;
typedef base::Callback<void(bool /* success */)> EnableProtectionCallback;
OutputProtectionProxy(int render_process_id, int render_frame_id);
void QueryStatus(const QueryStatusCallback& callback);
void EnableProtection(uint32_t desired_method_mask,
const EnableProtectionCallback& callback);
private:
// Makes sure this class can only be deleted on the UI thread.
friend class base::DeleteHelper<OutputProtectionProxy>;
friend struct content::BrowserThread::DeleteOnThread<
content::BrowserThread::UI>;
~OutputProtectionProxy();
// Callbacks for QueryStatus(). It also checks the network link and adds it
// to the |link_mask|.
void ProcessQueryStatusResult(const QueryStatusCallback& callback,
bool success,
uint32_t link_mask,
uint32_t protection_mask);
// Used to lookup the WebContents associated with the render frame.
int render_process_id_;
int render_frame_id_;
#if defined(OS_CHROMEOS)
chromeos::OutputProtectionDelegate output_protection_delegate_;
#endif
base::WeakPtrFactory<OutputProtectionProxy> weak_ptr_factory_;
};
} // namespace chrome
#endif // CHROME_BROWSER_MEDIA_OUTPUT_PROTECTION_PROXY_H_
...@@ -60,7 +60,6 @@ ChromeBrowserPepperHostFactory::CreateResourceHost( ...@@ -60,7 +60,6 @@ ChromeBrowserPepperHostFactory::CreateResourceHost(
host_->GetPpapiHost(), instance, resource, pv_filter)); host_->GetPpapiHost(), instance, resource, pv_filter));
} }
#endif #endif
#if defined(OS_CHROMEOS)
case PpapiHostMsg_OutputProtection_Create::ID: { case PpapiHostMsg_OutputProtection_Create::ID: {
scoped_refptr<ResourceMessageFilter> output_protection_filter( scoped_refptr<ResourceMessageFilter> output_protection_filter(
new chrome::PepperOutputProtectionMessageFilter(host_, instance)); new chrome::PepperOutputProtectionMessageFilter(host_, instance));
...@@ -68,7 +67,6 @@ ChromeBrowserPepperHostFactory::CreateResourceHost( ...@@ -68,7 +67,6 @@ ChromeBrowserPepperHostFactory::CreateResourceHost(
new MessageFilterHost(host_->GetPpapiHost(), instance, resource, new MessageFilterHost(host_->GetPpapiHost(), instance, resource,
output_protection_filter)); output_protection_filter));
} }
#endif
} }
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h" #include "chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/media/output_protection_proxy.h"
#include "content/public/browser/browser_ppapi_host.h" #include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
...@@ -14,19 +15,14 @@ ...@@ -14,19 +15,14 @@
#include "ppapi/host/host_message_context.h" #include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h" #include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/ppapi_messages.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/display/output_protection_delegate.h"
#include "ui/display/types/display_constants.h" #include "ui/display/types/display_constants.h"
#endif
namespace chrome { namespace chrome {
namespace { namespace {
#if defined(OS_CHROMEOS)
static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE) == static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE) ==
static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_NONE), static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_NONE),
"PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE value mismatch"); "PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE value mismatch");
static_assert( static_assert(
static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_UNKNOWN) == static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_UNKNOWN) ==
...@@ -37,14 +33,14 @@ static_assert( ...@@ -37,14 +33,14 @@ static_assert(
static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_INTERNAL), static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_INTERNAL),
"PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_INTERNAL value mismatch"); "PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_INTERNAL value mismatch");
static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA) == static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA) ==
static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_VGA), static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_VGA),
"PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA value mismatch"); "PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA value mismatch");
static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI) == static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI) ==
static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_HDMI), static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_HDMI),
"PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI value mismatch"); "PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI value mismatch");
static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DVI) == static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DVI) ==
static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_DVI), static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_DVI),
"PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DVI value mismatch"); "PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DVI value mismatch");
static_assert( static_assert(
static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT) == static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT) ==
static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_DISPLAYPORT), static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_DISPLAYPORT),
...@@ -54,12 +50,11 @@ static_assert( ...@@ -54,12 +50,11 @@ static_assert(
static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_NETWORK), static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_NETWORK),
"PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NETWORK value mismatch"); "PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NETWORK value mismatch");
static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE) == static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE) ==
static_cast<int>(ui::CONTENT_PROTECTION_METHOD_NONE), static_cast<int>(ui::CONTENT_PROTECTION_METHOD_NONE),
"PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE value mismatch"); "PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE value mismatch");
static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP) == static_assert(static_cast<int>(PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP) ==
static_cast<int>(ui::CONTENT_PROTECTION_METHOD_HDCP), static_cast<int>(ui::CONTENT_PROTECTION_METHOD_HDCP),
"PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP value mismatch"); "PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP value mismatch");
#endif
} // namespace } // namespace
...@@ -67,26 +62,15 @@ PepperOutputProtectionMessageFilter::PepperOutputProtectionMessageFilter( ...@@ -67,26 +62,15 @@ PepperOutputProtectionMessageFilter::PepperOutputProtectionMessageFilter(
content::BrowserPpapiHost* host, content::BrowserPpapiHost* host,
PP_Instance instance) PP_Instance instance)
: weak_ptr_factory_(this) { : weak_ptr_factory_(this) {
#if defined(OS_CHROMEOS)
DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
int render_process_id = 0; int render_process_id = 0;
int render_frame_id = 0; int render_frame_id = 0;
host->GetRenderFrameIDsForInstance( host->GetRenderFrameIDsForInstance(
instance, &render_process_id, &render_frame_id); instance, &render_process_id, &render_frame_id);
delegate_ = new chromeos::OutputProtectionDelegate(render_process_id, proxy_.reset(new OutputProtectionProxy(render_process_id, render_frame_id));
render_frame_id);
#else
NOTIMPLEMENTED();
#endif
} }
PepperOutputProtectionMessageFilter::~PepperOutputProtectionMessageFilter() { PepperOutputProtectionMessageFilter::~PepperOutputProtectionMessageFilter() {}
#if defined(OS_CHROMEOS)
content::BrowserThread::DeleteSoon(
content::BrowserThread::UI, FROM_HERE, delegate_);
delegate_ = NULL;
#endif
}
scoped_refptr<base::TaskRunner> scoped_refptr<base::TaskRunner>
PepperOutputProtectionMessageFilter::OverrideTaskRunnerForMessage( PepperOutputProtectionMessageFilter::OverrideTaskRunnerForMessage(
...@@ -109,35 +93,25 @@ int32_t PepperOutputProtectionMessageFilter::OnResourceMessageReceived( ...@@ -109,35 +93,25 @@ int32_t PepperOutputProtectionMessageFilter::OnResourceMessageReceived(
int32_t PepperOutputProtectionMessageFilter::OnQueryStatus( int32_t PepperOutputProtectionMessageFilter::OnQueryStatus(
ppapi::host::HostMessageContext* context) { ppapi::host::HostMessageContext* context) {
#if defined(OS_CHROMEOS)
ppapi::host::ReplyMessageContext reply_context = ppapi::host::ReplyMessageContext reply_context =
context->MakeReplyMessageContext(); context->MakeReplyMessageContext();
delegate_->QueryStatus( proxy_->QueryStatus(
base::Bind(&PepperOutputProtectionMessageFilter::OnQueryStatusComplete, base::Bind(&PepperOutputProtectionMessageFilter::OnQueryStatusComplete,
weak_ptr_factory_.GetWeakPtr(), reply_context)); weak_ptr_factory_.GetWeakPtr(), reply_context));
return PP_OK_COMPLETIONPENDING; return PP_OK_COMPLETIONPENDING;
#else
NOTIMPLEMENTED();
return PP_ERROR_NOTSUPPORTED;
#endif
} }
int32_t PepperOutputProtectionMessageFilter::OnEnableProtection( int32_t PepperOutputProtectionMessageFilter::OnEnableProtection(
ppapi::host::HostMessageContext* context, ppapi::host::HostMessageContext* context,
uint32_t desired_method_mask) { uint32_t desired_method_mask) {
#if defined(OS_CHROMEOS)
ppapi::host::ReplyMessageContext reply_context = ppapi::host::ReplyMessageContext reply_context =
context->MakeReplyMessageContext(); context->MakeReplyMessageContext();
delegate_->EnableProtection( proxy_->EnableProtection(
desired_method_mask, desired_method_mask,
base::Bind( base::Bind(
&PepperOutputProtectionMessageFilter::OnEnableProtectionComplete, &PepperOutputProtectionMessageFilter::OnEnableProtectionComplete,
weak_ptr_factory_.GetWeakPtr(), reply_context)); weak_ptr_factory_.GetWeakPtr(), reply_context));
return PP_OK_COMPLETIONPENDING; return PP_OK_COMPLETIONPENDING;
#else
NOTIMPLEMENTED();
return PP_ERROR_NOTSUPPORTED;
#endif
} }
void PepperOutputProtectionMessageFilter::OnQueryStatusComplete( void PepperOutputProtectionMessageFilter::OnQueryStatusComplete(
......
...@@ -7,8 +7,11 @@ ...@@ -7,8 +7,11 @@
#include <stdint.h> #include <stdint.h>
#include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "content/public/browser/browser_thread.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_instance.h"
#include "ppapi/host/resource_message_filter.h" #include "ppapi/host/resource_message_filter.h"
...@@ -23,14 +26,10 @@ struct HostMessageContext; ...@@ -23,14 +26,10 @@ struct HostMessageContext;
} // namespace host } // namespace host
} // namespace ppapi } // namespace ppapi
#if defined(OS_CHROMEOS)
namespace chromeos {
class OutputProtectionDelegate;
}
#endif
namespace chrome { namespace chrome {
class OutputProtectionProxy;
class PepperOutputProtectionMessageFilter class PepperOutputProtectionMessageFilter
: public ppapi::host::ResourceMessageFilter { : public ppapi::host::ResourceMessageFilter {
public: public:
...@@ -60,10 +59,9 @@ class PepperOutputProtectionMessageFilter ...@@ -60,10 +59,9 @@ class PepperOutputProtectionMessageFilter
ppapi::host::ReplyMessageContext reply_context, ppapi::host::ReplyMessageContext reply_context,
bool success); bool success);
#if defined(OS_CHROMEOS) std::unique_ptr<OutputProtectionProxy,
// Delegate. Should be deleted in UI thread. content::BrowserThread::DeleteOnUIThread>
chromeos::OutputProtectionDelegate* delegate_; proxy_;
#endif
base::WeakPtrFactory<PepperOutputProtectionMessageFilter> weak_ptr_factory_; base::WeakPtrFactory<PepperOutputProtectionMessageFilter> weak_ptr_factory_;
......
...@@ -388,6 +388,8 @@ ...@@ -388,6 +388,8 @@
'browser/media/midi_permission_context.h', 'browser/media/midi_permission_context.h',
'browser/media/native_desktop_media_list.cc', 'browser/media/native_desktop_media_list.cc',
'browser/media/native_desktop_media_list.h', 'browser/media/native_desktop_media_list.h',
'browser/media/output_protection_proxy.cc',
'browser/media/output_protection_proxy.h',
'browser/media/permission_bubble_media_access_handler.cc', 'browser/media/permission_bubble_media_access_handler.cc',
'browser/media/permission_bubble_media_access_handler.h', 'browser/media/permission_bubble_media_access_handler.h',
'browser/media/router/media_router_feature.cc', 'browser/media/router/media_router_feature.cc',
......
...@@ -134,6 +134,8 @@ static void AddExternalClearKey( ...@@ -134,6 +134,8 @@ static void AddExternalClearKey(
"org.chromium.externalclearkey.decryptonly"; "org.chromium.externalclearkey.decryptonly";
static const char kExternalClearKeyFileIOTestKeySystem[] = static const char kExternalClearKeyFileIOTestKeySystem[] =
"org.chromium.externalclearkey.fileiotest"; "org.chromium.externalclearkey.fileiotest";
static const char kExternalClearKeyOutputProtectionTestKeySystem[] =
"org.chromium.externalclearkey.outputprotectiontest";
static const char kExternalClearKeyInitializeFailKeySystem[] = static const char kExternalClearKeyInitializeFailKeySystem[] =
"org.chromium.externalclearkey.initializefail"; "org.chromium.externalclearkey.initializefail";
static const char kExternalClearKeyCrashKeySystem[] = static const char kExternalClearKeyCrashKeySystem[] =
...@@ -154,10 +156,14 @@ static void AddExternalClearKey( ...@@ -154,10 +156,14 @@ static void AddExternalClearKey(
concrete_key_systems->emplace_back( concrete_key_systems->emplace_back(
new ExternalClearKeyProperties(kExternalClearKeyDecryptOnlyKeySystem)); new ExternalClearKeyProperties(kExternalClearKeyDecryptOnlyKeySystem));
// A key system that triggers FileIO test in ClearKeyCdm. // A key system that triggers the FileIO test in ClearKeyCdm.
concrete_key_systems->emplace_back( concrete_key_systems->emplace_back(
new ExternalClearKeyProperties(kExternalClearKeyFileIOTestKeySystem)); new ExternalClearKeyProperties(kExternalClearKeyFileIOTestKeySystem));
// A key system that triggers the output protection test in ClearKeyCdm.
concrete_key_systems->emplace_back(new ExternalClearKeyProperties(
kExternalClearKeyOutputProtectionTestKeySystem));
// A key system that Chrome thinks is supported by ClearKeyCdm, but actually // A key system that Chrome thinks is supported by ClearKeyCdm, but actually
// will be refused by ClearKeyCdm. This is to test the CDM initialization // will be refused by ClearKeyCdm. This is to test the CDM initialization
// failure case. // failure case.
......
...@@ -58,10 +58,14 @@ static bool g_ffmpeg_lib_initialized = InitializeFFmpegLibraries(); ...@@ -58,10 +58,14 @@ static bool g_ffmpeg_lib_initialized = InitializeFFmpegLibraries();
const char kClearKeyCdmVersion[] = "0.1.0.1"; const char kClearKeyCdmVersion[] = "0.1.0.1";
const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey";
// Variants of External Clear Key key system to test different scenarios.
const char kExternalClearKeyDecryptOnlyKeySystem[] = const char kExternalClearKeyDecryptOnlyKeySystem[] =
"org.chromium.externalclearkey.decryptonly"; "org.chromium.externalclearkey.decryptonly";
const char kExternalClearKeyFileIOTestKeySystem[] = const char kExternalClearKeyFileIOTestKeySystem[] =
"org.chromium.externalclearkey.fileiotest"; "org.chromium.externalclearkey.fileiotest";
const char kExternalClearKeyOutputProtectionTestKeySystem[] =
"org.chromium.externalclearkey.outputprotectiontest";
const char kExternalClearKeyCrashKeySystem[] = const char kExternalClearKeyCrashKeySystem[] =
"org.chromium.externalclearkey.crash"; "org.chromium.externalclearkey.crash";
...@@ -82,8 +86,10 @@ const int64_t kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond; ...@@ -82,8 +86,10 @@ const int64_t kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond;
// |kRenewalHeader|, it's a renewal message. Otherwise, it's a key request. // |kRenewalHeader|, it's a renewal message. Otherwise, it's a key request.
// FIXME(jrummell): Remove this once prefixed EME goes away. // FIXME(jrummell): Remove this once prefixed EME goes away.
const char kRenewalHeader[] = "RENEWAL"; const char kRenewalHeader[] = "RENEWAL";
// CDM file IO test result header.
const char kFileIOTestResultHeader[] = "FILEIOTESTRESULT"; // CDM unit test result header. Must be in sync with UNIT_TEST_RESULT_HEADER in
// media/test/data/eme_player_js/globals.js.
const char kUnitTestResultHeader[] = "UNIT_TEST_RESULT";
// Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is // Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is
// empty, an empty (end-of-stream) media::DecoderBuffer is returned. // empty, an empty (end-of-stream) media::DecoderBuffer is returned.
...@@ -119,8 +125,8 @@ static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( ...@@ -119,8 +125,8 @@ static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom(
return output_buffer; return output_buffer;
} }
static std::string GetFileIOTestResultMessage(bool success) { static std::string GetUnitTestResultMessage(bool success) {
std::string message(kFileIOTestResultHeader); std::string message(kUnitTestResultHeader);
message += success ? '1' : '0'; message += success ? '1' : '0';
return message; return message;
} }
...@@ -232,6 +238,7 @@ void* CreateCdmInstance(int cdm_interface_version, ...@@ -232,6 +238,7 @@ void* CreateCdmInstance(int cdm_interface_version,
if (key_system_string != kExternalClearKeyKeySystem && if (key_system_string != kExternalClearKeyKeySystem &&
key_system_string != kExternalClearKeyDecryptOnlyKeySystem && key_system_string != kExternalClearKeyDecryptOnlyKeySystem &&
key_system_string != kExternalClearKeyFileIOTestKeySystem && key_system_string != kExternalClearKeyFileIOTestKeySystem &&
key_system_string != kExternalClearKeyOutputProtectionTestKeySystem &&
key_system_string != kExternalClearKeyCrashKeySystem) { key_system_string != kExternalClearKeyCrashKeySystem) {
DVLOG(1) << "Unsupported key system:" << key_system_string; DVLOG(1) << "Unsupported key system:" << key_system_string;
return NULL; return NULL;
...@@ -269,7 +276,8 @@ ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, ...@@ -269,7 +276,8 @@ ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host,
key_system_(key_system), key_system_(key_system),
has_received_keys_change_event_for_emulated_loadsession_(false), has_received_keys_change_event_for_emulated_loadsession_(false),
timer_delay_ms_(kInitialTimerDelayMs), timer_delay_ms_(kInitialTimerDelayMs),
renewal_timer_set_(false) { renewal_timer_set_(false),
is_running_output_protection_test_(false) {
#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
channel_count_ = 0; channel_count_ = 0;
bits_per_channel_ = 0; bits_per_channel_ = 0;
...@@ -306,8 +314,11 @@ void ClearKeyCdm::CreateSessionAndGenerateRequest( ...@@ -306,8 +314,11 @@ void ClearKeyCdm::CreateSessionAndGenerateRequest(
std::vector<uint8_t>(init_data, init_data + init_data_size), std::vector<uint8_t>(init_data, init_data + init_data_size),
std::move(promise)); std::move(promise));
if (key_system_ == kExternalClearKeyFileIOTestKeySystem) if (key_system_ == kExternalClearKeyFileIOTestKeySystem) {
StartFileIOTest(); StartFileIOTest();
} else if (key_system_ == kExternalClearKeyOutputProtectionTestKeySystem) {
StartOutputProtectionTest();
}
} }
// Loads a emulated stored session. Currently only |kLoadableSessionId| // Loads a emulated stored session. Currently only |kLoadableSessionId|
...@@ -694,7 +705,25 @@ void ClearKeyCdm::OnQueryOutputProtectionStatus( ...@@ -694,7 +705,25 @@ void ClearKeyCdm::OnQueryOutputProtectionStatus(
cdm::QueryResult result, cdm::QueryResult result,
uint32_t link_mask, uint32_t link_mask,
uint32_t output_protection_mask) { uint32_t output_protection_mask) {
NOTIMPLEMENTED(); if (!is_running_output_protection_test_) {
NOTREACHED() << "OnQueryOutputProtectionStatus() called unexpectedly.";
return;
}
is_running_output_protection_test_ = false;
// On Chrome OS, status query will fail on Linux Chrome OS build. So we ignore
// the query result. On all other platforms, status query should succeed.
// TODO(xhwang): Improve the check on Chrome OS builds. For example, use
// base::SysInfo::IsRunningOnChromeOS() to differentiate between real Chrome OS
// build and Linux Chrome OS build.
#if !defined(OS_CHROMEOS)
if (result != cdm::kQuerySucceeded || link_mask != 0) {
OnUnitTestComplete(false);
return;
}
#endif
OnUnitTestComplete(true);
}; };
void ClearKeyCdm::LoadLoadableSession() { void ClearKeyCdm::LoadLoadableSession() {
...@@ -903,6 +932,13 @@ cdm::Status ClearKeyCdm::GenerateFakeAudioFrames( ...@@ -903,6 +932,13 @@ cdm::Status ClearKeyCdm::GenerateFakeAudioFrames(
} }
#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
void ClearKeyCdm::OnUnitTestComplete(bool success) {
std::string message = GetUnitTestResultMessage(success);
host_->OnSessionMessage(last_session_id_.data(), last_session_id_.length(),
cdm::kLicenseRequest, message.data(),
message.length(), NULL, 0);
}
void ClearKeyCdm::StartFileIOTest() { void ClearKeyCdm::StartFileIOTest() {
file_io_test_runner_.reset(new FileIOTestRunner( file_io_test_runner_.reset(new FileIOTestRunner(
base::Bind(&ClearKeyCdmHost::CreateFileIO, base::Unretained(host_)))); base::Bind(&ClearKeyCdmHost::CreateFileIO, base::Unretained(host_))));
...@@ -912,11 +948,13 @@ void ClearKeyCdm::StartFileIOTest() { ...@@ -912,11 +948,13 @@ void ClearKeyCdm::StartFileIOTest() {
void ClearKeyCdm::OnFileIOTestComplete(bool success) { void ClearKeyCdm::OnFileIOTestComplete(bool success) {
DVLOG(1) << __FUNCTION__ << ": " << success; DVLOG(1) << __FUNCTION__ << ": " << success;
std::string message = GetFileIOTestResultMessage(success); OnUnitTestComplete(success);
host_->OnSessionMessage(last_session_id_.data(), last_session_id_.length(),
cdm::kLicenseRequest, message.data(),
message.length(), NULL, 0);
file_io_test_runner_.reset(); file_io_test_runner_.reset();
} }
void ClearKeyCdm::StartOutputProtectionTest() {
is_running_output_protection_test_ = true;
host_->QueryOutputProtectionStatus();
}
} // namespace media } // namespace media
...@@ -140,11 +140,15 @@ class ClearKeyCdm : public ClearKeyCdmInterface { ...@@ -140,11 +140,15 @@ class ClearKeyCdm : public ClearKeyCdmInterface {
cdm::AudioFrames* audio_frames); cdm::AudioFrames* audio_frames);
#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
void OnUnitTestComplete(bool success);
void StartFileIOTest(); void StartFileIOTest();
// Callback for CDM File IO test. // Callback for CDM File IO test.
void OnFileIOTestComplete(bool success); void OnFileIOTestComplete(bool success);
void StartOutputProtectionTest();
// Keep track of the last session created. // Keep track of the last session created.
void SetSessionId(const std::string& session_id); void SetSessionId(const std::string& session_id);
...@@ -209,6 +213,8 @@ class ClearKeyCdm : public ClearKeyCdmInterface { ...@@ -209,6 +213,8 @@ class ClearKeyCdm : public ClearKeyCdmInterface {
std::unique_ptr<FileIOTestRunner> file_io_test_runner_; std::unique_ptr<FileIOTestRunner> file_io_test_runner_;
bool is_running_output_protection_test_;
DISALLOW_COPY_AND_ASSIGN(ClearKeyCdm); DISALLOW_COPY_AND_ASSIGN(ClearKeyCdm);
}; };
......
...@@ -320,14 +320,14 @@ namespace media { ...@@ -320,14 +320,14 @@ namespace media {
PpapiCdmAdapter::PpapiCdmAdapter(PP_Instance instance, pp::Module* module) PpapiCdmAdapter::PpapiCdmAdapter(PP_Instance instance, pp::Module* module)
: pp::Instance(instance), : pp::Instance(instance),
pp::ContentDecryptor_Private(this), pp::ContentDecryptor_Private(this),
#if defined(OS_CHROMEOS)
output_protection_(this), output_protection_(this),
platform_verification_(this),
output_link_mask_(0), output_link_mask_(0),
output_protection_mask_(0), output_protection_mask_(0),
query_output_protection_in_progress_(false), query_output_protection_in_progress_(false),
uma_for_output_protection_query_reported_(false), uma_for_output_protection_query_reported_(false),
uma_for_output_protection_positive_result_reported_(false), uma_for_output_protection_positive_result_reported_(false),
#if defined(OS_CHROMEOS)
platform_verification_(this),
#endif #endif
allocator_(this), allocator_(this),
cdm_(NULL), cdm_(NULL),
...@@ -1069,7 +1069,6 @@ void PpapiCdmAdapter::SendPlatformChallenge(const char* service_id, ...@@ -1069,7 +1069,6 @@ void PpapiCdmAdapter::SendPlatformChallenge(const char* service_id,
} }
void PpapiCdmAdapter::EnableOutputProtection(uint32_t desired_protection_mask) { void PpapiCdmAdapter::EnableOutputProtection(uint32_t desired_protection_mask) {
#if defined(OS_CHROMEOS)
int32_t result = output_protection_.EnableProtection( int32_t result = output_protection_.EnableProtection(
desired_protection_mask, desired_protection_mask,
callback_factory_.NewCallback(&PpapiCdmAdapter::EnableProtectionDone)); callback_factory_.NewCallback(&PpapiCdmAdapter::EnableProtectionDone));
...@@ -1079,11 +1078,9 @@ void PpapiCdmAdapter::EnableOutputProtection(uint32_t desired_protection_mask) { ...@@ -1079,11 +1078,9 @@ void PpapiCdmAdapter::EnableOutputProtection(uint32_t desired_protection_mask) {
if (result != PP_OK && result != PP_OK_COMPLETIONPENDING) if (result != PP_OK && result != PP_OK_COMPLETIONPENDING)
CDM_DLOG() << __FUNCTION__ << " failed!"; CDM_DLOG() << __FUNCTION__ << " failed!";
#endif
} }
void PpapiCdmAdapter::QueryOutputProtectionStatus() { void PpapiCdmAdapter::QueryOutputProtectionStatus() {
#if defined(OS_CHROMEOS)
PP_DCHECK(!query_output_protection_in_progress_); PP_DCHECK(!query_output_protection_in_progress_);
output_link_mask_ = output_protection_mask_ = 0; output_link_mask_ = output_protection_mask_ = 0;
...@@ -1100,8 +1097,6 @@ void PpapiCdmAdapter::QueryOutputProtectionStatus() { ...@@ -1100,8 +1097,6 @@ void PpapiCdmAdapter::QueryOutputProtectionStatus() {
// Fall through on error and issue an empty OnQueryOutputProtectionStatus(). // Fall through on error and issue an empty OnQueryOutputProtectionStatus().
PP_DCHECK(result != PP_OK); PP_DCHECK(result != PP_OK);
CDM_DLOG() << __FUNCTION__ << " failed, result = " << result; CDM_DLOG() << __FUNCTION__ << " failed, result = " << result;
#endif
cdm_->OnQueryOutputProtectionStatus(cdm::kQueryFailed, 0, 0);
} }
void PpapiCdmAdapter::OnDeferredInitializationDone(cdm::StreamType stream_type, void PpapiCdmAdapter::OnDeferredInitializationDone(cdm::StreamType stream_type,
...@@ -1139,7 +1134,6 @@ cdm::FileIO* PpapiCdmAdapter::CreateFileIO(cdm::FileIOClient* client) { ...@@ -1139,7 +1134,6 @@ cdm::FileIO* PpapiCdmAdapter::CreateFileIO(cdm::FileIOClient* client) {
callback_factory_.NewCallback(&PpapiCdmAdapter::OnFirstFileRead)); callback_factory_.NewCallback(&PpapiCdmAdapter::OnFirstFileRead));
} }
#if defined(OS_CHROMEOS)
void PpapiCdmAdapter::ReportOutputProtectionUMA(OutputProtectionStatus status) { void PpapiCdmAdapter::ReportOutputProtectionUMA(OutputProtectionStatus status) {
pp::UMAPrivate uma_interface(this); pp::UMAPrivate uma_interface(this);
uma_interface.HistogramEnumeration("Media.EME.OutputProtection", status, uma_interface.HistogramEnumeration("Media.EME.OutputProtection", status,
...@@ -1169,9 +1163,10 @@ void PpapiCdmAdapter::ReportOutputProtectionQueryResult() { ...@@ -1169,9 +1163,10 @@ void PpapiCdmAdapter::ReportOutputProtectionQueryResult() {
const uint32_t kProtectableLinks = const uint32_t kProtectableLinks =
cdm::kLinkTypeHDMI | cdm::kLinkTypeDVI | cdm::kLinkTypeDisplayPort; cdm::kLinkTypeHDMI | cdm::kLinkTypeDVI | cdm::kLinkTypeDisplayPort;
bool is_unprotectable_link_connected = external_links & ~kProtectableLinks; bool is_unprotectable_link_connected =
(external_links & ~kProtectableLinks) != 0;
bool is_hdcp_enabled_on_all_protectable_links = bool is_hdcp_enabled_on_all_protectable_links =
output_protection_mask_ & cdm::kProtectionHDCP; (output_protection_mask_ & cdm::kProtectionHDCP) != 0;
if (!is_unprotectable_link_connected && if (!is_unprotectable_link_connected &&
is_hdcp_enabled_on_all_protectable_links) { is_hdcp_enabled_on_all_protectable_links) {
...@@ -1185,6 +1180,7 @@ void PpapiCdmAdapter::ReportOutputProtectionQueryResult() { ...@@ -1185,6 +1180,7 @@ void PpapiCdmAdapter::ReportOutputProtectionQueryResult() {
// queries and success results. // queries and success results.
} }
#if defined(OS_CHROMEOS)
void PpapiCdmAdapter::SendPlatformChallengeDone( void PpapiCdmAdapter::SendPlatformChallengeDone(
int32_t result, int32_t result,
const linked_ptr<PepperPlatformChallengeResponse>& response) { const linked_ptr<PepperPlatformChallengeResponse>& response) {
...@@ -1212,6 +1208,7 @@ void PpapiCdmAdapter::SendPlatformChallengeDone( ...@@ -1212,6 +1208,7 @@ void PpapiCdmAdapter::SendPlatformChallengeDone(
signed_data_var.Unmap(); signed_data_var.Unmap();
signed_data_signature_var.Unmap(); signed_data_signature_var.Unmap();
} }
#endif
void PpapiCdmAdapter::EnableProtectionDone(int32_t result) { void PpapiCdmAdapter::EnableProtectionDone(int32_t result) {
// Does nothing since clients must call QueryOutputProtectionStatus() to // Does nothing since clients must call QueryOutputProtectionStatus() to
...@@ -1237,7 +1234,6 @@ void PpapiCdmAdapter::QueryOutputProtectionStatusDone(int32_t result) { ...@@ -1237,7 +1234,6 @@ void PpapiCdmAdapter::QueryOutputProtectionStatusDone(int32_t result) {
cdm_->OnQueryOutputProtectionStatus(query_result, output_link_mask_, cdm_->OnQueryOutputProtectionStatus(query_result, output_link_mask_,
output_protection_mask_); output_protection_mask_);
} }
#endif
PpapiCdmAdapter::SessionError::SessionError( PpapiCdmAdapter::SessionError::SessionError(
cdm::Error error, cdm::Error error,
......
...@@ -20,12 +20,12 @@ ...@@ -20,12 +20,12 @@
#include "ppapi/c/private/pp_content_decryptor.h" #include "ppapi/c/private/pp_content_decryptor.h"
#include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/private/content_decryptor_private.h" #include "ppapi/cpp/private/content_decryptor_private.h"
#include "ppapi/cpp/private/output_protection_private.h"
#include "ppapi/cpp/var.h" #include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array_buffer.h" #include "ppapi/cpp/var_array_buffer.h"
#include "ppapi/utility/completion_callback_factory.h" #include "ppapi/utility/completion_callback_factory.h"
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "ppapi/cpp/private/output_protection_private.h"
#include "ppapi/cpp/private/platform_verification.h" #include "ppapi/cpp/private/platform_verification.h"
#endif #endif
...@@ -238,11 +238,14 @@ class PpapiCdmAdapter : public pp::Instance, ...@@ -238,11 +238,14 @@ class PpapiCdmAdapter : public pp::Instance,
void LogToConsole(const pp::Var& value); void LogToConsole(const pp::Var& value);
#endif // !defined(NDEBUG) #endif // !defined(NDEBUG)
#if defined(OS_CHROMEOS)
void ReportOutputProtectionUMA(OutputProtectionStatus status); void ReportOutputProtectionUMA(OutputProtectionStatus status);
void ReportOutputProtectionQuery(); void ReportOutputProtectionQuery();
void ReportOutputProtectionQueryResult(); void ReportOutputProtectionQueryResult();
void EnableProtectionDone(int32_t result);
void QueryOutputProtectionStatusDone(int32_t result);
#if defined(OS_CHROMEOS)
struct PepperPlatformChallengeResponse { struct PepperPlatformChallengeResponse {
pp::Var signed_data; pp::Var signed_data;
pp::Var signed_data_signature; pp::Var signed_data_signature;
...@@ -252,11 +255,9 @@ class PpapiCdmAdapter : public pp::Instance, ...@@ -252,11 +255,9 @@ class PpapiCdmAdapter : public pp::Instance,
void SendPlatformChallengeDone( void SendPlatformChallengeDone(
int32_t result, int32_t result,
const linked_ptr<PepperPlatformChallengeResponse>& response); const linked_ptr<PepperPlatformChallengeResponse>& response);
void EnableProtectionDone(int32_t result); #endif
void QueryOutputProtectionStatusDone(int32_t result);
pp::OutputProtection_Private output_protection_; pp::OutputProtection_Private output_protection_;
pp::PlatformVerification platform_verification_;
// Same as above, these are only read by QueryOutputProtectionStatusDone(). // Same as above, these are only read by QueryOutputProtectionStatusDone().
uint32_t output_link_mask_; uint32_t output_link_mask_;
...@@ -267,6 +268,9 @@ class PpapiCdmAdapter : public pp::Instance, ...@@ -267,6 +268,9 @@ class PpapiCdmAdapter : public pp::Instance,
// unprotected external link) have been reported to UMA. // unprotected external link) have been reported to UMA.
bool uma_for_output_protection_query_reported_; bool uma_for_output_protection_query_reported_;
bool uma_for_output_protection_positive_result_reported_; bool uma_for_output_protection_positive_result_reported_;
#if defined(OS_CHROMEOS)
pp::PlatformVerification platform_verification_;
#endif #endif
PpbBufferAllocator allocator_; PpbBufferAllocator allocator_;
......
...@@ -18,5 +18,5 @@ addScriptTag('media_source_utils.js'); ...@@ -18,5 +18,5 @@ addScriptTag('media_source_utils.js');
addScriptTag('player_utils.js'); addScriptTag('player_utils.js');
addScriptTag('clearkey_player.js'); addScriptTag('clearkey_player.js');
addScriptTag('widevine_player.js'); addScriptTag('widevine_player.js');
addScriptTag('file_io_test_player.js'); addScriptTag('unit_test_player.js');
addScriptTag('eme_app.js'); addScriptTag('eme_app.js');
...@@ -20,7 +20,7 @@ var DEFAULT_MEDIA_FILE = 'http://shadi.kir/alcatraz/Chrome_44-enc_av.webm'; ...@@ -20,7 +20,7 @@ var DEFAULT_MEDIA_FILE = 'http://shadi.kir/alcatraz/Chrome_44-enc_av.webm';
var KEY_ID = '0123456789012345'; var KEY_ID = '0123456789012345';
// Unique strings to identify test result expectations. // Unique strings to identify test result expectations.
var FILE_IO_TEST_SUCCESS = 'FILE_IO_TEST_SUCCESS'; var UNIT_TEST_SUCCESS = 'UNIT_TEST_SUCCESS';
var NOTSUPPORTEDERROR = 'NOTSUPPORTEDERROR'; var NOTSUPPORTEDERROR = 'NOTSUPPORTEDERROR';
var EME_GENERATEREQUEST_FAILED = 'EME_GENERATEREQUEST_FAILED'; var EME_GENERATEREQUEST_FAILED = 'EME_GENERATEREQUEST_FAILED';
var EME_SESSION_NOT_FOUND = 'EME_SESSION_NOT_FOUND'; var EME_SESSION_NOT_FOUND = 'EME_SESSION_NOT_FOUND';
...@@ -30,14 +30,16 @@ var EME_ERROR_EVENT = 'EME_ERROR_EVENT'; ...@@ -30,14 +30,16 @@ var EME_ERROR_EVENT = 'EME_ERROR_EVENT';
var EME_MESSAGE_UNEXPECTED_TYPE = 'EME_MESSAGE_UNEXPECTED_TYPE'; var EME_MESSAGE_UNEXPECTED_TYPE = 'EME_MESSAGE_UNEXPECTED_TYPE';
var EME_RENEWAL_MISSING_HEADER = 'EME_RENEWAL_MISSING_HEADER'; var EME_RENEWAL_MISSING_HEADER = 'EME_RENEWAL_MISSING_HEADER';
// Headers used when testing file I/O. // Headers used when running some specific unittests in the external CDM.
var FILE_IO_TEST_RESULT_HEADER = 'FILEIOTESTRESULT'; var UNIT_TEST_RESULT_HEADER = 'UNIT_TEST_RESULT';
// Available EME key systems to use. // Available EME key systems to use.
var CLEARKEY = 'org.w3.clearkey'; var CLEARKEY = 'org.w3.clearkey';
var EXTERNAL_CLEARKEY = 'org.chromium.externalclearkey'; var EXTERNAL_CLEARKEY = 'org.chromium.externalclearkey';
var WIDEVINE_KEYSYSTEM = 'com.widevine.alpha'; var WIDEVINE_KEYSYSTEM = 'com.widevine.alpha';
var FILE_IO_TEST_KEYSYSTEM = 'org.chromium.externalclearkey.fileiotest'; var FILE_IO_TEST_KEYSYSTEM = 'org.chromium.externalclearkey.fileiotest';
var OUTPUT_PROTECTION_TEST_KEYSYSTEM =
'org.chromium.externalclearkey.outputprotectiontest';
// Key system name:value map to show on the document page. // Key system name:value map to show on the document page.
var KEY_SYSTEMS = { var KEY_SYSTEMS = {
......
...@@ -148,7 +148,8 @@ PlayerUtils.createPlayer = function(video, testConfig) { ...@@ -148,7 +148,8 @@ PlayerUtils.createPlayer = function(video, testConfig) {
case CLEARKEY: case CLEARKEY:
return ClearKeyPlayer; return ClearKeyPlayer;
case FILE_IO_TEST_KEYSYSTEM: case FILE_IO_TEST_KEYSYSTEM:
return FileIOTestPlayer; case OUTPUT_PROTECTION_TEST_KEYSYSTEM:
return UnitTestPlayer;
default: default:
Utils.timeLog(keySystem + ' is not a known key system'); Utils.timeLog(keySystem + ' is not a known key system');
return ClearKeyPlayer; return ClearKeyPlayer;
......
...@@ -2,18 +2,20 @@ ...@@ -2,18 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// File IO test player is used to test File IO CDM functionality. // CDM unit test player is used to run a specific test within the CDM. The test
function FileIOTestPlayer(video, testConfig) { // result is reported via a special key message with UNIT_TEST_RESULT_HEADER
// followed by 1 for success, and 0 for failure.
function UnitTestPlayer(video, testConfig) {
this.video = video; this.video = video;
this.testConfig = testConfig; this.testConfig = testConfig;
} }
FileIOTestPlayer.prototype.init = function() { UnitTestPlayer.prototype.init = function() {
// Returns a promise. // Returns a promise.
return PlayerUtils.initEMEPlayer(this); return PlayerUtils.initEMEPlayer(this);
}; };
FileIOTestPlayer.prototype.registerEventListeners = function() { UnitTestPlayer.prototype.registerEventListeners = function() {
// Returns a promise. // Returns a promise.
return PlayerUtils.registerEMEEventListeners(this); return PlayerUtils.registerEMEEventListeners(this);
}; };
...@@ -21,19 +23,19 @@ FileIOTestPlayer.prototype.registerEventListeners = function() { ...@@ -21,19 +23,19 @@ FileIOTestPlayer.prototype.registerEventListeners = function() {
handleMessage = function(message) { handleMessage = function(message) {
// The test result is either '0' or '1' appended to the header. // The test result is either '0' or '1' appended to the header.
var msg = Utils.convertToUint8Array(message.message); var msg = Utils.convertToUint8Array(message.message);
if (Utils.hasPrefix(msg, FILE_IO_TEST_RESULT_HEADER)) { if (Utils.hasPrefix(msg, UNIT_TEST_RESULT_HEADER)) {
if (msg.length != FILE_IO_TEST_RESULT_HEADER.length + 1) { if (msg.length != UNIT_TEST_RESULT_HEADER.length + 1) {
Utils.failTest('Unexpected FileIOTest CDM message' + msg); Utils.failTest('Unexpected CDM Unit Test message' + msg);
return; return;
} }
var result_index = FILE_IO_TEST_RESULT_HEADER.length; var result_index = UNIT_TEST_RESULT_HEADER.length;
var success = String.fromCharCode(msg[result_index]) == 1; var success = String.fromCharCode(msg[result_index]) == 1;
Utils.timeLog('CDM file IO test: ' + (success ? 'Success' : 'Fail')); Utils.timeLog('CDM unit test: ' + (success ? 'Success' : 'Fail'));
if (success) if (success)
Utils.setResultInTitle(FILE_IO_TEST_SUCCESS); Utils.setResultInTitle(UNIT_TEST_SUCCESS);
else else
Utils.failTest('File IO CDM message fail status.'); Utils.failTest('CDM unit test failed.');
} }
}; };
FileIOTestPlayer.prototype.onMessage = handleMessage; UnitTestPlayer.prototype.onMessage = handleMessage;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment