Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5169)

Unified Diff: chrome/browser/ui/views/app_list/app_list_controller_win.cc

Issue 11968034: Enable profile switching for standalone App Launcher via the Settings App. (Closed) Base URL: git://nomatter.syd/chromium/src.git@master
Patch Set: private Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/app_list/app_list_controller_win.cc
diff --git a/chrome/browser/ui/views/app_list/app_list_controller_win.cc b/chrome/browser/ui/views/app_list/app_list_controller_win.cc
index f7f00c77ab76580559f6d577c1e98cba0134ebfa..56343505ea2109d16c147104e086a3175c076ddd 100644
--- a/chrome/browser/ui/views/app_list/app_list_controller_win.cc
+++ b/chrome/browser/ui/views/app_list/app_list_controller_win.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/lazy_instance.h"
+#include "base/memory/weak_ptr.h"
#include "base/path_service.h"
#include "base/time.h"
#include "base/timer.h"
@@ -18,6 +19,7 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/platform_util.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/shell_integration.h"
@@ -27,7 +29,9 @@
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/views/browser_dialogs.h"
#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
#include "chrome/installer/util/util_constants.h"
#include "content/public/browser/browser_thread.h"
#include "grit/chromium_strings.h"
@@ -145,24 +149,62 @@ class AppListControllerDelegateWin : public AppListControllerDelegate {
// The AppListController class manages global resources needed for the app
// list to operate, and controls when the app list is opened and closed.
-class AppListController {
+class AppListController : public ProfileInfoCacheObserver {
public:
- AppListController()
- : current_view_(NULL),
- can_close_app_list_(true),
- app_list_is_showing_(false) {}
- ~AppListController() {}
+ AppListController();
void set_can_close(bool can_close) { can_close_app_list_ = can_close; }
bool can_close() { return can_close_app_list_; }
- void CreateAppList();
- void ShowAppList();
+ Profile* profile() const { return profile_; }
+ bool app_list_is_showing() const { return app_list_is_showing_; }
+
+ // Creates the app list view and populates it from |profile|, but doesn't
+ // show it. Does nothing if the view already exists.
+ void InitView(Profile* profile);
+
+ // Activates the app list at the current mouse cursor location, creating the
+ // app list if necessary.
+ void ShowAppList(Profile* profile);
+
+ // Update the profile path stored in local prefs, load it (if not already
+ // loaded), and show the app list.
+ void SetProfilePath(const FilePath& profile_file_path);
+
void DismissAppList();
void AppListClosing();
void AppListActivationChanged(bool active);
app_list::AppListView* GetView() { return current_view_; }
+ // TODO(koz): Split the responsibility for tracking profiles into a
+ // platform-independent class.
+ // Overidden from ProfileInfoCacheObserver.
+ void OnProfileAdded(const FilePath& profilePath) OVERRIDE {}
+ // We need to watch for profile removal to keep kAppListProfile updated.
+ void OnProfileWillBeRemoved(const FilePath& profile_path) OVERRIDE;
+ void OnProfileWasRemoved(const FilePath& profile_path,
+ const string16& profile_name) OVERRIDE {}
+ void OnProfileNameChanged(const FilePath& profile_path,
+ const string16& profile_name) OVERRIDE {}
+ void OnProfileAvatarChanged(const FilePath& profile_path) OVERRIDE {}
+
private:
+ // Loads a profile asynchronously and calls OnProfileLoaded() when done.
+ void LoadProfileAsync(const FilePath& profile_file_path);
+
+ // Callback for asynchronous profile load.
+ void OnProfileLoaded(int profile_load_sequence_id,
+ Profile* profile,
+ Profile::CreateStatus status);
+
+ // We need to keep the browser alive while we are loading a profile as that
+ // shows intent to show the app list. These two functions track our pending
+ // profile loads and start or end browser keep alive accordingly.
+ void IncrementPendingProfileLoads();
+ void DecrementPendingProfileLoads();
+
+ // Create or recreate, and initialize |current_view_| from |profile|.
+ void PopulateViewFromProfile(Profile* profile);
+
// Utility methods for showing the app list.
void SnapArrowLocationToTaskbarEdge(
const gfx::Display& display,
@@ -191,6 +233,9 @@ class AppListController {
app_list::PaginationModel pagination_model_;
+ // The profile the AppList is currently displaying.
+ Profile* profile_;
+
// True if the controller can close the app list.
bool can_close_app_list_;
@@ -198,6 +243,14 @@ class AppListController {
// browser process keep-alives active.
bool app_list_is_showing_;
+ // Incremented to indicate that pending profile loads are no longer valid.
+ int profile_load_sequence_id_;
+
+ // How many profile loads are pending.
+ int pending_profile_loads_;
+
+ base::WeakPtrFactory<AppListController> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(AppListController);
};
@@ -297,15 +350,134 @@ void AppListControllerDelegateWin::LaunchApp(
profile, extension, NEW_FOREGROUND_TAB));
}
-void AppListController::CreateAppList() {
-#if !defined(USE_AURA)
+AppListController::AppListController()
+ : current_view_(NULL),
+ profile_(NULL),
+ can_close_app_list_(true),
+ app_list_is_showing_(false),
+ profile_load_sequence_id_(0),
+ pending_profile_loads_(0),
+ weak_factory_(this) {
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ profile_manager->GetProfileInfoCache().AddObserver(this);
+}
+
+void AppListController::OnProfileWillBeRemoved(const FilePath& profile_path) {
+ // If the profile the app list uses just got deleted, reset it to the last
+ // used profile.
+ PrefService* local_state = g_browser_process->local_state();
+ std::string app_list_last_profile = local_state->GetString(
+ prefs::kAppListProfile);
+ if (profile_path.BaseName().MaybeAsASCII() == app_list_last_profile) {
+ local_state->SetString(prefs::kAppListProfile,
+ local_state->GetString(prefs::kProfileLastUsed));
+ }
+}
+
+void AppListController::SetProfilePath(const FilePath& profile_file_path) {
+ g_browser_process->local_state()->SetString(
+ prefs::kAppListProfile,
+ profile_file_path.BaseName().MaybeAsASCII());
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ Profile* profile = profile_manager->GetProfileByPath(profile_file_path);
+
+ if (!profile) {
+ LoadProfileAsync(profile_file_path);
+ return;
+ }
+
+ ShowAppList(profile);
+}
+
+void AppListController::LoadProfileAsync(const FilePath& profile_file_path) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ // Invalidate any pending profile path loads.
+ profile_load_sequence_id_++;
+
+ IncrementPendingProfileLoads();
+
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ profile_manager->CreateProfileAsync(
+ profile_file_path,
+ base::Bind(&AppListController::OnProfileLoaded,
+ weak_factory_.GetWeakPtr(), profile_load_sequence_id_),
+ string16(), string16(), false);
+}
+
+void AppListController::OnProfileLoaded(int profile_load_sequence_id,
+ Profile* profile,
+ Profile::CreateStatus status) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ switch (status) {
+ case Profile::CREATE_STATUS_CREATED:
+ break;
+ case Profile::CREATE_STATUS_INITIALIZED:
+ // Only show if there has been no other profile shown since this load
+ // started.
+ if (profile_load_sequence_id == profile_load_sequence_id_)
+ ShowAppList(profile);
+ DecrementPendingProfileLoads();
+ break;
+ case Profile::CREATE_STATUS_FAIL:
+ DecrementPendingProfileLoads();
+ break;
+ }
+
+}
+
+void AppListController::IncrementPendingProfileLoads() {
+ pending_profile_loads_++;
+ if (pending_profile_loads_ == 1)
+ browser::StartKeepAlive();
+}
+
+void AppListController::DecrementPendingProfileLoads() {
+ pending_profile_loads_--;
+ if (pending_profile_loads_ == 0)
+ browser::EndKeepAlive();
+}
+
+void AppListController::ShowAppList(Profile* profile) {
+ DCHECK(profile);
+
+ // Invalidate any pending profile path loads.
+ profile_load_sequence_id_++;
+
+ // Do nothing if the app list is already displaying |profile|.
+ if (app_list_is_showing_ && (profile == profile_))
+ return;
+
+ DismissAppList();
+ PopulateViewFromProfile(profile);
+
+ if (!app_list_is_showing_) {
+ app_list_is_showing_ = true;
+ browser::StartKeepAlive();
+ }
+
+ DCHECK(current_view_ && app_list_is_showing_);
+ gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
+ UpdateArrowPositionAndAnchorPoint(cursor);
+ current_view_->Show();
+ current_view_->GetWidget()->Activate();
+}
+
+void AppListController::InitView(Profile* profile) {
if (current_view_)
return;
+ PopulateViewFromProfile(profile);
+}
+void AppListController::PopulateViewFromProfile(Profile* profile) {
+#if !defined(USE_AURA)
+ if (profile == profile_)
+ return;
+ profile_ = profile;
// The controller will be owned by the view delegate, and the delegate is
// owned by the app list view. The app list view manages it's own lifetime.
current_view_ = new app_list::AppListView(
- new AppListViewDelegate(new AppListControllerDelegateWin()));
+ new AppListViewDelegate(new AppListControllerDelegateWin(), profile_));
gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
current_view_->InitAsBubble(GetDesktopWindow(),
&pagination_model_,
@@ -327,22 +499,6 @@ void AppListController::CreateAppList() {
#endif
}
-void AppListController::ShowAppList() {
-#if !defined(USE_AURA)
- if (!current_view_)
- CreateAppList();
-
- if (app_list_is_showing_)
- return;
- app_list_is_showing_ = true;
- browser::StartKeepAlive();
- gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
- UpdateArrowPositionAndAnchorPoint(cursor);
- current_view_->Show();
- current_view_->GetWidget()->Activate();
-#endif
-}
-
void AppListController::DismissAppList() {
if (current_view_ && app_list_is_showing_ && can_close_app_list_) {
current_view_->GetWidget()->Hide();
@@ -614,18 +770,18 @@ void CheckAppListTaskbarShortcutOnFileThread(const FilePath& user_data_dir,
}
}
-void CreateAppList() {
- g_app_list_controller.Get().CreateAppList();
+void InitView(Profile* profile) {
+ g_app_list_controller.Get().InitView(profile);
}
} // namespace
namespace chrome {
-void InitAppList() {
- // Check that the presence of the app list shortcut matches the flag
- // kShowAppListShortcut. This will either create or delete a shortcut
- // file in the user data directory.
+void InitAppList(Profile* profile) {
+ // Check that the app list shortcut matches the flag kShowAppListShortcut.
+ // This will either create or delete a shortcut file in the user data
+ // directory.
// TODO(benwells): Remove this and the flag once the app list installation
// is implemented.
static bool checked_shortcut = false;
@@ -639,18 +795,61 @@ void InitAppList() {
GetAppModelId()));
}
+ // Instantiate AppListController so it listens for profile deletions.
+ g_app_list_controller.Get();
+
// Post a task to create the app list. This is posted to not impact startup
// time.
const int kInitWindowDelay = 5;
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
- base::Bind(&CreateAppList),
+ base::Bind(&InitView, profile),
base::TimeDelta::FromSeconds(kInitWindowDelay));
}
-void ShowAppList() {
- // Create the App list.
- g_app_list_controller.Get().ShowAppList();
+void ShowAppList(Profile* profile) {
+ g_app_list_controller.Get().ShowAppList(profile);
+}
+
+void SetAppListProfile(const FilePath& profile_file_path) {
+ g_app_list_controller.Get().SetProfilePath(profile_file_path);
+}
+
+FilePath GetAppListProfilePath(const FilePath& user_data_dir) {
+ PrefService* local_state = g_browser_process->local_state();
+ DCHECK(local_state);
+
+ std::string app_list_profile;
+ if (local_state->HasPrefPath(prefs::kAppListProfile))
+ app_list_profile = local_state->GetString(prefs::kAppListProfile);
+
+ // If the user has no profile preference for the app launcher, default to the
+ // last browser profile used.
+ if (app_list_profile.empty() &&
+ local_state->HasPrefPath(prefs::kProfileLastUsed))
+ app_list_profile = local_state->GetString(prefs::kProfileLastUsed);
+
+ std::string profile_path = app_list_profile.empty() ?
+ chrome::kInitialProfile :
+ app_list_profile;
+
+ return user_data_dir.AppendASCII(profile_path);
+}
+
+void RegisterAppListPrefs(PrefServiceSimple* prefs) {
+ prefs->RegisterStringPref(prefs::kAppListProfile, "");
+}
+
+void DismissAppList() {
+ g_app_list_controller.Get().DismissAppList();
+}
+
+Profile* GetCurrentAppListProfile() {
+ return g_app_list_controller.Get().profile();
+}
+
+bool IsAppListVisible() {
+ return g_app_list_controller.Get().app_list_is_showing();
}
} // namespace chrome
« no previous file with comments | « chrome/browser/ui/startup/startup_browser_creator_impl.cc ('k') | chrome/browser/ui/webui/options/browser_options_handler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698