diff options
author | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-14 01:44:32 +0000 |
---|---|---|
committer | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-14 01:44:32 +0000 |
commit | 057569b793e3b55e37ef20c1f2701159230ce9da (patch) | |
tree | 64a279fdc2222fe16cb5449ccb41fb034b6ca7d9 | |
parent | 87d5eb4dd3a416166993d856af6353e2a74aa2b8 (diff) | |
download | chromium_src-057569b793e3b55e37ef20c1f2701159230ce9da.zip chromium_src-057569b793e3b55e37ef20c1f2701159230ce9da.tar.gz chromium_src-057569b793e3b55e37ef20c1f2701159230ce9da.tar.bz2 |
Add profiles to wrench menu
This change adds a profile menu to the wrench menu.
If the user has one profile then the wrench menu looks like this:
Wrench Menu >
...
Downloads
-------
New Browsing Profile...
-------
...
If the user has two or more profile then the wrench menu looks like this:
Wrench Menu >
...
Downloads
-------
Browsing Profiles >
Profile 1
Profile 2
--------
New Browsing Profile...
-------
...
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/7138002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@88942 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/chrome_command_ids.h | 8 | ||||
-rw-r--r-- | chrome/app/generated_resources.grd | 24 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_manager.cc | 67 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_manager.h | 16 | ||||
-rw-r--r-- | chrome/browser/ui/profile_menu_model.cc | 7 | ||||
-rw-r--r-- | chrome/browser/ui/toolbar/wrench_menu_model.cc | 136 | ||||
-rw-r--r-- | chrome/browser/ui/toolbar/wrench_menu_model.h | 34 |
7 files changed, 283 insertions, 9 deletions
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index 562a650..cb01867 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h @@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef CHROME_APP_CHROME_COMMAND_IDS_H_ +#define CHROME_APP_CHROME_COMMAND_IDS_H_ +#pragma once + // This file lists all the command IDs understood by e.g. the browser. // It is used by Windows RC files, Mac NIB files, and other platforms too. @@ -166,6 +170,8 @@ #define IDC_PROFILING_ENABLED 40030 #define IDC_FILE_MANAGER 40031 #define IDC_BOOKMARKS_MENU 40032 +#define IDC_PROFILE_MENU 40033 +#define IDC_CREATE_NEW_PROFILE 40034 // Spell-check // Insert any additional suggestions before _LAST; these have to be consecutive. @@ -276,3 +282,5 @@ // Context menu items in the status tray #define IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND 51100 + +#endif // CHROME_APP_CHROME_COMMAND_IDS_H_ diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index be86961..f16860a 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -8120,8 +8120,28 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_PROFILES_OPTIONS_GROUP_NAME" desc="The name of the sync group in the options dialog."> Profile </message> - <message name="IDS_PROFILES_CREATE_NEW_PROFILE_OPTION" desc="Create new profile menu item and button title."> - Create a new profile... + <if expr="not pp_ifdef('use_titlecase')"> + <message name="IDS_PROFILES_CREATE_NEW_PROFILE_OPTION" desc="Create new profile menu item and button title."> + New <ph name="SHORT_PRODUCT_NAME">$1<ex>Chrome</ex> profile</ph> + </message> + </if> + <if expr="pp_ifdef('use_titlecase')"> + <message name="IDS_PROFILES_CREATE_NEW_PROFILE_OPTION" desc="In Title Case. Create new profile menu item and button title."> + New <ph name="SHORT_PRODUCT_NAME">$1<ex>Chrome</ex> Profile</ph> + </message> + </if> + <if expr="not pp_ifdef('use_titlecase')"> + <message name="IDS_PROFILES_MENU" desc="The title of the profiles submenu in the wrench menu."> + <ph name="SHORT_PRODUCT_NAME">$1<ex>Chrome</ex> profiles</ph> + </message> + </if> + <if expr="pp_ifdef('use_titlecase')"> + <message name="IDS_PROFILES_MENU" desc="In Title Case. The title of the profiles submenu in the wrench menu."> + <ph name="SHORT_PRODUCT_NAME">$1<ex>Chrome</ex> Profiles</ph> + </message> + </if> + <message name="IDS_DEFAULT_PROFILE_NAME" desc="The default name given to a profile. Displayed in wrench menu and settings UI."> + Default Profile </message> <if expr="not pp_ifdef('use_titlecase')"> <message name="IDS_PROFILES_CONNECT_BUTTON_LABEL" desc="The label that appears on the profile connect button in the options dialog when the user has not connected a Google Account to their profile."> diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index c30950a..7a66ef3 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc @@ -32,6 +32,7 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_job.h" +#include "ui/base/l10n/l10n_util.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/cros/cros_library.h" @@ -251,6 +252,8 @@ void ProfileManager::CreateProfileAsync(const FilePath& user_data_dir, if (info->created) { // Profile has already been created. Call observer immediately. observer->OnProfileCreated(info->profile.get()); + if (observer->DeleteAfterCreation()) + delete observer; } else { // Profile is being created. Add observer to list. info->observers.push_back(observer); @@ -302,6 +305,7 @@ ProfileManager::ProfileInfo* ProfileManager::RegisterProfile(Profile* profile, ProfileInfo* info = new ProfileInfo(profile, created); ProfilesInfoMap::iterator new_elem = (profiles_info_.insert(std::make_pair(profile->GetPath(), info))).first; + return info; } @@ -429,3 +433,66 @@ void ProfileManager::RegisterPrefs(PrefService* prefs) { prefs->RegisterDictionaryPref(prefs::kProfileDirectoryMap); prefs->RegisterIntegerPref(prefs::kProfilesNumCreated, 1); } + + +size_t ProfileManager::GetNumberOfProfiles() { + const DictionaryValue* path_map = + g_browser_process->local_state()->GetDictionary( + prefs::kProfileDirectoryMap); + return path_map ? path_map->size() : 0; +} + +string16 ProfileManager::GetNameOfProfileAtIndex(size_t index) { + return GetSortedProfilesFromDirectoryMap()[index].second; +} + +FilePath ProfileManager::GetFilePathOfProfileAtIndex( + size_t index, + const FilePath& user_data_dir) { + FilePath base_name = GetSortedProfilesFromDirectoryMap()[index].first; + return user_data_dir.Append(base_name); +} + +bool ProfileManager::CompareProfilePathAndName( + const ProfileManager::ProfilePathAndName& pair1, + const ProfileManager::ProfilePathAndName& pair2) { + int name_compare = pair1.second.compare(pair2.second); + if (name_compare < 0) { + return true; + } else if (name_compare > 0) { + return false; + } else { + return pair1.first < pair2.first; + } +} + +ProfileManager::ProfilePathAndNames +ProfileManager::GetSortedProfilesFromDirectoryMap() { + ProfilePathAndNames profiles; + + const DictionaryValue* path_map = + g_browser_process->local_state()->GetDictionary( + prefs::kProfileDirectoryMap); + if (!path_map) + return profiles; + + for (DictionaryValue::key_iterator it = path_map->begin_keys(); + it != path_map->end_keys(); ++it) { + std::string name_ascii; + path_map->GetString(*it, &name_ascii); + string16 name = ASCIIToUTF16(name_ascii); + if (name.empty()) + name = l10n_util::GetStringUTF16(IDS_DEFAULT_PROFILE_NAME); +#if defined(OS_POSIX) + FilePath file_path(*it); +#elif defined(OS_WIN) + FilePath file_path(ASCIIToWide(*it)); +#endif + + // Pending, need to insert it alphabetically. + profiles.push_back(std::pair<FilePath, string16>(file_path, name)); + } + + std::sort(profiles.begin(), profiles.end(), CompareProfilePathAndName); + return profiles; +} diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h index d06f700..e16aeb6 100644 --- a/chrome/browser/profiles/profile_manager.h +++ b/chrome/browser/profiles/profile_manager.h @@ -35,6 +35,8 @@ class ProfileManagerObserver { // If true, delete the observer after the profile has been created. Default // is false. virtual bool DeleteAfterCreation(); + + virtual ~ProfileManagerObserver() {} }; class ProfileManager : public base::NonThreadSafe, @@ -62,6 +64,12 @@ class ProfileManager : public base::NonThreadSafe, // otherwise it will create and manage it. Profile* GetProfile(const FilePath& profile_dir); + // Multi-profile support. + size_t GetNumberOfProfiles(); + string16 GetNameOfProfileAtIndex(size_t index); + FilePath GetFilePathOfProfileAtIndex(size_t index, + const FilePath& user_data_dir); + // Explicit asynchronous creation of the profile. |observer| is called // when profile is created. If profile has already been created, observer // is called immediately. Should be called on the UI thread. @@ -173,6 +181,14 @@ class ProfileManager : public base::NonThreadSafe, // entry. ProfileInfo* RegisterProfile(Profile* profile, bool created); + typedef std::pair<FilePath, string16> ProfilePathAndName; + typedef std::vector<ProfilePathAndName> ProfilePathAndNames; + ProfilePathAndNames GetSortedProfilesFromDirectoryMap(); + + static bool CompareProfilePathAndName( + const ProfileManager::ProfilePathAndName& pair1, + const ProfileManager::ProfilePathAndName& pair2); + NotificationRegistrar registrar_; // Indicates that a user has logged in and that the profile specified diff --git a/chrome/browser/ui/profile_menu_model.cc b/chrome/browser/ui/profile_menu_model.cc index 46ab4bc..bce0946 100644 --- a/chrome/browser/ui/profile_menu_model.cc +++ b/chrome/browser/ui/profile_menu_model.cc @@ -5,13 +5,16 @@ #include "chrome/browser/ui/profile_menu_model.h" #include "chrome/browser/profiles/profile_manager.h" +#include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" ProfileMenuModel::ProfileMenuModel() : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)) { - AddItem(COMMAND_CREATE_NEW_PROFILE, l10n_util::GetStringUTF16( - IDS_PROFILES_CREATE_NEW_PROFILE_OPTION)); + const string16 short_product_name = + l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME); + AddItem(COMMAND_CREATE_NEW_PROFILE, l10n_util::GetStringFUTF16( + IDS_PROFILES_CREATE_NEW_PROFILE_OPTION, short_product_name)); } ProfileMenuModel::~ProfileMenuModel() { diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc index f778a64..12ada90 100644 --- a/chrome/browser/ui/toolbar/wrench_menu_model.cc +++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc @@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/i18n/number_formatting.h" +#include "base/path_service.h" #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" @@ -17,13 +18,16 @@ #include "chrome/browser/defaults.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/task_manager/task_manager.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/toolbar/encoding_menu_controller.h" #include "chrome/browser/upgrade_detector.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/profiling.h" @@ -212,6 +216,95 @@ void BookmarkSubMenuModel::Build(Browser* browser) { //////////////////////////////////////////////////////////////////////////////// +// ProfilesSubMenuModel + +ProfilesSubMenuModel::ProfilesSubMenuModel( + ui::SimpleMenuModel::Delegate* delegate, Browser* browser) + : SimpleMenuModel(this), + browser_(browser), + delegate_(delegate) { + Build(); +} + +void ProfilesSubMenuModel::Build() { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + size_t count = profile_manager->GetNumberOfProfiles(); + for (size_t i = 0; i < count; ++i) { + AddCheckItem(COMMAND_SWITCH_TO_PROFILE + i, + profile_manager->GetNameOfProfileAtIndex(i)); + } + + AddSeparator(); + + const string16 short_product_name = + l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME); + AddItem(IDC_CREATE_NEW_PROFILE, l10n_util::GetStringFUTF16( + IDS_PROFILES_CREATE_NEW_PROFILE_OPTION, short_product_name)); +} + +class ProfileSwitchObserver : public ProfileManagerObserver { + virtual void OnProfileCreated(Profile* profile) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + Browser* browser = BrowserList::FindTabbedBrowser(profile, false); + if (browser) + browser->window()->Activate(); + else + Browser::NewWindowWithProfile(profile); + } + + virtual bool DeleteAfterCreation() OVERRIDE { return true; } +}; + +void ProfilesSubMenuModel::ExecuteCommand(int command_id) { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + size_t index = command_id; + if (index < profile_manager->GetNumberOfProfiles()) { + FilePath userDataFolder; + PathService::Get(chrome::DIR_USER_DATA, &userDataFolder); + FilePath profile_path = + profile_manager->GetFilePathOfProfileAtIndex(index, userDataFolder); + + ProfileSwitchObserver* observer = new ProfileSwitchObserver; + // The observer is deleted by the manager when profile creation is finished. + profile_manager->CreateProfileAsync(profile_path, observer); + } else { + delegate_->ExecuteCommand(command_id); + } +} + +bool ProfilesSubMenuModel::IsCommandIdChecked(int command_id) const { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + size_t index = command_id; + if (index < profile_manager->GetNumberOfProfiles()) { + FilePath userDataFolder; + PathService::Get(chrome::DIR_USER_DATA, &userDataFolder); + FilePath profile_path = + profile_manager->GetFilePathOfProfileAtIndex(index, userDataFolder); + return browser_->GetProfile()->GetPath() == profile_path; + } + return delegate_->IsCommandIdChecked(command_id); +} + +bool ProfilesSubMenuModel::IsCommandIdEnabled(int command_id) const { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + size_t index = command_id; + if (index < profile_manager->GetNumberOfProfiles()) + return true; + return delegate_->IsCommandIdEnabled(command_id); +} + +bool ProfilesSubMenuModel::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + size_t index = command_id; + if (index < profile_manager->GetNumberOfProfiles()) + return false; + return delegate_->GetAcceleratorForCommandId(command_id, accelerator); +} + +//////////////////////////////////////////////////////////////////////////////// // WrenchMenuModel WrenchMenuModel::WrenchMenuModel(ui::AcceleratorProvider* provider, @@ -306,7 +399,14 @@ bool WrenchMenuModel::GetIconForCommandId(int command_id, } void WrenchMenuModel::ExecuteCommand(int command_id) { - browser_->ExecuteCommand(command_id); + switch (command_id) { + case IDC_CREATE_NEW_PROFILE: + ProfileManager::CreateMultiProfileAsync(); + break; + default: + browser_->ExecuteCommand(command_id); + break; + } } bool WrenchMenuModel::IsCommandIdChecked(int command_id) const { @@ -320,11 +420,17 @@ bool WrenchMenuModel::IsCommandIdChecked(int command_id) const { } bool WrenchMenuModel::IsCommandIdEnabled(int command_id) const { - if (command_id == IDC_SHOW_BOOKMARK_BAR) { - return !browser_->profile()->GetPrefs()->IsManagedPreference( - prefs::kEnableBookmarkBar); + switch (command_id) { + case IDC_SHOW_BOOKMARK_BAR: + return !browser_->profile()->GetPrefs()->IsManagedPreference( + prefs::kEnableBookmarkBar); + case IDC_CREATE_NEW_PROFILE: + return true; + case IDC_PROFILE_MENU: + return true; + default: + return browser_->command_updater()->IsCommandEnabled(command_id); } - return browser_->command_updater()->IsCommandEnabled(command_id); } bool WrenchMenuModel::IsCommandIdVisible(int command_id) const { @@ -460,6 +566,26 @@ void WrenchMenuModel::Build() { AddItemWithStringId(IDC_SHOW_DOWNLOADS, IDS_SHOW_DOWNLOADS); AddSeparator(); +#if !defined(OS_CHROMEOS) + const string16 short_product_name = + l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME); + const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); + if (browser_command_line.HasSwitch(switches::kMultiProfiles)) { + if (g_browser_process->profile_manager()->GetNumberOfProfiles() > 1) { + profiles_sub_menu_model_.reset(new ProfilesSubMenuModel(this, browser_)); + AddSubMenu(IDC_PROFILE_MENU, l10n_util::GetStringFUTF16( + IDS_PROFILES_MENU, short_product_name), + profiles_sub_menu_model_.get()); + } else { + profiles_sub_menu_model_.reset(); + AddItem(IDC_CREATE_NEW_PROFILE, l10n_util::GetStringFUTF16( + IDS_PROFILES_CREATE_NEW_PROFILE_OPTION, short_product_name)); + } + + AddSeparator(); + } +#endif + #if defined(OS_CHROMEOS) AddItemWithStringId(IDC_OPTIONS, IDS_SETTINGS); #elif defined(OS_MACOSX) diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.h b/chrome/browser/ui/toolbar/wrench_menu_model.h index 9d5ff90..48622fc 100644 --- a/chrome/browser/ui/toolbar/wrench_menu_model.h +++ b/chrome/browser/ui/toolbar/wrench_menu_model.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_TOOLBAR_WRENCH_MENU_MODEL_H_ #pragma once +#include "base/file_path.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/tabs/tab_strip_model_observer.h" #include "content/common/notification_observer.h" @@ -81,6 +82,36 @@ class BookmarkSubMenuModel : public ui::SimpleMenuModel { DISALLOW_COPY_AND_ASSIGN(BookmarkSubMenuModel); }; +class ProfilesSubMenuModel : public ui::SimpleMenuModel, + public ui::SimpleMenuModel::Delegate { + public: + ProfilesSubMenuModel(ui::SimpleMenuModel::Delegate* delegate, + Browser* browser); + + virtual void ExecuteCommand(int command_id) OVERRIDE; + virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; + virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE; + virtual bool GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) OVERRIDE; + + private: + enum { + // The profiles submenu contains a menu item for each profile. For + // the i'th profile the command ID is COMMAND_SWITCH_TO_PROFILE + i. + // If the profile matches the profile of the wrench button's browser + // then the menu item is checked. + COMMAND_SWITCH_TO_PROFILE, + }; + + void Build(); + + Browser* browser_; // weak + ui::SimpleMenuModel::Delegate* delegate_; // weak + + DISALLOW_COPY_AND_ASSIGN(ProfilesSubMenuModel); +}; + // A menu model that builds the contents of the wrench menu. class WrenchMenuModel : public ui::SimpleMenuModel, public ui::SimpleMenuModel::Delegate, @@ -156,6 +187,9 @@ class WrenchMenuModel : public ui::SimpleMenuModel, // Bookmark submenu. scoped_ptr<BookmarkSubMenuModel> bookmark_sub_menu_model_; + // Profiles submenu. + scoped_ptr<ProfilesSubMenuModel> profiles_sub_menu_model_; + ui::AcceleratorProvider* provider_; // weak Browser* browser_; // weak |