summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-14 01:44:32 +0000
committersail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-14 01:44:32 +0000
commit057569b793e3b55e37ef20c1f2701159230ce9da (patch)
tree64a279fdc2222fe16cb5449ccb41fb034b6ca7d9
parent87d5eb4dd3a416166993d856af6353e2a74aa2b8 (diff)
downloadchromium_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.h8
-rw-r--r--chrome/app/generated_resources.grd24
-rw-r--r--chrome/browser/profiles/profile_manager.cc67
-rw-r--r--chrome/browser/profiles/profile_manager.h16
-rw-r--r--chrome/browser/ui/profile_menu_model.cc7
-rw-r--r--chrome/browser/ui/toolbar/wrench_menu_model.cc136
-rw-r--r--chrome/browser/ui/toolbar/wrench_menu_model.h34
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