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 "apps/app_window.h" 8 #include "apps/app_window_registry.h" 9 #include "ash/shell.h" 10 #include "ash/system/tray/system_tray_notifier.h" 11 #include "base/message_loop/message_loop.h" 12 #include "chrome/browser/chromeos/extensions/media_player_api.h" 13 #include "chrome/browser/chromeos/extensions/media_player_event_router.h" 14 #include "chrome/browser/media/media_stream_capture_indicator.h" 15 #include "chrome/browser/profiles/profile_manager.h" 16 #include "chrome/browser/ui/browser.h" 17 #include "chrome/browser/ui/browser_list.h" 18 #include "chrome/browser/ui/browser_window.h" 19 #include "chrome/browser/ui/tabs/tab_strip_model.h" 20 #include "content/public/browser/render_view_host.h" 21 #include "content/public/browser/web_contents.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 apps::AppWindowRegistry::AppWindowList& apps = 65 apps::AppWindowRegistry::Get(context)->app_windows(); 66 for (apps::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_view_id, 161 const content::MediaStreamDevice& device, 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