Home | History | Annotate | Download | only in ash
      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 "chrome/browser/ui/ash/media_delegate_chromeos.h"
      6 
      7 #include "ash/shell.h"
      8 #include "ash/system/tray/system_tray_notifier.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "chrome/browser/chromeos/extensions/media_player_api.h"
     11 #include "chrome/browser/chromeos/extensions/media_player_event_router.h"
     12 #include "chrome/browser/media/media_stream_capture_indicator.h"
     13 #include "chrome/browser/profiles/profile_manager.h"
     14 #include "chrome/browser/ui/browser.h"
     15 #include "chrome/browser/ui/browser_list.h"
     16 #include "chrome/browser/ui/browser_window.h"
     17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     18 #include "content/public/browser/render_view_host.h"
     19 #include "content/public/browser/web_contents.h"
     20 #include "extensions/browser/app_window/app_window.h"
     21 #include "extensions/browser/app_window/app_window_registry.h"
     22 #include "extensions/browser/extension_system.h"
     23 #include "extensions/browser/process_manager.h"
     24 
     25 namespace {
     26 
     27 void GetMediaCaptureState(
     28     const MediaStreamCaptureIndicator* indicator,
     29     content::WebContents* web_contents,
     30     int* media_state_out) {
     31   if (indicator->IsCapturingVideo(web_contents))
     32     *media_state_out |= ash::MEDIA_CAPTURE_VIDEO;
     33   if (indicator->IsCapturingAudio(web_contents))
     34     *media_state_out |= ash::MEDIA_CAPTURE_AUDIO;
     35 }
     36 
     37 void GetBrowserMediaCaptureState(
     38     const MediaStreamCaptureIndicator* indicator,
     39     const content::BrowserContext* context,
     40     int* media_state_out) {
     41 
     42   const BrowserList* desktop_list =
     43       BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
     44 
     45   for (BrowserList::BrowserVector::const_iterator iter = desktop_list->begin();
     46        iter != desktop_list->end();
     47        ++iter) {
     48     TabStripModel* tab_strip_model = (*iter)->tab_strip_model();
     49     for (int i = 0; i < tab_strip_model->count(); ++i) {
     50       content::WebContents* web_contents = tab_strip_model->GetWebContentsAt(i);
     51       if (web_contents->GetBrowserContext() != context)
     52         continue;
     53       GetMediaCaptureState(indicator, web_contents, media_state_out);
     54       if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
     55         return;
     56     }
     57   }
     58 }
     59 
     60 void GetAppMediaCaptureState(
     61     const MediaStreamCaptureIndicator* indicator,
     62     content::BrowserContext* context,
     63     int* media_state_out) {
     64   const extensions::AppWindowRegistry::AppWindowList& apps =
     65       extensions::AppWindowRegistry::Get(context)->app_windows();
     66   for (extensions::AppWindowRegistry::AppWindowList::const_iterator iter =
     67            apps.begin();
     68        iter != apps.end();
     69        ++iter) {
     70     GetMediaCaptureState(indicator, (*iter)->web_contents(), media_state_out);
     71     if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
     72       return;
     73   }
     74 }
     75 
     76 void GetExtensionMediaCaptureState(
     77     const MediaStreamCaptureIndicator* indicator,
     78     content::BrowserContext* context,
     79     int* media_state_out) {
     80   extensions::ProcessManager* process_manager =
     81       extensions::ExtensionSystem::Get(context)->process_manager();
     82   const extensions::ProcessManager::ViewSet view_set =
     83       process_manager->GetAllViews();
     84   for (extensions::ProcessManager::ViewSet::const_iterator iter =
     85            view_set.begin();
     86        iter != view_set.end();
     87        ++iter) {
     88     content::WebContents* web_contents =
     89         content::WebContents::FromRenderViewHost(*iter);
     90     // RVH may not have web contents.
     91     if (!web_contents)
     92       continue;
     93     GetMediaCaptureState(indicator, web_contents, media_state_out);
     94     if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
     95       return;
     96   }
     97 }
     98 
     99 ash::MediaCaptureState GetMediaCaptureStateOfAllWebContents(
    100     content::BrowserContext* context) {
    101   if (!context)
    102     return ash::MEDIA_CAPTURE_NONE;
    103 
    104   scoped_refptr<MediaStreamCaptureIndicator> indicator =
    105       MediaCaptureDevicesDispatcher::GetInstance()
    106           ->GetMediaStreamCaptureIndicator();
    107 
    108   int media_state = ash::MEDIA_CAPTURE_NONE;
    109   // Browser windows
    110   GetBrowserMediaCaptureState(indicator.get(), context, &media_state);
    111   if (media_state == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
    112     return ash::MEDIA_CAPTURE_AUDIO_VIDEO;
    113 
    114   // App windows
    115   GetAppMediaCaptureState(indicator.get(), context, &media_state);
    116   if (media_state == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
    117     return ash::MEDIA_CAPTURE_AUDIO_VIDEO;
    118 
    119   // Extensions
    120   GetExtensionMediaCaptureState(indicator.get(), context, &media_state);
    121 
    122   return static_cast<ash::MediaCaptureState>(media_state);
    123 }
    124 
    125 }  // namespace
    126 
    127 MediaDelegateChromeOS::MediaDelegateChromeOS() : weak_ptr_factory_(this) {
    128   MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this);
    129 }
    130 
    131 MediaDelegateChromeOS::~MediaDelegateChromeOS() {
    132   MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this);
    133 }
    134 
    135 void MediaDelegateChromeOS::HandleMediaNextTrack() {
    136   extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
    137       ->media_player_event_router()
    138       ->NotifyNextTrack();
    139 }
    140 
    141 void MediaDelegateChromeOS::HandleMediaPlayPause() {
    142   extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
    143       ->media_player_event_router()
    144       ->NotifyTogglePlayState();
    145 }
    146 
    147 void MediaDelegateChromeOS::HandleMediaPrevTrack() {
    148   extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
    149       ->media_player_event_router()
    150       ->NotifyPrevTrack();
    151 }
    152 
    153 ash::MediaCaptureState MediaDelegateChromeOS::GetMediaCaptureState(
    154     content::BrowserContext* context) {
    155   return GetMediaCaptureStateOfAllWebContents(context);
    156 }
    157 
    158 void MediaDelegateChromeOS::OnRequestUpdate(
    159     int render_process_id,
    160     int render_frame_id,
    161     content::MediaStreamType stream_type,
    162     const content::MediaRequestState state) {
    163   base::MessageLoopForUI::current()->PostTask(
    164       FROM_HERE,
    165       base::Bind(&MediaDelegateChromeOS::NotifyMediaCaptureChange,
    166                  weak_ptr_factory_.GetWeakPtr()));
    167 }
    168 
    169 void MediaDelegateChromeOS::NotifyMediaCaptureChange() {
    170   ash::Shell::GetInstance()
    171       ->system_tray_notifier()
    172       ->NotifyMediaCaptureChanged();
    173 }
    174