From 649b57279934b2bf99eda48e1b9dc40e6be169be Mon Sep 17 00:00:00 2001 From: "ycheo@chromium.org" Date: Fri, 9 May 2014 14:54:44 +0000 Subject: Componentize EncryptedMediaMessageFilter and rename it CdmMessageFilter. The motivation is to reuse the Widevine keysystem registration logic in Android Webview. BUG=322395 Review URL: https://codereview.chromium.org/253593002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269297 0039d316-1c4b-4281-b951-d872f2087c98 --- components/cdm/DEPS | 3 + components/cdm/OWNERS | 3 + components/cdm/browser/DEPS | 4 + .../cdm/browser/cdm_message_filter_android.cc | 115 +++++++++++++++++++++ .../cdm/browser/cdm_message_filter_android.h | 43 ++++++++ components/cdm/common/DEPS | 3 + components/cdm/common/OWNERS | 13 +++ components/cdm/common/cdm_message_generator.cc | 34 ++++++ components/cdm/common/cdm_message_generator.h | 11 ++ components/cdm/common/cdm_messages_android.h | 36 +++++++ components/cdm/renderer/DEPS | 3 + components/cdm/renderer/widevine_key_systems.cc | 93 +++++++++++++++++ components/cdm/renderer/widevine_key_systems.h | 33 ++++++ 13 files changed, 394 insertions(+) create mode 100644 components/cdm/DEPS create mode 100644 components/cdm/OWNERS create mode 100644 components/cdm/browser/DEPS create mode 100644 components/cdm/browser/cdm_message_filter_android.cc create mode 100644 components/cdm/browser/cdm_message_filter_android.h create mode 100644 components/cdm/common/DEPS create mode 100644 components/cdm/common/OWNERS create mode 100644 components/cdm/common/cdm_message_generator.cc create mode 100644 components/cdm/common/cdm_message_generator.h create mode 100644 components/cdm/common/cdm_messages_android.h create mode 100644 components/cdm/renderer/DEPS create mode 100644 components/cdm/renderer/widevine_key_systems.cc create mode 100644 components/cdm/renderer/widevine_key_systems.h (limited to 'components/cdm') diff --git a/components/cdm/DEPS b/components/cdm/DEPS new file mode 100644 index 0000000..1c40d98 --- /dev/null +++ b/components/cdm/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+ipc", +] diff --git a/components/cdm/OWNERS b/components/cdm/OWNERS new file mode 100644 index 0000000..1f6205e --- /dev/null +++ b/components/cdm/OWNERS @@ -0,0 +1,3 @@ +ddorwin@chromium.org +scherkus@chromium.org +xhwang@chromium.org diff --git a/components/cdm/browser/DEPS b/components/cdm/browser/DEPS new file mode 100644 index 0000000..d0fb59f --- /dev/null +++ b/components/cdm/browser/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + "+content/public/browser", + "+media/base/android", +] diff --git a/components/cdm/browser/cdm_message_filter_android.cc b/components/cdm/browser/cdm_message_filter_android.cc new file mode 100644 index 0000000..82dac5e --- /dev/null +++ b/components/cdm/browser/cdm_message_filter_android.cc @@ -0,0 +1,115 @@ +// Copyright 2014 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 "components/cdm/browser/cdm_message_filter_android.h" + +#include + +#include "components/cdm/common/cdm_messages_android.h" +#include "ipc/ipc_message_macros.h" +#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/media_drm_bridge.h" + +using content::BrowserThread; +using content::SupportedCodecs; +using media::MediaCodecBridge; +using media::MediaDrmBridge; + +namespace cdm { + +const size_t kMaxKeySystemLength = 256; + +enum CodecType { + CODEC_AUDIO, + CODEC_VIDEO +}; + +struct CodecInfo { + SupportedCodecs codec; + CodecType codec_type; + const char* codec_name; + const char* container_mime_type; +}; + +const CodecInfo kCodecsToQuery[] = { + {content::EME_CODEC_WEBM_VORBIS, CODEC_AUDIO, "vorbis", "video/webm"}, + {content::EME_CODEC_WEBM_VP8, CODEC_VIDEO, "vp8", "video/webm"}, + {content::EME_CODEC_WEBM_VP9, CODEC_VIDEO, "vp9", "video/webm"}, +#if defined(USE_PROPRIETARY_CODECS) + {content::EME_CODEC_MP4_AAC, CODEC_AUDIO, "mp4a", "video/mp4"}, + {content::EME_CODEC_MP4_AVC1, CODEC_VIDEO, "avc1", "video/mp4"} +#endif // defined(USE_PROPRIETARY_CODECS) +}; + +static SupportedCodecs GetSupportedCodecs( + const SupportedKeySystemRequest& request, + bool video_must_be_compositable) { + const std::string& key_system = request.key_system; + SupportedCodecs supported_codecs = content::EME_CODEC_NONE; + + for (size_t i = 0; i < arraysize(kCodecsToQuery); ++i) { + const CodecInfo& info = kCodecsToQuery[i]; + // TODO(qinmin): Remove the composition logic when secure contents can be + // composited. + bool is_secure = (info.codec_type == CODEC_VIDEO) + ? (!video_must_be_compositable) : false; + if ((request.codecs & info.codec) && + MediaDrmBridge::IsKeySystemSupportedWithType( + key_system, info.container_mime_type) && + MediaCodecBridge::CanDecode(info.codec_name, is_secure)) { + supported_codecs |= info.codec; + } + } + + return supported_codecs; +} + +CdmMessageFilterAndroid::CdmMessageFilterAndroid() + : BrowserMessageFilter(EncryptedMediaMsgStart) {} + +CdmMessageFilterAndroid::~CdmMessageFilterAndroid() {} + +bool CdmMessageFilterAndroid::OnMessageReceived( + const IPC::Message& message, bool* message_was_ok) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX( + CdmMessageFilterAndroid, message, *message_was_ok) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_GetSupportedKeySystems, + OnGetSupportedKeySystems) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + return handled; +} + +void CdmMessageFilterAndroid::OverrideThreadForMessage( + const IPC::Message& message, BrowserThread::ID* thread) { + // Move the IPC handling to FILE thread as it is not very cheap. + if (message.type() == ChromeViewHostMsg_GetSupportedKeySystems::ID) + *thread = BrowserThread::FILE; +} + +void CdmMessageFilterAndroid::OnGetSupportedKeySystems( + const SupportedKeySystemRequest& request, + SupportedKeySystemResponse* response) { + if (!response) { + NOTREACHED() << "NULL response pointer provided."; + return; + } + + if (request.key_system.size() > kMaxKeySystemLength) { + NOTREACHED() << "Invalid key system: " << request.key_system; + return; + } + + if (!MediaDrmBridge::IsKeySystemSupported(request.key_system)) + return; + + DCHECK(request.codecs & content::EME_CODEC_ALL) << "unrecognized codec"; + response->key_system = request.key_system; + // TODO(qinmin): check composition is supported or not. + response->compositing_codecs = GetSupportedCodecs(request, true); + response->non_compositing_codecs = GetSupportedCodecs(request, false); +} + +} // namespace cdm diff --git a/components/cdm/browser/cdm_message_filter_android.h b/components/cdm/browser/cdm_message_filter_android.h new file mode 100644 index 0000000..b639fa8 --- /dev/null +++ b/components/cdm/browser/cdm_message_filter_android.h @@ -0,0 +1,43 @@ +// Copyright 2014 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 COMPONENTS_CDM_BROWSER_CDM_MESSAGE_FILTER_ANDROID_H_ +#define COMPONENTS_CDM_BROWSER_CDM_MESSAGE_FILTER_ANDROID_H_ + +#include "base/basictypes.h" +#include "content/public/browser/browser_message_filter.h" + +struct SupportedKeySystemRequest; +struct SupportedKeySystemResponse; + +namespace cdm { + +// Message filter for EME on android. It is responsible for getting the +// SupportedKeySystems information and passing it back to renderer. +class CdmMessageFilterAndroid + : public content::BrowserMessageFilter { + public: + CdmMessageFilterAndroid(); + + private: + virtual ~CdmMessageFilterAndroid(); + + // BrowserMessageFilter implementation. + virtual bool OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) OVERRIDE; + virtual void OverrideThreadForMessage( + const IPC::Message& message, + content::BrowserThread::ID* thread) OVERRIDE; + + // Retrieve the supported key systems. + void OnGetSupportedKeySystems( + const SupportedKeySystemRequest& request, + SupportedKeySystemResponse* response); + + DISALLOW_COPY_AND_ASSIGN(CdmMessageFilterAndroid); +}; + +} // namespace cdm + +#endif // COMPONENTS_CDM_BROWSER_CDM_MESSAGE_FILTER_ANDROID_H_ diff --git a/components/cdm/common/DEPS b/components/cdm/common/DEPS new file mode 100644 index 0000000..d5923ee --- /dev/null +++ b/components/cdm/common/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+content/public/common", +] diff --git a/components/cdm/common/OWNERS b/components/cdm/common/OWNERS new file mode 100644 index 0000000..acdf360 --- /dev/null +++ b/components/cdm/common/OWNERS @@ -0,0 +1,13 @@ +# Changes to IPC messages require a security review to avoid introducing +# new sandbox escapes. +per-file encrypted_media_messages*.h=set noparent +per-file encrypted_media_messages*.h=cdn@chromium.org +per-file encrypted_media_messages*.h=cevans@chromium.org +per-file encrypted_media_messages*.h=dcheng@chromium.org +per-file encrypted_media_messages*.h=inferno@chromium.org +per-file encrypted_media_messages*.h=jln@chromium.org +per-file encrypted_media_messages*.h=jschuh@chromium.org +per-file encrypted_media_messages*.h=kenrb@chromium.org +per-file encrypted_media_messages*.h=nasko@chromium.org +per-file encrypted_media_messages*.h=palmer@chromium.org +per-file encrypted_media_messages*.h=tsepez@chromium.org diff --git a/components/cdm/common/cdm_message_generator.cc b/components/cdm/common/cdm_message_generator.cc new file mode 100644 index 0000000..2aabce7 --- /dev/null +++ b/components/cdm/common/cdm_message_generator.cc @@ -0,0 +1,34 @@ +// Copyright 2014 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. + +// Get basic type definitions. +#define IPC_MESSAGE_IMPL +#include "components/cdm/common/cdm_message_generator.h" + +// Generate constructors. +#include "ipc/struct_constructor_macros.h" +#include "components/cdm/common/cdm_message_generator.h" + +// Generate destructors. +#include "ipc/struct_destructor_macros.h" +#include "components/cdm/common/cdm_message_generator.h" + +// Generate param traits write methods. +#include "ipc/param_traits_write_macros.h" +namespace IPC { +#include "components/cdm/common/cdm_message_generator.h" +} // namespace IPC + +// Generate param traits read methods. +#include "ipc/param_traits_read_macros.h" +namespace IPC { +#include "components/cdm/common/cdm_message_generator.h" +} // namespace IPC + +// Generate param traits log methods. +#include "ipc/param_traits_log_macros.h" +namespace IPC { +#include "components/cdm/common/cdm_message_generator.h" +} // namespace IPC + diff --git a/components/cdm/common/cdm_message_generator.h b/components/cdm/common/cdm_message_generator.h new file mode 100644 index 0000000..b528207 --- /dev/null +++ b/components/cdm/common/cdm_message_generator.h @@ -0,0 +1,11 @@ +// Copyright 2014 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. + +// Multiply-included file, no traditional include guard. + +#include "base/basictypes.h" // for OS_ANDROID and some basic types. + +#if defined(OS_ANDROID) +#include "components/cdm/common/cdm_messages_android.h" +#endif diff --git a/components/cdm/common/cdm_messages_android.h b/components/cdm/common/cdm_messages_android.h new file mode 100644 index 0000000..e63f81b --- /dev/null +++ b/components/cdm/common/cdm_messages_android.h @@ -0,0 +1,36 @@ +// Copyright 2014 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. + +// IPC messages for EME on android. +// Multiply-included message file, hence no include guard. + +#include + +#include "content/public/common/eme_codec.h" +#include "ipc/ipc_message_macros.h" + +#define IPC_MESSAGE_START EncryptedMediaMsgStart + +IPC_STRUCT_BEGIN(SupportedKeySystemRequest) + IPC_STRUCT_MEMBER(std::string, key_system) + IPC_STRUCT_MEMBER(content::SupportedCodecs, codecs, content::EME_CODEC_NONE) +IPC_STRUCT_END() + +IPC_STRUCT_BEGIN(SupportedKeySystemResponse) + IPC_STRUCT_MEMBER(std::string, key_system) + IPC_STRUCT_MEMBER(content::SupportedCodecs, + compositing_codecs, + content::EME_CODEC_NONE) + IPC_STRUCT_MEMBER(content::SupportedCodecs, + non_compositing_codecs, + content::EME_CODEC_NONE) +IPC_STRUCT_END() + +// Messages sent from the renderer to the browser. + +// Synchronously get a list of supported EME key systems. +IPC_SYNC_MESSAGE_CONTROL1_1( + ChromeViewHostMsg_GetSupportedKeySystems, + SupportedKeySystemRequest /* key system information request */, + SupportedKeySystemResponse /* key system information response */) diff --git a/components/cdm/renderer/DEPS b/components/cdm/renderer/DEPS new file mode 100644 index 0000000..725e151 --- /dev/null +++ b/components/cdm/renderer/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+content/public/renderer", +] diff --git a/components/cdm/renderer/widevine_key_systems.cc b/components/cdm/renderer/widevine_key_systems.cc new file mode 100644 index 0000000..d42ec7d --- /dev/null +++ b/components/cdm/renderer/widevine_key_systems.cc @@ -0,0 +1,93 @@ +// Copyright 2014 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 "components/cdm/renderer/widevine_key_systems.h" + +#include +#include + +#include "base/logging.h" +#include "components/cdm/common/cdm_messages_android.h" +#include "content/public/renderer/key_system_info.h" +#include "content/public/renderer/render_thread.h" + +#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. + +#if defined(WIDEVINE_CDM_AVAILABLE) + +using content::KeySystemInfo; +using content::SupportedCodecs; + +namespace cdm { + +// Return |name|'s parent key system. +static std::string GetDirectParentName(std::string name) { + int last_period = name.find_last_of('.'); + DCHECK_GT(last_period, 0); + return name.substr(0, last_period); +} + +void AddWidevineWithCodecs(WidevineCdmType widevine_cdm_type, + SupportedCodecs supported_codecs, + std::vector* concrete_key_systems) { + KeySystemInfo info(kWidevineKeySystem); + + switch (widevine_cdm_type) { + case WIDEVINE: + // For standard Widevine, add parent name. + info.parent_key_system = GetDirectParentName(kWidevineKeySystem); + break; +#if defined(OS_ANDROID) + case WIDEVINE_HR_NON_COMPOSITING: + info.key_system.append(".hrnoncompositing"); + break; +#endif // defined(OS_ANDROID) + default: + NOTREACHED(); + } + + // TODO(xhwang): A container or an initDataType may be supported even though + // there are no codecs supported in that container. Fix this when we support + // initDataType. + info.supported_codecs = supported_codecs; + +#if defined(ENABLE_PEPPER_CDMS) + info.pepper_type = kWidevineCdmPluginMimeType; +#endif // defined(ENABLE_PEPPER_CDMS) + + concrete_key_systems->push_back(info); +} + +#if defined(OS_ANDROID) +void AddAndroidWidevine(std::vector* concrete_key_systems) { + SupportedKeySystemRequest request; + SupportedKeySystemResponse response; + + request.key_system = kWidevineKeySystem; + request.codecs = content::EME_CODEC_WEBM_ALL | content::EME_CODEC_MP4_ALL; + content::RenderThread::Get()->Send( + new ChromeViewHostMsg_GetSupportedKeySystems(request, &response)); + DCHECK(response.compositing_codecs & content::EME_CODEC_ALL) + << "unrecognized codec"; + DCHECK(response.non_compositing_codecs & content::EME_CODEC_ALL) + << "unrecognized codec"; + if (response.compositing_codecs != content::EME_CODEC_NONE) { + AddWidevineWithCodecs( + WIDEVINE, + static_cast(response.compositing_codecs), + concrete_key_systems); + } + + if (response.non_compositing_codecs != content::EME_CODEC_NONE) { + AddWidevineWithCodecs( + WIDEVINE_HR_NON_COMPOSITING, + static_cast(response.non_compositing_codecs), + concrete_key_systems); + } +} +#endif // OS_ANDROID + +} // namespace cdm + +#endif // defined(WIDEVINE_CDM_AVAILABLE) diff --git a/components/cdm/renderer/widevine_key_systems.h b/components/cdm/renderer/widevine_key_systems.h new file mode 100644 index 0000000..3bed60c --- /dev/null +++ b/components/cdm/renderer/widevine_key_systems.h @@ -0,0 +1,33 @@ +// Copyright 2014 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 COMPONENTS_CDM_RENDERER_WIDEVINE_KEY_SYSTEMS_H_ +#define COMPONENTS_CDM_RENDERER_WIDEVINE_KEY_SYSTEMS_H_ + +#include + +#include "content/public/renderer/key_system_info.h" + +namespace cdm { + +enum WidevineCdmType { + WIDEVINE, +#if defined(OS_ANDROID) + WIDEVINE_HR_NON_COMPOSITING, +#endif // defined(OS_ANDROID) +}; + +void AddWidevineWithCodecs( + WidevineCdmType widevine_cdm_type, + content::SupportedCodecs supported_codecs, + std::vector* concrete_key_systems); + +#if defined(OS_ANDROID) +void AddAndroidWidevine( + std::vector* concrete_key_systems); +#endif // defined(OS_ANDROID) + +} // namespace cdm + +#endif // COMPONENTS_CDM_RENDERER_WIDEVINE_KEY_SYSTEMS_H_ -- cgit v1.1