Index: chrome/browser/user_data_manager.cc |
=================================================================== |
--- chrome/browser/user_data_manager.cc (revision 0) |
+++ chrome/browser/user_data_manager.cc (revision 0) |
@@ -0,0 +1,298 @@ |
+// Copyright (c) 2006-2008 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/user_data_manager.h" |
+ |
+#include <windows.h> |
+#include <string> |
+ |
+#include "base/command_line.h" |
+#include "base/file_util.h" |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "base/path_service.h" |
+#include "base/process_util.h" |
+#include "base/string_util.h" |
+#include "chrome/browser/chrome_thread.h" |
+#include "chrome/common/chrome_constants.h" |
+#include "chrome/common/chrome_paths.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "chrome/common/l10n_util.h" |
+#include "chrome/installer/util/browser_distribution.h" |
+#include "chrome/installer/util/shell_util.h" |
+ |
+#include "chromium_strings.h" |
+ |
+namespace { |
+ |
+// Helper to start chrome for a given profile index. The helper takes care of |
+// enumerating profiles on the file thread and then it launches Chrome for the |
+// appropriate profile on the original thread. |
+// An instance of this class should always be created on the heap, and it will |
+// delete itself when the launch is done. |
+class LaunchChromeForProfileIndexHelper : GetProfilesHelper::Delegate { |
+ public: |
+ // Creates an instance with the given data manager and to launch chrome for |
+ // the profile with the given index. |
+ LaunchChromeForProfileIndexHelper(const UserDataManager* manager, int index); |
+ virtual ~LaunchChromeForProfileIndexHelper(); |
+ |
+ // Starts the asynchronous launch. |
+ void StartLaunch(); |
+ |
+ // GetProfilesHelper::Delegate method. |
+ void OnGetProfilesDone(const std::vector<std::wstring>& profiles); |
+ |
+ private: |
+ int index_; |
+ const UserDataManager* manager_; |
+ scoped_refptr<GetProfilesHelper> profiles_helper_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(LaunchChromeForProfileIndexHelper); |
+}; |
+ |
+} // namespace |
+ |
+LaunchChromeForProfileIndexHelper::LaunchChromeForProfileIndexHelper( |
+ const UserDataManager* manager, |
+ int index) |
+ : manager_(manager), |
+ index_(index), |
+ profiles_helper_(new GetProfilesHelper(this)) { |
+ DCHECK(manager); |
+} |
+ |
+LaunchChromeForProfileIndexHelper::~LaunchChromeForProfileIndexHelper() { |
+ profiles_helper_->OnDelegateDeleted(); |
+} |
+ |
+void LaunchChromeForProfileIndexHelper::StartLaunch() { |
+ profiles_helper_->GetProfiles(NULL); |
+} |
+ |
+void LaunchChromeForProfileIndexHelper::OnGetProfilesDone( |
+ const std::vector<std::wstring>& profiles) { |
+ if (index_ >= 0 && index_ < static_cast<int>(profiles.size())) |
+ manager_->LaunchChromeForProfile(profiles[index_]); |
+ |
+ // We are done, delete ourselves. |
+ delete this; |
+} |
+ |
+// Separator used in folder names between the prefix and the profile name. |
+// For e.g. a folder for the profile "Joe" would be named "User Data-Joe". |
+static const wchar_t kProfileFolderSeparator[] = L"-"; |
+ |
+// static |
+UserDataManager* UserDataManager::instance_ = NULL; |
+ |
+// static |
+void UserDataManager::Create() { |
+ DCHECK(!instance_); |
+ std::wstring user_data; |
+ PathService::Get(chrome::DIR_USER_DATA, &user_data); |
+ instance_ = new UserDataManager(user_data); |
+} |
+ |
+// static |
+UserDataManager* UserDataManager::Get() { |
+ DCHECK(instance_); |
+ return instance_; |
+} |
+ |
+UserDataManager::UserDataManager(const std::wstring& user_data_root) |
+ : user_data_root_(user_data_root) { |
+ // Determine current profile name, current folder name and whether the current |
+ // profile is the default. |
+ current_folder_name_ = file_util::GetFilenameFromPath(user_data_root); |
+ is_current_profile_default_ = |
+ (current_folder_name_ == chrome::kUserDataDirname); |
+ bool success = GetProfileNameFromFolderName(current_folder_name_, |
+ ¤t_profile_name_); |
+ DCHECK(success); |
+ file_util::UpOneDirectory(&user_data_root_); |
+} |
+ |
+UserDataManager::~UserDataManager() { |
+} |
+ |
+// static |
+bool UserDataManager::GetProfileNameFromFolderName( |
+ const std::wstring& folder_name, |
+ std::wstring* profile_name) { |
+ // The folder name should start with a specific prefix for it to be a valid |
+ // profile folder. |
+ if (folder_name.find(chrome::kUserDataDirname) != 0) |
+ return false; |
+ |
+ // Seems like we cannot use arraysize macro for externally defined constants. |
+ // Is there a way? |
+ unsigned int prefix_length = wcslen(chrome::kUserDataDirname); |
+ // Subtract 1 from the size of the array for trailing null character. |
+ unsigned int separator_length = arraysize(kProfileFolderSeparator) - 1; |
+ |
+ // It's safe to use profile_name variable for intermediate values since we |
+ // will always return true now. |
+ *profile_name = folder_name.substr(prefix_length); |
+ // Remove leading separator if present. |
+ if (profile_name->find_first_of(kProfileFolderSeparator) == 0) |
+ *profile_name = profile_name->substr(separator_length); |
+ |
+ if (profile_name->empty()) |
+ *profile_name = chrome::kNotSignedInProfile; |
+ |
+ return true; |
+} |
+ |
+// static |
+std::wstring UserDataManager::GetFolderNameFromProfileName( |
+ const std::wstring& profile_name) { |
+ std::wstring folder_name = chrome::kUserDataDirname; |
+ if (profile_name != chrome::kNotSignedInProfile) { |
+ folder_name += kProfileFolderSeparator; |
+ folder_name += profile_name; |
+ } |
+ return folder_name; |
+} |
+ |
+std::wstring UserDataManager::GetUserDataFolderForProfile( |
+ const std::wstring& profile_name) const { |
+ std::wstring folder_name = GetFolderNameFromProfileName(profile_name); |
+ std::wstring folder_path(user_data_root_); |
+ file_util::AppendToPath(&folder_path, folder_name); |
+ return folder_path; |
+} |
+ |
+std::wstring UserDataManager::GetCommandForProfile( |
+ const std::wstring& profile_name) const { |
+ std::wstring user_data_dir = GetUserDataFolderForProfile(profile_name); |
+ std::wstring command; |
+ PathService::Get(base::FILE_EXE, &command); |
+ CommandLine::AppendSwitchWithValue(&command, |
+ switches::kUserDataDir, |
+ user_data_dir); |
+ std::wstring local_state_path; |
+ PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); |
+ CommandLine::AppendSwitchWithValue(&command, |
+ switches::kParentProfile, |
+ local_state_path); |
+ return command; |
+} |
+ |
+void UserDataManager::LaunchChromeForProfile( |
+ const std::wstring& profile_name) const { |
+ std::wstring command = GetCommandForProfile(profile_name); |
+ base::LaunchApp(command, false, false, NULL); |
+} |
+ |
+void UserDataManager::LaunchChromeForProfile(int index) const { |
+ // Helper deletes itself when done. |
+ LaunchChromeForProfileIndexHelper* helper = |
+ new LaunchChromeForProfileIndexHelper(this, index); |
+ helper->StartLaunch(); |
+} |
+ |
+void UserDataManager::GetProfiles(std::vector<std::wstring>* profiles) const { |
+ // This function should be called on the file thread. |
+ DCHECK(MessageLoop::current() == |
+ ChromeThread::GetMessageLoop(ChromeThread::FILE)); |
+ file_util::FileEnumerator file_enum(user_data_root_, |
+ false, |
+ file_util::FileEnumerator::DIRECTORIES); |
+ std::wstring folder_name; |
+ while (!(folder_name = file_enum.Next()).empty()) { |
+ folder_name = file_util::GetFilenameFromPath(folder_name); |
+ std::wstring profile_name; |
+ if (GetProfileNameFromFolderName(folder_name, &profile_name)) |
+ profiles->push_back(profile_name); |
+ } |
+} |
+ |
+bool UserDataManager::CreateDesktopShortcutForProfile( |
+ const std::wstring& profile_name) const { |
+ std::wstring exe_path; |
+ std::wstring shortcut_path; |
+ if (!PathService::Get(base::FILE_EXE, &exe_path) || |
+ !ShellUtil::GetDesktopPath(false, &shortcut_path)) |
+ return false; |
+ |
+ // Working directory. |
+ std::wstring exe_folder = file_util::GetDirectoryFromPath(exe_path); |
+ |
+ // Command and arguments. |
+ std::wstring cmd; |
+ cmd = StringPrintf(L"\"%ls\"", exe_path.c_str()); |
+ std::wstring user_data_dir = GetUserDataFolderForProfile(profile_name); |
+ std::wstring args = CommandLine::PrefixedSwitchStringWithValue( |
+ switches::kUserDataDir, |
+ user_data_dir); |
+ args = StringPrintf(L"\"%ls\"", args.c_str()); |
+ |
+ // Shortcut path. |
+ std::wstring shortcut_name = l10n_util::GetStringF( |
+ IDS_START_IN_PROFILE_SHORTCUT_NAME, |
+ profile_name); |
+ shortcut_name.append(L".lnk"); |
+ file_util::AppendToPath(&shortcut_path, shortcut_name); |
+ |
+ return file_util::CreateShortcutLink(cmd.c_str(), |
+ shortcut_path.c_str(), |
+ exe_folder.c_str(), |
+ args.c_str(), |
+ NULL, |
+ exe_path.c_str(), |
+ 0); |
+} |
+ |
+GetProfilesHelper::GetProfilesHelper(Delegate* delegate) |
+ : delegate_(delegate) { |
+} |
+ |
+void GetProfilesHelper::GetProfiles(MessageLoop* target_loop) { |
+ // If the target loop is not NULL then use the target loop, or if it's NULL |
+ // then use the current message loop to post a task on it later when we are |
+ // done building a list of profiles. |
+ if (target_loop) { |
+ message_loop_ = target_loop; |
+ } else { |
+ message_loop_ = MessageLoop::current(); |
+ } |
+ DCHECK(message_loop_); |
+ MessageLoop* file_loop = ChromeThread::GetMessageLoop(ChromeThread::FILE); |
+ file_loop->PostTask( |
+ FROM_HERE, |
+ NewRunnableMethod(this, &GetProfilesHelper::GetProfilesFromManager)); |
+} |
+ |
+// Records that the delegate is closed. |
+void GetProfilesHelper::OnDelegateDeleted() { |
+ delegate_ = NULL; |
+} |
+ |
+void GetProfilesHelper::GetProfilesFromManager() { |
+ // This function should be called on the file thread. |
+ DCHECK(MessageLoop::current() == |
+ ChromeThread::GetMessageLoop(ChromeThread::FILE)); |
+ |
+ // If the delegate is gone by now, no need to do any work. |
+ if (!delegate_) |
+ return; |
+ |
+ scoped_ptr<std::vector<std::wstring>> profiles(new std::vector<std::wstring>); |
+ UserDataManager::Get()->GetProfiles(profiles.get()); |
+ |
+ // Post a task on the original thread to call the delegate. |
+ message_loop_->PostTask( |
+ FROM_HERE, |
+ NewRunnableMethod(this, |
+ &GetProfilesHelper::InvokeDelegate, |
+ profiles.release())); |
+} |
+ |
+void GetProfilesHelper::InvokeDelegate(std::vector<std::wstring>* profiles) { |
+ scoped_ptr<std::vector<std::wstring>> udd_profiles(profiles); |
+ // If the delegate is gone by now, no need to do any work. |
+ if (delegate_) |
+ delegate_->OnGetProfilesDone(*udd_profiles.get()); |
+} |
Property changes on: chrome\browser\user_data_manager.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |