Home | History | Annotate | Download | only in media
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/media/media_web_contents_observer.h"
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/stl_util.h"
      9 #include "content/browser/media/cdm/browser_cdm_manager.h"
     10 #include "content/common/media/cdm_messages.h"
     11 #include "content/public/browser/render_frame_host.h"
     12 #include "content/public/browser/web_contents.h"
     13 #include "ipc/ipc_message_macros.h"
     14 
     15 #if defined(OS_ANDROID)
     16 #include "content/browser/media/android/browser_media_player_manager.h"
     17 #include "content/common/media/media_player_messages_android.h"
     18 #include "media/base/android/media_player_android.h"
     19 #endif  // defined(OS_ANDROID)
     20 
     21 namespace content {
     22 
     23 MediaWebContentsObserver::MediaWebContentsObserver(
     24     RenderViewHost* render_view_host)
     25     : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)) {
     26 }
     27 
     28 MediaWebContentsObserver::~MediaWebContentsObserver() {
     29 }
     30 
     31 void MediaWebContentsObserver::RenderFrameDeleted(
     32     RenderFrameHost* render_frame_host) {
     33   uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
     34   // Always destroy the media players before CDMs because we do not support
     35   // detaching CDMs from media players yet. See http://crbug.com/330324
     36 #if defined(OS_ANDROID)
     37   media_player_managers_.erase(key);
     38 #endif
     39   cdm_managers_.erase(key);
     40 }
     41 
     42 bool MediaWebContentsObserver::OnMessageReceived(
     43     const IPC::Message& msg,
     44     RenderFrameHost* render_frame_host) {
     45 #if defined(OS_ANDROID)
     46   // Handles MediaPlayer messages first because MediaPlayers messages are much
     47   // more frequent than CDM messages.
     48   if (OnMediaPlayerMessageReceived(msg, render_frame_host))
     49     return true;
     50 
     51   if (OnMediaPlayerSetCdmMessageReceived(msg, render_frame_host))
     52     return true;
     53 #endif  // defined(OS_ANDROID)
     54 
     55   if (OnCdmMessageReceived(msg, render_frame_host))
     56     return true;
     57 
     58   return false;
     59 }
     60 
     61 bool MediaWebContentsObserver::OnCdmMessageReceived(
     62     const IPC::Message& msg,
     63     RenderFrameHost* render_frame_host) {
     64   bool handled = true;
     65   IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserver, msg)
     66     IPC_MESSAGE_FORWARD(CdmHostMsg_InitializeCdm,
     67                         GetCdmManager(render_frame_host),
     68                         BrowserCdmManager::OnInitializeCdm)
     69     IPC_MESSAGE_FORWARD(CdmHostMsg_CreateSession,
     70                         GetCdmManager(render_frame_host),
     71                         BrowserCdmManager::OnCreateSession)
     72     IPC_MESSAGE_FORWARD(CdmHostMsg_UpdateSession,
     73                         GetCdmManager(render_frame_host),
     74                         BrowserCdmManager::OnUpdateSession)
     75     IPC_MESSAGE_FORWARD(CdmHostMsg_ReleaseSession,
     76                         GetCdmManager(render_frame_host),
     77                         BrowserCdmManager::OnReleaseSession)
     78     IPC_MESSAGE_FORWARD(CdmHostMsg_DestroyCdm,
     79                         GetCdmManager(render_frame_host),
     80                         BrowserCdmManager::OnDestroyCdm)
     81     IPC_MESSAGE_UNHANDLED(handled = false)
     82   IPC_END_MESSAGE_MAP()
     83   return handled;
     84 }
     85 
     86 BrowserCdmManager* MediaWebContentsObserver::GetCdmManager(
     87     RenderFrameHost* render_frame_host) {
     88   uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
     89   if (!cdm_managers_.contains(key)) {
     90     cdm_managers_.set(
     91         key, make_scoped_ptr(BrowserCdmManager::Create(render_frame_host)));
     92   }
     93   return cdm_managers_.get(key);
     94 }
     95 
     96 #if defined(OS_ANDROID)
     97 bool MediaWebContentsObserver::OnMediaPlayerMessageReceived(
     98     const IPC::Message& msg,
     99     RenderFrameHost* render_frame_host) {
    100   bool handled = true;
    101   IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserver, msg)
    102     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_EnterFullscreen,
    103                         GetMediaPlayerManager(render_frame_host),
    104                         BrowserMediaPlayerManager::OnEnterFullscreen)
    105     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_ExitFullscreen,
    106                         GetMediaPlayerManager(render_frame_host),
    107                         BrowserMediaPlayerManager::OnExitFullscreen)
    108     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Initialize,
    109                         GetMediaPlayerManager(render_frame_host),
    110                         BrowserMediaPlayerManager::OnInitialize)
    111     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Start,
    112                         GetMediaPlayerManager(render_frame_host),
    113                         BrowserMediaPlayerManager::OnStart)
    114     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Seek,
    115                         GetMediaPlayerManager(render_frame_host),
    116                         BrowserMediaPlayerManager::OnSeek)
    117     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Pause,
    118                         GetMediaPlayerManager(render_frame_host),
    119                         BrowserMediaPlayerManager::OnPause)
    120     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_SetVolume,
    121                         GetMediaPlayerManager(render_frame_host),
    122                         BrowserMediaPlayerManager::OnSetVolume)
    123     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_SetPoster,
    124                         GetMediaPlayerManager(render_frame_host),
    125                         BrowserMediaPlayerManager::OnSetPoster)
    126     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Release,
    127                         GetMediaPlayerManager(render_frame_host),
    128                         BrowserMediaPlayerManager::OnReleaseResources)
    129     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_DestroyMediaPlayer,
    130                         GetMediaPlayerManager(render_frame_host),
    131                         BrowserMediaPlayerManager::OnDestroyPlayer)
    132 #if defined(VIDEO_HOLE)
    133     IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_NotifyExternalSurface,
    134                         GetMediaPlayerManager(render_frame_host),
    135                         BrowserMediaPlayerManager::OnNotifyExternalSurface)
    136 #endif  // defined(VIDEO_HOLE)
    137     IPC_MESSAGE_UNHANDLED(handled = false)
    138   IPC_END_MESSAGE_MAP()
    139   return handled;
    140 }
    141 
    142 bool MediaWebContentsObserver::OnMediaPlayerSetCdmMessageReceived(
    143     const IPC::Message& msg,
    144     RenderFrameHost* render_frame_host) {
    145   bool handled = true;
    146   IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(
    147       MediaWebContentsObserver, msg, render_frame_host)
    148     IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetCdm, OnSetCdm)
    149     IPC_MESSAGE_UNHANDLED(handled = false)
    150   IPC_END_MESSAGE_MAP()
    151   return handled;
    152 }
    153 
    154 void MediaWebContentsObserver::OnSetCdm(RenderFrameHost* render_frame_host,
    155                                         int player_id,
    156                                         int cdm_id) {
    157   media::MediaPlayerAndroid* media_player =
    158       GetMediaPlayerManager(render_frame_host)->GetPlayer(player_id);
    159   if (!media_player) {
    160     NOTREACHED() << "OnSetCdm: MediaPlayer not found for " << player_id;
    161     return;
    162   }
    163 
    164   media::BrowserCdm* cdm = GetCdmManager(render_frame_host)->GetCdm(cdm_id);
    165   if (!cdm) {
    166     NOTREACHED() << "OnSetCdm: CDM not found for " << cdm_id;
    167     return;
    168   }
    169 
    170   // TODO(xhwang): This could possibly fail. In that case we should reject the
    171   // promise.
    172   media_player->SetCdm(cdm);
    173 }
    174 
    175 BrowserMediaPlayerManager* MediaWebContentsObserver::GetMediaPlayerManager(
    176     RenderFrameHost* render_frame_host) {
    177   uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
    178   if (!media_player_managers_.contains(key)) {
    179     media_player_managers_.set(
    180         key,
    181         make_scoped_ptr(BrowserMediaPlayerManager::Create(render_frame_host)));
    182   }
    183   return media_player_managers_.get(key);
    184 }
    185 
    186 void MediaWebContentsObserver::PauseVideo() {
    187   for (MediaPlayerManagerMap::iterator iter = media_player_managers_.begin();
    188       iter != media_player_managers_.end(); ++iter) {
    189     BrowserMediaPlayerManager* manager = iter->second;
    190     manager->PauseVideo();
    191   }
    192 }
    193 
    194 #if defined(VIDEO_HOLE)
    195 void MediaWebContentsObserver::OnFrameInfoUpdated() {
    196   for (MediaPlayerManagerMap::iterator iter = media_player_managers_.begin();
    197       iter != media_player_managers_.end(); ++iter) {
    198     BrowserMediaPlayerManager* manager = iter->second;
    199     manager->OnFrameInfoUpdated();
    200   }
    201 }
    202 #endif  // defined(VIDEO_HOLE)
    203 
    204 #endif  // defined(OS_ANDROID)
    205 
    206 }  // namespace content
    207