1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file.
4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/ui/ash/media_delegate_chromeos.h"
6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ash/shell.h"
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ash/system/tray/system_tray_notifier.h"
9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/message_loop/message_loop.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/chromeos/extensions/media_player_api.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/chromeos/extensions/media_player_event_router.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/media/media_stream_capture_indicator.h"
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/public/browser/render_view_host.h"
19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/public/browser/web_contents.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window_registry.h"
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/browser/extension_system.h"
23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/browser/process_manager.h"
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace {
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void GetMediaCaptureState(
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const MediaStreamCaptureIndicator* indicator,
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::WebContents* web_contents,
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int* media_state_out) {
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (indicator->IsCapturingVideo(web_contents))
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    *media_state_out |= ash::MEDIA_CAPTURE_VIDEO;
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (indicator->IsCapturingAudio(web_contents))
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    *media_state_out |= ash::MEDIA_CAPTURE_AUDIO;
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void GetBrowserMediaCaptureState(
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const MediaStreamCaptureIndicator* indicator,
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const content::BrowserContext* context,
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int* media_state_out) {
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const BrowserList* desktop_list =
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (BrowserList::BrowserVector::const_iterator iter = desktop_list->begin();
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       iter != desktop_list->end();
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++iter) {
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    TabStripModel* tab_strip_model = (*iter)->tab_strip_model();
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    for (int i = 0; i < tab_strip_model->count(); ++i) {
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      content::WebContents* web_contents = tab_strip_model->GetWebContentsAt(i);
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (web_contents->GetBrowserContext() != context)
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        continue;
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      GetMediaCaptureState(indicator, web_contents, media_state_out);
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        return;
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void GetAppMediaCaptureState(
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const MediaStreamCaptureIndicator* indicator,
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* context,
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int* media_state_out) {
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const extensions::AppWindowRegistry::AppWindowList& apps =
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extensions::AppWindowRegistry::Get(context)->app_windows();
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (extensions::AppWindowRegistry::AppWindowList::const_iterator iter =
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           apps.begin();
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       iter != apps.end();
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++iter) {
70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    GetMediaCaptureState(indicator, (*iter)->web_contents(), media_state_out);
71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void GetExtensionMediaCaptureState(
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const MediaStreamCaptureIndicator* indicator,
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* context,
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int* media_state_out) {
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  extensions::ProcessManager* process_manager =
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      extensions::ExtensionSystem::Get(context)->process_manager();
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const extensions::ProcessManager::ViewSet view_set =
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      process_manager->GetAllViews();
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (extensions::ProcessManager::ViewSet::const_iterator iter =
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           view_set.begin();
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       iter != view_set.end();
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++iter) {
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::WebContents* web_contents =
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        content::WebContents::FromRenderViewHost(*iter);
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // RVH may not have web contents.
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!web_contents)
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      continue;
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    GetMediaCaptureState(indicator, web_contents, media_state_out);
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ash::MediaCaptureState GetMediaCaptureStateOfAllWebContents(
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* context) {
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!context)
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return ash::MEDIA_CAPTURE_NONE;
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<MediaStreamCaptureIndicator> indicator =
105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      MediaCaptureDevicesDispatcher::GetInstance()
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          ->GetMediaStreamCaptureIndicator();
107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int media_state = ash::MEDIA_CAPTURE_NONE;
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Browser windows
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  GetBrowserMediaCaptureState(indicator.get(), context, &media_state);
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (media_state == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return ash::MEDIA_CAPTURE_AUDIO_VIDEO;
113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // App windows
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  GetAppMediaCaptureState(indicator.get(), context, &media_state);
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (media_state == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return ash::MEDIA_CAPTURE_AUDIO_VIDEO;
118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Extensions
120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  GetExtensionMediaCaptureState(indicator.get(), context, &media_state);
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return static_cast<ash::MediaCaptureState>(media_state);
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}  // namespace
126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)MediaDelegateChromeOS::MediaDelegateChromeOS() : weak_ptr_factory_(this) {
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this);
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)MediaDelegateChromeOS::~MediaDelegateChromeOS() {
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this);
133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MediaDelegateChromeOS::HandleMediaNextTrack() {
136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->media_player_event_router()
138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->NotifyNextTrack();
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MediaDelegateChromeOS::HandleMediaPlayPause() {
142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->media_player_event_router()
144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->NotifyTogglePlayState();
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MediaDelegateChromeOS::HandleMediaPrevTrack() {
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->media_player_event_router()
150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->NotifyPrevTrack();
151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ash::MediaCaptureState MediaDelegateChromeOS::GetMediaCaptureState(
154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* context) {
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return GetMediaCaptureStateOfAllWebContents(context);
156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MediaDelegateChromeOS::OnRequestUpdate(
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int render_process_id,
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int render_frame_id,
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::MediaStreamType stream_type,
162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const content::MediaRequestState state) {
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::MessageLoopForUI::current()->PostTask(
164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&MediaDelegateChromeOS::NotifyMediaCaptureChange,
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MediaDelegateChromeOS::NotifyMediaCaptureChange() {
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ash::Shell::GetInstance()
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->system_tray_notifier()
172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->NotifyMediaCaptureChanged();
173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
174