diff options
author | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-16 16:55:29 +0000 |
---|---|---|
committer | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-16 16:55:29 +0000 |
commit | 4f91fc49aff3fb7b72a94b1293836ed3a8a0361c (patch) | |
tree | c7e26f54b2a6956aa4ea778747ad718d8d7b5d34 /content | |
parent | 8ba705136f136c2091d767f3ba04159b42891b1b (diff) | |
download | chromium_src-4f91fc49aff3fb7b72a94b1293836ed3a8a0361c.zip chromium_src-4f91fc49aff3fb7b72a94b1293836ed3a8a0361c.tar.gz chromium_src-4f91fc49aff3fb7b72a94b1293836ed3a8a0361c.tar.bz2 |
BrowserMediaPlayerManager manages MediaKeys objects.
Changes in this CL:
- Add cdm_factory.h to support platform specific CDM creation.
- Detach BrowserMediaPlayerManager from MediaDrmBridge.
- Store the security origin of CDMs in the manager so that CDMs don't need to
know it.
- Keep the CDM ID in the manager so that CDMs don't see it.
BUG=338910
TEST=Test page plays and tests still pass.
Review URL: https://codereview.chromium.org/276973005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271034 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
3 files changed, 125 insertions, 105 deletions
diff --git a/content/browser/media/android/browser_media_player_manager.cc b/content/browser/media/android/browser_media_player_manager.cc index b4a71e8..ac37e42 100644 --- a/content/browser/media/android/browser_media_player_manager.cc +++ b/content/browser/media/android/browser_media_player_manager.cc @@ -6,6 +6,7 @@ #include "base/android/scoped_java_ref.h" #include "base/command_line.h" +#include "base/stl_util.h" #include "content/browser/android/content_view_core_impl.h" #include "content/browser/media/android/browser_demuxer_android.h" #include "content/browser/media/android/media_resource_getter_impl.h" @@ -24,12 +25,12 @@ #include "content/public/browser/web_contents_delegate.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" -#include "media/base/android/media_drm_bridge.h" #include "media/base/android/media_player_bridge.h" #include "media/base/android/media_source_player.h" +#include "media/base/cdm_factory.h" #include "media/base/media_switches.h" -using media::MediaDrmBridge; +using media::MediaKeys; using media::MediaPlayerAndroid; using media::MediaPlayerBridge; using media::MediaPlayerManager; @@ -342,18 +343,14 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) { return NULL; } -MediaDrmBridge* BrowserMediaPlayerManager::GetDrmBridge(int cdm_id) { - for (ScopedVector<MediaDrmBridge>::iterator it = drm_bridges_.begin(); - it != drm_bridges_.end(); ++it) { - if ((*it)->cdm_id() == cdm_id) - return *it; - } - return NULL; +MediaKeys* BrowserMediaPlayerManager::GetCdm(int cdm_id) { + CdmMap::const_iterator iter = cdm_map_.find(cdm_id); + return (iter == cdm_map_.end()) ? NULL : iter->second; } void BrowserMediaPlayerManager::DestroyAllMediaPlayers() { players_.clear(); - drm_bridges_.clear(); + STLDeleteValues(&cdm_map_); if (fullscreen_player_id_ != -1) { video_view_.reset(); fullscreen_player_id_ = -1; @@ -394,9 +391,16 @@ void BrowserMediaPlayerManager::OnSessionMessage( int cdm_id, uint32 session_id, const std::vector<uint8>& message, - const GURL& destination_url) { + const std::string& destination_url) { + GURL destination_gurl(destination_url); + if (!destination_gurl.is_valid() && !destination_gurl.is_empty()) { + DLOG(WARNING) << "SessionMessage destination_url is invalid : " + << destination_gurl.possibly_invalid_spec(); + destination_gurl = GURL::EmptyGURL(); // Replace invalid destination_url. + } + Send(new CdmMsg_SessionMessage( - routing_id(), cdm_id, session_id, message, destination_url)); + routing_id(), cdm_id, session_id, message, destination_gurl)); } void BrowserMediaPlayerManager::OnSessionReady(int cdm_id, uint32 session_id) { @@ -591,17 +595,12 @@ void BrowserMediaPlayerManager::OnInitializeCdm(int cdm_id, const GURL& security_origin) { if (key_system.size() > kMaxKeySystemLength) { // This failure will be discovered and reported by OnCreateSession() - // as GetDrmBridge() will return null. + // as GetCdm() will return null. NOTREACHED() << "Invalid key system: " << key_system; return; } - if (!MediaDrmBridge::IsKeySystemSupported(key_system)) { - NOTREACHED() << "Unsupported key system: " << key_system; - return; - } - - AddDrmBridge(cdm_id, key_system, security_origin); + AddCdm(cdm_id, key_system, security_origin); } void BrowserMediaPlayerManager::OnCreateSession( @@ -639,9 +638,9 @@ void BrowserMediaPlayerManager::OnCreateSession( return; } - MediaDrmBridge* drm_bridge = GetDrmBridge(cdm_id); - if (!drm_bridge) { - DLOG(WARNING) << "No MediaDrmBridge for ID: " << cdm_id << " found"; + MediaKeys* cdm = GetCdm(cdm_id); + if (!cdm) { + DLOG(WARNING) << "No CDM for ID " << cdm_id << " found"; OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); return; } @@ -649,12 +648,20 @@ void BrowserMediaPlayerManager::OnCreateSession( BrowserContext* context = web_contents()->GetRenderProcessHost()->GetBrowserContext(); + std::map<int, GURL>::const_iterator iter = + cdm_security_origin_map_.find(cdm_id); + if (iter == cdm_security_origin_map_.end()) { + NOTREACHED(); + OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); + return; + } + context->RequestProtectedMediaIdentifierPermission( web_contents()->GetRenderProcessHost()->GetID(), web_contents()->GetRenderViewHost()->GetRoutingID(), static_cast<int>(session_id), cdm_id, - drm_bridge->security_origin(), + iter->second, base::Bind(&BrowserMediaPlayerManager::CreateSessionIfPermitted, weak_ptr_factory_.GetWeakPtr(), cdm_id, @@ -667,24 +674,24 @@ void BrowserMediaPlayerManager::OnUpdateSession( int cdm_id, uint32 session_id, const std::vector<uint8>& response) { - MediaDrmBridge* drm_bridge = GetDrmBridge(cdm_id); - if (!drm_bridge) { - DLOG(WARNING) << "No MediaDrmBridge for ID: " << cdm_id << " found"; + MediaKeys* cdm = GetCdm(cdm_id); + if (!cdm) { + DLOG(WARNING) << "No CDM for ID " << cdm_id << " found"; OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); return; } if (response.size() > kMaxSessionResponseLength) { - LOG(WARNING) << "Response for ID: " << cdm_id - << " too long: " << response.size(); + LOG(WARNING) << "Response for ID " << cdm_id + << " is too long: " << response.size(); OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); return; } - drm_bridge->UpdateSession(session_id, &response[0], response.size()); + cdm->UpdateSession(session_id, &response[0], response.size()); - DrmBridgePlayerMap::const_iterator iter = drm_bridge_player_map_.find(cdm_id); - if (iter == drm_bridge_player_map_.end()) + CdmToPlayerMap::const_iterator iter = cdm_to_player_map_.find(cdm_id); + if (iter == cdm_to_player_map_.end()) return; int player_id = iter->second; @@ -695,22 +702,23 @@ void BrowserMediaPlayerManager::OnUpdateSession( void BrowserMediaPlayerManager::OnReleaseSession(int cdm_id, uint32 session_id) { - MediaDrmBridge* drm_bridge = GetDrmBridge(cdm_id); - if (!drm_bridge) { - DLOG(WARNING) << "No MediaDrmBridge for ID: " << cdm_id << " found"; + MediaKeys* cdm = GetCdm(cdm_id); + if (!cdm) { + DLOG(WARNING) << "No CDM for ID " << cdm_id << " found"; OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); return; } - drm_bridge->ReleaseSession(session_id); + cdm->ReleaseSession(session_id); } void BrowserMediaPlayerManager::OnDestroyCdm(int cdm_id) { - MediaDrmBridge* drm_bridge = GetDrmBridge(cdm_id); - if (!drm_bridge) return; + MediaKeys* cdm = GetCdm(cdm_id); + if (!cdm) + return; CancelAllPendingSessionCreations(cdm_id); - RemoveDrmBridge(cdm_id); + RemoveCdm(cdm_id); } void BrowserMediaPlayerManager::CancelAllPendingSessionCreations(int cdm_id) { @@ -734,10 +742,11 @@ void BrowserMediaPlayerManager::RemovePlayer(int player_id) { } } - for (DrmBridgePlayerMap::iterator it = drm_bridge_player_map_.begin(); - it != drm_bridge_player_map_.end(); ++it) { + for (CdmToPlayerMap::iterator it = cdm_to_player_map_.begin(); + it != cdm_to_player_map_.end(); + ++it) { if (it->second == player_id) { - drm_bridge_player_map_.erase(it); + cdm_to_player_map_.erase(it); break; } } @@ -758,64 +767,70 @@ scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer( return scoped_ptr<media::MediaPlayerAndroid>(previous_player); } -void BrowserMediaPlayerManager::AddDrmBridge(int cdm_id, - const std::string& key_system, - const GURL& security_origin) { - DCHECK(!GetDrmBridge(cdm_id)); - - scoped_ptr<MediaDrmBridge> drm_bridge( - MediaDrmBridge::Create(cdm_id, key_system, security_origin, this)); - if (!drm_bridge) { +void BrowserMediaPlayerManager::AddCdm(int cdm_id, + const std::string& key_system, + const GURL& security_origin) { + DCHECK(!GetCdm(cdm_id)); + base::WeakPtr<BrowserMediaPlayerManager> weak_this = + weak_ptr_factory_.GetWeakPtr(); + + scoped_ptr<MediaKeys> cdm(media::CreateBrowserCdm( + key_system, + base::Bind( + &BrowserMediaPlayerManager::OnSessionCreated, weak_this, cdm_id), + base::Bind( + &BrowserMediaPlayerManager::OnSessionMessage, weak_this, cdm_id), + base::Bind( + &BrowserMediaPlayerManager::OnSessionReady, weak_this, cdm_id), + base::Bind( + &BrowserMediaPlayerManager::OnSessionClosed, weak_this, cdm_id), + base::Bind( + &BrowserMediaPlayerManager::OnSessionError, weak_this, cdm_id))); + + if (!cdm) { // This failure will be discovered and reported by OnCreateSession() - // as GetDrmBridge() will return null. - DVLOG(1) << "failed to create drm bridge."; - return; - } - - // TODO(xhwang/ddorwin): Pass the security level from key system. - MediaDrmBridge::SecurityLevel security_level = - MediaDrmBridge::SECURITY_LEVEL_3; - if (CommandLine::ForCurrentProcess() - ->HasSwitch(switches::kMediaDrmEnableNonCompositing)) { - security_level = MediaDrmBridge::SECURITY_LEVEL_1; - } - if (!drm_bridge->SetSecurityLevel(security_level)) { - DVLOG(1) << "failed to set security level " << security_level; + // as GetCdm() will return null. + DVLOG(1) << "failed to create CDM."; return; } - drm_bridges_.push_back(drm_bridge.release()); + cdm_map_[cdm_id] = cdm.release(); + cdm_security_origin_map_[cdm_id] = security_origin; } -void BrowserMediaPlayerManager::RemoveDrmBridge(int cdm_id) { - // TODO(xhwang): Detach DrmBridge from the player it's set to. In prefixed +void BrowserMediaPlayerManager::RemoveCdm(int cdm_id) { + // TODO(xhwang): Detach CDM from the player it's set to. In prefixed // EME implementation the current code is fine because we always destroy the // player before we destroy the DrmBridge. This will not always be the case // in unprefixed EME implementation. - for (ScopedVector<MediaDrmBridge>::iterator it = drm_bridges_.begin(); - it != drm_bridges_.end(); ++it) { - if ((*it)->cdm_id() == cdm_id) { - drm_bridges_.erase(it); - drm_bridge_player_map_.erase(cdm_id); - break; - } + CdmMap::iterator iter = cdm_map_.find(cdm_id); + if (iter != cdm_map_.end()) { + delete iter->second; + cdm_map_.erase(iter); } + cdm_to_player_map_.erase(cdm_id); + cdm_security_origin_map_.erase(cdm_id); } void BrowserMediaPlayerManager::OnSetCdm(int player_id, int cdm_id) { MediaPlayerAndroid* player = GetPlayer(player_id); - MediaDrmBridge* drm_bridge = GetDrmBridge(cdm_id); - if (!drm_bridge || !player) { + MediaKeys* cdm = GetCdm(cdm_id); + if (!cdm || !player) { DVLOG(1) << "Cannot set CDM on the specified player."; return; } // TODO(qinmin): add the logic to decide whether we should create the // fullscreen surface for EME lv1. - player->SetDrmBridge(drm_bridge); + player->SetCdm(cdm); // Do now support setting one CDM on multiple players. - DCHECK(drm_bridge_player_map_.find(cdm_id) == drm_bridge_player_map_.end()); - drm_bridge_player_map_[cdm_id] = player_id; + + if (ContainsKey(cdm_to_player_map_, cdm_id)) { + DVLOG(1) << "CDM is already set on another player."; + return; + } + + cdm_to_player_map_[cdm_id] = player_id; } void BrowserMediaPlayerManager::CreateSessionIfPermitted( @@ -829,16 +844,15 @@ void BrowserMediaPlayerManager::CreateSessionIfPermitted( return; } - MediaDrmBridge* drm_bridge = GetDrmBridge(cdm_id); - if (!drm_bridge) { - DLOG(WARNING) << "No MediaDrmBridge for ID: " << cdm_id << " found"; + MediaKeys* cdm = GetCdm(cdm_id); + if (!cdm) { + DLOG(WARNING) << "No CDM for ID: " << cdm_id << " found"; OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); return; } // This could fail, in which case a SessionError will be fired. - drm_bridge->CreateSession( - session_id, content_type, &init_data[0], init_data.size()); + cdm->CreateSession(session_id, content_type, &init_data[0], init_data.size()); } void BrowserMediaPlayerManager::ReleaseFullscreenPlayer( diff --git a/content/browser/media/android/browser_media_player_manager.h b/content/browser/media/android/browser_media_player_manager.h index 308ed02..b6648f0 100644 --- a/content/browser/media/android/browser_media_player_manager.h +++ b/content/browser/media/android/browser_media_player_manager.h @@ -26,7 +26,7 @@ namespace media { class DemuxerAndroid; -class MediaDrmBridge; +class MediaKeys; } namespace content { @@ -35,11 +35,11 @@ class ContentViewCoreImpl; class ExternalVideoSurfaceContainer; class WebContents; -// This class manages all the MediaPlayerAndroid objects. It receives -// control operations from the the render process, and forwards -// them to corresponding MediaPlayerAndroid object. Callbacks from -// MediaPlayerAndroid objects are converted to IPCs and then sent to the -// render process. +// This class manages all the MediaPlayerAndroid and CDM objects. +// It receives control operations from the the render process, and forwards +// them to corresponding MediaPlayerAndroid or CDM object. Callbacks from +// MediaPlayerAndroid and CDM objects are converted to IPCs and then sent to +// the render process. class CONTENT_EXPORT BrowserMediaPlayerManager : public WebContentsObserver, public media::MediaPlayerManager { @@ -90,7 +90,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager virtual media::MediaResourceGetter* GetMediaResourceGetter() OVERRIDE; virtual media::MediaPlayerAndroid* GetFullscreenPlayer() OVERRIDE; virtual media::MediaPlayerAndroid* GetPlayer(int player_id) OVERRIDE; - virtual media::MediaDrmBridge* GetDrmBridge(int cdm_id) OVERRIDE; + virtual media::MediaKeys* GetCdm(int cdm_id) OVERRIDE; virtual void DestroyAllMediaPlayers() OVERRIDE; virtual void RequestFullScreen(int player_id) OVERRIDE; virtual void OnSessionCreated(int cdm_id, @@ -99,7 +99,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager virtual void OnSessionMessage(int cdm_id, uint32 session_id, const std::vector<uint8>& message, - const GURL& destination_url) OVERRIDE; + const std::string& destination_url) OVERRIDE; virtual void OnSessionReady(int cdm_id, uint32 session_id) OVERRIDE; virtual void OnSessionClosed(int cdm_id, uint32 session_id) OVERRIDE; virtual void OnSessionError(int cdm_id, @@ -164,14 +164,14 @@ class CONTENT_EXPORT BrowserMediaPlayerManager int player_id, media::MediaPlayerAndroid* player); - // Adds a new MediaDrmBridge for the given |key_system|, |cdm_id|, and - // |frame_url|. - void AddDrmBridge(int cdm_id, - const std::string& key_system, - const GURL& frame_url); + // Adds a new CDM identified by |cdm_id| for the given |key_system| and + // |security_origin|. + void AddCdm(int cdm_id, + const std::string& key_system, + const GURL& security_origin); - // Removes the DRM bridge with the specified id. - void RemoveDrmBridge(int cdm_id); + // Removes the CDM with the specified id. + void RemoveCdm(int cdm_id); private: // If |permitted| is false, it does nothing but send @@ -216,13 +216,19 @@ class CONTENT_EXPORT BrowserMediaPlayerManager // An array of managed players. ScopedVector<media::MediaPlayerAndroid> players_; - // An array of managed media DRM bridges. - ScopedVector<media::MediaDrmBridge> drm_bridges_; + // A map from CDM IDs to managed CDMs. + typedef std::map<int, media::MediaKeys*> CdmMap; + CdmMap cdm_map_; - // Map from DrmBridge cdm_id to MediaPlayerAndroid player_id to indicate that - // the DrmBridge is set on the MediaPlayerAndroid object. - typedef std::map<int, int> DrmBridgePlayerMap; - DrmBridgePlayerMap drm_bridge_player_map_; + // Map from CDM ID to MediaPlayerAndroid player ID to indicate that + // the CDM is set on the MediaPlayerAndroid object. + // TODO(xhwang): Register a callback in the CDM to resume playback so that we + // can remove this map. See http://crbug.com/373327 + typedef std::map<int, int> CdmToPlayerMap; + CdmToPlayerMap cdm_to_player_map_; + + // Map from CDM ID to CDM's security origin. + std::map<int, GURL> cdm_security_origin_map_; // The fullscreen video view object or NULL if video is not played in // fullscreen. diff --git a/content/browser/media/android/media_drm_credential_manager.cc b/content/browser/media/android/media_drm_credential_manager.cc index 0fb8618..23c6cf2 100644 --- a/content/browser/media/android/media_drm_credential_manager.cc +++ b/content/browser/media/android/media_drm_credential_manager.cc @@ -90,7 +90,7 @@ void MediaDrmCredentialManager::OnResetCredentialsCompleted( bool MediaDrmCredentialManager::ResetCredentialsInternal( SecurityLevel security_level) { media_drm_bridge_ = - media::MediaDrmBridge::Create(0, kWidevineKeySystem, GURL(), NULL); + media::MediaDrmBridge::CreateSessionless(kWidevineKeySystem); if (!media_drm_bridge_) return false; |