summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/ash.gyp18
-rw-r--r--ash/ash_chromeos_strings.grdp11
-rw-r--r--ash/ash_view_ids.h18
-rw-r--r--ash/media_delegate.h16
-rw-r--r--ash/resources/ash_resources.grd3
-rw-r--r--ash/session/session_state_delegate_stub.cc137
-rw-r--r--ash/session/session_state_delegate_stub.h58
-rw-r--r--ash/shell/shell_delegate_impl.cc107
-rw-r--r--ash/system/tray/media_security/media_capture_observer.h23
-rw-r--r--ash/system/tray/media_security/multi_profile_media_tray_item.cc85
-rw-r--r--ash/system/tray/media_security/multi_profile_media_tray_item.h35
-rw-r--r--ash/system/tray/media_security/multi_profile_media_tray_item_unittest.cc58
-rw-r--r--ash/system/tray/system_tray.cc2
-rw-r--r--ash/system/tray/system_tray_notifier.cc15
-rw-r--r--ash/system/tray/system_tray_notifier.h6
-rw-r--r--ash/system/user/user_card_view.cc129
-rw-r--r--ash/system/user/user_view.cc4
-rw-r--r--ash/test/test_shell_delegate.cc36
-rw-r--r--ash/test/test_shell_delegate.h7
-rw-r--r--chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc33
-rw-r--r--chrome/browser/ui/ash/chrome_shell_delegate_views.cc4
-rw-r--r--chrome/browser/ui/ash/media_delegate_chromeos.cc173
-rw-r--r--chrome/browser/ui/ash/media_delegate_chromeos.h39
-rw-r--r--chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc6
-rw-r--r--chrome/chrome_browser_ui.gypi2
25 files changed, 767 insertions, 258 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 8c9cfdf..eedf7a7 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -325,21 +325,21 @@
'system/chromeos/audio/tray_audio_chromeos.h',
'system/chromeos/audio/tray_audio_delegate_chromeos.cc',
'system/chromeos/audio/tray_audio_delegate_chromeos.h',
- 'system/chromeos/enterprise/enterprise_domain_observer.h',
'system/chromeos/bluetooth/bluetooth_notification_controller.cc',
'system/chromeos/bluetooth/bluetooth_notification_controller.h',
'system/chromeos/brightness/brightness_controller_chromeos.cc',
'system/chromeos/brightness/brightness_controller_chromeos.h',
'system/chromeos/brightness/tray_brightness.cc',
'system/chromeos/brightness/tray_brightness.h',
- 'system/chromeos/enterprise/tray_enterprise.h',
+ 'system/chromeos/enterprise/enterprise_domain_observer.h',
'system/chromeos/enterprise/tray_enterprise.cc',
+ 'system/chromeos/enterprise/tray_enterprise.h',
'system/chromeos/keyboard_brightness_controller.cc',
'system/chromeos/keyboard_brightness_controller.h',
- 'system/chromeos/label_tray_view.h',
'system/chromeos/label_tray_view.cc',
- 'system/chromeos/managed/tray_locally_managed_user.h',
+ 'system/chromeos/label_tray_view.h',
'system/chromeos/managed/tray_locally_managed_user.cc',
+ 'system/chromeos/managed/tray_locally_managed_user.h',
'system/chromeos/network/network_connect.cc',
'system/chromeos/network/network_connect.h',
'system/chromeos/network/network_detailed_view.h',
@@ -441,6 +441,9 @@
'system/tray/fixed_sized_scroll_view.h',
'system/tray/hover_highlight_view.cc',
'system/tray/hover_highlight_view.h',
+ 'system/tray/media_security/media_capture_observer.h',
+ 'system/tray/media_security/multi_profile_media_tray_item.cc',
+ 'system/tray/media_security/multi_profile_media_tray_item.h',
'system/tray/special_popup_row.cc',
'system/tray/special_popup_row.h',
'system/tray/system_tray.cc',
@@ -729,6 +732,9 @@
['exclude', 'display/display_configurator_animation.h'],
['exclude', 'display/resolution_notification_controller.cc'],
['exclude', 'display/resolution_notification_controller.h'],
+ ['exclude', 'system/tray/media_security/media_capture_observer.h'],
+ ['exclude', 'system/tray/media_security/multi_profile_media_tray_item.cc'],
+ ['exclude', 'system/tray/media_security/multi_profile_media_tray_item.h'],
],
}],
],
@@ -966,6 +972,7 @@
'system/chromeos/tray_display_unittest.cc',
'system/date/date_view_unittest.cc',
'system/overview/overview_button_tray_unittest.cc',
+ 'system/tray/media_security/multi_profile_media_tray_item_unittest.cc',
'system/tray/system_tray_unittest.cc',
'system/tray/tray_details_view_unittest.cc',
'system/user/tray_user_unittest.cc',
@@ -1031,6 +1038,7 @@
['exclude', 'wm/workspace/workspace_window_resizer_unittest.cc'],
['exclude', 'sticky_keys/sticky_keys_overlay_unittest.cc'],
['exclude', 'sticky_keys/sticky_keys_unittest.cc'],
+ ['exclude', 'system/tray/media_security/multi_profile_media_tray_item_unittest.cc'],
['exclude', 'autoclick/autoclick_unittest.cc'],
],
'sources': [
@@ -1117,8 +1125,6 @@
'sources': [
'../content/app/startup_helper_win.cc',
'../ui/views/test/test_views_delegate.cc',
- 'session/session_state_delegate_stub.cc',
- 'session/session_state_delegate_stub.h',
'shell/app_list.cc',
'shell/bubble.cc',
'shell/content_client/shell_browser_main_parts.cc',
diff --git a/ash/ash_chromeos_strings.grdp b/ash/ash_chromeos_strings.grdp
index b0333ec..15a0fb7 100644
--- a/ash/ash_chromeos_strings.grdp
+++ b/ash/ash_chromeos_strings.grdp
@@ -305,6 +305,17 @@ Server message: <ph name="server_msg">$3<ex>Incorrect password</ex></ph>
Stop
</message>
+ <!-- Status tray media recording state strings. -->
+ <message name="IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO" desc="label used to indicate that the microphone is used by a background user">
+ Micropohne is in use.
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_VIDEO" desc="label used to indicate that the camera is used by a background user">
+ Camera is in use.
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO_VIDEO" desc="label used to indicate that the camera and microphone are used by a background user">
+ Camera and microphone are in use.
+ </message>
+
<!-- Status tray screen share strings. -->
<message name="IDS_ASH_STATUS_TRAY_SCREEN_SHARE_STOP" desc="label used for screen sharing stop button">
Stop
diff --git a/ash/ash_view_ids.h b/ash/ash_view_ids.h
new file mode 100644
index 0000000..61bf3cf
--- /dev/null
+++ b/ash/ash_view_ids.h
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_ASH_VIEW_IDS_H_
+#define ASH_ASH_VIEW_IDS_H_
+
+namespace ash {
+
+enum ViewID {
+ VIEW_ID_NONE = 10000,
+ VIEW_ID_MEDIA_TRAY_VIEW,
+ VIEW_ID_USER_VIEW_MEDIA_INDICATOR,
+};
+
+} // namespace ash
+
+#endif // ASH_ASH_VIEW_IDS_H_
diff --git a/ash/media_delegate.h b/ash/media_delegate.h
index 1dac059..4ea9a17 100644
--- a/ash/media_delegate.h
+++ b/ash/media_delegate.h
@@ -5,8 +5,19 @@
#ifndef ASH_MEDIA_DELEGATE_H_
#define ASH_MEDIA_DELEGATE_H_
+namespace content {
+class BrowserContext;
+}
+
namespace ash {
+enum MediaCaptureState {
+ MEDIA_CAPTURE_NONE = 0,
+ MEDIA_CAPTURE_AUDIO = 1 << 0,
+ MEDIA_CAPTURE_VIDEO = 1 << 1,
+ MEDIA_CAPTURE_AUDIO_VIDEO = MEDIA_CAPTURE_AUDIO | MEDIA_CAPTURE_VIDEO,
+};
+
// A delegate class to control media playback.
class MediaDelegate {
public:
@@ -20,6 +31,11 @@ class MediaDelegate {
// Handles the Previous Track Media shortcut key.
virtual void HandleMediaPrevTrack() = 0;
+
+ // Returns the current media recording state of web contents
+ // that belongs to the |context|.
+ virtual MediaCaptureState GetMediaCaptureState(
+ content::BrowserContext* context) = 0;
};
} // namespace ash
diff --git a/ash/resources/ash_resources.grd b/ash/resources/ash_resources.grd
index 1201745..aabbc18 100644
--- a/ash/resources/ash_resources.grd
+++ b/ash/resources/ash_resources.grd
@@ -77,6 +77,7 @@
<structure type="chrome_scaled_image" name="IDR_AURA_WARNING_ICON" file="common/alert_small.png" />
+ <!-- TODO(oshima): Make following resources cros only -->
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_ACCESSIBILITY" file="cros/status/status_accessibility_mode.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_ACCESSIBILITY_DARK" file="cros/status/status_accessibility_dark.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_BLUETOOTH" file="cros/status/status_bluetooth.png" />
@@ -187,6 +188,8 @@
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_VPN" file="cros/network/statusbar_vpn_dark.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_VPN_BADGE" file="cros/network/statusbar_network_vpn_badge.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_WIRED" file="cros/network/statusbar_wired.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_RECORDING" file="cros/status/status_recording.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_RECORDING_RED" file="cros/status/status_recording_red.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_VIRTUAL_KEYBOARD" file="cros/status/status_virtual_keyboard.png" />
</if>
diff --git a/ash/session/session_state_delegate_stub.cc b/ash/session/session_state_delegate_stub.cc
deleted file mode 100644
index 05bca13..0000000
--- a/ash/session/session_state_delegate_stub.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/session/session_state_delegate_stub.h"
-
-#include "ash/session/user_info.h"
-#include "ash/shell.h"
-#include "ash/shell/example_factory.h"
-#include "ash/shell_delegate.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "ui/gfx/image/image_skia.h"
-
-namespace ash {
-namespace {
-
-class UserInfoStub : public UserInfo {
- public:
- UserInfoStub() {}
- virtual ~UserInfoStub() {}
-
- // UserInfo:
- virtual base::string16 GetDisplayName() const OVERRIDE {
- return base::UTF8ToUTF16("stub-user");
- }
- virtual base::string16 GetGivenName() const OVERRIDE {
- return base::UTF8ToUTF16("Stub");
- }
- virtual std::string GetEmail() const OVERRIDE {
- return "stub-user@domain.com";
- }
- virtual std::string GetUserID() const OVERRIDE { return GetEmail(); }
- virtual const gfx::ImageSkia& GetImage() const OVERRIDE {
- return user_image_;
- }
-
- private:
- gfx::ImageSkia user_image_;
-
- DISALLOW_COPY_AND_ASSIGN(UserInfoStub);
-};
-
-} // namespace
-
-SessionStateDelegateStub::SessionStateDelegateStub()
- : screen_locked_(false), user_info_(new UserInfoStub()) {
-}
-
-SessionStateDelegateStub::~SessionStateDelegateStub() {
-}
-
-content::BrowserContext* SessionStateDelegateStub::GetBrowserContextByIndex(
- MultiProfileIndex index) {
- return Shell::GetInstance()->delegate()->GetActiveBrowserContext();
-}
-
-content::BrowserContext* SessionStateDelegateStub::GetBrowserContextForWindow(
- aura::Window* window) {
- return Shell::GetInstance()->delegate()->GetActiveBrowserContext();
-}
-
-int SessionStateDelegateStub::GetMaximumNumberOfLoggedInUsers() const {
- return 3;
-}
-
-int SessionStateDelegateStub::NumberOfLoggedInUsers() const {
- return 1;
-}
-
-bool SessionStateDelegateStub::IsActiveUserSessionStarted() const {
- return true;
-}
-
-bool SessionStateDelegateStub::CanLockScreen() const {
- return true;
-}
-
-bool SessionStateDelegateStub::IsScreenLocked() const {
- return screen_locked_;
-}
-
-bool SessionStateDelegateStub::ShouldLockScreenBeforeSuspending() const {
- return false;
-}
-
-void SessionStateDelegateStub::LockScreen() {
- shell::CreateLockScreen();
- screen_locked_ = true;
- Shell::GetInstance()->UpdateShelfVisibility();
-}
-
-void SessionStateDelegateStub::UnlockScreen() {
- screen_locked_ = false;
- Shell::GetInstance()->UpdateShelfVisibility();
-}
-
-bool SessionStateDelegateStub::IsUserSessionBlocked() const {
- return !IsActiveUserSessionStarted() || IsScreenLocked();
-}
-
-SessionStateDelegate::SessionState SessionStateDelegateStub::GetSessionState()
- const {
- // Assume that if session is not active we're at login.
- return IsActiveUserSessionStarted() ? SESSION_STATE_ACTIVE
- : SESSION_STATE_LOGIN_PRIMARY;
-}
-
-const UserInfo* SessionStateDelegateStub::GetUserInfo(
- MultiProfileIndex index) const {
- return user_info_.get();
-}
-
-const UserInfo* SessionStateDelegateStub::GetUserInfo(
- content::BrowserContext* context) const {
- return user_info_.get();
-}
-
-bool SessionStateDelegateStub::ShouldShowAvatar(aura::Window* window) const {
- return !user_info_->GetImage().isNull();
-}
-
-void SessionStateDelegateStub::SwitchActiveUser(const std::string& user_id) {
-}
-
-void SessionStateDelegateStub::CycleActiveUser(CycleUser cycle_user) {
-}
-
-void SessionStateDelegateStub::AddSessionStateObserver(
- ash::SessionStateObserver* observer) {
-}
-
-void SessionStateDelegateStub::RemoveSessionStateObserver(
- ash::SessionStateObserver* observer) {
-}
-
-} // namespace ash
diff --git a/ash/session/session_state_delegate_stub.h b/ash/session/session_state_delegate_stub.h
deleted file mode 100644
index 5ce9cf3..0000000
--- a/ash/session/session_state_delegate_stub.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SESSION_SESSION_STATE_DELEGATE_STUB_H_
-#define ASH_SESSION_SESSION_STATE_DELEGATE_STUB_H_
-
-#include "ash/session/session_state_delegate.h"
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-
-namespace ash {
-
-// Stub implementation of SessionStateDelegate for testing.
-class SessionStateDelegateStub : public SessionStateDelegate {
- public:
- SessionStateDelegateStub();
- virtual ~SessionStateDelegateStub();
-
- // SessionStateDelegate:
- virtual content::BrowserContext* GetBrowserContextByIndex(
- MultiProfileIndex index) OVERRIDE;
- virtual content::BrowserContext* GetBrowserContextForWindow(
- aura::Window* window) OVERRIDE;
- virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE;
- virtual int NumberOfLoggedInUsers() const OVERRIDE;
- virtual bool IsActiveUserSessionStarted() const OVERRIDE;
- virtual bool CanLockScreen() const OVERRIDE;
- virtual bool IsScreenLocked() const OVERRIDE;
- virtual bool ShouldLockScreenBeforeSuspending() const OVERRIDE;
- virtual void LockScreen() OVERRIDE;
- virtual void UnlockScreen() OVERRIDE;
- virtual bool IsUserSessionBlocked() const OVERRIDE;
- virtual SessionState GetSessionState() const OVERRIDE;
- virtual const UserInfo* GetUserInfo(MultiProfileIndex index) const OVERRIDE;
- virtual const UserInfo* GetUserInfo(
- content::BrowserContext* context) const OVERRIDE;
- virtual bool ShouldShowAvatar(aura::Window* window) const OVERRIDE;
- virtual void SwitchActiveUser(const std::string& user_id) OVERRIDE;
- virtual void CycleActiveUser(CycleUser cycle_user) OVERRIDE;
- virtual void AddSessionStateObserver(
- ash::SessionStateObserver* observer) OVERRIDE;
- virtual void RemoveSessionStateObserver(
- ash::SessionStateObserver* observer) OVERRIDE;
-
- private:
- bool screen_locked_;
-
- // A pseudo user info.
- scoped_ptr<UserInfo> user_info_;
-
- DISALLOW_COPY_AND_ASSIGN(SessionStateDelegateStub);
-};
-
-} // namespace ash
-
-#endif // ASH_SESSION_SESSION_STATE_DELEGATE_STUB_H_
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc
index 2bf14e8..289d769 100644
--- a/ash/shell/shell_delegate_impl.cc
+++ b/ash/shell/shell_delegate_impl.cc
@@ -11,7 +11,7 @@
#include "ash/media_delegate.h"
#include "ash/new_window_delegate.h"
#include "ash/session/session_state_delegate.h"
-#include "ash/session/session_state_delegate_stub.h"
+#include "ash/session/user_info.h"
#include "ash/shell/context_menu.h"
#include "ash/shell/example_factory.h"
#include "ash/shell/keyboard_controller_proxy_stub.h"
@@ -21,6 +21,7 @@
#include "ash/system/tray/default_system_tray_delegate.h"
#include "ash/wm/window_state.h"
#include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
#include "ui/aura/window.h"
#include "ui/wm/core/input_method_event_filter.h"
@@ -33,6 +34,7 @@ class NewWindowDelegateImpl : public NewWindowDelegate {
NewWindowDelegateImpl() {}
virtual ~NewWindowDelegateImpl() {}
+ // NewWindowDelegate:
virtual void NewTab() OVERRIDE {}
virtual void NewWindow(bool incognito) OVERRIDE {
ash::shell::ToplevelWindow::CreateParams create_params;
@@ -56,14 +58,115 @@ class MediaDelegateImpl : public MediaDelegate {
MediaDelegateImpl() {}
virtual ~MediaDelegateImpl() {}
+ // MediaDelegate:
virtual void HandleMediaNextTrack() OVERRIDE {}
virtual void HandleMediaPlayPause() OVERRIDE {}
virtual void HandleMediaPrevTrack() OVERRIDE {}
+ virtual MediaCaptureState GetMediaCaptureState(
+ content::BrowserContext* context) OVERRIDE {
+ return MEDIA_CAPTURE_VIDEO;
+ }
private:
DISALLOW_COPY_AND_ASSIGN(MediaDelegateImpl);
};
+class UserInfoImpl : public UserInfo {
+ public:
+ UserInfoImpl() {}
+ virtual ~UserInfoImpl() {}
+
+ // UserInfo:
+ virtual base::string16 GetDisplayName() const OVERRIDE {
+ return base::UTF8ToUTF16("stub-user");
+ }
+ virtual base::string16 GetGivenName() const OVERRIDE {
+ return base::UTF8ToUTF16("Stub");
+ }
+ virtual std::string GetEmail() const OVERRIDE {
+ return "stub-user@domain.com";
+ }
+ virtual std::string GetUserID() const OVERRIDE { return GetEmail(); }
+ virtual const gfx::ImageSkia& GetImage() const OVERRIDE {
+ return user_image_;
+ }
+
+ private:
+ gfx::ImageSkia user_image_;
+
+ DISALLOW_COPY_AND_ASSIGN(UserInfoImpl);
+};
+
+class SessionStateDelegateImpl : public SessionStateDelegate {
+ public:
+ SessionStateDelegateImpl()
+ : screen_locked_(false), user_info_(new UserInfoImpl()) {}
+
+ virtual ~SessionStateDelegateImpl() {}
+
+ // SessionStateDelegate:
+ virtual content::BrowserContext* GetBrowserContextByIndex(
+ MultiProfileIndex index) OVERRIDE {
+ return Shell::GetInstance()->delegate()->GetActiveBrowserContext();
+ }
+ virtual content::BrowserContext* GetBrowserContextForWindow(
+ aura::Window* window) OVERRIDE {
+ return Shell::GetInstance()->delegate()->GetActiveBrowserContext();
+ }
+ virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE { return 3; }
+ virtual int NumberOfLoggedInUsers() const OVERRIDE {
+ // ash_shell has 2 users.
+ return 2;
+ }
+ virtual bool IsActiveUserSessionStarted() const OVERRIDE { return true; }
+ virtual bool CanLockScreen() const OVERRIDE { return true; }
+ virtual bool IsScreenLocked() const OVERRIDE { return screen_locked_; }
+ virtual bool ShouldLockScreenBeforeSuspending() const OVERRIDE {
+ return false;
+ }
+ virtual void LockScreen() OVERRIDE {
+ shell::CreateLockScreen();
+ screen_locked_ = true;
+ Shell::GetInstance()->UpdateShelfVisibility();
+ }
+ virtual void UnlockScreen() OVERRIDE {
+ screen_locked_ = false;
+ Shell::GetInstance()->UpdateShelfVisibility();
+ }
+ virtual bool IsUserSessionBlocked() const OVERRIDE {
+ return !IsActiveUserSessionStarted() || IsScreenLocked();
+ }
+ virtual SessionState GetSessionState() const OVERRIDE {
+ // Assume that if session is not active we're at login.
+ return IsActiveUserSessionStarted() ? SESSION_STATE_ACTIVE
+ : SESSION_STATE_LOGIN_PRIMARY;
+ }
+ virtual const UserInfo* GetUserInfo(MultiProfileIndex index) const OVERRIDE {
+ return user_info_.get();
+ }
+ virtual const UserInfo* GetUserInfo(
+ content::BrowserContext* context) const OVERRIDE {
+ return user_info_.get();
+ }
+ virtual bool ShouldShowAvatar(aura::Window* window) const OVERRIDE {
+ return !user_info_->GetImage().isNull();
+ }
+ virtual void SwitchActiveUser(const std::string& user_id) OVERRIDE {}
+ virtual void CycleActiveUser(CycleUser cycle_user) OVERRIDE {}
+ virtual void AddSessionStateObserver(
+ ash::SessionStateObserver* observer) OVERRIDE {}
+ virtual void RemoveSessionStateObserver(
+ ash::SessionStateObserver* observer) OVERRIDE {}
+
+ private:
+ bool screen_locked_;
+
+ // A pseudo user info.
+ scoped_ptr<UserInfo> user_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(SessionStateDelegateImpl);
+};
+
} // namespace
ShellDelegateImpl::ShellDelegateImpl()
@@ -149,7 +252,7 @@ ash::UserWallpaperDelegate* ShellDelegateImpl::CreateUserWallpaperDelegate() {
}
ash::SessionStateDelegate* ShellDelegateImpl::CreateSessionStateDelegate() {
- return new SessionStateDelegateStub;
+ return new SessionStateDelegateImpl;
}
ash::AccessibilityDelegate* ShellDelegateImpl::CreateAccessibilityDelegate() {
diff --git a/ash/system/tray/media_security/media_capture_observer.h b/ash/system/tray/media_security/media_capture_observer.h
new file mode 100644
index 0000000..9a217b2
--- /dev/null
+++ b/ash/system/tray/media_security/media_capture_observer.h
@@ -0,0 +1,23 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MEDIA_CAPTURE_OBSERVER_H_
+#define ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MEDIA_CAPTURE_OBSERVER_H_
+
+#include "ash/ash_export.h"
+
+namespace ash {
+
+class ASH_EXPORT MediaCaptureObserver {
+ public:
+ // Called when media capture state has changed.
+ virtual void OnMediaCaptureChanged() = 0;
+
+ protected:
+ virtual ~MediaCaptureObserver() {}
+};
+
+} // namespace ash
+
+#endif // ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MEDIA_CAPTURE_OBSERVER_H_
diff --git a/ash/system/tray/media_security/multi_profile_media_tray_item.cc b/ash/system/tray/media_security/multi_profile_media_tray_item.cc
new file mode 100644
index 0000000..7826fb7
--- /dev/null
+++ b/ash/system/tray/media_security/multi_profile_media_tray_item.cc
@@ -0,0 +1,85 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/system/tray/media_security/multi_profile_media_tray_item.h"
+
+#include "ash/ash_view_ids.h"
+#include "ash/media_delegate.h"
+#include "ash/session/session_state_delegate.h"
+#include "ash/shell.h"
+#include "ash/system/tray/media_security/media_capture_observer.h"
+#include "ash/system/tray/system_tray_notifier.h"
+#include "ash/system/tray/tray_item_view.h"
+#include "grit/ash_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/layout/fill_layout.h"
+
+namespace ash {
+namespace tray {
+
+class MultiProfileMediaTrayView : public TrayItemView,
+ public MediaCaptureObserver {
+ public:
+ explicit MultiProfileMediaTrayView(SystemTrayItem* system_tray_item)
+ : TrayItemView(system_tray_item) {
+ SetLayoutManager(new views::FillLayout);
+ views::ImageView* icon = new views::ImageView;
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ icon->SetImage(
+ bundle.GetImageNamed(IDR_AURA_UBER_TRAY_RECORDING).ToImageSkia());
+ AddChildView(icon);
+ OnMediaCaptureChanged();
+ Shell::GetInstance()->system_tray_notifier()->AddMediaCaptureObserver(this);
+ set_id(VIEW_ID_MEDIA_TRAY_VIEW);
+ }
+
+ virtual ~MultiProfileMediaTrayView() {
+ Shell::GetInstance()->system_tray_notifier()->RemoveMediaCaptureObserver(
+ this);
+ }
+
+ // MediaCaptureObserver:
+ virtual void OnMediaCaptureChanged() OVERRIDE {
+ MediaDelegate* media_delegate = Shell::GetInstance()->media_delegate();
+ SessionStateDelegate* session_state_delegate =
+ Shell::GetInstance()->session_state_delegate();
+ // The user at 0 is the current desktop user.
+ for (MultiProfileIndex index = 1;
+ index < session_state_delegate->NumberOfLoggedInUsers();
+ ++index) {
+ content::BrowserContext* context =
+ session_state_delegate->GetBrowserContextByIndex(index);
+ if (media_delegate->GetMediaCaptureState(context) != MEDIA_CAPTURE_NONE) {
+ SetVisible(true);
+ return;
+ }
+ }
+ SetVisible(false);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MultiProfileMediaTrayView);
+};
+
+} // namespace tray
+
+MultiProfileMediaTrayItem::MultiProfileMediaTrayItem(SystemTray* system_tray)
+ : SystemTrayItem(system_tray), tray_view_(NULL) {
+}
+
+MultiProfileMediaTrayItem::~MultiProfileMediaTrayItem() {
+}
+
+views::View* MultiProfileMediaTrayItem::CreateTrayView(
+ user::LoginStatus status) {
+ tray_view_ = new tray::MultiProfileMediaTrayView(this);
+ return tray_view_;
+}
+
+void MultiProfileMediaTrayItem::DestroyTrayView() {
+ tray_view_ = NULL;
+}
+
+} // namespace ash
diff --git a/ash/system/tray/media_security/multi_profile_media_tray_item.h b/ash/system/tray/media_security/multi_profile_media_tray_item.h
new file mode 100644
index 0000000..038bf8d
--- /dev/null
+++ b/ash/system/tray/media_security/multi_profile_media_tray_item.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_SYSTEM_CHROMEOS_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
+#define ASH_SYSTEM_CHROMEOS_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
+
+#include "ash/system/tray/system_tray_item.h"
+#include "ui/message_center/notification_delegate.h"
+#include "ui/views/view.h"
+
+namespace ash {
+namespace tray {
+class MultiProfileMediaTrayView;
+}
+
+// The tray item for media recording.
+class ASH_EXPORT MultiProfileMediaTrayItem : public SystemTrayItem {
+ public:
+ explicit MultiProfileMediaTrayItem(SystemTray* system_tray);
+ virtual ~MultiProfileMediaTrayItem();
+
+ // SystemTrayItem:
+ virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE;
+ virtual void DestroyTrayView() OVERRIDE;
+
+ private:
+ tray::MultiProfileMediaTrayView* tray_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(MultiProfileMediaTrayItem);
+};
+
+} // namespace ash
+
+#endif // ASH_SYSTEM_CHROMEOS_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
diff --git a/ash/system/tray/media_security/multi_profile_media_tray_item_unittest.cc b/ash/system/tray/media_security/multi_profile_media_tray_item_unittest.cc
new file mode 100644
index 0000000..1dcfeaa
--- /dev/null
+++ b/ash/system/tray/media_security/multi_profile_media_tray_item_unittest.cc
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/system/tray/media_security/multi_profile_media_tray_item.h"
+
+#include "ash/ash_view_ids.h"
+#include "ash/shell.h"
+#include "ash/system/status_area_widget.h"
+#include "ash/system/tray/system_tray.h"
+#include "ash/system/tray/system_tray_bubble.h"
+#include "ash/system/tray/tray_item_view.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/test/test_session_state_delegate.h"
+#include "ash/test/test_shell_delegate.h"
+#include "ui/views/bubble/tray_bubble_view.h"
+
+namespace ash {
+
+typedef test::AshTestBase MultiProfileMediaTrayItemTest;
+
+TEST_F(MultiProfileMediaTrayItemTest, NotifyMediaCaptureChange) {
+ TrayItemView::DisableAnimationsForTest();
+ test::TestShellDelegate* shell_delegate =
+ static_cast<test::TestShellDelegate*>(Shell::GetInstance()->delegate());
+ test::TestSessionStateDelegate* session_state_delegate =
+ static_cast<test::TestSessionStateDelegate*>(
+ Shell::GetInstance()->session_state_delegate());
+ session_state_delegate->set_logged_in_users(2);
+
+ SystemTray* system_tray = Shell::GetInstance()->GetPrimarySystemTray();
+ system_tray->ShowDefaultView(BUBBLE_CREATE_NEW);
+ views::View* in_user_view =
+ system_tray->GetSystemBubble()->bubble_view()->GetViewByID(
+ VIEW_ID_USER_VIEW_MEDIA_INDICATOR);
+
+ StatusAreaWidget* widget = system_tray->status_area_widget();
+ EXPECT_TRUE(widget->GetRootView()->visible());
+ views::View* tray_view =
+ widget->GetRootView()->GetViewByID(VIEW_ID_MEDIA_TRAY_VIEW);
+
+ EXPECT_FALSE(tray_view->visible());
+ EXPECT_FALSE(in_user_view->visible());
+
+ shell_delegate->SetMediaCaptureState(MEDIA_CAPTURE_AUDIO);
+ EXPECT_TRUE(tray_view->visible());
+ EXPECT_TRUE(in_user_view->visible());
+
+ shell_delegate->SetMediaCaptureState(MEDIA_CAPTURE_AUDIO_VIDEO);
+ EXPECT_TRUE(tray_view->visible());
+ EXPECT_TRUE(in_user_view->visible());
+
+ shell_delegate->SetMediaCaptureState(MEDIA_CAPTURE_NONE);
+ EXPECT_FALSE(tray_view->visible());
+ EXPECT_FALSE(in_user_view->visible());
+}
+
+} // namespace ash
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
index 726bbf3..d8ac9a5 100644
--- a/ash/system/tray/system_tray.cc
+++ b/ash/system/tray/system_tray.cc
@@ -61,6 +61,7 @@
#include "ash/system/chromeos/tray_caps_lock.h"
#include "ash/system/chromeos/tray_display.h"
#include "ash/system/chromeos/tray_tracing.h"
+#include "ash/system/tray/media_security/multi_profile_media_tray_item.h"
#include "ui/message_center/message_center.h"
#elif defined(OS_WIN)
#include "ash/system/win/audio/tray_audio_win.h"
@@ -188,6 +189,7 @@ void SystemTray::CreateItems(SystemTrayDelegate* delegate) {
AddTrayItem(new TrayDisplay(this));
AddTrayItem(new ScreenCaptureTrayItem(this));
AddTrayItem(new ScreenShareTrayItem(this));
+ AddTrayItem(new MultiProfileMediaTrayItem(this));
AddTrayItem(new TrayAudioChromeOs(this));
AddTrayItem(new TrayBrightness(this));
AddTrayItem(new TrayCapsLock(this));
diff --git a/ash/system/tray/system_tray_notifier.cc b/ash/system/tray/system_tray_notifier.cc
index ed858c3..5801ce6 100644
--- a/ash/system/tray/system_tray_notifier.cc
+++ b/ash/system/tray/system_tray_notifier.cc
@@ -151,6 +151,16 @@ void SystemTrayNotifier::RemoveEnterpriseDomainObserver(
enterprise_domain_observers_.RemoveObserver(observer);
}
+void SystemTrayNotifier::AddMediaCaptureObserver(
+ MediaCaptureObserver* observer) {
+ media_capture_observers_.AddObserver(observer);
+}
+
+void SystemTrayNotifier::RemoveMediaCaptureObserver(
+ MediaCaptureObserver* observer) {
+ media_capture_observers_.RemoveObserver(observer);
+}
+
void SystemTrayNotifier::AddScreenCaptureObserver(
ScreenCaptureObserver* observer) {
screen_capture_observers_.AddObserver(observer);
@@ -354,6 +364,11 @@ void SystemTrayNotifier::NotifyEnterpriseDomainChanged() {
OnEnterpriseDomainChanged());
}
+void SystemTrayNotifier::NotifyMediaCaptureChanged() {
+ FOR_EACH_OBSERVER(
+ MediaCaptureObserver, media_capture_observers_, OnMediaCaptureChanged());
+}
+
void SystemTrayNotifier::NotifyScreenCaptureStart(
const base::Closure& stop_callback,
const base::string16& sharing_app_name) {
diff --git a/ash/system/tray/system_tray_notifier.h b/ash/system/tray/system_tray_notifier.h
index 29cd9d2..6e6b03f 100644
--- a/ash/system/tray/system_tray_notifier.h
+++ b/ash/system/tray/system_tray_notifier.h
@@ -30,6 +30,7 @@
#include "ash/system/chromeos/session/last_window_closed_observer.h"
#include "ash/system/chromeos/session/logout_button_observer.h"
#include "ash/system/chromeos/session/session_length_limit_observer.h"
+#include "ash/system/tray/media_security/media_capture_observer.h"
#include "base/time/time.h"
#endif
@@ -92,6 +93,9 @@ class ASH_EXPORT SystemTrayNotifier {
void AddEnterpriseDomainObserver(EnterpriseDomainObserver* observer);
void RemoveEnterpriseDomainObserver(EnterpriseDomainObserver* observer);
+ void AddMediaCaptureObserver(MediaCaptureObserver* observer);
+ void RemoveMediaCaptureObserver(MediaCaptureObserver* observer);
+
void AddScreenCaptureObserver(ScreenCaptureObserver* observer);
void RemoveScreenCaptureObserver(ScreenCaptureObserver* observer);
@@ -133,6 +137,7 @@ class ASH_EXPORT SystemTrayNotifier {
void NotifyRequestToggleWifi();
void NotifyOnCaptivePortalDetected(const std::string& service_path);
void NotifyEnterpriseDomainChanged();
+ void NotifyMediaCaptureChanged();
void NotifyScreenCaptureStart(const base::Closure& stop_callback,
const base::string16& sharing_app_name);
void NotifyScreenCaptureStop();
@@ -164,6 +169,7 @@ class ASH_EXPORT SystemTrayNotifier {
ObserverList<NetworkPortalDetectorObserver>
network_portal_detector_observers_;
ObserverList<EnterpriseDomainObserver> enterprise_domain_observers_;
+ ObserverList<MediaCaptureObserver> media_capture_observers_;
ObserverList<ScreenCaptureObserver> screen_capture_observers_;
ObserverList<ScreenShareObserver> screen_share_observers_;
ObserverList<LastWindowClosedObserver> last_window_closed_observers_;
diff --git a/ash/system/user/user_card_view.cc b/ash/system/user/user_card_view.cc
index af568ae..c1bdd15 100644
--- a/ash/system/user/user_card_view.cc
+++ b/ash/system/user/user_card_view.cc
@@ -11,6 +11,7 @@
#include "ash/session/user_info.h"
#include "ash/shell.h"
#include "ash/system/tray/system_tray_delegate.h"
+#include "ash/system/tray/system_tray_notifier.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/user/config.h"
#include "ash/system/user/rounded_image_view.h"
@@ -35,6 +36,14 @@
#include "ui/views/controls/link_listener.h"
#include "ui/views/layout/box_layout.h"
+#if defined(OS_CHROMEOS)
+#include "ash/ash_view_ids.h"
+#include "ash/media_delegate.h"
+#include "ash/system/tray/media_security/media_capture_observer.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/layout/fill_layout.h"
+#endif
+
namespace ash {
namespace tray {
@@ -46,6 +55,70 @@ const int kUserDetailsVerticalPadding = 5;
// and end of the user's display name in the public account user card's text.
const base::char16 kDisplayNameMark[] = {0x2060, 0};
+#if defined(OS_CHROMEOS)
+class MediaIndicator : public views::View, public MediaCaptureObserver {
+ public:
+ explicit MediaIndicator(MultiProfileIndex index)
+ : index_(index), label_(new views::Label) {
+ SetLayoutManager(new views::FillLayout);
+ views::ImageView* icon = new views::ImageView;
+ icon->SetImage(ui::ResourceBundle::GetSharedInstance()
+ .GetImageNamed(IDR_AURA_UBER_TRAY_RECORDING_RED)
+ .ToImageSkia());
+ AddChildView(icon);
+ label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ label_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
+ ui::ResourceBundle::SmallFont));
+ OnMediaCaptureChanged();
+ Shell::GetInstance()->system_tray_notifier()->AddMediaCaptureObserver(this);
+ set_id(VIEW_ID_USER_VIEW_MEDIA_INDICATOR);
+ }
+
+ virtual ~MediaIndicator() {
+ Shell::GetInstance()->system_tray_notifier()->RemoveMediaCaptureObserver(
+ this);
+ }
+
+ // MediaCaptureObserver:
+ virtual void OnMediaCaptureChanged() OVERRIDE {
+ Shell* shell = Shell::GetInstance();
+ content::BrowserContext* context =
+ shell->session_state_delegate()->GetBrowserContextByIndex(index_);
+ MediaCaptureState state =
+ Shell::GetInstance()->media_delegate()->GetMediaCaptureState(context);
+ int res_id = 0;
+ switch (state) {
+ case MEDIA_CAPTURE_AUDIO_VIDEO:
+ res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO_VIDEO;
+ break;
+ case MEDIA_CAPTURE_AUDIO:
+ res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_AUDIO;
+ break;
+ case MEDIA_CAPTURE_VIDEO:
+ res_id = IDS_ASH_STATUS_TRAY_MEDIA_RECORDING_VIDEO;
+ break;
+ case MEDIA_CAPTURE_NONE:
+ break;
+ }
+ SetMessage(res_id ? l10n_util::GetStringUTF16(res_id) : base::string16());
+ }
+
+ views::View* GetMessageView() { return label_; }
+
+ void SetMessage(const base::string16& message) {
+ SetVisible(!message.empty());
+ label_->SetText(message);
+ label_->SetVisible(!message.empty());
+ }
+
+ private:
+ MultiProfileIndex index_;
+ views::Label* label_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaIndicator);
+};
+#endif
+
// The user details shown in public account mode. This is essentially a label
// but with custom painting code as the text is styled with multiple colors and
// contains a link.
@@ -301,7 +374,7 @@ void UserCardView::AddUserContent(user::LoginStatus login_status,
int multiprofile_index) {
views::View* icon = CreateIcon(login_status, multiprofile_index);
AddChildView(icon);
- views::Label* username = NULL;
+ views::Label* user_name = NULL;
SessionStateDelegate* delegate =
Shell::GetInstance()->session_state_delegate();
if (!multiprofile_index) {
@@ -313,12 +386,12 @@ void UserCardView::AddUserContent(user::LoginStatus login_status,
user_name_string = base::ASCIIToUTF16(
delegate->GetUserInfo(multiprofile_index)->GetEmail());
if (!user_name_string.empty()) {
- username = new views::Label(user_name_string);
- username->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ user_name = new views::Label(user_name_string);
+ user_name->SetHorizontalAlignment(gfx::ALIGN_LEFT);
}
}
- views::Label* additional = NULL;
+ views::Label* user_email = NULL;
if (login_status != user::LOGGED_IN_GUEST &&
(multiprofile_index || !IsMultiAccountSupportedAndUserActive())) {
base::string16 user_email_string =
@@ -328,37 +401,55 @@ void UserCardView::AddUserContent(user::LoginStatus login_status,
: base::UTF8ToUTF16(
delegate->GetUserInfo(multiprofile_index)->GetEmail());
if (!user_email_string.empty()) {
- additional = new views::Label(user_email_string);
- additional->SetFontList(
+ user_email = new views::Label(user_email_string);
+ user_email->SetFontList(
ui::ResourceBundle::GetSharedInstance().GetFontList(
ui::ResourceBundle::SmallFont));
- additional->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ user_email->SetHorizontalAlignment(gfx::ALIGN_LEFT);
}
}
// Adjust text properties dependent on if it is an active or inactive user.
if (multiprofile_index) {
// Fade the text of non active users to 50%.
- SkColor text_color = additional->enabled_color();
+ SkColor text_color = user_email->enabled_color();
text_color = SkColorSetA(text_color, SkColorGetA(text_color) / 2);
- if (additional)
- additional->SetDisabledColor(text_color);
- if (username)
- username->SetDisabledColor(text_color);
+ if (user_email)
+ user_email->SetDisabledColor(text_color);
+ if (user_name)
+ user_name->SetDisabledColor(text_color);
}
- if (additional && username) {
+ if (user_email && user_name) {
views::View* details = new views::View;
details->SetLayoutManager(new views::BoxLayout(
views::BoxLayout::kVertical, 0, kUserDetailsVerticalPadding, 0));
- details->AddChildView(username);
- details->AddChildView(additional);
+ details->AddChildView(user_name);
+ details->AddChildView(user_email);
AddChildView(details);
} else {
- if (username)
- AddChildView(username);
- if (additional)
- AddChildView(additional);
+ if (user_name)
+ AddChildView(user_name);
+ if (user_email) {
+#if defined(OS_CHROMEOS)
+ // Only non active user can have a media indicator.
+ MediaIndicator* media_indicator = new MediaIndicator(multiprofile_index);
+ views::View* email_indicator_view = new views::View;
+ email_indicator_view->SetLayoutManager(new views::BoxLayout(
+ views::BoxLayout::kHorizontal, 0, 0, kTrayPopupPaddingBetweenItems));
+ email_indicator_view->AddChildView(user_email);
+ email_indicator_view->AddChildView(media_indicator);
+
+ views::View* details = new views::View;
+ details->SetLayoutManager(new views::BoxLayout(
+ views::BoxLayout::kVertical, 0, kUserDetailsVerticalPadding, 0));
+ details->AddChildView(email_indicator_view);
+ details->AddChildView(media_indicator->GetMessageView());
+ AddChildView(details);
+#else
+ AddChildView(user_email);
+#endif
+ }
}
}
diff --git a/ash/system/user/user_view.cc b/ash/system/user/user_view.cc
index f5eb6833..6707686 100644
--- a/ash/system/user/user_view.cc
+++ b/ash/system/user/user_view.cc
@@ -283,8 +283,8 @@ void UserView::Layout() {
int remaining_width = contents_area.width() - logout_area.width();
if (IsMultiProfileSupportedAndUserActive() ||
IsMultiAccountSupportedAndUserActive()) {
- // In multiprofile case |user_card_view_| and |logout_button_| have to
- // have the same height.
+ // In multiprofile/multiaccount case |user_card_view_| and
+ // |logout_button_| have to have the same height.
int y = std::min(user_card_area.y(), logout_area.y());
int height = std::max(user_card_area.height(), logout_area.height());
logout_area.set_y(y);
diff --git a/ash/test/test_shell_delegate.cc b/ash/test/test_shell_delegate.cc
index 52962ee..2a6597d 100644
--- a/ash/test/test_shell_delegate.cc
+++ b/ash/test/test_shell_delegate.cc
@@ -27,11 +27,21 @@
#include "ui/app_list/test/app_list_test_view_delegate.h"
#include "ui/aura/window.h"
+#if defined(OS_CHROMEOS)
+#include "ash/system/tray/system_tray_notifier.h"
+#endif
+
namespace ash {
namespace test {
namespace {
class NewWindowDelegateImpl : public NewWindowDelegate {
+ public:
+ NewWindowDelegateImpl() {}
+ virtual ~NewWindowDelegateImpl() {}
+
+ private:
+ // NewWindowDelegate:
virtual void NewTab() OVERRIDE {}
virtual void NewWindow(bool incognito) OVERRIDE {}
virtual void OpenFileManager() OVERRIDE {}
@@ -40,13 +50,30 @@ class NewWindowDelegateImpl : public NewWindowDelegate {
virtual void ShowKeyboardOverlay() OVERRIDE {}
virtual void ShowTaskManager() OVERRIDE {}
virtual void OpenFeedbackPage() OVERRIDE {}
+
+ DISALLOW_COPY_AND_ASSIGN(NewWindowDelegateImpl);
};
class MediaDelegateImpl : public MediaDelegate {
public:
+ MediaDelegateImpl() : state_(MEDIA_CAPTURE_NONE) {}
+ virtual ~MediaDelegateImpl() {}
+
+ void set_media_capture_state(MediaCaptureState state) { state_ = state; }
+
+ private:
+ // MediaDelegate:
virtual void HandleMediaNextTrack() OVERRIDE {}
virtual void HandleMediaPlayPause() OVERRIDE {}
virtual void HandleMediaPrevTrack() OVERRIDE {}
+ virtual MediaCaptureState GetMediaCaptureState(
+ content::BrowserContext* context) OVERRIDE {
+ return state_;
+ }
+
+ MediaCaptureState state_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaDelegateImpl);
};
} // namespace
@@ -161,8 +188,13 @@ base::string16 TestShellDelegate::GetProductName() const {
return base::string16();
}
-TestSessionStateDelegate* TestShellDelegate::test_session_state_delegate() {
- return test_session_state_delegate_;
+void TestShellDelegate::SetMediaCaptureState(MediaCaptureState state) {
+#if defined(OS_CHROMEOS)
+ Shell* shell = Shell::GetInstance();
+ static_cast<MediaDelegateImpl*>(shell->media_delegate())
+ ->set_media_capture_state(state);
+ shell->system_tray_notifier()->NotifyMediaCaptureChanged();
+#endif
}
} // namespace test
diff --git a/ash/test/test_shell_delegate.h b/ash/test/test_shell_delegate.h
index 1d8da2f..d92f80d 100644
--- a/ash/test/test_shell_delegate.h
+++ b/ash/test/test_shell_delegate.h
@@ -7,6 +7,7 @@
#include <string>
+#include "ash/media_delegate.h"
#include "ash/shell_delegate.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
@@ -63,7 +64,11 @@ class TestShellDelegate : public ShellDelegate {
int num_exit_requests() const { return num_exit_requests_; }
- TestSessionStateDelegate* test_session_state_delegate();
+ TestSessionStateDelegate* test_session_state_delegate() {
+ return test_session_state_delegate_;
+ }
+
+ void SetMediaCaptureState(MediaCaptureState state);
private:
int num_exit_requests_;
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
index 3bfe3df..138ad5a 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
@@ -7,7 +7,6 @@
#include "ash/accelerators/magnifier_key_scroller.h"
#include "ash/accelerators/spoken_feedback_toggler.h"
#include "ash/accessibility_delegate.h"
-#include "ash/media_delegate.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
@@ -20,8 +19,6 @@
#include "chrome/browser/chromeos/background/ash_user_wallpaper_delegate.h"
#include "chrome/browser/chromeos/display/display_configuration_observer.h"
#include "chrome/browser/chromeos/display/display_preferences.h"
-#include "chrome/browser/chromeos/extensions/media_player_api.h"
-#include "chrome/browser/chromeos/extensions/media_player_event_router.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -29,6 +26,7 @@
#include "chrome/browser/speech/tts_controller.h"
#include "chrome/browser/sync/sync_error_notifier_factory_ash.h"
#include "chrome/browser/ui/ash/chrome_new_window_delegate_chromeos.h"
+#include "chrome/browser/ui/ash/media_delegate_chromeos.h"
#include "chrome/browser/ui/ash/session_state_delegate_chromeos.h"
#include "chrome/browser/ui/ash/system_tray_delegate_chromeos.h"
#include "chrome/browser/ui/browser.h"
@@ -209,33 +207,6 @@ class AccessibilityDelegateImpl : public ash::AccessibilityDelegate {
DISALLOW_COPY_AND_ASSIGN(AccessibilityDelegateImpl);
};
-class MediaDelegateImpl : public ash::MediaDelegate {
- public:
- MediaDelegateImpl() {}
- virtual ~MediaDelegateImpl() {}
-
- virtual void HandleMediaNextTrack() OVERRIDE {
- extensions::MediaPlayerAPI::Get(
- ProfileManager::GetActiveUserProfile())->
- media_player_event_router()->NotifyNextTrack();
- }
-
- virtual void HandleMediaPlayPause() OVERRIDE {
- extensions::MediaPlayerAPI::Get(
- ProfileManager::GetActiveUserProfile())->
- media_player_event_router()->NotifyTogglePlayState();
- }
-
- virtual void HandleMediaPrevTrack() OVERRIDE {
- extensions::MediaPlayerAPI::Get(
- ProfileManager::GetActiveUserProfile())->
- media_player_event_router()->NotifyPrevTrack();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MediaDelegateImpl);
-};
-
} // anonymous namespace
bool ChromeShellDelegate::IsFirstRunAfterBoot() const {
@@ -268,7 +239,7 @@ ash::NewWindowDelegate* ChromeShellDelegate::CreateNewWindowDelegate() {
}
ash::MediaDelegate* ChromeShellDelegate::CreateMediaDelegate() {
- return new MediaDelegateImpl;
+ return new MediaDelegateChromeOS;
}
ash::SystemTrayDelegate* ChromeShellDelegate::CreateSystemTrayDelegate() {
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_views.cc b/chrome/browser/ui/ash/chrome_shell_delegate_views.cc
index 1ce1cc0..3522aa5 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_views.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_views.cc
@@ -61,6 +61,10 @@ class MediaDelegateImpl : public ash::MediaDelegate {
virtual void HandleMediaNextTrack() OVERRIDE {}
virtual void HandleMediaPlayPause() OVERRIDE {}
virtual void HandleMediaPrevTrack() OVERRIDE {}
+ virtual ash::MediaCaptureState GetMediaCaptureState(
+ content::BrowserContext* context) OVERRIDE {
+ return ash::MEDIA_CAPTURE_NONE;
+ }
private:
DISALLOW_COPY_AND_ASSIGN(MediaDelegateImpl);
diff --git a/chrome/browser/ui/ash/media_delegate_chromeos.cc b/chrome/browser/ui/ash/media_delegate_chromeos.cc
new file mode 100644
index 0000000..ff92c70
--- /dev/null
+++ b/chrome/browser/ui/ash/media_delegate_chromeos.cc
@@ -0,0 +1,173 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/media_delegate_chromeos.h"
+
+#include "apps/app_window.h"
+#include "apps/app_window_registry.h"
+#include "ash/shell.h"
+#include "ash/system/tray/system_tray_notifier.h"
+#include "base/message_loop/message_loop.h"
+#include "chrome/browser/chromeos/extensions/media_player_api.h"
+#include "chrome/browser/chromeos/extensions/media_player_event_router.h"
+#include "chrome/browser/media/media_stream_capture_indicator.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/browser/process_manager.h"
+
+namespace {
+
+void GetMediaCaptureState(
+ const MediaStreamCaptureIndicator* indicator,
+ content::WebContents* web_contents,
+ int* media_state_out) {
+ if (indicator->IsCapturingVideo(web_contents))
+ *media_state_out |= ash::MEDIA_CAPTURE_VIDEO;
+ if (indicator->IsCapturingAudio(web_contents))
+ *media_state_out |= ash::MEDIA_CAPTURE_AUDIO;
+}
+
+void GetBrowserMediaCaptureState(
+ const MediaStreamCaptureIndicator* indicator,
+ const content::BrowserContext* context,
+ int* media_state_out) {
+
+ const BrowserList* desktop_list =
+ BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
+
+ for (BrowserList::BrowserVector::const_iterator iter = desktop_list->begin();
+ iter != desktop_list->end();
+ ++iter) {
+ TabStripModel* tab_strip_model = (*iter)->tab_strip_model();
+ for (int i = 0; i < tab_strip_model->count(); ++i) {
+ content::WebContents* web_contents = tab_strip_model->GetWebContentsAt(i);
+ if (web_contents->GetBrowserContext() != context)
+ continue;
+ GetMediaCaptureState(indicator, web_contents, media_state_out);
+ if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
+ return;
+ }
+ }
+}
+
+void GetAppMediaCaptureState(
+ const MediaStreamCaptureIndicator* indicator,
+ content::BrowserContext* context,
+ int* media_state_out) {
+ const apps::AppWindowRegistry::AppWindowList& apps =
+ apps::AppWindowRegistry::Get(context)->app_windows();
+ for (apps::AppWindowRegistry::AppWindowList::const_iterator iter =
+ apps.begin();
+ iter != apps.end();
+ ++iter) {
+ GetMediaCaptureState(indicator, (*iter)->web_contents(), media_state_out);
+ if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
+ return;
+ }
+}
+
+void GetExtensionMediaCaptureState(
+ const MediaStreamCaptureIndicator* indicator,
+ content::BrowserContext* context,
+ int* media_state_out) {
+ extensions::ProcessManager* process_manager =
+ extensions::ExtensionSystem::Get(context)->process_manager();
+ const extensions::ProcessManager::ViewSet view_set =
+ process_manager->GetAllViews();
+ for (extensions::ProcessManager::ViewSet::const_iterator iter =
+ view_set.begin();
+ iter != view_set.end();
+ ++iter) {
+ content::WebContents* web_contents =
+ content::WebContents::FromRenderViewHost(*iter);
+ // RVH may not have web contents.
+ if (!web_contents)
+ continue;
+ GetMediaCaptureState(indicator, web_contents, media_state_out);
+ if (*media_state_out == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
+ return;
+ }
+}
+
+ash::MediaCaptureState GetMediaCaptureStateOfAllWebContents(
+ content::BrowserContext* context) {
+ if (!context)
+ return ash::MEDIA_CAPTURE_NONE;
+
+ scoped_refptr<MediaStreamCaptureIndicator> indicator =
+ MediaCaptureDevicesDispatcher::GetInstance()
+ ->GetMediaStreamCaptureIndicator();
+
+ int media_state = ash::MEDIA_CAPTURE_NONE;
+ // Browser windows
+ GetBrowserMediaCaptureState(indicator.get(), context, &media_state);
+ if (media_state == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
+ return ash::MEDIA_CAPTURE_AUDIO_VIDEO;
+
+ // App windows
+ GetAppMediaCaptureState(indicator.get(), context, &media_state);
+ if (media_state == ash::MEDIA_CAPTURE_AUDIO_VIDEO)
+ return ash::MEDIA_CAPTURE_AUDIO_VIDEO;
+
+ // Extensions
+ GetExtensionMediaCaptureState(indicator.get(), context, &media_state);
+
+ return static_cast<ash::MediaCaptureState>(media_state);
+}
+
+} // namespace
+
+MediaDelegateChromeOS::MediaDelegateChromeOS() : weak_ptr_factory_(this) {
+ MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this);
+}
+
+MediaDelegateChromeOS::~MediaDelegateChromeOS() {
+ MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this);
+}
+
+void MediaDelegateChromeOS::HandleMediaNextTrack() {
+ extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
+ ->media_player_event_router()
+ ->NotifyNextTrack();
+}
+
+void MediaDelegateChromeOS::HandleMediaPlayPause() {
+ extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
+ ->media_player_event_router()
+ ->NotifyTogglePlayState();
+}
+
+void MediaDelegateChromeOS::HandleMediaPrevTrack() {
+ extensions::MediaPlayerAPI::Get(ProfileManager::GetActiveUserProfile())
+ ->media_player_event_router()
+ ->NotifyPrevTrack();
+}
+
+ash::MediaCaptureState MediaDelegateChromeOS::GetMediaCaptureState(
+ content::BrowserContext* context) {
+ return GetMediaCaptureStateOfAllWebContents(context);
+}
+
+void MediaDelegateChromeOS::OnRequestUpdate(
+ int render_process_id,
+ int render_view_id,
+ const content::MediaStreamDevice& device,
+ const content::MediaRequestState state) {
+ base::MessageLoopForUI::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaDelegateChromeOS::NotifyMediaCaptureChange,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void MediaDelegateChromeOS::NotifyMediaCaptureChange() {
+ ash::Shell::GetInstance()
+ ->system_tray_notifier()
+ ->NotifyMediaCaptureChanged();
+}
diff --git a/chrome/browser/ui/ash/media_delegate_chromeos.h b/chrome/browser/ui/ash/media_delegate_chromeos.h
new file mode 100644
index 0000000..7370432
--- /dev/null
+++ b/chrome/browser/ui/ash/media_delegate_chromeos.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ASH_MEDIA_DELEGATE_CHROMEOS_H_
+#define CHROME_BROWSER_UI_ASH_MEDIA_DELEGATE_CHROMEOS_H_
+
+#include "ash/media_delegate.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/media/media_capture_devices_dispatcher.h"
+
+class MediaDelegateChromeOS : public ash::MediaDelegate,
+ MediaCaptureDevicesDispatcher::Observer {
+ public:
+ MediaDelegateChromeOS();
+ virtual ~MediaDelegateChromeOS();
+
+ // ash::MediaDelegate:
+ virtual void HandleMediaNextTrack() OVERRIDE;
+ virtual void HandleMediaPlayPause() OVERRIDE;
+ virtual void HandleMediaPrevTrack() OVERRIDE;
+ virtual ash::MediaCaptureState GetMediaCaptureState(
+ content::BrowserContext* context) OVERRIDE;
+
+ // MediaCaptureDevicesDispatcher::Observer:
+ virtual void OnRequestUpdate(int render_process_id,
+ int render_view_id,
+ const content::MediaStreamDevice& device,
+ const content::MediaRequestState state) OVERRIDE;
+
+ private:
+ void NotifyMediaCaptureChange();
+
+ base::WeakPtrFactory<MediaDelegateChromeOS> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaDelegateChromeOS);
+};
+
+#endif // CHROME_BROWSER_UI_ASH_MEDIA_DELEGATE_CHROMEOS_H_
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
index 22798ca..452eacc 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
@@ -14,6 +14,7 @@
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/shell_window_ids.h"
+#include "ash/system/tray/system_tray_notifier.h"
#include "ash/wm/window_state.h"
#include "base/auto_reset.h"
#include "base/message_loop/message_loop.h"
@@ -400,6 +401,11 @@ void MultiUserWindowManagerChromeOS::ActiveUserChanged(
animation_.reset(
new UserSwichAnimatorChromeOS(
this, user_id, GetAdjustedAnimationTimeInMS(kUserFadeTimeMS)));
+ // Call notifier here instead of observing ActiveUserChanged because
+ // this must happen after MultiUserWindowManagerChromeOS is notified.
+ ash::Shell::GetInstance()
+ ->system_tray_notifier()
+ ->NotifyMediaCaptureChanged();
}
void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) {
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 9f7dd0e..5aa3781 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -333,6 +333,8 @@
'browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.h',
'browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc',
'browser/ui/ash/launcher/multi_profile_browser_status_monitor.h',
+ 'browser/ui/ash/media_delegate_chromeos.cc',
+ 'browser/ui/ash/media_delegate_chromeos.h',
'browser/ui/ash/multi_user/multi_user_context_menu.cc',
'browser/ui/ash/multi_user/multi_user_context_menu.h',
'browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc',