1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/cdm/browser/cdm_message_filter_android.h"
6
7#include <string>
8#include <vector>
9
10#include "components/cdm/common/cdm_messages_android.h"
11#include "ipc/ipc_message_macros.h"
12#include "media/base/android/media_codec_bridge.h"
13#include "media/base/android/media_drm_bridge.h"
14
15using content::BrowserThread;
16using content::SupportedCodecs;
17using media::MediaCodecBridge;
18using media::MediaDrmBridge;
19
20namespace cdm {
21
22const size_t kMaxKeySystemLength = 256;
23
24enum CodecType {
25  CODEC_AUDIO,
26  CODEC_VIDEO
27};
28
29struct CodecInfo {
30  SupportedCodecs codec;
31  CodecType codec_type;
32  const char* codec_name;
33  const char* container_mime_type;
34};
35
36const CodecInfo kCodecsToQuery[] = {
37  {content::EME_CODEC_WEBM_VORBIS, CODEC_AUDIO, "vorbis", "video/webm"},
38  {content::EME_CODEC_WEBM_VP8, CODEC_VIDEO, "vp8", "video/webm"},
39  {content::EME_CODEC_WEBM_VP9, CODEC_VIDEO, "vp9", "video/webm"},
40#if defined(USE_PROPRIETARY_CODECS)
41  {content::EME_CODEC_MP4_AAC, CODEC_AUDIO, "mp4a", "video/mp4"},
42  {content::EME_CODEC_MP4_AVC1, CODEC_VIDEO, "avc1", "video/mp4"}
43#endif  // defined(USE_PROPRIETARY_CODECS)
44};
45
46static SupportedCodecs GetSupportedCodecs(
47    const SupportedKeySystemRequest& request,
48    bool video_must_be_compositable) {
49  const std::string& key_system = request.key_system;
50  SupportedCodecs supported_codecs = content::EME_CODEC_NONE;
51
52  for (size_t i = 0; i < arraysize(kCodecsToQuery); ++i) {
53    const CodecInfo& info = kCodecsToQuery[i];
54    // TODO(qinmin): Remove the composition logic when secure contents can be
55    // composited.
56    bool is_secure = (info.codec_type == CODEC_VIDEO)
57                         ? (!video_must_be_compositable) : false;
58    if ((request.codecs & info.codec) &&
59        MediaDrmBridge::IsKeySystemSupportedWithType(
60            key_system, info.container_mime_type) &&
61        MediaCodecBridge::CanDecode(info.codec_name, is_secure)) {
62      supported_codecs |= info.codec;
63    }
64  }
65
66  return supported_codecs;
67}
68
69CdmMessageFilterAndroid::CdmMessageFilterAndroid()
70    : BrowserMessageFilter(EncryptedMediaMsgStart) {}
71
72CdmMessageFilterAndroid::~CdmMessageFilterAndroid() {}
73
74bool CdmMessageFilterAndroid::OnMessageReceived(const IPC::Message& message) {
75  bool handled = true;
76  IPC_BEGIN_MESSAGE_MAP(CdmMessageFilterAndroid, message)
77    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_QueryKeySystemSupport,
78                        OnQueryKeySystemSupport)
79    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_GetPlatformKeySystemNames,
80                        OnGetPlatformKeySystemNames)
81    IPC_MESSAGE_UNHANDLED(handled = false)
82  IPC_END_MESSAGE_MAP()
83  return handled;
84}
85
86void CdmMessageFilterAndroid::OverrideThreadForMessage(
87    const IPC::Message& message, BrowserThread::ID* thread) {
88  // Move the IPC handling to FILE thread as it is not very cheap.
89  if (message.type() == ChromeViewHostMsg_QueryKeySystemSupport::ID)
90    *thread = BrowserThread::FILE;
91}
92
93void CdmMessageFilterAndroid::OnQueryKeySystemSupport(
94    const SupportedKeySystemRequest& request,
95    SupportedKeySystemResponse* response) {
96  if (!response) {
97    NOTREACHED() << "NULL response pointer provided.";
98    return;
99  }
100
101  if (request.key_system.size() > kMaxKeySystemLength) {
102    NOTREACHED() << "Invalid key system: " << request.key_system;
103    return;
104  }
105
106  if (!MediaDrmBridge::IsKeySystemSupported(request.key_system))
107    return;
108
109  DCHECK(request.codecs & content::EME_CODEC_ALL) << "unrecognized codec";
110  response->key_system = request.key_system;
111  // TODO(qinmin): check composition is supported or not.
112  response->compositing_codecs = GetSupportedCodecs(request, true);
113  response->non_compositing_codecs = GetSupportedCodecs(request, false);
114}
115
116void CdmMessageFilterAndroid::OnGetPlatformKeySystemNames(
117    std::vector<std::string>* key_systems) {
118  *key_systems = MediaDrmBridge::GetPlatformKeySystemNames();
119}
120
121}  // namespace cdm
122