summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/generated_resources.grd4
-rw-r--r--chrome/app/theme/theme_resources.grd62
-rw-r--r--chrome/browser/profiles/profiles_state.cc26
-rw-r--r--chrome/browser/profiles/profiles_state.h6
-rw-r--r--chrome/browser/ui/view_ids.h1
-rw-r--r--chrome/browser/ui/views/avatar_menu_bubble_view.h1
-rw-r--r--chrome/browser/ui/views/avatar_menu_button_browsertest.cc89
-rw-r--r--chrome/browser/ui/views/frame/browser_frame.cc4
-rw-r--r--chrome/browser/ui/views/frame/browser_frame.h3
-rw-r--r--chrome/browser/ui/views/frame/browser_non_client_frame_view.cc47
-rw-r--r--chrome/browser/ui/views/frame/browser_non_client_frame_view.h18
-rw-r--r--chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc3
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc13
-rw-r--r--chrome/browser/ui/views/frame/browser_view.h12
-rw-r--r--chrome/browser/ui/views/frame/glass_browser_frame_view.cc75
-rw-r--r--chrome/browser/ui/views/frame/glass_browser_frame_view.h6
-rw-r--r--chrome/browser/ui/views/frame/opaque_browser_frame_view.cc25
-rw-r--r--chrome/browser/ui/views/frame/opaque_browser_frame_view.h2
-rw-r--r--chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc35
-rw-r--r--chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h3
-rw-r--r--chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h3
-rw-r--r--chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc35
-rw-r--r--chrome/browser/ui/views/new_avatar_button.cc96
-rw-r--r--chrome/browser/ui/views/new_avatar_button.h35
-rw-r--r--chrome/browser/ui/views/new_avatar_menu_button_browsertest.cc123
-rw-r--r--chrome/browser/ui/views/profile_chooser_view.cc4
-rw-r--r--chrome/browser/ui/views/profile_chooser_view.h5
-rw-r--r--chrome/chrome_browser_ui.gypi4
-rw-r--r--chrome/chrome_tests.gypi1
29 files changed, 626 insertions, 115 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 621f534d..7aa78be 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -11270,6 +11270,10 @@ Would you like to start <ph name="CONTROL_PANEL_APPLET_NAME">$1<ex>Add/Remove Pr
<message name="IDS_NUMBERED_PROFILE_NAME" desc="The name given to a newly created profile. Displayed in wrench menu and settings UI.">
User <ph name="VALUE">$1<ex>1</ex></ph>
</message>
+ <message name="IDS_GUEST_PROFILE_NAME" desc="The name given to the guest
+ browsing profile. Displayed in the avatar menu bubble and button UI.">
+ Guest
+ </message>
<message name="IDS_DEFAULT_AVATAR_NAME_8" desc="The default name given to a newly created profile with the female spy avatar.">
Agent X
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index d50f1c5..10923dc 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -713,6 +713,68 @@
<structure type="chrome_scaled_image" name="IDR_PROFILE_AVATAR_24" file="profile_avatar_note.png" />
<structure type="chrome_scaled_image" name="IDR_PROFILE_AVATAR_25" file="profile_avatar_sun_cloud.png" />
</if>
+
+ <!-- New style avatar button -->
+ <!-- Windows, themed windows -->
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_DROPARROW" file="win/avatar_button/themed/sign_in_button_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_BOTTOM" file="win/avatar_button/themed/sign_in_button_bottom.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_BOTTOM_LEFT" file="win/avatar_button/themed/sign_in_button_bottom_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_BOTTOM_RIGHT" file="win/avatar_button/themed/sign_in_button_bottom_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_CENTER" file="win/avatar_button/themed/sign_in_button_center.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_LEFT" file="win/avatar_button/themed/sign_in_button_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_RIGHT" file="win/avatar_button/themed/sign_in_button_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_TOP" file="win/avatar_button/themed/sign_in_button_top.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_TOP_LEFT" file="win/avatar_button/themed/sign_in_button_top_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_NORMAL_TOP_RIGHT" file="win/avatar_button/themed/sign_in_button_top_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_BOTTOM" file="win/avatar_button/themed/sign_in_button_hover_bottom.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_BOTTOM_LEFT" file="win/avatar_button/themed/sign_in_button_hover_bottom_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_BOTTOM_RIGHT" file="win/avatar_button/themed/sign_in_button_hover_bottom_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_CENTER" file="win/avatar_button/themed/sign_in_button_hover_center.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_LEFT" file="win/avatar_button/themed/sign_in_button_hover_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_RIGHT" file="win/avatar_button/themed/sign_in_button_hover_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_TOP" file="win/avatar_button/themed/sign_in_button_hover_top.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_TOP_LEFT" file="win/avatar_button/themed/sign_in_button_hover_top_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_HOVER_TOP_RIGHT" file="win/avatar_button/themed/sign_in_button_hover_top_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_BOTTOM" file="win/avatar_button/themed/sign_in_button_pressed_bottom.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_BOTTOM_LEFT" file="win/avatar_button/themed/sign_in_button_pressed_bottom_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_BOTTOM_RIGHT" file="win/avatar_button/themed/sign_in_button_pressed_bottom_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_CENTER" file="win/avatar_button/themed/sign_in_button_pressed_center.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_LEFT" file="win/avatar_button/themed/sign_in_button_pressed_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_RIGHT" file="win/avatar_button/themed/sign_in_button_pressed_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_TOP" file="win/avatar_button/themed/sign_in_button_pressed_top.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_TOP_LEFT" file="win/avatar_button/themed/sign_in_button_pressed_top_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_THEMED_BUTTON_PRESSED_TOP_RIGHT" file="win/avatar_button/themed/sign_in_button_pressed_top_right.png" />
+
+ <!-- Windows, glass windows -->
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_DROPARROW" file="win/avatar_button/win7/sign_in_button_arrow.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_BOTTOM" file="win/avatar_button/win7/sign_in_button_bottom.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_BOTTOM_LEFT" file="win/avatar_button/win7/sign_in_button_bottom_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_BOTTOM_RIGHT" file="win/avatar_button/win7/sign_in_button_bottom_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_CENTER" file="win/avatar_button/win7/sign_in_button_center.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_LEFT" file="win/avatar_button/win7/sign_in_button_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_RIGHT" file="win/avatar_button/win7/sign_in_button_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_TOP" file="win/avatar_button/win7/sign_in_button_top.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_TOP_LEFT" file="win/avatar_button/win7/sign_in_button_top_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_NORMAL_TOP_RIGHT" file="win/avatar_button/win7/sign_in_button_top_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_BOTTOM" file="win/avatar_button/win7/sign_in_button_hover_bottom.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_BOTTOM_LEFT" file="win/avatar_button/win7/sign_in_button_hover_bottom_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_BOTTOM_RIGHT" file="win/avatar_button/win7/sign_in_button_hover_bottom_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_CENTER" file="win/avatar_button/win7/sign_in_button_hover_center.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_LEFT" file="win/avatar_button/win7/sign_in_button_hover_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_RIGHT" file="win/avatar_button/win7/sign_in_button_hover_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_TOP" file="win/avatar_button/win7/sign_in_button_hover_top.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_TOP_LEFT" file="win/avatar_button/win7/sign_in_button_hover_top_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_HOVER_TOP_RIGHT" file="win/avatar_button/win7/sign_in_button_hover_top_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_BOTTOM" file="win/avatar_button/win7/sign_in_button_pressed_bottom.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_BOTTOM_LEFT" file="win/avatar_button/win7/sign_in_button_pressed_bottom_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_BOTTOM_RIGHT" file="win/avatar_button/win7/sign_in_button_pressed_bottom_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_CENTER" file="win/avatar_button/win7/sign_in_button_pressed_center.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_LEFT" file="win/avatar_button/win7/sign_in_button_pressed_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_RIGHT" file="win/avatar_button/win7/sign_in_button_pressed_right.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_TOP" file="win/avatar_button/win7/sign_in_button_pressed_top.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_TOP_LEFT" file="win/avatar_button/win7/sign_in_button_pressed_top_left.png" />
+ <structure type="chrome_scaled_image" name="IDR_AVATAR_GLASS_BUTTON_PRESSED_TOP_RIGHT" file="win/avatar_button/win7/sign_in_button_pressed_top_right.png" />
+
<if expr="pp_ifdef('chromeos')">
<structure type="chrome_scaled_image" name="IDR_PROFILE_PICTURE_LOADING" file="profile_loading.png" />
<structure type="chrome_scaled_image" name="IDR_RESET_WARNING" file="reset_warning.png" />
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc
index 72e1295..3165271 100644
--- a/chrome/browser/profiles/profiles_state.cc
+++ b/chrome/browser/profiles/profiles_state.cc
@@ -7,9 +7,16 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/prefs/pref_registry_simple.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/user_manager.h"
@@ -33,8 +40,7 @@ bool IsNewProfileManagementEnabled() {
switches::kNewProfileManagement);
}
-base::FilePath GetDefaultProfileDir(
- const base::FilePath& user_data_dir) {
+base::FilePath GetDefaultProfileDir(const base::FilePath& user_data_dir) {
base::FilePath default_profile_dir(user_data_dir);
default_profile_dir =
default_profile_dir.AppendASCII(chrome::kInitialProfile);
@@ -54,4 +60,20 @@ void RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterListPref(prefs::kProfilesLastActive);
}
+string16 GetActiveProfileDisplayName(Browser* browser) {
+ string16 profile_name;
+ Profile* profile = browser->profile();
+
+ if (profile->IsGuestSession()) {
+ profile_name = l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME);
+ } else {
+ ProfileInfoCache& cache =
+ g_browser_process->profile_manager()->GetProfileInfoCache();
+ size_t index = cache.GetIndexOfProfileWithPath(profile->GetPath());
+ if (index != std::string::npos)
+ profile_name = cache.GetNameOfProfileAtIndex(index);
+ }
+ return profile_name;
+}
+
} // namespace profiles
diff --git a/chrome/browser/profiles/profiles_state.h b/chrome/browser/profiles/profiles_state.h
index 2858e62..3f6debc 100644
--- a/chrome/browser/profiles/profiles_state.h
+++ b/chrome/browser/profiles/profiles_state.h
@@ -5,6 +5,9 @@
#ifndef CHROME_BROWSER_PROFILES_PROFILES_STATE_H_
#define CHROME_BROWSER_PROFILES_PROFILES_STATE_H_
+#include "base/strings/string16.h"
+
+class Browser;
class PrefRegistrySimple;
namespace base { class FilePath; }
@@ -26,6 +29,9 @@ base::FilePath GetProfilePrefsPath(const base::FilePath& profile_dir);
// Register multi-profile related preferences in Local State.
void RegisterPrefs(PrefRegistrySimple* registry);
+// Returns the display name of the active on-the-record profile (or guest).
+string16 GetActiveProfileDisplayName(Browser* browser);
+
} // namespace profiles
#endif // CHROME_BROWSER_PROFILES_PROFILES_STATE_H_
diff --git a/chrome/browser/ui/view_ids.h b/chrome/browser/ui/view_ids.h
index 3d0fcb8..81e035e 100644
--- a/chrome/browser/ui/view_ids.h
+++ b/chrome/browser/ui/view_ids.h
@@ -24,6 +24,7 @@ enum ViewID {
VIEW_ID_WINDOW_TITLE,
VIEW_ID_AVATAR_LABEL,
VIEW_ID_AVATAR_BUTTON,
+ VIEW_ID_NEW_AVATAR_BUTTON,
// Tabs within a window/tab strip, counting from the left.
VIEW_ID_TAB_0,
diff --git a/chrome/browser/ui/views/avatar_menu_bubble_view.h b/chrome/browser/ui/views/avatar_menu_bubble_view.h
index 781e6be..e9e7225 100644
--- a/chrome/browser/ui/views/avatar_menu_bubble_view.h
+++ b/chrome/browser/ui/views/avatar_menu_bubble_view.h
@@ -131,7 +131,6 @@ class AvatarMenuBubbleView : public views::BubbleDelegateView,
bool expanded_;
DISALLOW_COPY_AND_ASSIGN(AvatarMenuBubbleView);
- FRIEND_TEST_ALL_PREFIXES(AvatarMenuButtonTest, SignOut);
};
#endif // CHROME_BROWSER_UI_VIEWS_AVATAR_MENU_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
index a3c0125..02f5cb3 100644
--- a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
+++ b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
@@ -7,35 +7,24 @@
#include "base/command_line.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/avatar_menu.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/views/avatar_menu_bubble_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/profile_chooser_view.h"
-#include "chrome/browser/ui/views/user_manager_view.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_switches.h"
#include "chrome/test/base/testing_browser_process.h"
-#include "content/public/test/test_utils.h"
#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/views/controls/button/label_button.h"
-class AvatarMenuButtonTest : public InProcessBrowserTest,
- public testing::WithParamInterface<bool> {
+class AvatarMenuButtonTest : public InProcessBrowserTest {
public:
AvatarMenuButtonTest();
virtual ~AvatarMenuButtonTest();
protected:
- virtual void SetUp() OVERRIDE;
-
- bool UsingNewProfileChooser();
void CreateTestingProfile();
AvatarMenuButton* GetAvatarMenuButton();
void StartAvatarMenu();
@@ -50,33 +39,10 @@ AvatarMenuButtonTest::AvatarMenuButtonTest() {
AvatarMenuButtonTest::~AvatarMenuButtonTest() {
}
-void AvatarMenuButtonTest::SetUp() {
- if (GetParam()) {
- if (!UsingNewProfileChooser()) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kNewProfileManagement);
- }
- DCHECK(UsingNewProfileChooser());
- } else {
- DCHECK(!UsingNewProfileChooser());
- }
-
- InProcessBrowserTest::SetUp();
-}
-
-bool AvatarMenuButtonTest::UsingNewProfileChooser() {
- return CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kNewProfileManagement);
-}
-
void AvatarMenuButtonTest::CreateTestingProfile() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
EXPECT_EQ(1u, profile_manager->GetNumberOfProfiles());
- // Sign in the default profile
- ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
- cache.SetUserNameOfProfileAtIndex(0, UTF8ToUTF16("user_name"));
-
base::FilePath path;
PathService::Get(chrome::DIR_USER_DATA, &path);
path = path.AppendASCII("test_profile");
@@ -99,28 +65,25 @@ void AvatarMenuButtonTest::StartAvatarMenu() {
ASSERT_TRUE(button);
AvatarMenuBubbleView::set_close_on_deactivate(false);
- ProfileChooserView::set_close_on_deactivate(false);
static_cast<views::MenuButtonListener*>(button)->OnMenuButtonClicked(
NULL, gfx::Point());
base::MessageLoop::current()->RunUntilIdle();
- EXPECT_NE(AvatarMenuBubbleView::IsShowing(),
- ProfileChooserView::IsShowing());
+ EXPECT_TRUE(AvatarMenuBubbleView::IsShowing());
}
-IN_PROC_BROWSER_TEST_P(AvatarMenuButtonTest, HideOnSecondClick) {
+IN_PROC_BROWSER_TEST_F(AvatarMenuButtonTest, HideOnSecondClick) {
#if defined(OS_WIN) && defined(USE_ASH)
// Disable this test in Metro+Ash for now (http://crbug.com/262796).
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
return;
#endif
- if (!profiles::IsMultipleProfilesEnabled() ||
- UsingNewProfileChooser()) {
+ // If multiprofile mode is not enabled, you can't switch between profiles.
+ if (!profiles::IsMultipleProfilesEnabled())
return;
- }
CreateTestingProfile();
- StartAvatarMenu();
+ ASSERT_NO_FATAL_FAILURE(StartAvatarMenu());
// Verify that clicking again doesn't reshow it.
AvatarMenuButton* button = GetAvatarMenuButton();
@@ -131,44 +94,4 @@ IN_PROC_BROWSER_TEST_P(AvatarMenuButtonTest, HideOnSecondClick) {
AvatarMenuBubbleView::Hide();
base::MessageLoop::current()->RunUntilIdle();
EXPECT_FALSE(AvatarMenuBubbleView::IsShowing());
- EXPECT_FALSE(ProfileChooserView::IsShowing());
-}
-
-IN_PROC_BROWSER_TEST_P(AvatarMenuButtonTest, NewSignOut) {
- if (!profiles::IsMultipleProfilesEnabled() ||
- !UsingNewProfileChooser()) {
- return;
- }
-
- CreateTestingProfile();
- StartAvatarMenu();
-
- BrowserList* browser_list =
- BrowserList::GetInstance(chrome::GetActiveDesktop());
- EXPECT_EQ(1U, browser_list->size());
- content::WindowedNotificationObserver window_close_observer(
- chrome::NOTIFICATION_BROWSER_CLOSED,
- content::Source<Browser>(browser()));
-
- AvatarMenu* menu =
- ProfileChooserView::profile_bubble_->avatar_menu_.get();
- const AvatarMenu::Item& menu_item_before =
- menu->GetItemAt(menu->GetActiveProfileIndex());
- EXPECT_FALSE(menu_item_before.signin_required);
-
- ui::MouseEvent mouse_ev(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0);
- menu->SetLogoutURL("about:blank");
-
- ProfileChooserView::profile_bubble_->LinkClicked(
- static_cast<views::Link*>(
- ProfileChooserView::profile_bubble_->signout_current_profile_link_),
- 0);
-
- EXPECT_TRUE(menu->GetItemAt(menu->GetActiveProfileIndex()).signin_required);
-
- window_close_observer.Wait(); // Rely on test timeout for failure indication.
- EXPECT_TRUE(browser_list->empty());
}
-
-INSTANTIATE_TEST_CASE_P(Old, AvatarMenuButtonTest, testing::Values(false));
-INSTANTIATE_TEST_CASE_P(New, AvatarMenuButtonTest, testing::Values(true));
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc
index 3c5fb8b..3788223 100644
--- a/chrome/browser/ui/views/frame/browser_frame.cc
+++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -252,6 +252,10 @@ AvatarMenuButton* BrowserFrame::GetAvatarMenuButton() {
return browser_frame_view_->avatar_button();
}
+NewAvatarButton* BrowserFrame::GetNewAvatarMenuButton() {
+ return browser_frame_view_->new_avatar_button();
+}
+
#if !defined(OS_WIN) || defined(USE_AURA)
bool BrowserFrame::ShouldLeaveOffsetNearTopBorder() {
return !IsMaximized();
diff --git a/chrome/browser/ui/views/frame/browser_frame.h b/chrome/browser/ui/views/frame/browser_frame.h
index 023e143..3a2a852 100644
--- a/chrome/browser/ui/views/frame/browser_frame.h
+++ b/chrome/browser/ui/views/frame/browser_frame.h
@@ -16,6 +16,7 @@ class AvatarMenuButton;
class BrowserRootView;
class BrowserView;
class NativeBrowserFrame;
+class NewAvatarButton;
class NonClientFrameView;
class SystemMenuModelBuilder;
@@ -98,6 +99,8 @@ class BrowserFrame
AvatarMenuButton* GetAvatarMenuButton();
+ NewAvatarButton* GetNewAvatarMenuButton();
+
// Returns the menu model. BrowserFrame owns the returned model.
ui::MenuModel* GetSystemMenuModel();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
index 367aae1..d7f46d9 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -9,11 +9,14 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/avatar_label.h"
#include "chrome/browser/ui/views/avatar_menu_button.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/taskbar_decorator.h"
+#include "chrome/browser/ui/views/new_avatar_button.h"
+#include "chrome/browser/ui/views/profile_chooser_view.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -28,7 +31,8 @@ BrowserNonClientFrameView::BrowserNonClientFrameView(BrowserFrame* frame,
: frame_(frame),
browser_view_(browser_view),
avatar_button_(NULL),
- avatar_label_(NULL) {
+ avatar_label_(NULL),
+ new_avatar_button_(NULL) {
}
BrowserNonClientFrameView::~BrowserNonClientFrameView() {
@@ -41,7 +45,9 @@ void BrowserNonClientFrameView::VisibilityChanged(views::View* starting_from,
// The first time UpdateAvatarInfo() is called the window is not visible so
// DrawTaskBarDecoration() has no effect. Therefore we need to call it again
// once the window is visible.
- UpdateAvatarInfo();
+ if (!browser_view_->IsRegularOrGuestSession() ||
+ !profiles::IsNewProfileManagementEnabled())
+ UpdateAvatarInfo();
}
void BrowserNonClientFrameView::OnThemeChanged() {
@@ -59,8 +65,7 @@ void BrowserNonClientFrameView::UpdateAvatarInfo() {
AddChildView(avatar_label_);
}
avatar_button_ = new AvatarMenuButton(
- browser_view_->browser(),
- browser_view_->IsOffTheRecord() && !browser_view_->IsGuestSession());
+ browser_view_->browser(), !browser_view_->IsRegularOrGuestSession());
avatar_button_->set_id(VIEW_ID_AVATAR_BUTTON);
AddChildView(avatar_button_);
frame_->GetRootView()->Layout();
@@ -111,3 +116,37 @@ void BrowserNonClientFrameView::UpdateAvatarInfo() {
frame_->GetNativeWindow(),
AvatarMenu::ShouldShowAvatarMenu() ? &avatar : NULL);
}
+
+void BrowserNonClientFrameView::UpdateNewStyleAvatarInfo(
+ views::ButtonListener* listener,
+ const NewAvatarButton::AvatarButtonStyle style) {
+ DCHECK(profiles::IsNewProfileManagementEnabled());
+ // This should never be called in incognito mode.
+ DCHECK(browser_view_->IsRegularOrGuestSession());
+
+ if (browser_view_->ShouldShowAvatar()) {
+ if (!new_avatar_button_) {
+ string16 profile_name =
+ profiles::GetActiveProfileDisplayName(browser_view_->browser());
+ new_avatar_button_ = new NewAvatarButton(listener, profile_name, style);
+ new_avatar_button_->set_id(VIEW_ID_NEW_AVATAR_BUTTON);
+ AddChildView(new_avatar_button_);
+ frame_->GetRootView()->Layout();
+ }
+ } else if (new_avatar_button_) {
+ delete new_avatar_button_;
+ new_avatar_button_ = NULL;
+ frame_->GetRootView()->Layout();
+ }
+}
+
+void BrowserNonClientFrameView::ShowProfileChooserViewBubble() {
+ gfx::Point origin;
+ views::View::ConvertPointToScreen(new_avatar_button(), &origin);
+ gfx::Rect bounds(origin, size());
+
+ ProfileChooserView::ShowBubble(
+ new_avatar_button(), views::BubbleBorder::TOP_RIGHT,
+ views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, bounds,
+ browser_view_->browser());
+}
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index 91a9b0d..681a06e 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -5,12 +5,14 @@
#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_H_
+#include "chrome/browser/ui/views/new_avatar_button.h"
#include "ui/views/window/non_client_view.h"
class AvatarLabel;
class AvatarMenuButton;
class BrowserFrame;
class BrowserView;
+class NewAvatarButton;
// A specialization of the NonClientFrameView object that provides additional
// Browser-specific methods.
@@ -34,6 +36,8 @@ class BrowserNonClientFrameView : public views::NonClientFrameView {
AvatarMenuButton* avatar_button() const { return avatar_button_; }
+ NewAvatarButton* new_avatar_button() const { return new_avatar_button_; }
+
AvatarLabel* avatar_label() const { return avatar_label_; }
// Returns the bounds within which the TabStrip should be laid out.
@@ -62,6 +66,16 @@ class BrowserNonClientFrameView : public views::NonClientFrameView {
// Updates the title and icon of the avatar button.
void UpdateAvatarInfo();
+ // Updates the title of the avatar button displayed in the caption area.
+ // The button uses |style| to match the browser window style and notifies
+ // |listener| when it is clicked.
+ void UpdateNewStyleAvatarInfo(views::ButtonListener* listener,
+ const NewAvatarButton::AvatarButtonStyle style);
+
+ // Anchor and show the ProfileChooser bubble under the avatar button in
+ // the caption area.
+ void ShowProfileChooserViewBubble();
+
private:
// The frame that hosts this view.
BrowserFrame* frame_;
@@ -75,6 +89,10 @@ class BrowserNonClientFrameView : public views::NonClientFrameView {
// Avatar label that is used for a managed user.
AvatarLabel* avatar_label_;
+
+ // Menu button that displays the name of the active or guest profile.
+ // May be NULL and will not be displayed for off the record profiles.
+ NewAvatarButton* new_avatar_button_;
};
namespace chrome {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index 22ef7d3..f9c577b 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -531,8 +531,7 @@ void BrowserNonClientFrameViewAsh::PaintContentEdge(gfx::Canvas* canvas) {
}
int BrowserNonClientFrameViewAsh::GetThemeFrameImageId() const {
- bool is_incognito = browser_view()->IsOffTheRecord() &&
- !browser_view()->IsGuestSession();
+ bool is_incognito = !browser_view()->IsRegularOrGuestSession();
if (browser_view()->IsBrowserTypeNormal()) {
// Use the standard resource ids to allow users to theme the frames.
if (ShouldPaintAsActive()) {
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index b12feea..a7dd621 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -548,6 +548,15 @@ bool BrowserView::IsOffTheRecord() const {
return browser_->profile()->IsOffTheRecord();
}
+bool BrowserView::IsGuestSession() const {
+ return browser_->profile()->IsGuestSession();
+}
+
+bool BrowserView::IsRegularOrGuestSession() const {
+ Profile* profile = browser_->profile();
+ return (profile->IsGuestSession() || !profile->IsOffTheRecord());
+}
+
int BrowserView::GetOTRIconResourceID() const {
int otr_resource_id = IDR_OTR_ICON;
if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) {
@@ -562,10 +571,6 @@ int BrowserView::GetOTRIconResourceID() const {
return otr_resource_id;
}
-bool BrowserView::IsGuestSession() const {
- return browser_->profile()->IsGuestSession();
-}
-
int BrowserView::GetGuestIconResourceID() const {
return IDR_GUEST_ICON;
}
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 5e589b8..9991575 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -192,14 +192,18 @@ class BrowserView : public BrowserWindow,
// incognito.
bool IsOffTheRecord() const;
- // Returns the resource ID to use for the OTR icon, which depends on
- // which layout is being shown and whether we are full-screen.
- int GetOTRIconResourceID() const;
-
// Returns true if the profile associated with this Browser window is
// a guest session.
bool IsGuestSession() const;
+ // Returns true if the profile associated with this Browser window is
+ // not off the record or a guest session.
+ bool IsRegularOrGuestSession() const;
+
+ // Returns the resource ID to use for the OTR icon, which depends on
+ // which layout is being shown and whether we are full-screen.
+ int GetOTRIconResourceID() const;
+
// Returns the resource ID to use for the Guest icon, which may depend on
// which layout is being shown and whether we are full-screen.
int GetGuestIconResourceID() const;
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index b482292..6d70928 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -11,9 +11,11 @@
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/views/avatar_menu_button.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/new_avatar_button.h"
#include "chrome/browser/ui/views/tabs/tab.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h"
#include "chrome/browser/ui/views/toolbar_view.h"
@@ -55,6 +57,8 @@ const int kAvatarBottomSpacing = 2;
const int kAvatarLeftSpacing = 2;
// Space between the right edge of the avatar and the tabstrip.
const int kAvatarRightSpacing = -2;
+// How far the new avatar button is from the left of the minimize button.
+const int kNewAvatarButtonOffset = 5;
// The content left/right images have a shadow built into them.
const int kContentEdgeShadowThickness = 2;
// The top 3 px of the tabstrip is shadow; in maximized mode we push this off
@@ -85,7 +89,12 @@ GlassBrowserFrameView::GlassBrowserFrameView(BrowserFrame* frame,
if (browser_view->ShouldShowWindowIcon())
InitThrobberIcons();
- UpdateAvatarInfo();
+ if (browser_view->IsRegularOrGuestSession() &&
+ profiles::IsNewProfileManagementEnabled())
+ UpdateNewStyleAvatarInfo(this, NewAvatarButton::GLASS_BUTTON);
+ else
+ UpdateAvatarInfo();
+
if (!browser_view->IsOffTheRecord()) {
registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
content::NotificationService::AllSources());
@@ -102,6 +111,12 @@ gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip(
views::View* tabstrip) const {
int minimize_button_offset =
std::min(frame()->GetMinimizeButtonOffset(), width());
+
+ // The new avatar button is optionally displayed to the left of the
+ // minimize button.
+ if (browser_view()->ShouldShowAvatar() && new_avatar_button())
+ minimize_button_offset -= new_avatar_button()->width();
+
int tabstrip_x = browser_view()->ShouldShowAvatar() ?
(avatar_bounds_.right() + kAvatarRightSpacing) :
NonClientBorderThickness() + kTabStripIndent;
@@ -210,6 +225,10 @@ int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) {
if (avatar_button() && avatar_button()->GetMirroredBounds().Contains(point))
return HTCLIENT;
+ if (new_avatar_button() &&
+ new_avatar_button()->GetMirroredBounds().Contains(point))
+ return HTCLIENT;
+
int frame_component = frame()->client_view()->NonClientHitTest(point);
// See if we're in the sysmenu region. We still have to check the tabstrip
@@ -244,14 +263,32 @@ void GlassBrowserFrameView::OnPaint(gfx::Canvas* canvas) {
}
void GlassBrowserFrameView::Layout() {
- LayoutAvatar();
+ if (browser_view()->ShouldShowAvatar()) {
+ if (browser_view()->IsRegularOrGuestSession() &&
+ profiles::IsNewProfileManagementEnabled())
+ LayoutNewStyleAvatar();
+ else
+ LayoutAvatar();
+ }
+
LayoutClientView();
}
bool GlassBrowserFrameView::HitTestRect(const gfx::Rect& rect) const {
- return (avatar_button() &&
- avatar_button()->GetMirroredBounds().Intersects(rect)) ||
- !frame()->client_view()->bounds().Intersects(rect);
+ bool hit_avatar_button = avatar_button() &&
+ avatar_button()->GetMirroredBounds().Intersects(rect);
+ bool hit_new_avatar_button = new_avatar_button() &&
+ new_avatar_button()->GetMirroredBounds().Intersects(rect);
+ return hit_avatar_button || hit_new_avatar_button ||
+ !frame()->client_view()->bounds().Intersects(rect);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// GlassBrowserFrameView, views::ButtonListener overrides:
+void GlassBrowserFrameView::ButtonPressed(views::Button* sender,
+ const ui::Event& event) {
+ if (sender == new_avatar_button())
+ ShowProfileChooserViewBubble();
}
///////////////////////////////////////////////////////////////////////////////
@@ -403,6 +440,28 @@ void GlassBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) {
toolbar_color);
}
+void GlassBrowserFrameView::LayoutNewStyleAvatar() {
+ if (!new_avatar_button())
+ return;
+
+ gfx::Size label_size = new_avatar_button()->GetPreferredSize();
+ int button_size_with_offset = kNewAvatarButtonOffset + label_size.width();
+
+ int button_x = frame()->GetMinimizeButtonOffset() -
+ kNewAvatarButtonOffset - label_size.width();
+
+ if (base::i18n::IsRTL())
+ button_x = width() - frame()->GetMinimizeButtonOffset() +
+ kNewAvatarButtonOffset;
+
+ int button_y = frame()->IsMaximized() ? NonClientTopBorderHeight(false) : 1;
+ new_avatar_button()->SetBounds(
+ button_x,
+ button_y,
+ label_size.width(),
+ button_y + gfx::win::GetSystemMetricsInDIP(SM_CXMENUSIZE));
+}
+
void GlassBrowserFrameView::LayoutAvatar() {
// Even though the avatar is used for both incognito and profiles we always
// use the incognito icon to layout the avatar button. The profile icon
@@ -504,7 +563,11 @@ void GlassBrowserFrameView::Observe(
const content::NotificationDetails& details) {
switch (type) {
case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED:
- UpdateAvatarInfo();
+ if (browser_view()->IsRegularOrGuestSession() &&
+ profiles::IsNewProfileManagementEnabled())
+ UpdateNewStyleAvatarInfo(this, NewAvatarButton::GLASS_BUTTON);
+ else
+ UpdateAvatarInfo();
break;
default:
NOTREACHED() << "Got a notification we didn't register for!";
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
index d872738..c9b2701c 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -16,6 +16,7 @@
class BrowserView;
class GlassBrowserFrameView : public BrowserNonClientFrameView,
+ public views::ButtonListener,
public content::NotificationObserver {
public:
// Constructs a non-client view for an BrowserFrame.
@@ -46,6 +47,10 @@ class GlassBrowserFrameView : public BrowserNonClientFrameView,
virtual void Layout() OVERRIDE;
virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE;
+ // Overidden from views::ButtonListener:
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE;
+
private:
// Returns the thickness of the border that makes up the window frame edges.
// This does not include any client edge.
@@ -66,6 +71,7 @@ class GlassBrowserFrameView : public BrowserNonClientFrameView,
// Layout various sub-components of this view.
void LayoutAvatar();
+ void LayoutNewStyleAvatar();
void LayoutClientView();
// Returns the insets of the client area.
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index fdfe4c7..4de7694c 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -12,6 +12,7 @@
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/views/avatar_label.h"
#include "chrome/browser/ui/views/avatar_menu_button.h"
@@ -19,6 +20,7 @@
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h"
#include "chrome/browser/ui/views/frame/opaque_browser_frame_view_platform_specific.h"
+#include "chrome/browser/ui/views/new_avatar_button.h"
#include "chrome/browser/ui/views/tab_icon_view.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h"
#include "chrome/browser/ui/views/toolbar_view.h"
@@ -150,7 +152,12 @@ OpaqueBrowserFrameView::OpaqueBrowserFrameView(BrowserFrame* frame,
window_title_->set_id(VIEW_ID_WINDOW_TITLE);
AddChildView(window_title_);
- UpdateAvatarInfo();
+ if (browser_view->IsRegularOrGuestSession() &&
+ profiles::IsNewProfileManagementEnabled())
+ UpdateNewStyleAvatarInfo(this, NewAvatarButton::THEMED_BUTTON);
+ else
+ UpdateAvatarInfo();
+
if (!browser_view->IsOffTheRecord()) {
registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
content::NotificationService::AllSources());
@@ -215,7 +222,9 @@ int OpaqueBrowserFrameView::NonClientHitTest(const gfx::Point& point) {
// label.
if ((avatar_button() &&
avatar_button()->GetMirroredBounds().Contains(point)) ||
- (avatar_label() && avatar_label()->GetMirroredBounds().Contains(point)))
+ (avatar_label() && avatar_label()->GetMirroredBounds().Contains(point)) ||
+ (new_avatar_button() &&
+ new_avatar_button()->GetMirroredBounds().Contains(point)))
return HTCLIENT;
int frame_component = frame()->client_view()->NonClientHitTest(point);
@@ -396,6 +405,8 @@ void OpaqueBrowserFrameView::ButtonPressed(views::Button* sender,
frame()->Restore();
else if (sender == close_button_)
frame()->Close();
+ else if (sender == new_avatar_button())
+ ShowProfileChooserViewBubble();
}
///////////////////////////////////////////////////////////////////////////////
@@ -427,7 +438,11 @@ void OpaqueBrowserFrameView::Observe(
const content::NotificationDetails& details) {
switch (type) {
case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED:
- UpdateAvatarInfo();
+ if (browser_view() ->IsRegularOrGuestSession() &&
+ profiles::IsNewProfileManagementEnabled())
+ UpdateNewStyleAvatarInfo(this, NewAvatarButton::THEMED_BUTTON);
+ else
+ UpdateAvatarInfo();
break;
default:
NOTREACHED() << "Got a notification we didn't register for!";
@@ -477,6 +492,10 @@ bool OpaqueBrowserFrameView::ShouldShowAvatar() const {
return browser_view()->ShouldShowAvatar();
}
+bool OpaqueBrowserFrameView::IsRegularOrGuestSession() const {
+ return browser_view()->IsRegularOrGuestSession();
+}
+
gfx::ImageSkia OpaqueBrowserFrameView::GetOTRAvatarIcon() const {
return browser_view()->GetOTRAvatarIcon();
}
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
index e732d01..1e9b018 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -20,6 +20,7 @@ class BrowserView;
class OpaqueBrowserFrameViewLayout;
class OpaqueBrowserFrameViewPlatformSpecific;
class TabIconView;
+class NewAvatarButton;
namespace views {
class ImageButton;
@@ -87,6 +88,7 @@ class OpaqueBrowserFrameView : public BrowserNonClientFrameView,
virtual bool ShouldLeaveOffsetNearTopBorder() const OVERRIDE;
virtual gfx::Size GetBrowserViewMinimumSize() const OVERRIDE;
virtual bool ShouldShowAvatar() const OVERRIDE;
+ virtual bool IsRegularOrGuestSession() const OVERRIDE;
virtual gfx::ImageSkia GetOTRAvatarIcon() const OVERRIDE;
virtual bool IsMaximized() const OVERRIDE;
virtual bool IsMinimized() const OVERRIDE;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
index c0848d8..071e392 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h"
+#include "chrome/browser/profiles/profiles_state.h"
+#include "chrome/browser/ui/views/new_avatar_button.h"
#include "ui/gfx/font.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/label.h"
@@ -49,6 +51,9 @@ const int kAvatarLeftSpacing = 2;
// Space between the right edge of the avatar and the tabstrip.
const int kAvatarRightSpacing = -4;
+// How far the new avatar button is from the closest caption button.
+const int kNewAvatarButtonOffset = 5;
+
// In restored mode, the New Tab button isn't at the same height as the caption
// buttons, but the space will look cluttered if it actually slides under them,
// so we stop it when the gap between the two is down to 5 px.
@@ -101,7 +106,8 @@ OpaqueBrowserFrameViewLayout::OpaqueBrowserFrameViewLayout(
window_icon_(NULL),
window_title_(NULL),
avatar_label_(NULL),
- avatar_button_(NULL) {
+ avatar_button_(NULL),
+ new_avatar_button_(NULL) {
trailing_buttons_.push_back(views::FRAME_BUTTON_MINIMIZE);
trailing_buttons_.push_back(views::FRAME_BUTTON_MAXIMIZE);
trailing_buttons_.push_back(views::FRAME_BUTTON_CLOSE);
@@ -355,6 +361,24 @@ void OpaqueBrowserFrameViewLayout::LayoutTitleBar(views::View* host) {
}
}
+void OpaqueBrowserFrameViewLayout::LayoutNewStyleAvatar(views::View* host) {
+ gfx::Size label_size = new_avatar_button_->GetPreferredSize();
+ int button_size_with_offset = kNewAvatarButtonOffset + label_size.width();
+
+ int button_x = host->width() - trailing_button_start_ -
+ button_size_with_offset;
+ int button_y = CaptionButtonY(false);
+
+ trailing_button_start_ += button_size_with_offset;
+ minimum_size_for_buttons_ += button_size_with_offset;
+
+ new_avatar_button_->SetBounds(
+ button_x,
+ button_y,
+ label_size.width(),
+ button_y + kCaptionButtonHeightWithPadding);
+}
+
void OpaqueBrowserFrameViewLayout::LayoutAvatar() {
// Even though the avatar is used for both incognito and profiles we always
// use the incognito icon to layout the avatar button. The profile icon
@@ -567,6 +591,9 @@ void OpaqueBrowserFrameViewLayout::SetView(int id, views::View* view) {
case VIEW_ID_AVATAR_BUTTON:
avatar_button_ = view;
break;
+ case VIEW_ID_NEW_AVATAR_BUTTON:
+ new_avatar_button_ = static_cast<NewAvatarButton*>(view);
+ break;
default:
NOTIMPLEMENTED() << "Unknown view id " << id;
break;
@@ -593,7 +620,11 @@ void OpaqueBrowserFrameViewLayout::Layout(views::View* host) {
// on the trailing side.
leading_button_start_++;
- LayoutAvatar();
+ if (delegate_->IsRegularOrGuestSession() &&
+ profiles::IsNewProfileManagementEnabled())
+ LayoutNewStyleAvatar(host);
+ else
+ LayoutAvatar();
client_view_bounds_ = CalculateClientAreaBounds(
host->width(), host->height());
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h
index 12f6dea..b37bd51 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h
@@ -9,6 +9,7 @@
#include "ui/views/layout/layout_manager.h"
#include "ui/views/window/frame_buttons.h"
+class NewAvatarButton;
class OpaqueBrowserFrameViewLayoutDelegate;
namespace views {
@@ -100,6 +101,7 @@ class OpaqueBrowserFrameViewLayout : public views::LayoutManager {
void LayoutWindowControls(views::View* host);
void LayoutTitleBar(views::View* host);
void LayoutAvatar();
+ void LayoutNewStyleAvatar(views::View* host);
void ConfigureButton(views::View* host,
views::FrameButton button_id,
@@ -167,6 +169,7 @@ class OpaqueBrowserFrameViewLayout : public views::LayoutManager {
views::View* avatar_label_;
views::View* avatar_button_;
+ NewAvatarButton* new_avatar_button_;
std::vector<views::FrameButton> leading_buttons_;
std::vector<views::FrameButton> trailing_buttons_;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h
index 7858ed1..58709c8 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h
@@ -35,6 +35,9 @@ class OpaqueBrowserFrameViewLayoutDelegate {
// Controls the visualization of the avatar
virtual bool ShouldShowAvatar() const = 0;
+ // Returns true if in guest mode or a non off the record session.
+ virtual bool IsRegularOrGuestSession() const = 0;
+
// We don't have a ThemeProvider in the layout manager, so plumb in the icon
// source here.
virtual gfx::ImageSkia GetOTRAvatarIcon() const = 0;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
index 5962fb0..c75f09a 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -5,9 +5,11 @@
#include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h"
#include "base/basictypes.h"
+#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/views/tab_icon_view.h"
#include "chrome/browser/ui/views/tabs/tab.h"
+#include "chrome/common/chrome_switches.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/text_constants.h"
@@ -80,6 +82,10 @@ class TestLayoutDelegate : public OpaqueBrowserFrameViewLayoutDelegate {
return show_avatar_;
}
+ virtual bool IsRegularOrGuestSession() const OVERRIDE {
+ return true;
+ }
+
virtual gfx::ImageSkia GetOTRAvatarIcon() const OVERRIDE {
// The calculations depend on the size of the OTR resource, and chromeos
// uses a different sized image, so hard code the size of the current
@@ -213,6 +219,12 @@ class OpaqueBrowserFrameViewLayoutTest : public views::ViewsTestBase {
AddAvatarButton();
}
+ void AddNewAvatarButton() {
+ new_avatar_button_ = new views::MenuButton(NULL, string16(), NULL, false);
+ new_avatar_button_->set_id(VIEW_ID_NEW_AVATAR_BUTTON);
+ root_view_->AddChildView(new_avatar_button_);
+ }
+
void ExpectBasicWindowBounds() {
EXPECT_EQ("428,1 25x18", maximize_button_->bounds().ToString());
EXPECT_EQ("402,1 26x18", minimize_button_->bounds().ToString());
@@ -238,6 +250,7 @@ class OpaqueBrowserFrameViewLayoutTest : public views::ViewsTestBase {
views::MenuButton* menu_button_;
views::MenuButton* avatar_label_;
+ views::MenuButton* new_avatar_button_;
DISALLOW_COPY_AND_ASSIGN(OpaqueBrowserFrameViewLayoutTest);
};
@@ -314,6 +327,28 @@ TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithAvatar) {
EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString());
}
+
+TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithNewAvatar) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kNewProfileManagement);
+
+ // Tests a normal tabstrip window with the new style avatar icon.
+ AddNewAvatarButton();
+ root_view_->Layout();
+
+ ExpectBasicWindowBounds();
+
+ // Check the location of the caption button
+ EXPECT_EQ("385,1 12x20", new_avatar_button_->bounds().ToString());
+ // The basic window bounds are (-1, 13 398x29). There should not be an icon
+ // avatar in the left, and the new avatar button has an offset of 5 to its
+ // next control.
+ EXPECT_EQ("-1,13 381x29",
+ layout_manager_->GetBoundsForTabStrip(
+ delegate_->GetTabstripPreferredSize(), kWidth).ToString());
+ EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString());
+}
+
TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithAvatarLabelAndButton) {
AddAvatarLabel();
root_view_->Layout();
diff --git a/chrome/browser/ui/views/new_avatar_button.cc b/chrome/browser/ui/views/new_avatar_button.cc
new file mode 100644
index 0000000..9cf0d54
--- /dev/null
+++ b/chrome/browser/ui/views/new_avatar_button.cc
@@ -0,0 +1,96 @@
+// Copyright 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 "chrome/browser/ui/views/new_avatar_button.h"
+
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/views/border.h"
+#include "ui/views/painter.h"
+
+namespace {
+
+// Text padding within the button border.
+const int kInset = 10;
+
+views::TextButtonDefaultBorder* CreateBorder(const int normal_image_set[],
+ const int hot_image_set[],
+ const int pushed_image_set[]) {
+ views::TextButtonDefaultBorder* border = new views::TextButtonDefaultBorder();
+
+ border->SetInsets(gfx::Insets(kInset, kInset, kInset, kInset));
+ border->set_normal_painter(
+ views::Painter::CreateImageGridPainter(normal_image_set));
+ border->set_hot_painter(
+ views::Painter::CreateImageGridPainter(hot_image_set));
+ border->set_pushed_painter(
+ views::Painter::CreateImageGridPainter(pushed_image_set));
+
+ return border;
+}
+
+} // namespace
+
+NewAvatarButton::NewAvatarButton(
+ views::ButtonListener* listener,
+ const string16& profile_name,
+ AvatarButtonStyle button_style)
+ : MenuButton(listener, profile_name, NULL, true) {
+ set_animate_on_state_change(false);
+
+ ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
+ SetFont(rb->GetFont(ui::ResourceBundle::BaseFont));
+
+ if (button_style == GLASS_BUTTON) {
+ const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_NORMAL);
+ const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_HOVER);
+ const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_GLASS_BUTTON_PRESSED);
+
+ set_border(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet));
+ set_menu_marker(
+ rb->GetImageNamed(IDR_AVATAR_GLASS_BUTTON_DROPARROW).ToImageSkia());
+ } else {
+ const int kNormalImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_NORMAL);
+ const int kHotImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_HOVER);
+ const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_THEMED_BUTTON_PRESSED);
+
+ set_border(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet));
+ set_menu_marker(
+ rb->GetImageNamed(IDR_AVATAR_THEMED_BUTTON_DROPARROW).ToImageSkia());
+ }
+ SchedulePaint();
+}
+
+NewAvatarButton::~NewAvatarButton() {
+}
+
+void NewAvatarButton::OnPaint(gfx::Canvas* canvas) {
+ // From TextButton::PaintButton, draw everything but the text.
+ OnPaintBackground(canvas);
+ OnPaintBorder(canvas);
+ OnPaintFocusBorder(canvas);
+
+ gfx::Rect rect;
+ // In RTL languages the marker gets drawn leftmost, so account for its offset.
+ if (base::i18n::IsRTL())
+ rect = gfx::Rect(-kInset, 0, size().width(), size().height());
+ else
+ rect = gfx::Rect(kInset, 0, size().width(), size().height());
+ // TODO(noms): This should be DrawStringRectWithHalo but that function
+ // has a bug at the moment and incorrectly draws the background.
+ canvas->DrawStringRectWithFlags(
+ text(),
+ gfx::FontList(ui::ResourceBundle::GetSharedInstance().GetFont(
+ ui::ResourceBundle::BaseFont)),
+ SK_ColorBLACK,
+ rect,
+ gfx::Canvas::NO_SUBPIXEL_RENDERING);
+
+ // From MenuButton::PaintButton, paint the marker
+ PaintMenuMarker(canvas);
+}
diff --git a/chrome/browser/ui/views/new_avatar_button.h b/chrome/browser/ui/views/new_avatar_button.h
new file mode 100644
index 0000000..ad0d64a
--- /dev/null
+++ b/chrome/browser/ui/views/new_avatar_button.h
@@ -0,0 +1,35 @@
+// Copyright 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 CHROME_BROWSER_UI_VIEWS_NEW_AVATAR_BUTTON_H_
+#define CHROME_BROWSER_UI_VIEWS_NEW_AVATAR_BUTTON_H_
+
+#include "ui/views/controls/button/menu_button.h"
+
+// Avatar button that displays the active profile's name in the caption area.
+class NewAvatarButton : public views::MenuButton {
+ public:
+ // Different button styles that can be applied.
+ enum AvatarButtonStyle {
+ THEMED_BUTTON, // Used in a themed browser window.
+ GLASS_BUTTON, // Used in a native aero window.
+ METRO_BUTTON // Used in a metro window.
+ };
+
+ NewAvatarButton(views::ButtonListener* listener,
+ const string16& profile_name,
+ AvatarButtonStyle button_style);
+ virtual ~NewAvatarButton();
+
+ // views::View:
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
+
+ private:
+ friend class NewAvatarMenuButtonTest;
+ FRIEND_TEST_ALL_PREFIXES(NewAvatarMenuButtonTest, SignOut);
+
+ DISALLOW_COPY_AND_ASSIGN(NewAvatarButton);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_NEW_AVATAR_BUTTON_H_
diff --git a/chrome/browser/ui/views/new_avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/new_avatar_menu_button_browsertest.cc
new file mode 100644
index 0000000..c4b21df
--- /dev/null
+++ b/chrome/browser/ui/views/new_avatar_menu_button_browsertest.cc
@@ -0,0 +1,123 @@
+// Copyright 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 "base/command_line.h"
+#include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profiles_state.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/views/avatar_menu_button.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/new_avatar_button.h"
+#include "chrome/browser/ui/views/profile_chooser_view.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/test_switches.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "content/public/test/test_utils.h"
+#include "grit/generated_resources.h"
+
+class NewAvatarMenuButtonTest : public InProcessBrowserTest {
+ public:
+ NewAvatarMenuButtonTest();
+ virtual ~NewAvatarMenuButtonTest();
+
+ protected:
+ virtual void SetUp() OVERRIDE;
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
+ void CreateTestingProfile();
+ void StartAvatarMenu();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NewAvatarMenuButtonTest);
+};
+
+NewAvatarMenuButtonTest::NewAvatarMenuButtonTest() {
+}
+
+NewAvatarMenuButtonTest::~NewAvatarMenuButtonTest() {
+}
+
+void NewAvatarMenuButtonTest::SetUp() {
+ InProcessBrowserTest::SetUp();
+ DCHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kNewProfileManagement));
+}
+
+void NewAvatarMenuButtonTest::SetUpCommandLine(CommandLine* command_line) {
+ command_line->AppendSwitch(switches::kNewProfileManagement);
+}
+
+void NewAvatarMenuButtonTest::CreateTestingProfile() {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ EXPECT_EQ(1u, profile_manager->GetNumberOfProfiles());
+
+ // Sign in the default profile
+ ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
+ cache.SetUserNameOfProfileAtIndex(0, UTF8ToUTF16("user_name"));
+
+ base::FilePath path;
+ PathService::Get(chrome::DIR_USER_DATA, &path);
+ path = path.AppendASCII("test_profile");
+ if (!base::PathExists(path))
+ ASSERT_TRUE(file_util::CreateDirectory(path));
+ Profile* profile =
+ Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
+ profile_manager->RegisterTestingProfile(profile, true, false);
+ EXPECT_EQ(2u, profile_manager->GetNumberOfProfiles());
+}
+
+void NewAvatarMenuButtonTest::StartAvatarMenu() {
+ BrowserView* browser_view = reinterpret_cast<BrowserView*>(
+ browser()->window());
+
+ // Ensure that the avatar icon button is not also showing.
+ NewAvatarButton* button = browser_view->frame()->GetNewAvatarMenuButton();
+ ASSERT_TRUE(button);
+ ASSERT_FALSE(browser_view->frame()->GetAvatarMenuButton());
+
+ ProfileChooserView::set_close_on_deactivate(false);
+ ui::MouseEvent mouse_ev(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0);
+ button->NotifyClick(mouse_ev);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_TRUE(ProfileChooserView::IsShowing());
+}
+
+IN_PROC_BROWSER_TEST_F(NewAvatarMenuButtonTest, SignOut) {
+ // If multiprofile mode is not enabled, you can't switch between profiles.
+ if (!profiles::IsMultipleProfilesEnabled())
+ return;
+
+ CreateTestingProfile();
+ ASSERT_NO_FATAL_FAILURE(StartAvatarMenu());
+
+ BrowserList* browser_list =
+ BrowserList::GetInstance(chrome::GetActiveDesktop());
+ EXPECT_EQ(1U, browser_list->size());
+ content::WindowedNotificationObserver window_close_observer(
+ chrome::NOTIFICATION_BROWSER_CLOSED,
+ content::Source<Browser>(browser()));
+
+ AvatarMenu* menu =
+ ProfileChooserView::profile_bubble_->avatar_menu_.get();
+ const AvatarMenu::Item& menu_item_before =
+ menu->GetItemAt(menu->GetActiveProfileIndex());
+ EXPECT_FALSE(menu_item_before.signin_required);
+
+ ui::MouseEvent mouse_ev(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0);
+ menu->SetLogoutURL("about:blank");
+
+ ProfileChooserView::profile_bubble_->LinkClicked(
+ static_cast<views::Link*>(
+ ProfileChooserView::profile_bubble_->signout_current_profile_link_),
+ 0);
+
+ EXPECT_TRUE(menu->GetItemAt(menu->GetActiveProfileIndex()).signin_required);
+
+ window_close_observer.Wait(); // Rely on test timeout for failure indication.
+ EXPECT_TRUE(browser_list->empty());
+}
diff --git a/chrome/browser/ui/views/profile_chooser_view.cc b/chrome/browser/ui/views/profile_chooser_view.cc
index 8518378..ca25cc2 100644
--- a/chrome/browser/ui/views/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profile_chooser_view.cc
@@ -48,6 +48,7 @@ const int kLargeImageSide = 64;
const int kSmallImageSide = 32;
const int kMinMenuWidth = 250;
const int kButtonHeight = 29;
+const int kArrowHeight = 10;
// Current profile avatar image.
views::View* CreateProfileImageView(const gfx::Image& icon) {
@@ -199,6 +200,7 @@ void ProfileChooserView::ShowBubble(
profile_bubble_->set_close_on_deactivate(close_on_deactivate_);
profile_bubble_->SetAlignment(border_alignment);
profile_bubble_->GetWidget()->Show();
+ profile_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
}
// static
@@ -220,6 +222,8 @@ ProfileChooserView::ProfileChooserView(views::View* anchor_view,
browser_(browser) {
// Reset the default margins inherited from the BubbleDelegateView.
set_margins(gfx::Insets());
+ // Compensate for built-in vertical padding in the anchor view's image.
+ set_anchor_view_insets(gfx::Insets(kArrowHeight, 0, kArrowHeight, 0));
ResetLinksAndButtons();
diff --git a/chrome/browser/ui/views/profile_chooser_view.h b/chrome/browser/ui/views/profile_chooser_view.h
index eec7f2e..8affea1 100644
--- a/chrome/browser/ui/views/profile_chooser_view.h
+++ b/chrome/browser/ui/views/profile_chooser_view.h
@@ -55,9 +55,8 @@ class ProfileChooserView : public views::BubbleDelegateView,
}
private:
- friend class AvatarMenuButtonTest;
- FRIEND_TEST_ALL_PREFIXES(AvatarMenuButtonTest, NewSignOut);
- FRIEND_TEST_ALL_PREFIXES(AvatarMenuButtonTest, LaunchUserManagerScreen);
+ friend class NewAvatarMenuButtonTest;
+ FRIEND_TEST_ALL_PREFIXES(NewAvatarMenuButtonTest, SignOut);
typedef std::vector<size_t> Indexes;
typedef std::map<views::Button*, int> ButtonIndexes;
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 5fdfbdd..301547c 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -1618,7 +1618,7 @@
'browser/ui/views/avatar_menu_button.cc',
'browser/ui/views/avatar_menu_button.h',
'browser/ui/views/avatar_label.cc',
- 'browser/ui/views/avatar_label.cc',
+ 'browser/ui/views/avatar_label.h',
'browser/ui/views/bookmarks/bookmark_bar_instructions_view.cc',
'browser/ui/views/bookmarks/bookmark_bar_instructions_view.h',
'browser/ui/views/bookmarks/bookmark_bar_view.cc',
@@ -1907,6 +1907,8 @@
'browser/ui/views/native_focus_tracker_views.h',
'browser/ui/views/native_focus_tracker_views_aura.cc',
'browser/ui/views/native_focus_tracker_views_win.cc',
+ 'browser/ui/views/new_avatar_button.cc',
+ 'browser/ui/views/new_avatar_button.h',
'browser/ui/views/notifications/balloon_collection_views.cc',
'browser/ui/views/notifications/balloon_view_host.cc',
'browser/ui/views/notifications/balloon_view_host.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 5d382f6..42ab87e 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1404,6 +1404,7 @@
'browser/ui/views/frame/browser_view_browsertest.cc',
'browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc',
'browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc',
+ 'browser/ui/views/new_avatar_menu_button_browsertest.cc',
'browser/ui/views/select_file_dialog_extension_browsertest.cc',
'browser/ui/views/toolbar_view_browsertest.cc',
'browser/ui/views/web_dialog_view_browsertest.cc',