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

Side by Side Diff: chrome/browser/user_data_manager.cc

Issue 12895: Chromium-MultiProfile-Prototype... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/user_data_manager.h ('k') | chrome/browser/views/browser_views.vcproj » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/user_data_manager.h"
6
7 #include <windows.h>
8 #include <string>
9
10 #include "base/command_line.h"
11 #include "base/file_util.h"
12 #include "base/logging.h"
13 #include "base/message_loop.h"
14 #include "base/path_service.h"
15 #include "base/process_util.h"
16 #include "base/string_util.h"
17 #include "chrome/browser/chrome_thread.h"
18 #include "chrome/common/chrome_constants.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/l10n_util.h"
22 #include "chrome/installer/util/browser_distribution.h"
23 #include "chrome/installer/util/shell_util.h"
24
25 #include "chromium_strings.h"
26
27 namespace {
28
29 // Helper to start chrome for a given profile index. The helper takes care of
30 // enumerating profiles on the file thread and then it launches Chrome for the
31 // appropriate profile on the original thread.
32 // An instance of this class should always be created on the heap, and it will
33 // delete itself when the launch is done.
34 class LaunchChromeForProfileIndexHelper : GetProfilesHelper::Delegate {
35 public:
36 // Creates an instance with the given data manager and to launch chrome for
37 // the profile with the given index.
38 LaunchChromeForProfileIndexHelper(const UserDataManager* manager, int index);
39 virtual ~LaunchChromeForProfileIndexHelper();
40
41 // Starts the asynchronous launch.
42 void StartLaunch();
43
44 // GetProfilesHelper::Delegate method.
45 void OnGetProfilesDone(const std::vector<std::wstring>& profiles);
46
47 private:
48 int index_;
49 const UserDataManager* manager_;
50 scoped_refptr<GetProfilesHelper> profiles_helper_;
51
52 DISALLOW_COPY_AND_ASSIGN(LaunchChromeForProfileIndexHelper);
53 };
54
55 } // namespace
56
57 LaunchChromeForProfileIndexHelper::LaunchChromeForProfileIndexHelper(
58 const UserDataManager* manager,
59 int index)
60 : manager_(manager),
61 index_(index),
62 profiles_helper_(new GetProfilesHelper(this)) {
63 DCHECK(manager);
64 }
65
66 LaunchChromeForProfileIndexHelper::~LaunchChromeForProfileIndexHelper() {
67 profiles_helper_->OnDelegateDeleted();
68 }
69
70 void LaunchChromeForProfileIndexHelper::StartLaunch() {
71 profiles_helper_->GetProfiles(NULL);
72 }
73
74 void LaunchChromeForProfileIndexHelper::OnGetProfilesDone(
75 const std::vector<std::wstring>& profiles) {
76 if (index_ >= 0 && index_ < static_cast<int>(profiles.size()))
77 manager_->LaunchChromeForProfile(profiles[index_]);
78
79 // We are done, delete ourselves.
80 delete this;
81 }
82
83 // Separator used in folder names between the prefix and the profile name.
84 // For e.g. a folder for the profile "Joe" would be named "User Data-Joe".
85 static const wchar_t kProfileFolderSeparator[] = L"-";
86
87 // static
88 UserDataManager* UserDataManager::instance_ = NULL;
89
90 // static
91 void UserDataManager::Create() {
92 DCHECK(!instance_);
93 std::wstring user_data;
94 PathService::Get(chrome::DIR_USER_DATA, &user_data);
95 instance_ = new UserDataManager(user_data);
96 }
97
98 // static
99 UserDataManager* UserDataManager::Get() {
100 DCHECK(instance_);
101 return instance_;
102 }
103
104 UserDataManager::UserDataManager(const std::wstring& user_data_root)
105 : user_data_root_(user_data_root) {
106 // Determine current profile name, current folder name and whether the current
107 // profile is the default.
108 current_folder_name_ = file_util::GetFilenameFromPath(user_data_root);
109 is_current_profile_default_ =
110 (current_folder_name_ == chrome::kUserDataDirname);
111 bool success = GetProfileNameFromFolderName(current_folder_name_,
112 &current_profile_name_);
113 DCHECK(success);
114 file_util::UpOneDirectory(&user_data_root_);
115 }
116
117 UserDataManager::~UserDataManager() {
118 }
119
120 // static
121 bool UserDataManager::GetProfileNameFromFolderName(
122 const std::wstring& folder_name,
123 std::wstring* profile_name) {
124 // The folder name should start with a specific prefix for it to be a valid
125 // profile folder.
126 if (folder_name.find(chrome::kUserDataDirname) != 0)
127 return false;
128
129 // Seems like we cannot use arraysize macro for externally defined constants.
130 // Is there a way?
131 unsigned int prefix_length = wcslen(chrome::kUserDataDirname);
132 // Subtract 1 from the size of the array for trailing null character.
133 unsigned int separator_length = arraysize(kProfileFolderSeparator) - 1;
134
135 // It's safe to use profile_name variable for intermediate values since we
136 // will always return true now.
137 *profile_name = folder_name.substr(prefix_length);
138 // Remove leading separator if present.
139 if (profile_name->find_first_of(kProfileFolderSeparator) == 0)
140 *profile_name = profile_name->substr(separator_length);
141
142 if (profile_name->empty())
143 *profile_name = chrome::kNotSignedInProfile;
144
145 return true;
146 }
147
148 // static
149 std::wstring UserDataManager::GetFolderNameFromProfileName(
150 const std::wstring& profile_name) {
151 std::wstring folder_name = chrome::kUserDataDirname;
152 if (profile_name != chrome::kNotSignedInProfile) {
153 folder_name += kProfileFolderSeparator;
154 folder_name += profile_name;
155 }
156 return folder_name;
157 }
158
159 std::wstring UserDataManager::GetUserDataFolderForProfile(
160 const std::wstring& profile_name) const {
161 std::wstring folder_name = GetFolderNameFromProfileName(profile_name);
162 std::wstring folder_path(user_data_root_);
163 file_util::AppendToPath(&folder_path, folder_name);
164 return folder_path;
165 }
166
167 std::wstring UserDataManager::GetCommandForProfile(
168 const std::wstring& profile_name) const {
169 std::wstring user_data_dir = GetUserDataFolderForProfile(profile_name);
170 std::wstring command;
171 PathService::Get(base::FILE_EXE, &command);
172 CommandLine::AppendSwitchWithValue(&command,
173 switches::kUserDataDir,
174 user_data_dir);
175 std::wstring local_state_path;
176 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
177 CommandLine::AppendSwitchWithValue(&command,
178 switches::kParentProfile,
179 local_state_path);
180 return command;
181 }
182
183 void UserDataManager::LaunchChromeForProfile(
184 const std::wstring& profile_name) const {
185 std::wstring command = GetCommandForProfile(profile_name);
186 base::LaunchApp(command, false, false, NULL);
187 }
188
189 void UserDataManager::LaunchChromeForProfile(int index) const {
190 // Helper deletes itself when done.
191 LaunchChromeForProfileIndexHelper* helper =
192 new LaunchChromeForProfileIndexHelper(this, index);
193 helper->StartLaunch();
194 }
195
196 void UserDataManager::GetProfiles(std::vector<std::wstring>* profiles) const {
197 // This function should be called on the file thread.
198 DCHECK(MessageLoop::current() ==
199 ChromeThread::GetMessageLoop(ChromeThread::FILE));
200 file_util::FileEnumerator file_enum(user_data_root_,
201 false,
202 file_util::FileEnumerator::DIRECTORIES);
203 std::wstring folder_name;
204 while (!(folder_name = file_enum.Next()).empty()) {
205 folder_name = file_util::GetFilenameFromPath(folder_name);
206 std::wstring profile_name;
207 if (GetProfileNameFromFolderName(folder_name, &profile_name))
208 profiles->push_back(profile_name);
209 }
210 }
211
212 bool UserDataManager::CreateDesktopShortcutForProfile(
213 const std::wstring& profile_name) const {
214 std::wstring exe_path;
215 std::wstring shortcut_path;
216 if (!PathService::Get(base::FILE_EXE, &exe_path) ||
217 !ShellUtil::GetDesktopPath(false, &shortcut_path))
218 return false;
219
220 // Working directory.
221 std::wstring exe_folder = file_util::GetDirectoryFromPath(exe_path);
222
223 // Command and arguments.
224 std::wstring cmd;
225 cmd = StringPrintf(L"\"%ls\"", exe_path.c_str());
226 std::wstring user_data_dir = GetUserDataFolderForProfile(profile_name);
227 std::wstring args = CommandLine::PrefixedSwitchStringWithValue(
228 switches::kUserDataDir,
229 user_data_dir);
230 args = StringPrintf(L"\"%ls\"", args.c_str());
231
232 // Shortcut path.
233 std::wstring shortcut_name = l10n_util::GetStringF(
234 IDS_START_IN_PROFILE_SHORTCUT_NAME,
235 profile_name);
236 shortcut_name.append(L".lnk");
237 file_util::AppendToPath(&shortcut_path, shortcut_name);
238
239 return file_util::CreateShortcutLink(cmd.c_str(),
240 shortcut_path.c_str(),
241 exe_folder.c_str(),
242 args.c_str(),
243 NULL,
244 exe_path.c_str(),
245 0);
246 }
247
248 GetProfilesHelper::GetProfilesHelper(Delegate* delegate)
249 : delegate_(delegate) {
250 }
251
252 void GetProfilesHelper::GetProfiles(MessageLoop* target_loop) {
253 // If the target loop is not NULL then use the target loop, or if it's NULL
254 // then use the current message loop to post a task on it later when we are
255 // done building a list of profiles.
256 if (target_loop) {
257 message_loop_ = target_loop;
258 } else {
259 message_loop_ = MessageLoop::current();
260 }
261 DCHECK(message_loop_);
262 MessageLoop* file_loop = ChromeThread::GetMessageLoop(ChromeThread::FILE);
263 file_loop->PostTask(
264 FROM_HERE,
265 NewRunnableMethod(this, &GetProfilesHelper::GetProfilesFromManager));
266 }
267
268 // Records that the delegate is closed.
269 void GetProfilesHelper::OnDelegateDeleted() {
270 delegate_ = NULL;
271 }
272
273 void GetProfilesHelper::GetProfilesFromManager() {
274 // This function should be called on the file thread.
275 DCHECK(MessageLoop::current() ==
276 ChromeThread::GetMessageLoop(ChromeThread::FILE));
277
278 // If the delegate is gone by now, no need to do any work.
279 if (!delegate_)
280 return;
281
282 scoped_ptr<std::vector<std::wstring>> profiles(new std::vector<std::wstring>);
283 UserDataManager::Get()->GetProfiles(profiles.get());
284
285 // Post a task on the original thread to call the delegate.
286 message_loop_->PostTask(
287 FROM_HERE,
288 NewRunnableMethod(this,
289 &GetProfilesHelper::InvokeDelegate,
290 profiles.release()));
291 }
292
293 void GetProfilesHelper::InvokeDelegate(std::vector<std::wstring>* profiles) {
294 scoped_ptr<std::vector<std::wstring>> udd_profiles(profiles);
295 // If the delegate is gone by now, no need to do any work.
296 if (delegate_)
297 delegate_->OnGetProfilesDone(*udd_profiles.get());
298 }
OLDNEW
« no previous file with comments | « chrome/browser/user_data_manager.h ('k') | chrome/browser/views/browser_views.vcproj » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698