OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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 <set> | |
6 | |
7 #include "chrome/browser/profile_manager.h" | |
8 | |
9 #include "base/command_line.h" | |
10 #include "base/file_util.h" | |
11 #include "base/path_service.h" | |
12 #include "base/string_util.h" | |
13 #include "chrome/browser/browser_process.h" | |
14 #include "chrome/browser/browser_thread.h" | |
15 #include "chrome/browser/prefs/pref_service.h" | |
16 #include "chrome/browser/ui/browser.h" | |
17 #include "chrome/browser/ui/browser_list.h" | |
18 #include "chrome/browser/ui/browser_window.h" | |
19 #include "chrome/common/chrome_constants.h" | |
20 #include "chrome/common/chrome_paths.h" | |
21 #include "chrome/common/chrome_switches.h" | |
22 #include "chrome/common/logging_chrome.h" | |
23 #include "chrome/common/net/url_request_context_getter.h" | |
24 #include "chrome/common/notification_service.h" | |
25 #include "chrome/common/notification_type.h" | |
26 #include "chrome/common/pref_names.h" | |
27 #include "grit/generated_resources.h" | |
28 #include "net/http/http_transaction_factory.h" | |
29 #include "net/url_request/url_request_context.h" | |
30 #include "net/url_request/url_request_job.h" | |
31 #include "net/url_request/url_request_job_tracker.h" | |
32 | |
33 #if defined(OS_CHROMEOS) | |
34 #include "chrome/browser/chromeos/cros/cros_library.h" | |
35 #include "chrome/browser/chromeos/cros/cryptohome_library.h" | |
36 #endif | |
37 | |
38 // static | |
39 void ProfileManager::ShutdownSessionServices() { | |
40 ProfileManager* pm = g_browser_process->profile_manager(); | |
41 if (!pm) // Is NULL when running unit tests. | |
42 return; | |
43 for (ProfileManager::const_iterator i = pm->begin(); i != pm->end(); ++i) | |
44 (*i)->ShutdownSessionService(); | |
45 } | |
46 | |
47 // static | |
48 Profile* ProfileManager::GetDefaultProfile() { | |
49 FilePath user_data_dir; | |
50 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); | |
51 ProfileManager* profile_manager = g_browser_process->profile_manager(); | |
52 return profile_manager->GetDefaultProfile(user_data_dir); | |
53 } | |
54 | |
55 ProfileManager::ProfileManager() : logged_in_(false) { | |
56 SystemMonitor::Get()->AddObserver(this); | |
57 #if defined(OS_CHROMEOS) | |
58 registrar_.Add( | |
59 this, | |
60 NotificationType::LOGIN_USER_CHANGED, | |
61 NotificationService::AllSources()); | |
62 #endif | |
63 } | |
64 | |
65 ProfileManager::~ProfileManager() { | |
66 SystemMonitor* system_monitor = SystemMonitor::Get(); | |
67 if (system_monitor) | |
68 system_monitor->RemoveObserver(this); | |
69 | |
70 // Destroy all profiles that we're keeping track of. | |
71 for (const_iterator i(begin()); i != end(); ++i) | |
72 delete *i; | |
73 profiles_.clear(); | |
74 } | |
75 | |
76 FilePath ProfileManager::GetDefaultProfileDir( | |
77 const FilePath& user_data_dir) { | |
78 FilePath default_profile_dir(user_data_dir); | |
79 default_profile_dir = default_profile_dir.Append( | |
80 FilePath::FromWStringHack(chrome::kNotSignedInProfile)); | |
81 return default_profile_dir; | |
82 } | |
83 | |
84 FilePath ProfileManager::GetProfilePrefsPath( | |
85 const FilePath &profile_dir) { | |
86 FilePath default_prefs_path(profile_dir); | |
87 default_prefs_path = default_prefs_path.Append(chrome::kPreferencesFilename); | |
88 return default_prefs_path; | |
89 } | |
90 | |
91 FilePath ProfileManager::GetCurrentProfileDir() { | |
92 FilePath relative_profile_dir; | |
93 #if defined(OS_CHROMEOS) | |
94 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
95 if (logged_in_) { | |
96 FilePath profile_dir; | |
97 // If the user has logged in, pick up the new profile. | |
98 if (command_line.HasSwitch(switches::kLoginProfile)) { | |
99 profile_dir = command_line.GetSwitchValuePath(switches::kLoginProfile); | |
100 } else { | |
101 // We should never be logged in with no profile dir. | |
102 NOTREACHED(); | |
103 return FilePath(""); | |
104 } | |
105 relative_profile_dir = relative_profile_dir.Append(profile_dir); | |
106 return relative_profile_dir; | |
107 } | |
108 #endif | |
109 relative_profile_dir = relative_profile_dir.Append( | |
110 FilePath::FromWStringHack(chrome::kNotSignedInProfile)); | |
111 return relative_profile_dir; | |
112 } | |
113 | |
114 Profile* ProfileManager::GetDefaultProfile(const FilePath& user_data_dir) { | |
115 FilePath default_profile_dir(user_data_dir); | |
116 default_profile_dir = default_profile_dir.Append(GetCurrentProfileDir()); | |
117 #if defined(OS_CHROMEOS) | |
118 if (!logged_in_) { | |
119 Profile* profile; | |
120 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
121 | |
122 // For cros, return the OTR profile so we never accidentally keep | |
123 // user data in an unencrypted profile. But doing this makes | |
124 // many of the browser and ui tests fail. We do return the OTR profile | |
125 // if the login-profile switch is passed so that we can test this. | |
126 // TODO(davemoore) Fix the tests so they allow OTR profiles. | |
127 if (!command_line.HasSwitch(switches::kTestType) || | |
128 command_line.HasSwitch(switches::kLoginProfile)) { | |
129 // Don't init extensions for this profile | |
130 profile = GetProfile(default_profile_dir, false); | |
131 profile = profile->GetOffTheRecordProfile(); | |
132 } else { | |
133 profile = GetProfile(default_profile_dir, true); | |
134 } | |
135 return profile; | |
136 } | |
137 #endif | |
138 return GetProfile(default_profile_dir); | |
139 } | |
140 | |
141 Profile* ProfileManager::GetProfile(const FilePath& profile_dir) { | |
142 return GetProfile(profile_dir, true); | |
143 } | |
144 | |
145 Profile* ProfileManager::GetProfile( | |
146 const FilePath& profile_dir, bool init_extensions) { | |
147 // If the profile is already loaded (e.g., chrome.exe launched twice), just | |
148 // return it. | |
149 Profile* profile = GetProfileByPath(profile_dir); | |
150 if (NULL != profile) | |
151 return profile; | |
152 | |
153 if (!ProfileManager::IsProfile(profile_dir)) { | |
154 // If the profile directory doesn't exist, create it. | |
155 profile = ProfileManager::CreateProfile(profile_dir); | |
156 } else { | |
157 // The profile already exists on disk, just load it. | |
158 profile = Profile::CreateProfile(profile_dir); | |
159 } | |
160 DCHECK(profile); | |
161 if (profile) { | |
162 bool result = AddProfile(profile, init_extensions); | |
163 DCHECK(result); | |
164 } | |
165 return profile; | |
166 } | |
167 | |
168 bool ProfileManager::AddProfile(Profile* profile, bool init_extensions) { | |
169 DCHECK(profile); | |
170 | |
171 // Make sure that we're not loading a profile with the same ID as a profile | |
172 // that's already loaded. | |
173 if (GetProfileByPath(profile->GetPath())) { | |
174 NOTREACHED() << "Attempted to add profile with the same path (" << | |
175 profile->GetPath().value() << | |
176 ") as an already-loaded profile."; | |
177 return false; | |
178 } | |
179 | |
180 profiles_.insert(profiles_.end(), profile); | |
181 if (init_extensions) | |
182 profile->InitExtensions(); | |
183 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
184 if (!command_line.HasSwitch(switches::kDisableWebResources)) | |
185 profile->InitWebResources(); | |
186 return true; | |
187 } | |
188 | |
189 Profile* ProfileManager::GetProfileByPath(const FilePath& path) const { | |
190 for (const_iterator i(begin()); i != end(); ++i) { | |
191 if ((*i)->GetPath() == path) | |
192 return *i; | |
193 } | |
194 | |
195 return NULL; | |
196 } | |
197 | |
198 void ProfileManager::OnSuspend() { | |
199 DCHECK(CalledOnValidThread()); | |
200 | |
201 for (const_iterator i(begin()); i != end(); ++i) { | |
202 BrowserThread::PostTask( | |
203 BrowserThread::IO, FROM_HERE, | |
204 NewRunnableFunction(&ProfileManager::SuspendProfile, *i)); | |
205 } | |
206 } | |
207 | |
208 void ProfileManager::OnResume() { | |
209 DCHECK(CalledOnValidThread()); | |
210 for (const_iterator i(begin()); i != end(); ++i) { | |
211 BrowserThread::PostTask( | |
212 BrowserThread::IO, FROM_HERE, | |
213 NewRunnableFunction(&ProfileManager::ResumeProfile, *i)); | |
214 } | |
215 } | |
216 | |
217 void ProfileManager::Observe( | |
218 NotificationType type, | |
219 const NotificationSource& source, | |
220 const NotificationDetails& details) { | |
221 #if defined(OS_CHROMEOS) | |
222 if (type == NotificationType::LOGIN_USER_CHANGED) { | |
223 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
224 if (!command_line.HasSwitch(switches::kTestType)) { | |
225 // This will fail when running on non cros os. | |
226 // TODO(davemoore) Need to mock this enough to enable testing. | |
227 CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); | |
228 // If we don't have a mounted profile directory we're in trouble. | |
229 // TODO(davemoore) Once we have better api this check should ensure that | |
230 // our profile directory is the one that's mounted, and that it's mounted | |
231 // as the current user. | |
232 CHECK(chromeos::CrosLibrary::Get()->GetCryptohomeLibrary()->IsMounted()); | |
233 } | |
234 logged_in_ = true; | |
235 } | |
236 #endif | |
237 } | |
238 | |
239 void ProfileManager::SuspendProfile(Profile* profile) { | |
240 DCHECK(profile); | |
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
242 | |
243 for (URLRequestJobTracker::JobIterator i = g_url_request_job_tracker.begin(); | |
244 i != g_url_request_job_tracker.end(); ++i) | |
245 (*i)->Kill(); | |
246 | |
247 profile->GetRequestContext()->GetURLRequestContext()-> | |
248 http_transaction_factory()->Suspend(true); | |
249 } | |
250 | |
251 void ProfileManager::ResumeProfile(Profile* profile) { | |
252 DCHECK(profile); | |
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
254 profile->GetRequestContext()->GetURLRequestContext()-> | |
255 http_transaction_factory()->Suspend(false); | |
256 } | |
257 | |
258 // static | |
259 bool ProfileManager::IsProfile(const FilePath& path) { | |
260 FilePath prefs_path = GetProfilePrefsPath(path); | |
261 FilePath history_path = path; | |
262 history_path = history_path.Append(chrome::kHistoryFilename); | |
263 | |
264 return file_util::PathExists(prefs_path) && | |
265 file_util::PathExists(history_path); | |
266 } | |
267 | |
268 // static | |
269 Profile* ProfileManager::CreateProfile(const FilePath& path) { | |
270 if (IsProfile(path)) { | |
271 DCHECK(false) << "Attempted to create a profile with the path:\n" | |
272 << path.value() << "\n but that path already contains a profile"; | |
273 } | |
274 | |
275 if (!file_util::PathExists(path)) { | |
276 // TODO(tc): http://b/1094718 Bad things happen if we can't write to the | |
277 // profile directory. We should eventually be able to run in this | |
278 // situation. | |
279 if (!file_util::CreateDirectory(path)) | |
280 return NULL; | |
281 } | |
282 | |
283 return Profile::CreateProfile(path); | |
284 } | |
OLD | NEW |