summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android_webview/android_webview.gyp2
-rw-r--r--android_webview/browser/DEPS2
-rw-r--r--android_webview/browser/aw_browser_main_parts.cc6
-rw-r--r--android_webview/browser/aw_media_client_android.cc71
-rw-r--r--android_webview/browser/aw_media_client_android.h36
-rw-r--r--android_webview/common/aw_resource.h1
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java19
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwResource.java7
-rw-r--r--android_webview/native/aw_resource.cc11
-rw-r--r--chrome/browser/android/chrome_media_client_android.cc19
-rw-r--r--chrome/browser/android/chrome_media_client_android.h27
-rw-r--r--chrome/browser/chrome_browser_main_android.cc8
-rw-r--r--chrome/browser/chrome_browser_main_android.h1
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chromecast/browser/DEPS1
-rw-r--r--chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastBrowserHelper.java8
-rw-r--r--chromecast/browser/cast_browser_main_parts.cc11
-rw-r--r--chromecast/browser/cast_content_browser_client.cc3
-rw-r--r--chromecast/browser/media/cast_media_client_android.cc44
-rw-r--r--chromecast/browser/media/cast_media_client_android.h41
-rw-r--r--chromecast/chromecast.gyp8
-rw-r--r--chromecast/media/base/key_systems_common.h12
-rw-r--r--chromecast/media/base/key_systems_common_simple.cc8
-rw-r--r--chromecast/media/cdm/playready_drm_delegate_android.cc85
-rw-r--r--chromecast/media/cdm/playready_drm_delegate_android.h34
-rw-r--r--chromecast/media/media.gyp8
-rw-r--r--components/OWNERS4
-rw-r--r--components/cdm.gypi2
-rw-r--r--components/cdm/browser/BUILD.gn2
-rw-r--r--components/cdm/browser/widevine_drm_delegate_android.cc163
-rw-r--r--components/cdm/browser/widevine_drm_delegate_android.h32
-rw-r--r--media/base/android/BUILD.gn4
-rw-r--r--media/base/android/java/src/org/chromium/media/MediaDrmBridge.java71
-rw-r--r--media/base/android/media_client_android.cc37
-rw-r--r--media/base/android/media_client_android.h59
-rw-r--r--media/base/android/media_drm_bridge.cc212
-rw-r--r--media/base/android/media_drm_bridge_delegate.cc27
-rw-r--r--media/base/android/media_drm_bridge_delegate.h46
-rw-r--r--media/media.gyp4
39 files changed, 910 insertions, 228 deletions
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp
index 83f165f..77aeafc 100644
--- a/android_webview/android_webview.gyp
+++ b/android_webview/android_webview.gyp
@@ -222,6 +222,8 @@
'browser/aw_javascript_dialog_manager.h',
'browser/aw_login_delegate.cc',
'browser/aw_login_delegate.h',
+ 'browser/aw_media_client_android.cc',
+ 'browser/aw_media_client_android.h',
'browser/aw_message_port_message_filter.cc',
'browser/aw_message_port_message_filter.h',
'browser/aw_message_port_service.h',
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS
index ba8fe5b..9fd4db1 100644
--- a/android_webview/browser/DEPS
+++ b/android_webview/browser/DEPS
@@ -24,6 +24,8 @@ include_rules = [
"+content/public/browser",
"+content/public/test",
+ "+media/base/android",
+
"+printing",
"+ui/gfx",
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index b10b4d4..24f552b 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -6,7 +6,9 @@
#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_dev_tools_discovery_provider.h"
+#include "android_webview/browser/aw_media_client_android.h"
#include "android_webview/browser/aw_result_codes.h"
+#include "android_webview/common/aw_resource.h"
#include "android_webview/native/public/aw_assets.h"
#include "base/android/build_info.h"
#include "base/android/locale_utils.h"
@@ -18,6 +20,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_utils.h"
+#include "media/base/android/media_client_android.h"
#include "net/android/network_change_notifier_factory_android.h"
#include "net/base/network_change_notifier.h"
#include "ui/base/l10n/l10n_util.h"
@@ -96,6 +99,9 @@ void AwBrowserMainParts::PreMainMessageLoopRun() {
AwDevToolsDiscoveryProvider::Install();
+ media::SetMediaClientAndroid(
+ new AwMediaClientAndroid(AwResource::GetConfigKeySystemUuidMapping()));
+
// This is needed for WebView Classic backwards compatibility
// See crbug.com/298495
content::SetMaxURLChars(20 * 1024 * 1024);
diff --git a/android_webview/browser/aw_media_client_android.cc b/android_webview/browser/aw_media_client_android.cc
new file mode 100644
index 0000000..bc71465
--- /dev/null
+++ b/android_webview/browser/aw_media_client_android.cc
@@ -0,0 +1,71 @@
+// Copyright 2015 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 "android_webview/browser/aw_media_client_android.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+
+namespace android_webview {
+
+namespace {
+
+const size_t kGUIDLength = 36U;
+
+#define RCHECK(x) \
+ if (!(x)) { \
+ LOG(ERROR) << "Can't parse key-system mapping: " \
+ << key_system_uuid_mapping; \
+ return std::make_pair("", uuid); \
+ }
+
+media::MediaClientAndroid::KeySystemUuidMap::value_type CreateMappingFromString(
+ const std::string& key_system_uuid_mapping) {
+ std::vector<uint8_t> uuid;
+
+ std::vector<std::string> tokens;
+ Tokenize(key_system_uuid_mapping, ",", &tokens);
+ RCHECK(tokens.size() == 2);
+
+ std::string key_system;
+ base::TrimWhitespaceASCII(tokens[0], base::TRIM_ALL, &key_system);
+
+ std::string guid(tokens[1]);
+ RCHECK(guid.length() == kGUIDLength);
+ base::RemoveChars(guid, "-", &guid);
+ RCHECK(base::HexStringToBytes(guid, &uuid));
+
+ return std::make_pair(key_system, uuid);
+}
+
+} // namespace
+
+AwMediaClientAndroid::AwMediaClientAndroid(
+ const std::vector<std::string>& key_system_uuid_mappings)
+ : key_system_uuid_mappings_(key_system_uuid_mappings) {
+}
+
+AwMediaClientAndroid::~AwMediaClientAndroid() {
+}
+
+void AwMediaClientAndroid::AddKeySystemUUIDMappings(KeySystemUuidMap* map) {
+ for (const std::string& key_system_uuid_mapping : key_system_uuid_mappings_) {
+ auto mapping = CreateMappingFromString(key_system_uuid_mapping);
+ if (!mapping.first.empty())
+ map->insert(mapping);
+ }
+}
+
+media::MediaDrmBridgeDelegate* AwMediaClientAndroid::GetMediaDrmBridgeDelegate(
+ const media::UUID& scheme_uuid) {
+ if (scheme_uuid == widevine_delegate_.GetUUID())
+ return &widevine_delegate_;
+ return nullptr;
+}
+
+} // namespace android_webview
diff --git a/android_webview/browser/aw_media_client_android.h b/android_webview/browser/aw_media_client_android.h
new file mode 100644
index 0000000..a2a6718
--- /dev/null
+++ b/android_webview/browser/aw_media_client_android.h
@@ -0,0 +1,36 @@
+// Copyright 2015 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 ANDROID_WEBVIEW_BROWSER_AW_MEDIA_CLIENT_ANDROID_H_
+#define ANDROID_WEBVIEW_BROWSER_AW_MEDIA_CLIENT_ANDROID_H_
+
+#include "base/macros.h"
+#include "components/cdm/browser/widevine_drm_delegate_android.h"
+#include "media/base/android/media_client_android.h"
+
+namespace android_webview {
+
+class AwMediaClientAndroid : public media::MediaClientAndroid {
+ public:
+ // |key_system_uuid_mappings| is a list of strings containing key-system/UUID
+ // pairs, in the format "key system name,UUID as string".
+ explicit AwMediaClientAndroid(
+ const std::vector<std::string>& key_system_uuid_mappings);
+ ~AwMediaClientAndroid() override;
+
+ private:
+ // media::MediaClientAndroid implementation:
+ void AddKeySystemUUIDMappings(KeySystemUuidMap* map) override;
+ media::MediaDrmBridgeDelegate* GetMediaDrmBridgeDelegate(
+ const media::UUID& scheme_uuid) override;
+
+ std::vector<std::string> key_system_uuid_mappings_;
+ cdm::WidevineDrmDelegateAndroid widevine_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(AwMediaClientAndroid);
+};
+
+} // namespace android_webview
+
+#endif // ANDROID_WEBVIEW_BROWSER_AW_MEDIA_CLIENT_ANDROID_H_
diff --git a/android_webview/common/aw_resource.h b/android_webview/common/aw_resource.h
index 00613c3..e5c04179 100644
--- a/android_webview/common/aw_resource.h
+++ b/android_webview/common/aw_resource.h
@@ -14,6 +14,7 @@ namespace AwResource {
std::string GetLoadErrorPageContent();
std::string GetNoDomainPageContent();
+std::vector<std::string> GetConfigKeySystemUuidMapping();
} // namespace AwResource
} // namsespace android_webview
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
index c1529e6..592e48f 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
@@ -5,7 +5,6 @@
package org.chromium.android_webview;
import android.content.Context;
-import android.util.Log;
import org.chromium.base.PathUtils;
import org.chromium.base.ThreadUtils;
@@ -13,9 +12,6 @@ import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.content.browser.BrowserStartupController;
-import org.chromium.media.MediaDrmBridge;
-
-import java.util.UUID;
/**
* Wrapper for the steps needed to initialize the java and native sides of webview chromium.
@@ -60,25 +56,10 @@ public abstract class AwBrowserProcess {
try {
BrowserStartupController.get(context, LibraryProcessType.PROCESS_WEBVIEW)
.startBrowserProcessesSync(true);
- initializePlatformKeySystem();
} catch (ProcessInitException e) {
throw new RuntimeException("Cannot initialize WebView", e);
}
}
});
}
-
- private static void initializePlatformKeySystem() {
- String[] mappings = AwResource.getConfigKeySystemUuidMapping();
- for (String mapping : mappings) {
- try {
- String fragments[] = mapping.split(",");
- String keySystem = fragments[0].trim();
- UUID uuid = UUID.fromString(fragments[1]);
- MediaDrmBridge.addKeySystemUuidMapping(keySystem, uuid);
- } catch (java.lang.RuntimeException e) {
- Log.e(TAG, "Can't parse key-system mapping: " + mapping);
- }
- }
- }
}
diff --git a/android_webview/java/src/org/chromium/android_webview/AwResource.java b/android_webview/java/src/org/chromium/android_webview/AwResource.java
index e74206d..7939fe8 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwResource.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwResource.java
@@ -60,16 +60,17 @@ public class AwResource {
}
@CalledByNative
- public static String getNoDomainPageContent() {
+ private static String getNoDomainPageContent() {
return getResource(sRawNoDomain, TYPE_RAW);
}
@CalledByNative
- public static String getLoadErrorPageContent() {
+ private static String getLoadErrorPageContent() {
return getResource(sRawLoadError, TYPE_RAW);
}
- public static String[] getConfigKeySystemUuidMapping() {
+ @CalledByNative
+ private static String[] getConfigKeySystemUuidMapping() {
// No need to cache, since this should be called only once.
return sResources.getStringArray(sStringArrayConfigKeySystemUUIDMapping);
}
diff --git a/android_webview/native/aw_resource.cc b/android_webview/native/aw_resource.cc
index 498a201..75f75b5 100644
--- a/android_webview/native/aw_resource.cc
+++ b/android_webview/native/aw_resource.cc
@@ -4,6 +4,7 @@
#include "android_webview/native/aw_resource.h"
+#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "jni/AwResource_jni.h"
@@ -30,6 +31,16 @@ std::string GetNoDomainPageContent() {
return base::android::ConvertJavaStringToUTF8(content);
}
+std::vector<std::string> GetConfigKeySystemUuidMapping() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ std::vector<std::string> key_system_uuid_mappings;
+ ScopedJavaLocalRef<jobjectArray> mappings =
+ Java_AwResource_getConfigKeySystemUuidMapping(env);
+ base::android::AppendJavaStringArrayToStringVector(env, mappings.obj(),
+ &key_system_uuid_mappings);
+ return key_system_uuid_mappings;
+}
+
bool RegisterAwResource(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/chrome/browser/android/chrome_media_client_android.cc b/chrome/browser/android/chrome_media_client_android.cc
new file mode 100644
index 0000000..1f8a542
--- /dev/null
+++ b/chrome/browser/android/chrome_media_client_android.cc
@@ -0,0 +1,19 @@
+// Copyright 2015 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/android/chrome_media_client_android.h"
+
+ChromeMediaClientAndroid::ChromeMediaClientAndroid() {
+}
+
+ChromeMediaClientAndroid::~ChromeMediaClientAndroid() {
+}
+
+media::MediaDrmBridgeDelegate*
+ChromeMediaClientAndroid::GetMediaDrmBridgeDelegate(
+ const std::vector<uint8_t>& scheme_uuid) {
+ if (scheme_uuid == widevine_delegate_.GetUUID())
+ return &widevine_delegate_;
+ return nullptr;
+}
diff --git a/chrome/browser/android/chrome_media_client_android.h b/chrome/browser/android/chrome_media_client_android.h
new file mode 100644
index 0000000..d489e42
--- /dev/null
+++ b/chrome/browser/android/chrome_media_client_android.h
@@ -0,0 +1,27 @@
+// Copyright 2015 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_ANDROID_CHROME_MEDIA_CLIENT_ANDROID_H_
+#define CHROME_BROWSER_ANDROID_CHROME_MEDIA_CLIENT_ANDROID_H_
+
+#include "base/macros.h"
+#include "components/cdm/browser/widevine_drm_delegate_android.h"
+#include "media/base/android/media_client_android.h"
+
+class ChromeMediaClientAndroid : public media::MediaClientAndroid {
+ public:
+ ChromeMediaClientAndroid();
+ ~ChromeMediaClientAndroid() override;
+
+ private:
+ // media::MediaClientAndroid implementation:
+ media::MediaDrmBridgeDelegate* GetMediaDrmBridgeDelegate(
+ const std::vector<uint8_t>& scheme_uuid) override;
+
+ cdm::WidevineDrmDelegateAndroid widevine_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromeMediaClientAndroid);
+};
+
+#endif // CHROME_BROWSER_ANDROID_CHROME_MEDIA_CLIENT_ANDROID_H_
diff --git a/chrome/browser/chrome_browser_main_android.cc b/chrome/browser/chrome_browser_main_android.cc
index 9f977fc..4e05a99 100644
--- a/chrome/browser/chrome_browser_main_android.cc
+++ b/chrome/browser/chrome_browser_main_android.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/path_service.h"
#include "base/trace_event/trace_event.h"
+#include "chrome/browser/android/chrome_media_client_android.h"
#include "chrome/browser/android/seccomp_support_detector.h"
#include "chrome/browser/google/google_search_counter_android.h"
#include "chrome/browser/signin/signin_manager_factory.h"
@@ -18,6 +19,7 @@
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/main_function_params.h"
+#include "media/base/android/media_client_android.h"
#include "net/android/network_change_notifier_factory_android.h"
#include "net/base/network_change_notifier.h"
#include "ui/base/ui_base_paths.h"
@@ -96,6 +98,12 @@ void ChromeBrowserMainPartsAndroid::PreEarlyInitialization() {
ChromeBrowserMainParts::PreEarlyInitialization();
}
+void ChromeBrowserMainPartsAndroid::PreMainMessageLoopRun() {
+ media::SetMediaClientAndroid(new ChromeMediaClientAndroid);
+
+ ChromeBrowserMainParts::PreMainMessageLoopRun();
+}
+
void ChromeBrowserMainPartsAndroid::PostBrowserStart() {
ChromeBrowserMainParts::PostBrowserStart();
diff --git a/chrome/browser/chrome_browser_main_android.h b/chrome/browser/chrome_browser_main_android.h
index fbb3ab3..a20f090 100644
--- a/chrome/browser/chrome_browser_main_android.h
+++ b/chrome/browser/chrome_browser_main_android.h
@@ -23,6 +23,7 @@ class ChromeBrowserMainPartsAndroid : public ChromeBrowserMainParts {
int PreCreateThreads() override;
void PostProfileInit() override;
void PreEarlyInitialization() override;
+ void PreMainMessageLoopRun() override;
// ChromeBrowserMainParts overrides.
void PostBrowserStart() override;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 4e7d857..6b2cbec 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -45,6 +45,8 @@
'browser/android/bookmarks/partner_bookmarks_shim.h',
'browser/android/chrome_jni_registrar.cc',
'browser/android/chrome_jni_registrar.h',
+ 'browser/android/chrome_media_client_android.cc',
+ 'browser/android/chrome_media_client_android.h',
'browser/android/chrome_startup_flags.cc',
'browser/android/chrome_startup_flags.h',
'browser/android/chrome_web_contents_delegate_android.cc',
diff --git a/chromecast/browser/DEPS b/chromecast/browser/DEPS
index 5306642..bd203a8 100644
--- a/chromecast/browser/DEPS
+++ b/chromecast/browser/DEPS
@@ -3,6 +3,7 @@ include_rules = [
# embedder and can include from all other chromecast/ directories.
"+cc/base/switches.h",
"+chromecast",
+ "+components/cdm/browser",
"+components/crash",
"+components/devtools_discovery",
"+components/devtools_http_handler",
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastBrowserHelper.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastBrowserHelper.java
index 937018d..7b56973 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastBrowserHelper.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastBrowserHelper.java
@@ -19,11 +19,8 @@ import org.chromium.content.app.ContentApplication;
import org.chromium.content.browser.BrowserStartupController;
import org.chromium.content.browser.DeviceUtils;
import org.chromium.content.common.ContentSwitches;
-import org.chromium.media.MediaDrmBridge;
import org.chromium.net.NetworkChangeNotifier;
-import java.util.UUID;
-
/**
* Static, one-time initialization for the browser process.
*/
@@ -32,10 +29,6 @@ public class CastBrowserHelper {
public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs";
- private static final String PLAYREADY_KEY_SYSTEM_NAME = "com.chromecast.playready";
- private static final UUID PLAYREADY_UUID =
- UUID.fromString("9A04F079-9840-4286-AB92-E65BE0885F95");
-
private static boolean sIsBrowserInitialized = false;
/**
@@ -80,7 +73,6 @@ public class CastBrowserHelper {
// Cast shell always expects to receive notifications to track network state.
NetworkChangeNotifier.registerToReceiveNotificationsAlways();
sIsBrowserInitialized = true;
- MediaDrmBridge.addKeySystemUuidMapping(PLAYREADY_KEY_SYSTEM_NAME, PLAYREADY_UUID);
return true;
} catch (ProcessInitException e) {
Log.e(TAG, "Unable to launch browser process.", e);
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 45edf44..1c0ca15 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -29,6 +29,7 @@
#include "chromecast/browser/url_request_context_factory.h"
#include "chromecast/common/chromecast_switches.h"
#include "chromecast/common/platform_client_auth.h"
+#include "chromecast/media/base/key_systems_common.h"
#include "chromecast/net/connectivity_checker.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
@@ -36,8 +37,10 @@
#include "media/base/media_switches.h"
#if defined(OS_ANDROID)
+#include "chromecast/browser/media/cast_media_client_android.h"
#include "chromecast/crash/android/crash_handler.h"
#include "components/crash/browser/crash_dump_manager_android.h"
+#include "media/base/android/media_client_android.h"
#include "net/android/network_change_notifier_factory_android.h"
#else
#include "chromecast/browser/media/cast_browser_cdm_factory.h"
@@ -259,11 +262,13 @@ void CastBrowserMainParts::PreMainMessageLoopRun() {
cast_browser_process_->SetPrefService(
PrefServiceHelper::CreatePrefService(pref_registry.get()));
-#if !defined(OS_ANDROID)
+#if defined(OS_ANDROID)
+ ::media::SetMediaClientAndroid(new media::CastMediaClientAndroid());
+#else
const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (cmd_line->HasSwitch(switches::kEnableCmaMediaPipeline))
- ::media::SetBrowserCdmFactory(new media::CastBrowserCdmFactory);
-#endif // !defined(OS_ANDROID)
+ ::media::SetBrowserCdmFactory(new media::CastBrowserCdmFactory());
+#endif // defined(OS_ANDROID)
cast_browser_process_->SetConnectivityChecker(
make_scoped_refptr(new ConnectivityChecker(
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 01430da..4a07649 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -44,9 +44,6 @@
#if defined(OS_ANDROID)
#include "chromecast/browser/android/external_video_surface_container_impl.h"
-#endif // defined(OS_ANDROID)
-
-#if defined(OS_ANDROID)
#include "components/crash/browser/crash_dump_manager_android.h"
#endif // defined(OS_ANDROID)
diff --git a/chromecast/browser/media/cast_media_client_android.cc b/chromecast/browser/media/cast_media_client_android.cc
new file mode 100644
index 0000000..696471e
--- /dev/null
+++ b/chromecast/browser/media/cast_media_client_android.cc
@@ -0,0 +1,44 @@
+// Copyright 2015 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 "chromecast/browser/media/cast_media_client_android.h"
+
+#include "chromecast/media/base/key_systems_common.h"
+
+namespace chromecast {
+namespace media {
+
+CastMediaClientAndroid::CastMediaClientAndroid() {
+}
+
+CastMediaClientAndroid::~CastMediaClientAndroid() {
+}
+
+void CastMediaClientAndroid::AddKeySystemUUIDMappings(KeySystemUuidMap* map) {
+ // Note: MediaDrmBridge adds the Widevine UUID mapping automatically.
+#if defined(PLAYREADY_CDM_AVAILABLE)
+ (*map)[kChromecastPlayreadyKeySystem] = playready_delegate_.GetUUID();
+#endif
+
+ auto platform_mappings = GetPlatformKeySystemUUIDMappings();
+ for (const auto& mapping : platform_mappings)
+ map->insert(mapping);
+}
+
+::media::MediaDrmBridgeDelegate*
+CastMediaClientAndroid::GetMediaDrmBridgeDelegate(
+ const ::media::UUID& scheme_uuid) {
+#if defined(PLAYREADY_CDM_AVAILABLE)
+ if (scheme_uuid == playready_delegate_.GetUUID())
+ return &playready_delegate_;
+#endif
+
+ if (scheme_uuid == widevine_delegate_.GetUUID())
+ return &widevine_delegate_;
+
+ return nullptr;
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromecast/browser/media/cast_media_client_android.h b/chromecast/browser/media/cast_media_client_android.h
new file mode 100644
index 0000000..a7aaa1d
--- /dev/null
+++ b/chromecast/browser/media/cast_media_client_android.h
@@ -0,0 +1,41 @@
+// Copyright 2015 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 CHROMECAST_BROWSER_MEDIA_CAST_MEDIA_CLIENT_ANDROID_H_
+#define CHROMECAST_BROWSER_MEDIA_CAST_MEDIA_CLIENT_ANDROID_H_
+
+#include <map>
+
+#include "base/macros.h"
+#include "chromecast/media/cdm/playready_drm_delegate_android.h"
+#include "components/cdm/browser/widevine_drm_delegate_android.h"
+#include "media/base/android/media_client_android.h"
+
+namespace chromecast {
+namespace media {
+
+class CastMediaClientAndroid : public ::media::MediaClientAndroid {
+ public:
+ CastMediaClientAndroid();
+ ~CastMediaClientAndroid() override;
+
+ private:
+ // ::media::MediaClientAndroid implementation:
+ void AddKeySystemUUIDMappings(KeySystemUuidMap* map) override;
+ ::media::MediaDrmBridgeDelegate* GetMediaDrmBridgeDelegate(
+ const ::media::UUID& scheme_uuid) override;
+
+#if defined(PLAYREADY_CDM_AVAILABLE)
+ PlayreadyDrmDelegateAndroid playready_delegate_;
+#endif
+
+ cdm::WidevineDrmDelegateAndroid widevine_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(CastMediaClientAndroid);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_BROWSER_MEDIA_CAST_MEDIA_CLIENT_ANDROID_H_
diff --git a/chromecast/chromecast.gyp b/chromecast/chromecast.gyp
index a9892ab..f882b8a 100644
--- a/chromecast/chromecast.gyp
+++ b/chromecast/chromecast.gyp
@@ -189,6 +189,7 @@
'chromecast_locales.gyp:chromecast_locales_pak',
'chromecast_locales.gyp:chromecast_settings',
'media/media.gyp:media_base',
+ 'media/media.gyp:media_cdm',
'../base/base.gyp:base',
'../components/components.gyp:breakpad_host',
'../components/components.gyp:cdm_renderer',
@@ -239,6 +240,8 @@
'browser/devtools/remote_debugging_server.h',
'browser/geolocation/cast_access_token_store.cc',
'browser/geolocation/cast_access_token_store.h',
+ 'browser/media/cast_media_client_android.cc',
+ 'browser/media/cast_media_client_android.h',
'browser/metrics/cast_metrics_prefs.cc',
'browser/metrics/cast_metrics_prefs.h',
'browser/metrics/cast_metrics_service_client.cc',
@@ -319,6 +322,11 @@
'../ui/aura/aura.gyp:aura_test_support',
],
}],
+ ['OS=="android"', {
+ 'dependencies': [
+ '../components/components.gyp:cdm_browser',
+ ],
+ }],
],
},
{
diff --git a/chromecast/media/base/key_systems_common.h b/chromecast/media/base/key_systems_common.h
index 4ab8ea7..1537afd 100644
--- a/chromecast/media/base/key_systems_common.h
+++ b/chromecast/media/base/key_systems_common.h
@@ -6,6 +6,11 @@
#define CHROMECAST_MEDIA_BASE_KEY_SYSTEMS_COMMON_H_
#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "media/base/android/media_client_android.h"
namespace chromecast {
namespace media {
@@ -29,6 +34,13 @@ CastKeySystem GetKeySystemByName(const std::string& key_system_name);
// TODO(gunsch): Remove when prefixed EME is removed.
CastKeySystem GetPlatformKeySystemByName(const std::string& key_system_name);
+// Translates a platform-specific key system string into a CastKeySystem.
+// TODO(gunsch): Remove when prefixed EME is removed.
+#if defined(OS_ANDROID)
+std::vector<::media::MediaClientAndroid::KeySystemUuidMap::value_type>
+GetPlatformKeySystemUUIDMappings();
+#endif
+
} // namespace media
} // namespace chromecast
diff --git a/chromecast/media/base/key_systems_common_simple.cc b/chromecast/media/base/key_systems_common_simple.cc
index e6dbd02..671ce03 100644
--- a/chromecast/media/base/key_systems_common_simple.cc
+++ b/chromecast/media/base/key_systems_common_simple.cc
@@ -11,5 +11,13 @@ CastKeySystem GetPlatformKeySystemByName(const std::string& key_system_name) {
return KEY_SYSTEM_NONE;
}
+#if defined(OS_ANDROID)
+std::vector<::media::MediaClientAndroid::KeySystemUuidMap::value_type>
+GetPlatformKeySystemUUIDMappings() {
+ return std::vector<
+ ::media::MediaClientAndroid::KeySystemUuidMap::value_type>();
+}
+#endif
+
} // namespace media
} // namespace chromecast
diff --git a/chromecast/media/cdm/playready_drm_delegate_android.cc b/chromecast/media/cdm/playready_drm_delegate_android.cc
new file mode 100644
index 0000000..135fc44
--- /dev/null
+++ b/chromecast/media/cdm/playready_drm_delegate_android.cc
@@ -0,0 +1,85 @@
+// Copyright 2015 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 "chromecast/media/cdm/playready_drm_delegate_android.h"
+
+#include "base/logging.h"
+#include "media/base/bit_reader.h"
+
+namespace chromecast {
+namespace media {
+
+const uint8_t kPlayreadyUuid[16] = {
+ 0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86,
+ 0xab, 0x92, 0xe6, 0x5b, 0xe0, 0x88, 0x5f, 0x95};
+
+const uint8_t kPlayreadyCustomDataUuid[] = {
+ 0x2b, 0xf8, 0x66, 0x80, 0xc6, 0xe5, 0x4e, 0x24,
+ 0xbe, 0x23, 0x0f, 0x81, 0x5a, 0x60, 0x6e, 0xb2};
+
+// ASCII "uuid" as an 4-byte integer
+const uint32_t kBoxTypeUuid = 1970628964;
+
+PlayreadyDrmDelegateAndroid::PlayreadyDrmDelegateAndroid() {
+}
+
+PlayreadyDrmDelegateAndroid::~PlayreadyDrmDelegateAndroid() {
+}
+
+const ::media::UUID PlayreadyDrmDelegateAndroid::GetUUID() const {
+ return ::media::UUID(kPlayreadyUuid,
+ kPlayreadyUuid + arraysize(kPlayreadyUuid));
+}
+
+bool PlayreadyDrmDelegateAndroid::OnCreateSession(
+ const ::media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ std::vector<uint8_t>* /* init_data_out */,
+ std::vector<std::string>* optional_parameters_out) {
+ if (init_data_type == ::media::EmeInitDataType::CENC) {
+ ::media::BitReader reader(&init_data[0], init_data.size());
+ while (reader.bits_available() > 64) {
+ uint32_t box_size;
+ uint32_t box_type;
+ reader.ReadBits(32, &box_size);
+ reader.ReadBits(32, &box_type);
+ int bytes_read = 8;
+
+ if (box_type != kBoxTypeUuid) {
+ if (box_size < 8 + sizeof(kPlayreadyCustomDataUuid)) {
+ break;
+ }
+ // Box size includes the bytes already consumed
+ reader.SkipBits((box_size - bytes_read) * 8);
+ continue;
+ }
+
+ // "uuid" was found, look for custom data format as per b/10246367
+ reader.SkipBits(128);
+ bytes_read += 16;
+ if (!memcmp(&init_data[0] + reader.bits_read() / 8,
+ kPlayreadyCustomDataUuid, 16)) {
+ reader.SkipBits((box_size - bytes_read) * 8);
+ continue;
+ }
+
+ int custom_data_size = box_size - bytes_read;
+ DCHECK(reader.bits_read() % 8 == 0);
+ int total_bytes_read = reader.bits_read() / 8;
+
+ optional_parameters_out->clear();
+ optional_parameters_out->push_back("PRCustomData");
+ optional_parameters_out->push_back(
+ std::string(&init_data[0] + total_bytes_read,
+ &init_data[0] + total_bytes_read + custom_data_size));
+ reader.SkipBits(custom_data_size * 8);
+ LOG(INFO) << "Including " << custom_data_size
+ << " bytes of custom PlayReady data";
+ }
+ }
+ return true;
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromecast/media/cdm/playready_drm_delegate_android.h b/chromecast/media/cdm/playready_drm_delegate_android.h
new file mode 100644
index 0000000..3a934c45
--- /dev/null
+++ b/chromecast/media/cdm/playready_drm_delegate_android.h
@@ -0,0 +1,34 @@
+// Copyright 2015 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 CHROMECAST_MEDIA_CDM_PLAYREADY_DRM_DELEGATE_ANDROID_H_
+#define CHROMECAST_MEDIA_CDM_PLAYREADY_DRM_DELEGATE_ANDROID_H_
+
+#include "base/macros.h"
+#include "media/base/android/media_drm_bridge_delegate.h"
+
+namespace chromecast {
+namespace media {
+
+class PlayreadyDrmDelegateAndroid : public ::media::MediaDrmBridgeDelegate {
+ public:
+ PlayreadyDrmDelegateAndroid();
+ ~PlayreadyDrmDelegateAndroid() override;
+
+ // ::media::MediaDrmBridgeDelegate implementation:
+ const ::media::UUID GetUUID() const override;
+ bool OnCreateSession(
+ const ::media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ std::vector<uint8_t>* init_data_out,
+ std::vector<std::string>* optional_parameters_out) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PlayreadyDrmDelegateAndroid);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_CDM_PLAYREADY_DRM_DELEGATE_ANDROID_H_
diff --git a/chromecast/media/media.gyp b/chromecast/media/media.gyp
index 8b98ec9..3ca9eff 100644
--- a/chromecast/media/media.gyp
+++ b/chromecast/media/media.gyp
@@ -54,6 +54,14 @@
'cdm/browser_cdm_cast.cc',
'cdm/browser_cdm_cast.h',
],
+ 'conditions': [
+ ['use_playready==1', {
+ 'sources': [
+ 'cdm/playready_drm_delegate_android.cc',
+ 'cdm/playready_drm_delegate_android.h',
+ ],
+ }],
+ ],
},
{
'target_name': 'cma_base',
diff --git a/components/OWNERS b/components/OWNERS
index 9180998..86bc6db 100644
--- a/components/OWNERS
+++ b/components/OWNERS
@@ -25,6 +25,10 @@ per-file browsing_data.gypi=mkwst@chromium.org
per-file browsing_data.gypi=bauerb@chromium.org
per-file browsing_data.gypi=michaeln@chromium.org
+per-file cdm.gypi=ddorwin@chromium.org
+per-file cdm.gypi=scherkus@chromium.org
+per-file cdm.gypi=xhwang@chromium.org
+
per-file cloud_devices*=gene@chromium.org
per-file cloud_devices*=vitalybuka@chromium.org
diff --git a/components/cdm.gypi b/components/cdm.gypi
index d6f640a..853ff35 100644
--- a/components/cdm.gypi
+++ b/components/cdm.gypi
@@ -64,6 +64,8 @@
'sources': [
'cdm/browser/cdm_message_filter_android.cc',
'cdm/browser/cdm_message_filter_android.h',
+ 'cdm/browser/widevine_drm_delegate_android.cc',
+ 'cdm/browser/widevine_drm_delegate_android.h',
],
},
],
diff --git a/components/cdm/browser/BUILD.gn b/components/cdm/browser/BUILD.gn
index e18b670..cea393b 100644
--- a/components/cdm/browser/BUILD.gn
+++ b/components/cdm/browser/BUILD.gn
@@ -6,6 +6,8 @@ source_set("browser") {
sources = [
"cdm_message_filter_android.cc",
"cdm_message_filter_android.h",
+ "widevine_drm_delegate_android.cc",
+ "widevine_drm_delegate_android.h",
]
deps = [
diff --git a/components/cdm/browser/widevine_drm_delegate_android.cc b/components/cdm/browser/widevine_drm_delegate_android.cc
new file mode 100644
index 0000000..64b90bf
--- /dev/null
+++ b/components/cdm/browser/widevine_drm_delegate_android.cc
@@ -0,0 +1,163 @@
+// Copyright 2015 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/widevine_drm_delegate_android.h"
+
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+
+namespace cdm {
+
+namespace {
+
+uint32_t ReadUint32(const uint8_t* data) {
+ uint32_t value = 0;
+ for (int i = 0; i < 4; ++i)
+ value = (value << 8) | data[i];
+ return value;
+}
+
+uint64_t ReadUint64(const uint8_t* data) {
+ uint64_t value = 0;
+ for (int i = 0; i < 8; ++i)
+ value = (value << 8) | data[i];
+ return value;
+}
+
+// The structure of an ISO CENC Protection System Specific Header (PSSH) box is
+// as follows. (See ISO/IEC FDIS 23001-7:2011(E).)
+// Note: ISO boxes use big-endian values.
+//
+// PSSH {
+// uint32_t Size
+// uint32_t Type
+// uint64_t LargeSize # Field is only present if value(Size) == 1.
+// uint32_t VersionAndFlags
+// uint8_t[16] SystemId
+// uint32_t DataSize
+// uint8_t[DataSize] Data
+// }
+const int kBoxHeaderSize = 8; // Box's header contains Size and Type.
+const int kBoxLargeSizeSize = 8;
+const int kPsshVersionFlagSize = 4;
+const int kPsshSystemIdSize = 16;
+const int kPsshDataSizeSize = 4;
+const uint32_t kTencType = 0x74656e63;
+const uint32_t kPsshType = 0x70737368;
+
+const uint8_t kWidevineUuid[16] = {
+ 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE,
+ 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED };
+
+// Tries to find a PSSH box with the Widevine UUID, parses the
+// "Data" of the box and put it in |pssh_data|. Returns true if such a box is
+// found and successfully parsed. Returns false otherwise.
+// Notes:
+// 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box
+// will be set in |pssh_data|.
+// 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped.
+bool GetPsshData(const std::vector<uint8_t>& data,
+ std::vector<uint8_t>* pssh_data) {
+ int bytes_left = base::checked_cast<int>(data.size());
+ const uint8_t* cur = &data[0];
+ const uint8_t* data_end = cur + bytes_left;
+
+ while (bytes_left > 0) {
+ const uint8_t* box_head = cur;
+
+ if (bytes_left < kBoxHeaderSize)
+ return false;
+
+ uint64_t box_size = ReadUint32(cur);
+ uint32_t type = ReadUint32(cur + 4);
+ cur += kBoxHeaderSize;
+ bytes_left -= kBoxHeaderSize;
+
+ if (box_size == 1) { // LargeSize is present.
+ if (bytes_left < kBoxLargeSizeSize)
+ return false;
+
+ box_size = ReadUint64(cur);
+ cur += kBoxLargeSizeSize;
+ bytes_left -= kBoxLargeSizeSize;
+ } else if (box_size == 0) {
+ box_size = bytes_left + kBoxHeaderSize;
+ }
+
+ const uint8_t* box_end = box_head + box_size;
+ if (data_end < box_end)
+ return false;
+
+ if (type == kTencType) {
+ // Skip 'tenc' box.
+ cur = box_end;
+ bytes_left = data_end - cur;
+ continue;
+ } else if (type != kPsshType) {
+ return false;
+ }
+
+ const int kPsshBoxMinimumSize =
+ kPsshVersionFlagSize + kPsshSystemIdSize + kPsshDataSizeSize;
+ if (box_end < cur + kPsshBoxMinimumSize)
+ return false;
+
+ uint32_t version_and_flags = ReadUint32(cur);
+ cur += kPsshVersionFlagSize;
+ bytes_left -= kPsshVersionFlagSize;
+ if (version_and_flags != 0)
+ return false;
+
+ DCHECK_GE(bytes_left, kPsshSystemIdSize);
+ if (!std::equal(kWidevineUuid,
+ kWidevineUuid + sizeof(kWidevineUuid), cur)) {
+ cur = box_end;
+ bytes_left = data_end - cur;
+ continue;
+ }
+
+ cur += kPsshSystemIdSize;
+ bytes_left -= kPsshSystemIdSize;
+
+ uint32_t data_size = ReadUint32(cur);
+ cur += kPsshDataSizeSize;
+ bytes_left -= kPsshDataSizeSize;
+
+ if (box_end < cur + data_size)
+ return false;
+
+ pssh_data->assign(cur, cur + data_size);
+ return true;
+ }
+
+ return false;
+}
+
+}
+
+WidevineDrmDelegateAndroid::WidevineDrmDelegateAndroid() {
+}
+
+WidevineDrmDelegateAndroid::~WidevineDrmDelegateAndroid() {
+}
+
+const std::vector<uint8_t> WidevineDrmDelegateAndroid::GetUUID() const {
+ return std::vector<uint8_t>(kWidevineUuid,
+ kWidevineUuid + arraysize(kWidevineUuid));
+}
+
+bool WidevineDrmDelegateAndroid::OnCreateSession(
+ const media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ std::vector<uint8_t>* init_data_out,
+ std::vector<std::string>* /* optional_parameters_out */) {
+ if (init_data_type != media::EmeInitDataType::CENC)
+ return true;
+
+ // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as
+ // the init data when using MP4 container.
+ return GetPsshData(init_data, init_data_out);
+}
+
+} // namespace cdm
diff --git a/components/cdm/browser/widevine_drm_delegate_android.h b/components/cdm/browser/widevine_drm_delegate_android.h
new file mode 100644
index 0000000..09a54ae
--- /dev/null
+++ b/components/cdm/browser/widevine_drm_delegate_android.h
@@ -0,0 +1,32 @@
+// Copyright 2015 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_WIDEVINE_DRM_DELEGATE_ANDROID_H_
+#define COMPONENTS_CDM_BROWSER_WIDEVINE_DRM_DELEGATE_ANDROID_H_
+
+#include "base/macros.h"
+#include "media/base/android/media_drm_bridge_delegate.h"
+
+namespace cdm {
+
+class WidevineDrmDelegateAndroid : public media::MediaDrmBridgeDelegate {
+ public:
+ WidevineDrmDelegateAndroid();
+ ~WidevineDrmDelegateAndroid() override;
+
+ // media::MediaDrmBridgeDelegate implementation:
+ const std::vector<uint8_t> GetUUID() const override;
+ bool OnCreateSession(
+ const media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ std::vector<uint8_t>* init_data_out,
+ std::vector<std::string>* optional_parameters_out) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WidevineDrmDelegateAndroid);
+};
+
+} // namespace cdm
+
+#endif // COMPONENTS_CDM_BROWSER_WIDEVINE_DRM_DELEGATE_ANDROID_H_
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn
index 6108389..c407b17 100644
--- a/media/base/android/BUILD.gn
+++ b/media/base/android/BUILD.gn
@@ -19,12 +19,16 @@ source_set("android") {
"demuxer_android.h",
"demuxer_stream_player_params.cc",
"demuxer_stream_player_params.h",
+ "media_client_android.cc",
+ "media_client_android.h",
"media_codec_bridge.cc",
"media_codec_bridge.h",
"media_decoder_job.cc",
"media_decoder_job.h",
"media_drm_bridge.cc",
"media_drm_bridge.h",
+ "media_drm_bridge_delegate.cc",
+ "media_drm_bridge_delegate.h",
"media_jni_registrar.cc",
"media_jni_registrar.h",
"media_player_android.cc",
diff --git a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java
index 8f32ccb..9d49232 100644
--- a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java
+++ b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java
@@ -22,7 +22,6 @@ import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.HashMap;
@@ -107,11 +106,14 @@ public class MediaDrmBridge {
private static class PendingCreateSessionData {
private final byte[] mInitData;
private final String mMimeType;
+ private final HashMap<String, String> mOptionalParameters;
private final long mPromiseId;
- private PendingCreateSessionData(byte[] initData, String mimeType, long promiseId) {
+ private PendingCreateSessionData(byte[] initData, String mimeType,
+ HashMap<String, String> optionalParameters, long promiseId) {
mInitData = initData;
mMimeType = mimeType;
+ mOptionalParameters = optionalParameters;
mPromiseId = promiseId;
}
@@ -123,6 +125,10 @@ public class MediaDrmBridge {
return mMimeType;
}
+ private HashMap<String, String> optionalParameters() {
+ return mOptionalParameters;
+ }
+
private long promiseId() {
return mPromiseId;
}
@@ -410,16 +416,20 @@ public class MediaDrmBridge {
* @param sessionId ID of session on which we need to get the key request.
* @param data Data needed to get the key request.
* @param mime Mime type to get the key request.
+ * @param optionalParameters Optional parameters to pass to the DRM plugin.
*
* @return the key request.
*/
- private MediaDrm.KeyRequest getKeyRequest(byte[] sessionId, byte[] data, String mime)
+ private MediaDrm.KeyRequest getKeyRequest(
+ byte[] sessionId, byte[] data, String mime, HashMap<String, String> optionalParameters)
throws android.media.NotProvisionedException {
assert mMediaDrm != null;
assert mMediaCrypto != null;
assert !mProvisioningPending;
- HashMap<String, String> optionalParameters = new HashMap<String, String>();
+ if (optionalParameters == null) {
+ optionalParameters = new HashMap<String, String>();
+ }
MediaDrm.KeyRequest request = mMediaDrm.getKeyRequest(
sessionId, data, mime, MediaDrm.KEY_TYPE_STREAMING, optionalParameters);
String result = (request != null) ? "successed" : "failed";
@@ -433,12 +443,14 @@ public class MediaDrmBridge {
*
* @param initData Data needed to generate the key request.
* @param mime Mime type.
+ * @param optionalParameters Optional parameters to pass to the DRM plugin.
* @param promiseId Promise ID for the createSession() call.
*/
- private void savePendingCreateSessionData(byte[] initData, String mime, long promiseId) {
+ private void savePendingCreateSessionData(byte[] initData, String mime,
+ HashMap<String, String> optionalParameters, long promiseId) {
Log.d(TAG, "savePendingCreateSessionData()");
mPendingCreateSessionDataQueue.offer(
- new PendingCreateSessionData(initData, mime, promiseId));
+ new PendingCreateSessionData(initData, mime, optionalParameters, promiseId));
}
/**
@@ -456,8 +468,9 @@ public class MediaDrmBridge {
PendingCreateSessionData pendingData = mPendingCreateSessionDataQueue.poll();
byte[] initData = pendingData.initData();
String mime = pendingData.mimeType();
+ HashMap<String, String> optionalParameters = pendingData.optionalParameters();
long promiseId = pendingData.promiseId();
- createSession(initData, mime, promiseId);
+ createSession(initData, mime, optionalParameters, promiseId);
}
}
@@ -474,14 +487,35 @@ public class MediaDrmBridge {
}
/**
+ * createSession interface to be called from native using primitive types.
+ * @see createSession(byte[], String, HashMap<String, String>, long)
+ */
+ @CalledByNative
+ private void createSessionFromNative(
+ byte[] initData, String mime, String[] optionalParamsArray, long promiseId) {
+ HashMap<String, String> optionalParameters = new HashMap<String, String>();
+ if (optionalParamsArray != null) {
+ if (optionalParamsArray.length % 2 != 0) {
+ throw new IllegalArgumentException(
+ "Additional data array doesn't have equal keys/values");
+ }
+ for (int i = 0; i < optionalParamsArray.length; i += 2) {
+ optionalParameters.put(optionalParamsArray[i], optionalParamsArray[i + 1]);
+ }
+ }
+ createSession(initData, mime, optionalParameters, promiseId);
+ }
+
+ /**
* Create a session, and generate a request with |initData| and |mime|.
*
* @param initData Data needed to generate the key request.
* @param mime Mime type.
+ * @param optionalParameters Additional data to pass to getKeyRequest.
* @param promiseId Promise ID for this call.
*/
- @CalledByNative
- private void createSession(byte[] initData, String mime, long promiseId) {
+ private void createSession(byte[] initData, String mime,
+ HashMap<String, String> optionalParameters, long promiseId) {
Log.d(TAG, "createSession()");
if (mMediaDrm == null) {
Log.e(TAG, "createSession() called when MediaDrm is null.");
@@ -490,7 +524,7 @@ public class MediaDrmBridge {
if (mProvisioningPending) {
assert mMediaCrypto == null;
- savePendingCreateSessionData(initData, mime, promiseId);
+ savePendingCreateSessionData(initData, mime, optionalParameters, promiseId);
return;
}
@@ -514,7 +548,7 @@ public class MediaDrmBridge {
assert !sessionExists(sessionId);
MediaDrm.KeyRequest request = null;
- request = getKeyRequest(sessionId, initData, mime);
+ request = getKeyRequest(sessionId, initData, mime, optionalParameters);
if (request == null) {
mMediaDrm.closeSession(sessionId);
onPromiseRejected(promiseId, "Generate request failed.");
@@ -531,7 +565,7 @@ public class MediaDrmBridge {
if (newSessionOpened) {
mMediaDrm.closeSession(sessionId);
}
- savePendingCreateSessionData(initData, mime, promiseId);
+ savePendingCreateSessionData(initData, mime, optionalParameters, promiseId);
startProvisioning();
}
}
@@ -832,7 +866,7 @@ public class MediaDrmBridge {
String mime = mSessionIds.get(ByteBuffer.wrap(sessionId));
MediaDrm.KeyRequest request = null;
try {
- request = getKeyRequest(sessionId, data, mime);
+ request = getKeyRequest(sessionId, data, mime, null);
} catch (android.media.NotProvisionedException e) {
Log.e(TAG, "Device not provisioned", e);
startProvisioning();
@@ -933,15 +967,6 @@ public class MediaDrmBridge {
}
}
- public static void addKeySystemUuidMapping(String keySystem, UUID uuid) {
- ByteBuffer uuidBuffer = ByteBuffer.allocateDirect(16);
- // MSB (byte) should be positioned at the first element.
- uuidBuffer.order(ByteOrder.BIG_ENDIAN);
- uuidBuffer.putLong(uuid.getMostSignificantBits());
- uuidBuffer.putLong(uuid.getLeastSignificantBits());
- nativeAddKeySystemUuidMapping(keySystem, uuidBuffer);
- }
-
private native void nativeOnMediaCryptoReady(long nativeMediaDrmBridge);
private native void nativeOnPromiseResolved(long nativeMediaDrmBridge, long promiseId);
@@ -960,6 +985,4 @@ public class MediaDrmBridge {
private native void nativeOnResetDeviceCredentialsCompleted(
long nativeMediaDrmBridge, boolean success);
-
- private static native void nativeAddKeySystemUuidMapping(String keySystem, ByteBuffer uuid);
}
diff --git a/media/base/android/media_client_android.cc b/media/base/android/media_client_android.cc
new file mode 100644
index 0000000..ad4e11b
--- /dev/null
+++ b/media/base/android/media_client_android.cc
@@ -0,0 +1,37 @@
+// Copyright 2015 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 "media/base/android/media_client_android.h"
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+
+namespace media {
+
+static MediaClientAndroid* g_media_client = nullptr;
+
+void SetMediaClientAndroid(MediaClientAndroid* media_client) {
+ DCHECK(!g_media_client);
+ g_media_client = media_client;
+}
+
+MediaClientAndroid* GetMediaClientAndroid() {
+ return g_media_client;
+}
+
+MediaClientAndroid::MediaClientAndroid() {
+}
+
+MediaClientAndroid::~MediaClientAndroid() {
+}
+
+void MediaClientAndroid::AddKeySystemUUIDMappings(KeySystemUuidMap* map) {
+}
+
+media::MediaDrmBridgeDelegate* MediaClientAndroid::GetMediaDrmBridgeDelegate(
+ const std::vector<uint8_t>& scheme_uuid) {
+ return nullptr;
+}
+
+} // namespace media
diff --git a/media/base/android/media_client_android.h b/media/base/android/media_client_android.h
new file mode 100644
index 0000000..0753b3b
--- /dev/null
+++ b/media/base/android/media_client_android.h
@@ -0,0 +1,59 @@
+// Copyright 2015 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 MEDIA_BASE_ANDROID_MEDIA_CLIENT_ANDROID_H_
+#define MEDIA_BASE_ANDROID_MEDIA_CLIENT_ANDROID_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/containers/hash_tables.h"
+#include "base/macros.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+class MediaClientAndroid;
+class MediaDrmBridgeDelegate;
+
+// Setter for MediaClientAndroid. This should be called early in embedder
+// lifecycle, before any media playback could occur.
+MEDIA_EXPORT void SetMediaClientAndroid(MediaClientAndroid* media_client);
+
+#if defined(MEDIA_IMPLEMENTATION)
+// Getter for the client. Returns nullptr if no customized client is needed.
+MediaClientAndroid* GetMediaClientAndroid();
+#endif
+
+using UUID = std::vector<uint8_t>;
+
+// A client interface for embedders (e.g. content/browser) to provide customized
+// additions to Android's browser-side media handling.
+class MEDIA_EXPORT MediaClientAndroid {
+ public:
+ typedef base::hash_map<std::string, UUID> KeySystemUuidMap;
+
+ MediaClientAndroid();
+ virtual ~MediaClientAndroid();
+
+ // Adds extra mappings from key-system name to Android UUID into |map|.
+ virtual void AddKeySystemUUIDMappings(KeySystemUuidMap* map);
+
+ // Returns a MediaDrmBridgeDelegate that corresponds to |scheme_uuid|.
+ // MediaClientAndroid retains ownership.
+ virtual media::MediaDrmBridgeDelegate* GetMediaDrmBridgeDelegate(
+ const UUID& scheme_uuid);
+
+ private:
+ friend class KeySystemManager;
+
+ base::hash_map<std::string, UUID> key_system_uuid_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaClientAndroid);
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_ANDROID_MEDIA_CLIENT_ANDROID_H_
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc
index 0aaeef4..79f7d42 100644
--- a/media/base/android/media_drm_bridge.cc
+++ b/media/base/android/media_drm_bridge.cc
@@ -15,12 +15,13 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "base/numerics/safe_conversions.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/sys_byteorder.h"
#include "base/sys_info.h"
#include "jni/MediaDrmBridge_jni.h"
+#include "media/base/android/media_client_android.h"
+#include "media/base/android/media_drm_bridge_delegate.h"
#include "media/base/cdm_key_information.h"
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
@@ -40,20 +41,6 @@ namespace {
// here to report session expiration info.
const char kDummyKeyId[] = "Dummy Key Id";
-uint32 ReadUint32(const uint8_t* data) {
- uint32 value = 0;
- for (int i = 0; i < 4; ++i)
- value = (value << 8) | data[i];
- return value;
-}
-
-uint64 ReadUint64(const uint8_t* data) {
- uint64 value = 0;
- for (int i = 0; i < 8; ++i)
- value = (value << 8) | data[i];
- return value;
-}
-
// Returns string session ID from jbyteArray (byte[] in Java).
std::string GetSessionId(JNIEnv* env, jbyteArray j_session_id) {
std::vector<uint8> session_id_vector;
@@ -61,116 +48,10 @@ std::string GetSessionId(JNIEnv* env, jbyteArray j_session_id) {
return std::string(session_id_vector.begin(), session_id_vector.end());
}
-// The structure of an ISO CENC Protection System Specific Header (PSSH) box is
-// as follows. (See ISO/IEC FDIS 23001-7:2011(E).)
-// Note: ISO boxes use big-endian values.
-//
-// PSSH {
-// uint32 Size
-// uint32 Type
-// uint64 LargeSize # Field is only present if value(Size) == 1.
-// uint32 VersionAndFlags
-// uint8[16] SystemId
-// uint32 DataSize
-// uint8[DataSize] Data
-// }
-const int kBoxHeaderSize = 8; // Box's header contains Size and Type.
-const int kBoxLargeSizeSize = 8;
-const int kPsshVersionFlagSize = 4;
-const int kPsshSystemIdSize = 16;
-const int kPsshDataSizeSize = 4;
-const uint32 kTencType = 0x74656e63;
-const uint32 kPsshType = 0x70737368;
const uint8 kWidevineUuid[16] = {
0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE,
0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED };
-typedef std::vector<uint8> UUID;
-
-// Tries to find a PSSH box whose "SystemId" is |uuid| in |data|, parses the
-// "Data" of the box and put it in |pssh_data|. Returns true if such a box is
-// found and successfully parsed. Returns false otherwise.
-// Notes:
-// 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box
-// will be set in |pssh_data|.
-// 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped.
-bool GetPsshData(const std::vector<uint8_t>& data,
- const UUID& uuid,
- std::vector<uint8>* pssh_data) {
- int bytes_left = base::checked_cast<int>(data.size());
- const uint8_t* cur = &data[0];
- const uint8_t* data_end = cur + bytes_left;
-
- while (bytes_left > 0) {
- const uint8* box_head = cur;
-
- if (bytes_left < kBoxHeaderSize)
- return false;
-
- uint64_t box_size = ReadUint32(cur);
- uint32 type = ReadUint32(cur + 4);
- cur += kBoxHeaderSize;
- bytes_left -= kBoxHeaderSize;
-
- if (box_size == 1) { // LargeSize is present.
- if (bytes_left < kBoxLargeSizeSize)
- return false;
-
- box_size = ReadUint64(cur);
- cur += kBoxLargeSizeSize;
- bytes_left -= kBoxLargeSizeSize;
- } else if (box_size == 0) {
- box_size = bytes_left + kBoxHeaderSize;
- }
-
- const uint8* box_end = box_head + box_size;
- if (data_end < box_end)
- return false;
-
- if (type == kTencType) {
- // Skip 'tenc' box.
- cur = box_end;
- bytes_left = data_end - cur;
- continue;
- } else if (type != kPsshType) {
- return false;
- }
-
- const int kPsshBoxMinimumSize =
- kPsshVersionFlagSize + kPsshSystemIdSize + kPsshDataSizeSize;
- if (box_end < cur + kPsshBoxMinimumSize)
- return false;
-
- uint32 version_and_flags = ReadUint32(cur);
- cur += kPsshVersionFlagSize;
- bytes_left -= kPsshVersionFlagSize;
- if (version_and_flags != 0)
- return false;
-
- DCHECK_GE(bytes_left, kPsshSystemIdSize);
- if (!std::equal(uuid.begin(), uuid.end(), cur)) {
- cur = box_end;
- bytes_left = data_end - cur;
- continue;
- }
-
- cur += kPsshSystemIdSize;
- bytes_left -= kPsshSystemIdSize;
-
- uint32 data_size = ReadUint32(cur);
- cur += kPsshDataSizeSize;
- bytes_left -= kPsshDataSizeSize;
-
- if (box_end < cur + data_size)
- return false;
-
- pssh_data->assign(cur, cur + data_size);
- return true;
- }
-
- return false;
-}
-
// Convert |init_data_type| to a string supported by MediaDRM.
// "audio"/"video" does not matter, so use "video".
std::string ConvertInitDataType(media::EmeInitDataType init_data_type) {
@@ -187,45 +68,37 @@ std::string ConvertInitDataType(media::EmeInitDataType init_data_type) {
}
}
-class KeySystemUuidManager {
+class KeySystemManager {
public:
- KeySystemUuidManager();
+ KeySystemManager();
UUID GetUUID(const std::string& key_system);
- void AddMapping(const std::string& key_system, const UUID& uuid);
std::vector<std::string> GetPlatformKeySystemNames();
private:
- typedef base::hash_map<std::string, UUID> KeySystemUuidMap;
+ using KeySystemUuidMap = MediaClientAndroid::KeySystemUuidMap;
KeySystemUuidMap key_system_uuid_map_;
- DISALLOW_COPY_AND_ASSIGN(KeySystemUuidManager);
+ DISALLOW_COPY_AND_ASSIGN(KeySystemManager);
};
-KeySystemUuidManager::KeySystemUuidManager() {
+KeySystemManager::KeySystemManager() {
// Widevine is always supported in Android.
key_system_uuid_map_[kWidevineKeySystem] =
UUID(kWidevineUuid, kWidevineUuid + arraysize(kWidevineUuid));
+ MediaClientAndroid* client = GetMediaClientAndroid();
+ if (client)
+ client->AddKeySystemUUIDMappings(&key_system_uuid_map_);
}
-UUID KeySystemUuidManager::GetUUID(const std::string& key_system) {
+UUID KeySystemManager::GetUUID(const std::string& key_system) {
KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system);
if (it == key_system_uuid_map_.end())
return UUID();
return it->second;
}
-void KeySystemUuidManager::AddMapping(const std::string& key_system,
- const UUID& uuid) {
- KeySystemUuidMap::iterator it = key_system_uuid_map_.find(key_system);
- DCHECK(it == key_system_uuid_map_.end())
- << "Shouldn't overwrite an existing key system.";
- if (it != key_system_uuid_map_.end())
- return;
- key_system_uuid_map_[key_system] = uuid;
-}
-
-std::vector<std::string> KeySystemUuidManager::GetPlatformKeySystemNames() {
+std::vector<std::string> KeySystemManager::GetPlatformKeySystemNames() {
std::vector<std::string> key_systems;
for (KeySystemUuidMap::iterator it = key_system_uuid_map_.begin();
it != key_system_uuid_map_.end(); ++it) {
@@ -236,7 +109,7 @@ std::vector<std::string> KeySystemUuidManager::GetPlatformKeySystemNames() {
return key_systems;
}
-base::LazyInstance<KeySystemUuidManager>::Leaky g_key_system_uuid_manager =
+base::LazyInstance<KeySystemManager>::Leaky g_key_system_manager =
LAZY_INSTANCE_INITIALIZER;
// Checks whether |key_system| is supported with |container_mime_type|. Only
@@ -249,7 +122,7 @@ bool IsKeySystemSupportedWithTypeImpl(const std::string& key_system,
if (!MediaDrmBridge::IsAvailable())
return false;
- UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system);
+ UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system);
if (scheme_uuid.empty())
return false;
@@ -287,17 +160,6 @@ std::string GetSecurityLevelString(
} // namespace
-// Called by Java.
-static void AddKeySystemUuidMapping(JNIEnv* env,
- jclass clazz,
- jstring j_key_system,
- jobject j_buffer) {
- std::string key_system = ConvertJavaStringToUTF8(env, j_key_system);
- uint8* buffer = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer));
- UUID uuid(buffer, buffer + 16);
- g_key_system_uuid_manager.Get().AddMapping(key_system, uuid);
-}
-
// static
bool MediaDrmBridge::IsAvailable() {
if (base::android::BuildInfo::GetInstance()->sdk_int() < 19)
@@ -324,7 +186,7 @@ bool MediaDrmBridge::IsSecureDecoderRequired(SecurityLevel security_level) {
// static
std::vector<std::string> MediaDrmBridge::GetPlatformKeySystemNames() {
- return g_key_system_uuid_manager.Get().GetPlatformKeySystemNames();
+ return g_key_system_manager.Get().GetPlatformKeySystemNames();
}
// static
@@ -385,7 +247,7 @@ scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(
if (!IsAvailable())
return media_drm_bridge.Pass();
- UUID scheme_uuid = g_key_system_uuid_manager.Get().GetUUID(key_system);
+ UUID scheme_uuid = g_key_system_manager.Get().GetUUID(key_system);
if (scheme_uuid.empty())
return media_drm_bridge.Pass();
@@ -449,19 +311,31 @@ void MediaDrmBridge::CreateSessionAndGenerateRequest(
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jbyteArray> j_init_data;
-
- // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as
- // the init data when using MP4 container.
- if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) &&
- init_data_type == media::EmeInitDataType::CENC) {
- std::vector<uint8> pssh_data;
- if (!GetPsshData(init_data, scheme_uuid_, &pssh_data)) {
- promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid PSSH data.");
- return;
+ ScopedJavaLocalRef<jobjectArray> j_optional_parameters;
+
+ MediaClientAndroid* client = GetMediaClientAndroid();
+ if (client) {
+ MediaDrmBridgeDelegate* delegate =
+ client->GetMediaDrmBridgeDelegate(scheme_uuid_);
+ if (delegate) {
+ std::vector<uint8> init_data_from_delegate;
+ std::vector<std::string> optional_parameters_from_delegate;
+ if (!delegate->OnCreateSession(init_data_type, init_data,
+ &init_data_from_delegate,
+ &optional_parameters_from_delegate)) {
+ promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid init data.");
+ }
+ j_init_data = base::android::ToJavaByteArray(
+ env, vector_as_array(&init_data_from_delegate),
+ init_data_from_delegate.size());
+ if (!optional_parameters_from_delegate.empty()) {
+ j_optional_parameters = base::android::ToJavaArrayOfStrings(
+ env, optional_parameters_from_delegate);
+ }
}
- j_init_data = base::android::ToJavaByteArray(
- env, vector_as_array(&pssh_data), pssh_data.size());
- } else {
+ }
+
+ if (j_init_data.is_null()) {
j_init_data = base::android::ToJavaByteArray(
env, vector_as_array(&init_data), init_data.size());
}
@@ -469,8 +343,10 @@ void MediaDrmBridge::CreateSessionAndGenerateRequest(
ScopedJavaLocalRef<jstring> j_mime =
ConvertUTF8ToJavaString(env, ConvertInitDataType(init_data_type));
uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass());
- Java_MediaDrmBridge_createSession(env, j_media_drm_.obj(), j_init_data.obj(),
- j_mime.obj(), promise_id);
+ Java_MediaDrmBridge_createSessionFromNative(env, j_media_drm_.obj(),
+ j_init_data.obj(), j_mime.obj(),
+ j_optional_parameters.obj(),
+ promise_id);
}
void MediaDrmBridge::LoadSession(
diff --git a/media/base/android/media_drm_bridge_delegate.cc b/media/base/android/media_drm_bridge_delegate.cc
new file mode 100644
index 0000000..5630d4a
--- /dev/null
+++ b/media/base/android/media_drm_bridge_delegate.cc
@@ -0,0 +1,27 @@
+// Copyright 2015 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 "media/base/android/media_drm_bridge_delegate.h"
+
+#include "base/logging.h"
+
+namespace media {
+
+MediaDrmBridgeDelegate::MediaDrmBridgeDelegate() {
+}
+
+MediaDrmBridgeDelegate::~MediaDrmBridgeDelegate() {
+}
+
+bool MediaDrmBridgeDelegate::OnCreateSession(
+ const EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ std::vector<uint8_t>* init_data_out,
+ std::vector<std::string>* optional_parameters_out) {
+ DCHECK(init_data_out->empty());
+ DCHECK(optional_parameters_out->empty());
+ return true;
+}
+
+} // namespace media
diff --git a/media/base/android/media_drm_bridge_delegate.h b/media/base/android/media_drm_bridge_delegate.h
new file mode 100644
index 0000000..7a18dac
--- /dev/null
+++ b/media/base/android/media_drm_bridge_delegate.h
@@ -0,0 +1,46 @@
+// Copyright 2015 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 MEDIA_BASE_ANDROID_MEDIA_DRM_BRIDGE_DELEGATE_H_
+#define MEDIA_BASE_ANDROID_MEDIA_DRM_BRIDGE_DELEGATE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "media/base/android/media_client_android.h"
+#include "media/base/eme_constants.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+// Allows embedders to modify the Android MediaDrm flow. Delegates are
+// registered to a specific key system.
+class MEDIA_EXPORT MediaDrmBridgeDelegate {
+ public:
+ MediaDrmBridgeDelegate();
+ virtual ~MediaDrmBridgeDelegate();
+
+ // Returns the UUID of the DRM scheme that this delegate applies to.
+ virtual const UUID GetUUID() const = 0;
+
+ // Invoked from CreateSession.
+ // If |init_data_out| is filled, it replaces |init_data| to send to the
+ // MediaDrm instance.
+ // If |optional_parameters_out| is filled, it is expected to be an
+ // even-length list of (key, value) pairs to send to the MediaDrm instance.
+ // Returns false if the request should be rejected.
+ virtual bool OnCreateSession(
+ const EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data,
+ std::vector<uint8_t>* init_data_out,
+ std::vector<std::string>* optional_parameters_out);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MediaDrmBridgeDelegate);
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_ANDROID_MEDIA_DRM_BRIDGE_DELEGATE_H_
diff --git a/media/media.gyp b/media/media.gyp
index e530e90..c228c83 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -1739,6 +1739,8 @@
'base/android/demuxer_android.h',
'base/android/demuxer_stream_player_params.cc',
'base/android/demuxer_stream_player_params.h',
+ 'base/android/media_client_android.cc',
+ 'base/android/media_client_android.h',
'base/android/media_codec_bridge.cc',
'base/android/media_codec_bridge.h',
'base/android/media_common_android.h',
@@ -1746,6 +1748,8 @@
'base/android/media_decoder_job.h',
'base/android/media_drm_bridge.cc',
'base/android/media_drm_bridge.h',
+ 'base/android/media_drm_bridge_delegate.cc',
+ 'base/android/media_drm_bridge_delegate.h',
'base/android/media_jni_registrar.cc',
'base/android/media_jni_registrar.h',
'base/android/media_player_android.cc',