| 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 |