Adds MediaClientAndroid to support embedder/MediaDrmBridge interaction.

This CL does a few things:
* Adds a MediaDrmBridgeDelegate interface to support per DRM-scheme logic for Android in MediaDrmBridge.
* Adds a MediaClientAndroid interface for embedders to provide MediaDrmBridgeDelegate implementations and key-system-UUID mappings
* Removes the Java-based key-system-UUID mapping path
* Embedders no longer call directly into MediaDrmBridge

[email protected],[email protected],[email protected],[email protected]
BUG=462443

Review URL: https://codereview.chromium.org/962793005

Cr-Commit-Position: refs/heads/master@{#327650}
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 ba8fe5b6..9fd4db1c 100644
--- a/android_webview/browser/DEPS
+++ b/android_webview/browser/DEPS
@@ -24,6 +24,8 @@
   "+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 @@
 
   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 00613c3c..e5c04179 100644
--- a/android_webview/common/aw_resource.h
+++ b/android_webview/common/aw_resource.h
@@ -14,6 +14,7 @@
 
 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..592e48f8 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.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 @@
                 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 @@
     }
 
     @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..75f75b5b 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 @@
   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..d489e420
--- /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 9f977fc8..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 @@
   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 @@
   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 53066424..bd203a8 100644
--- a/chromecast/browser/DEPS
+++ b/chromecast/browser/DEPS
@@ -3,6 +3,7 @@
   # 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 937018d8..7b569732 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.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 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 @@
             // 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 @@
   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..696471e6
--- /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..1537afd3 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 @@
 // 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 e6dbd028..671ce03 100644
--- a/chromecast/media/base/key_systems_common_simple.cc
+++ b/chromecast/media/base/key_systems_common_simple.cc
@@ -11,5 +11,13 @@
   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..3ca9effd 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..86bc6db9 100644
--- a/components/OWNERS
+++ b/components/OWNERS
@@ -25,6 +25,10 @@
 per-file [email protected]
 per-file [email protected]
 
+per-file [email protected]
+per-file [email protected]
+per-file [email protected]
+
 per-file cloud_devices*[email protected]
 per-file cloud_devices*[email protected]
 
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 @@
   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..64b90bf9
--- /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 @@
     "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..9d49232d 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.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 @@
     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 @@
             return mMimeType;
         }
 
+        private HashMap<String, String> optionalParameters() {
+            return mOptionalParameters;
+        }
+
         private long promiseId() {
             return mPromiseId;
         }
@@ -410,16 +416,20 @@
      * @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 @@
      *
      * @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 @@
             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 @@
     }
 
     /**
+     * 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 @@
 
         if (mProvisioningPending) {
             assert mMediaCrypto == null;
-            savePendingCreateSessionData(initData, mime, promiseId);
+            savePendingCreateSessionData(initData, mime, optionalParameters, promiseId);
             return;
         }
 
@@ -514,7 +548,7 @@
             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 @@
             if (newSessionOpened) {
                 mMediaDrm.closeSession(sessionId);
             }
-            savePendingCreateSessionData(initData, mime, promiseId);
+            savePendingCreateSessionData(initData, mime, optionalParameters, promiseId);
             startProvisioning();
         }
     }
@@ -832,7 +866,7 @@
                     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 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 @@
 
     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..ad4e11bd
--- /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 @@
 // 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 @@
   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 @@
   }
 }
 
-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 @@
   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 @@
   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 @@
 
 }  // 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 @@
 
 // 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 @@
   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 @@
 
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jbyteArray> j_init_data;
+  ScopedJavaLocalRef<jobjectArray> j_optional_parameters;
 
-  // 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;
+  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 @@
   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..5630d4af
--- /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..c228c832 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',