content_decryption_module_factory.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1// Copyright 2013 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 "content/renderer/media/crypto/content_decryption_module_factory.h"
6
7#include "base/logging.h"
8#include "content/renderer/media/crypto/key_systems.h"
9#include "media/cdm/aes_decryptor.h"
10
11#if defined(ENABLE_PEPPER_CDMS)
12#include "content/renderer/media/crypto/ppapi_decryptor.h"
13#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
14#include "content/renderer/pepper/pepper_webplugin_impl.h"
15#include "third_party/WebKit/public/platform/WebString.h"
16#include "third_party/WebKit/public/web/WebFrame.h"
17#include "third_party/WebKit/public/web/WebMediaPlayerClient.h"
18#elif defined(OS_ANDROID)
19#include "content/renderer/media/android/proxy_media_keys.h"
20#include "content/renderer/media/android/webmediaplayer_proxy_android.h"
21#endif  // defined(ENABLE_PEPPER_CDMS)
22
23namespace content {
24
25#if defined(ENABLE_PEPPER_CDMS)
26// Returns the PepperPluginInstanceImpl associated with the Helper Plugin.
27// If a non-NULL pointer is returned, the caller must call
28// closeHelperPluginSoon() when the Helper Plugin is no longer needed.
29static scoped_refptr<PepperPluginInstanceImpl> CreateHelperPlugin(
30    const std::string& plugin_type,
31    WebKit::WebMediaPlayerClient* web_media_player_client,
32    WebKit::WebFrame* web_frame) {
33  DCHECK(web_media_player_client);
34  DCHECK(web_frame);
35
36  WebKit::WebPlugin* web_plugin = web_media_player_client->createHelperPlugin(
37      WebKit::WebString::fromUTF8(plugin_type), web_frame);
38  if (!web_plugin)
39    return NULL;
40
41  DCHECK(!web_plugin->isPlaceholder());  // Prevented by Blink.
42  // Only Pepper plugins are supported, so it must be a ppapi object.
43  PepperWebPluginImpl* ppapi_plugin =
44      static_cast<PepperWebPluginImpl*>(web_plugin);
45  return ppapi_plugin->instance();
46}
47
48static scoped_ptr<media::MediaKeys> CreatePpapiDecryptor(
49    const std::string& key_system,
50    const media::KeyAddedCB& key_added_cb,
51    const media::KeyErrorCB& key_error_cb,
52    const media::KeyMessageCB& key_message_cb,
53    const base::Closure& destroy_plugin_cb,
54    WebKit::WebMediaPlayerClient* web_media_player_client,
55    WebKit::WebFrame* web_frame) {
56  DCHECK(web_media_player_client);
57  DCHECK(web_frame);
58
59  std::string plugin_type = GetPepperType(key_system);
60  DCHECK(!plugin_type.empty());
61  const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance =
62      CreateHelperPlugin(plugin_type, web_media_player_client, web_frame);
63  if (!plugin_instance.get()) {
64    DLOG(ERROR) << "ProxyDecryptor: plugin instance creation failed.";
65    return scoped_ptr<media::MediaKeys>();
66  }
67
68  scoped_ptr<PpapiDecryptor> decryptor =
69      PpapiDecryptor::Create(key_system,
70                             plugin_instance,
71                             key_added_cb,
72                             key_error_cb,
73                             key_message_cb,
74                             destroy_plugin_cb);
75
76  if (!decryptor)
77    destroy_plugin_cb.Run();
78  // Else the new object will call destroy_plugin_cb to destroy Helper Plugin.
79
80  return scoped_ptr<media::MediaKeys>(decryptor.Pass());
81}
82
83void ContentDecryptionModuleFactory::DestroyHelperPlugin(
84    WebKit::WebMediaPlayerClient* web_media_player_client,
85    WebKit::WebFrame* web_frame) {
86  web_media_player_client->closeHelperPluginSoon(web_frame);
87}
88#endif  // defined(ENABLE_PEPPER_CDMS)
89
90scoped_ptr<media::MediaKeys> ContentDecryptionModuleFactory::Create(
91    const std::string& key_system,
92#if defined(ENABLE_PEPPER_CDMS)
93    WebKit::WebMediaPlayerClient* web_media_player_client,
94    WebKit::WebFrame* web_frame,
95    const base::Closure& destroy_plugin_cb,
96#elif defined(OS_ANDROID)
97    WebMediaPlayerProxyAndroid* proxy,
98    int media_keys_id,
99    const GURL& frame_url,
100#endif  // defined(ENABLE_PEPPER_CDMS)
101    const media::KeyAddedCB& key_added_cb,
102    const media::KeyErrorCB& key_error_cb,
103    const media::KeyMessageCB& key_message_cb) {
104  if (CanUseAesDecryptor(key_system)) {
105    return scoped_ptr<media::MediaKeys>(
106        new media::AesDecryptor(key_added_cb, key_error_cb, key_message_cb));
107  }
108
109#if defined(ENABLE_PEPPER_CDMS)
110  // TODO(ddorwin): Remove when the WD API implementation supports loading
111  // Pepper-based CDMs: http://crbug.com/250049
112  if (!web_media_player_client)
113    return scoped_ptr<media::MediaKeys>();
114
115  return CreatePpapiDecryptor(
116      key_system, key_added_cb, key_error_cb, key_message_cb,
117      destroy_plugin_cb, web_media_player_client, web_frame);
118#elif defined(OS_ANDROID)
119  scoped_ptr<ProxyMediaKeys> proxy_media_keys(
120      new ProxyMediaKeys(proxy, media_keys_id));
121  proxy_media_keys->InitializeCDM(key_system, frame_url);
122  return proxy_media_keys.PassAs<media::MediaKeys>();
123#else
124  return scoped_ptr<media::MediaKeys>();
125#endif  // defined(ENABLE_PEPPER_CDMS)
126}
127
128}  // namespace content
129