Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/profiles/profile_manager.h" | 5 #include "chrome/browser/profiles/profile_manager.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <map> | |
| 9 #include <set> | 10 #include <set> |
| 10 #include <string> | 11 #include <string> |
| 11 | 12 |
| 12 #include "base/bind.h" | 13 #include "base/bind.h" |
| 13 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 14 #include "base/deferred_sequenced_task_runner.h" | 15 #include "base/deferred_sequenced_task_runner.h" |
| 15 #include "base/feature_list.h" | 16 #include "base/feature_list.h" |
| 16 #include "base/files/file_enumerator.h" | 17 #include "base/files/file_enumerator.h" |
| 17 #include "base/files/file_path.h" | 18 #include "base/files/file_path.h" |
| 18 #include "base/files/file_util.h" | 19 #include "base/files/file_util.h" |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) | 124 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) |
| 124 #include "chrome/browser/profiles/profile_statistics.h" | 125 #include "chrome/browser/profiles/profile_statistics.h" |
| 125 #include "chrome/browser/profiles/profile_statistics_factory.h" | 126 #include "chrome/browser/profiles/profile_statistics_factory.h" |
| 126 #endif | 127 #endif |
| 127 | 128 |
| 128 using base::UserMetricsAction; | 129 using base::UserMetricsAction; |
| 129 using content::BrowserThread; | 130 using content::BrowserThread; |
| 130 | 131 |
| 131 namespace { | 132 namespace { |
| 132 | 133 |
| 133 // Profiles that should be deleted on shutdown. | 134 // Profile deletion can pass through two stages: |
| 134 std::vector<base::FilePath>& ProfilesToDelete() { | 135 enum class ProfileDeletionStage { |
| 135 CR_DEFINE_STATIC_LOCAL(std::vector<base::FilePath>, profiles_to_delete, ()); | 136 // At SCHEDULED stage will be performed necessary activity prior to |
| 137 // profile deletion. Such as new profile creation, if none is left, or load | |
| 138 // fallback profile for Macs, if it not loaded yet. | |
| 139 SCHEDULED, | |
| 140 // At ABANDONED stage profile can be safely removed from disk. | |
| 141 ABANDONED | |
|
Bernhard Bauer
2016/08/04 16:28:36
MARKED maybe?
| |
| 142 }; | |
| 143 using ProfileDeletionMap = std::map<base::FilePath, ProfileDeletionStage>; | |
| 144 ProfileDeletionMap& ProfilesToDelete() { | |
| 145 CR_DEFINE_STATIC_LOCAL(ProfileDeletionMap, profiles_to_delete, ()); | |
| 136 return profiles_to_delete; | 146 return profiles_to_delete; |
| 137 } | 147 } |
| 138 | 148 |
| 139 int64_t ComputeFilesSize(const base::FilePath& directory, | 149 int64_t ComputeFilesSize(const base::FilePath& directory, |
| 140 const base::FilePath::StringType& pattern) { | 150 const base::FilePath::StringType& pattern) { |
| 141 int64_t running_size = 0; | 151 int64_t running_size = 0; |
| 142 base::FileEnumerator iter(directory, false, base::FileEnumerator::FILES, | 152 base::FileEnumerator iter(directory, false, base::FileEnumerator::FILES, |
| 143 pattern); | 153 pattern); |
| 144 while (!iter.Next().empty()) | 154 while (!iter.Next().empty()) |
| 145 running_size += iter.GetInfo().GetSize(); | 155 running_size += iter.GetInfo().GetSize(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 194 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Policy")); | 204 size = ComputeFilesSize(path, FILE_PATH_LITERAL("Policy")); |
| 195 size_MB = static_cast<int>(size / kBytesInOneMB); | 205 size_MB = static_cast<int>(size / kBytesInOneMB); |
| 196 UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB); | 206 UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB); |
| 197 | 207 |
| 198 // Count number of enabled apps in this profile, if we know. | 208 // Count number of enabled apps in this profile, if we know. |
| 199 if (enabled_app_count != -1) | 209 if (enabled_app_count != -1) |
| 200 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", enabled_app_count); | 210 UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", enabled_app_count); |
| 201 } | 211 } |
| 202 | 212 |
| 203 #if !defined(OS_ANDROID) | 213 #if !defined(OS_ANDROID) |
| 204 void QueueProfileDirectoryForDeletion(const base::FilePath& path) { | 214 // Schedule a profile for deletion if it isn't already scheduled. |
| 205 ProfilesToDelete().push_back(path); | 215 // Returns whether the profile has been newly scheduled. |
| 216 bool ScheduleProfileDirectoryForDeletion(const base::FilePath& path) { | |
| 217 if (ContainsKey(ProfilesToDelete(), path)) | |
| 218 return false; | |
| 219 ProfilesToDelete()[path] = ProfileDeletionStage::SCHEDULED; | |
| 220 return true; | |
| 221 } | |
| 222 | |
| 223 void MarkProfileDirectoryForDeletion(const base::FilePath& path) { | |
| 224 DCHECK(!ContainsKey(ProfilesToDelete(), path) || | |
| 225 ProfilesToDelete()[path] == ProfileDeletionStage::SCHEDULED); | |
| 226 ProfilesToDelete()[path] = ProfileDeletionStage::ABANDONED; | |
| 206 } | 227 } |
| 207 #endif | 228 #endif |
| 208 | 229 |
| 209 bool IsProfileMarkedForDeletion(const base::FilePath& profile_path) { | 230 bool IsProfileDirectoryMarkedForDeletion(const base::FilePath& profile_path) { |
| 210 return std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(), | 231 auto it = ProfilesToDelete().find(profile_path); |
| 211 profile_path) != ProfilesToDelete().end(); | 232 return it != ProfilesToDelete().end() && |
| 233 it->second == ProfileDeletionStage::ABANDONED; | |
| 212 } | 234 } |
| 213 | 235 |
| 214 // Physically remove deleted profile directories from disk. | 236 // Physically remove deleted profile directories from disk. |
| 215 void NukeProfileFromDisk(const base::FilePath& profile_path) { | 237 void NukeProfileFromDisk(const base::FilePath& profile_path) { |
| 216 // Delete both the profile directory and its corresponding cache. | 238 // Delete both the profile directory and its corresponding cache. |
| 217 base::FilePath cache_path; | 239 base::FilePath cache_path; |
| 218 chrome::GetUserCacheDirectory(profile_path, &cache_path); | 240 chrome::GetUserCacheDirectory(profile_path, &cache_path); |
| 219 base::DeleteFile(profile_path, true); | 241 base::DeleteFile(profile_path, true); |
| 220 base::DeleteFile(cache_path, true); | 242 base::DeleteFile(cache_path, true); |
| 221 } | 243 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 326 if (!pm) // Is NULL when running unit tests. | 348 if (!pm) // Is NULL when running unit tests. |
| 327 return; | 349 return; |
| 328 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); | 350 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); |
| 329 for (size_t i = 0; i < profiles.size(); ++i) | 351 for (size_t i = 0; i < profiles.size(); ++i) |
| 330 SessionServiceFactory::ShutdownForProfile(profiles[i]); | 352 SessionServiceFactory::ShutdownForProfile(profiles[i]); |
| 331 } | 353 } |
| 332 #endif | 354 #endif |
| 333 | 355 |
| 334 // static | 356 // static |
| 335 void ProfileManager::NukeDeletedProfilesFromDisk() { | 357 void ProfileManager::NukeDeletedProfilesFromDisk() { |
| 336 for (std::vector<base::FilePath>::iterator it = | 358 for (const auto& item : ProfilesToDelete()) { |
| 337 ProfilesToDelete().begin(); | 359 if (item.second == ProfileDeletionStage::ABANDONED) |
| 338 it != ProfilesToDelete().end(); | 360 NukeProfileFromDisk(item.first); |
| 339 ++it) { | |
| 340 NukeProfileFromDisk(*it); | |
| 341 } | 361 } |
| 342 ProfilesToDelete().clear(); | 362 ProfilesToDelete().clear(); |
| 343 } | 363 } |
| 344 | 364 |
| 345 // static | 365 // static |
| 346 Profile* ProfileManager::GetLastUsedProfile() { | 366 Profile* ProfileManager::GetLastUsedProfile() { |
| 347 ProfileManager* profile_manager = g_browser_process->profile_manager(); | 367 ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| 348 return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_); | 368 return profile_manager->GetLastUsedProfile(profile_manager->user_data_dir_); |
| 349 } | 369 } |
| 350 | 370 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 const base::string16& name, | 480 const base::string16& name, |
| 461 const std::string& icon_url, | 481 const std::string& icon_url, |
| 462 const std::string& supervised_user_id) { | 482 const std::string& supervised_user_id) { |
| 463 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 483 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 464 TRACE_EVENT1("browser,startup", | 484 TRACE_EVENT1("browser,startup", |
| 465 "ProfileManager::CreateProfileAsync", | 485 "ProfileManager::CreateProfileAsync", |
| 466 "profile_path", | 486 "profile_path", |
| 467 profile_path.AsUTF8Unsafe()); | 487 profile_path.AsUTF8Unsafe()); |
| 468 | 488 |
| 469 // Make sure that this profile is not pending deletion. | 489 // Make sure that this profile is not pending deletion. |
| 470 if (IsProfileMarkedForDeletion(profile_path)) { | 490 if (IsProfileDirectoryMarkedForDeletion(profile_path)) { |
| 471 if (!callback.is_null()) | 491 if (!callback.is_null()) |
| 472 callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL); | 492 callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL); |
| 473 return; | 493 return; |
| 474 } | 494 } |
| 475 | 495 |
| 476 // Create the profile if needed and collect its ProfileInfo. | 496 // Create the profile if needed and collect its ProfileInfo. |
| 477 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path); | 497 ProfilesInfoMap::iterator iter = profiles_info_.find(profile_path); |
| 478 ProfileInfo* info = NULL; | 498 ProfileInfo* info = NULL; |
| 479 | 499 |
| 480 if (iter != profiles_info_.end()) { | 500 if (iter != profiles_info_.end()) { |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 728 | 748 |
| 729 ProfileShortcutManager* ProfileManager::profile_shortcut_manager() { | 749 ProfileShortcutManager* ProfileManager::profile_shortcut_manager() { |
| 730 return profile_shortcut_manager_.get(); | 750 return profile_shortcut_manager_.get(); |
| 731 } | 751 } |
| 732 | 752 |
| 733 #if !defined(OS_ANDROID) | 753 #if !defined(OS_ANDROID) |
| 734 bool ProfileManager::MaybeScheduleProfileForDeletion( | 754 bool ProfileManager::MaybeScheduleProfileForDeletion( |
| 735 const base::FilePath& profile_dir, | 755 const base::FilePath& profile_dir, |
| 736 const CreateCallback& callback, | 756 const CreateCallback& callback, |
| 737 ProfileMetrics::ProfileDelete deletion_source) { | 757 ProfileMetrics::ProfileDelete deletion_source) { |
| 738 if (IsProfileMarkedForDeletion(profile_dir)) | 758 if (!ScheduleProfileDirectoryForDeletion(profile_dir)) |
| 739 return false; | 759 return false; |
| 740 ScheduleProfileForDeletion(profile_dir, callback); | 760 ScheduleProfileForDeletion(profile_dir, callback); |
| 741 ProfileMetrics::LogProfileDeleteUser(deletion_source); | 761 ProfileMetrics::LogProfileDeleteUser(deletion_source); |
| 742 return true; | 762 return true; |
| 743 } | 763 } |
| 744 | 764 |
| 745 void ProfileManager::ScheduleProfileForDeletion( | 765 void ProfileManager::ScheduleProfileForDeletion( |
| 746 const base::FilePath& profile_dir, | 766 const base::FilePath& profile_dir, |
| 747 const CreateCallback& callback) { | 767 const CreateCallback& callback) { |
| 748 DCHECK(profiles::IsMultipleProfilesEnabled()); | 768 DCHECK(profiles::IsMultipleProfilesEnabled()); |
| 749 DCHECK(!IsProfileMarkedForDeletion(profile_dir)); | 769 DCHECK(!IsProfileDirectoryMarkedForDeletion(profile_dir)); |
| 750 | 770 |
| 751 // Cancel all in-progress downloads before deleting the profile to prevent a | 771 // Cancel all in-progress downloads before deleting the profile to prevent a |
| 752 // "Do you want to exit Google Chrome and cancel the downloads?" prompt | 772 // "Do you want to exit Google Chrome and cancel the downloads?" prompt |
| 753 // (crbug.com/336725). | 773 // (crbug.com/336725). |
| 754 Profile* profile = GetProfileByPath(profile_dir); | 774 Profile* profile = GetProfileByPath(profile_dir); |
| 755 if (profile) { | 775 if (profile) { |
| 756 DownloadService* service = | 776 DownloadService* service = |
| 757 DownloadServiceFactory::GetForBrowserContext(profile); | 777 DownloadServiceFactory::GetForBrowserContext(profile); |
| 758 service->CancelDownloads(); | 778 service->CancelDownloads(); |
| 759 } | 779 } |
| 760 | 780 |
| 761 ProfileAttributesStorage& storage = GetProfileAttributesStorage(); | 781 ProfileAttributesStorage& storage = GetProfileAttributesStorage(); |
| 762 // If we're deleting the last (non-legacy-supervised) profile, then create a | 782 // If we're deleting the last (non-legacy-supervised) profile, then create a |
| 763 // new profile in its place. | 783 // new profile in its place. |
| 764 base::FilePath last_non_supervised_profile_path; | 784 base::FilePath last_non_supervised_profile_path; |
| 765 std::vector<ProfileAttributesEntry*> entries = | 785 std::vector<ProfileAttributesEntry*> entries = |
| 766 storage.GetAllProfilesAttributes(); | 786 storage.GetAllProfilesAttributes(); |
| 767 for (ProfileAttributesEntry* entry : entries) { | 787 for (ProfileAttributesEntry* entry : entries) { |
| 768 base::FilePath cur_path = entry->GetPath(); | 788 base::FilePath cur_path = entry->GetPath(); |
| 769 // Make sure that this profile is not pending deletion, and is not | 789 // Make sure that this profile is not pending deletion, and is not |
| 770 // legacy-supervised. | 790 // legacy-supervised. |
| 771 if (cur_path != profile_dir && | 791 if (cur_path != profile_dir && |
| 772 !entry->IsLegacySupervised() && | 792 !entry->IsLegacySupervised() && |
| 773 !IsProfileMarkedForDeletion(cur_path)) { | 793 !IsProfileDirectoryMarkedForDeletion(cur_path)) { |
| 774 last_non_supervised_profile_path = cur_path; | 794 last_non_supervised_profile_path = cur_path; |
| 775 break; | 795 break; |
| 776 } | 796 } |
| 777 } | 797 } |
| 778 | 798 |
| 779 if (last_non_supervised_profile_path.empty()) { | 799 if (last_non_supervised_profile_path.empty()) { |
| 780 std::string new_avatar_url; | 800 std::string new_avatar_url; |
| 781 base::string16 new_profile_name; | 801 base::string16 new_profile_name; |
| 782 | 802 |
| 783 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) | 803 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) |
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1396 profiles::RemoveBrowsingDataForProfile(profile_dir); | 1416 profiles::RemoveBrowsingDataForProfile(profile_dir); |
| 1397 } else { | 1417 } else { |
| 1398 // It is safe to delete a not yet loaded Profile from disk. | 1418 // It is safe to delete a not yet loaded Profile from disk. |
| 1399 BrowserThread::PostTask( | 1419 BrowserThread::PostTask( |
| 1400 BrowserThread::FILE, FROM_HERE, | 1420 BrowserThread::FILE, FROM_HERE, |
| 1401 base::Bind(&NukeProfileFromDisk, profile_dir)); | 1421 base::Bind(&NukeProfileFromDisk, profile_dir)); |
| 1402 } | 1422 } |
| 1403 | 1423 |
| 1404 // Queue even a profile that was nuked so it will be MarkedForDeletion and so | 1424 // Queue even a profile that was nuked so it will be MarkedForDeletion and so |
| 1405 // CreateProfileAsync can't create it. | 1425 // CreateProfileAsync can't create it. |
| 1406 QueueProfileDirectoryForDeletion(profile_dir); | 1426 MarkProfileDirectoryForDeletion(profile_dir); |
| 1407 storage.RemoveProfile(profile_dir); | 1427 storage.RemoveProfile(profile_dir); |
| 1408 ProfileMetrics::UpdateReportedProfilesStatistics(this); | 1428 ProfileMetrics::UpdateReportedProfilesStatistics(this); |
| 1409 } | 1429 } |
| 1410 #endif // !defined(OS_ANDROID) | 1430 #endif // !defined(OS_ANDROID) |
| 1411 | 1431 |
| 1412 ProfileManager::ProfileInfo* ProfileManager::RegisterProfile( | 1432 ProfileManager::ProfileInfo* ProfileManager::RegisterProfile( |
| 1413 Profile* profile, | 1433 Profile* profile, |
| 1414 bool created) { | 1434 bool created) { |
| 1415 TRACE_EVENT0("browser", "ProfileManager::RegisterProfile"); | 1435 TRACE_EVENT0("browser", "ProfileManager::RegisterProfile"); |
| 1416 ProfileInfo* info = new ProfileInfo(profile, created); | 1436 ProfileInfo* info = new ProfileInfo(profile, created); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1559 Browser* browser) { | 1579 Browser* browser) { |
| 1560 Profile* profile = browser->profile(); | 1580 Profile* profile = browser->profile(); |
| 1561 Profile* original_profile = profile->GetOriginalProfile(); | 1581 Profile* original_profile = profile->GetOriginalProfile(); |
| 1562 // Do nothing if the closed window is not the last window of the same profile. | 1582 // Do nothing if the closed window is not the last window of the same profile. |
| 1563 for (auto* browser : *BrowserList::GetInstance()) { | 1583 for (auto* browser : *BrowserList::GetInstance()) { |
| 1564 if (browser->profile()->GetOriginalProfile() == original_profile) | 1584 if (browser->profile()->GetOriginalProfile() == original_profile) |
| 1565 return; | 1585 return; |
| 1566 } | 1586 } |
| 1567 | 1587 |
| 1568 base::FilePath path = profile->GetPath(); | 1588 base::FilePath path = profile->GetPath(); |
| 1569 if (IsProfileMarkedForDeletion(path)) { | 1589 if (IsProfileDirectoryMarkedForDeletion(path)) { |
| 1570 // Do nothing if the profile is already being deleted. | 1590 // Do nothing if the profile is already being deleted. |
| 1571 } else if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) { | 1591 } else if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) { |
| 1572 // Delete if the profile is an ephemeral profile. | 1592 // Delete if the profile is an ephemeral profile. |
| 1573 g_browser_process->profile_manager()->ScheduleProfileForDeletion( | 1593 g_browser_process->profile_manager()->ScheduleProfileForDeletion( |
| 1574 path, ProfileManager::CreateCallback()); | 1594 path, ProfileManager::CreateCallback()); |
| 1575 } else { | 1595 } else { |
| 1576 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) | 1596 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) |
| 1577 // Gather statistics and store into ProfileInfoCache. For incognito profile | 1597 // Gather statistics and store into ProfileInfoCache. For incognito profile |
| 1578 // we gather the statistics of its parent profile instead, because a window | 1598 // we gather the statistics of its parent profile instead, because a window |
| 1579 // of the parent profile was open. | 1599 // of the parent profile was open. |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1610 const CreateCallback& original_callback, | 1630 const CreateCallback& original_callback, |
| 1611 Profile* loaded_profile, | 1631 Profile* loaded_profile, |
| 1612 Profile::CreateStatus status) { | 1632 Profile::CreateStatus status) { |
| 1613 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL && | 1633 DCHECK(status != Profile::CREATE_STATUS_LOCAL_FAIL && |
| 1614 status != Profile::CREATE_STATUS_REMOTE_FAIL); | 1634 status != Profile::CREATE_STATUS_REMOTE_FAIL); |
| 1615 | 1635 |
| 1616 // Only run the code if the profile initialization has finished completely. | 1636 // Only run the code if the profile initialization has finished completely. |
| 1617 if (status != Profile::CREATE_STATUS_INITIALIZED) | 1637 if (status != Profile::CREATE_STATUS_INITIALIZED) |
| 1618 return; | 1638 return; |
| 1619 | 1639 |
| 1620 if (IsProfileMarkedForDeletion(new_active_profile_path)) { | 1640 if (IsProfileDirectoryMarkedForDeletion(new_active_profile_path)) { |
| 1621 // If the profile we tried to load as the next active profile has been | 1641 // If the profile we tried to load as the next active profile has been |
| 1622 // deleted, then retry deleting this profile to redo the logic to load | 1642 // deleted, then retry deleting this profile to redo the logic to load |
| 1623 // the next available profile. | 1643 // the next available profile. |
| 1624 ScheduleProfileForDeletion(profile_to_delete_path, original_callback); | 1644 ScheduleProfileForDeletion(profile_to_delete_path, original_callback); |
| 1625 return; | 1645 return; |
| 1626 } | 1646 } |
| 1627 | 1647 |
| 1628 FinishDeletingProfile(profile_to_delete_path, new_active_profile_path); | 1648 FinishDeletingProfile(profile_to_delete_path, new_active_profile_path); |
| 1629 if (!original_callback.is_null()) | 1649 if (!original_callback.is_null()) |
| 1630 original_callback.Run(loaded_profile, status); | 1650 original_callback.Run(loaded_profile, status); |
| 1631 } | 1651 } |
| 1632 #endif // !defined(OS_ANDROID) | 1652 #endif // !defined(OS_ANDROID) |
| 1633 | 1653 |
| 1634 ProfileManagerWithoutInit::ProfileManagerWithoutInit( | 1654 ProfileManagerWithoutInit::ProfileManagerWithoutInit( |
| 1635 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) { | 1655 const base::FilePath& user_data_dir) : ProfileManager(user_data_dir) { |
| 1636 } | 1656 } |
| OLD | NEW |