OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "ios/chrome/browser/browser_state/chrome_browser_state_removal_controll
er.h" |
| 6 |
| 7 #import <Foundation/Foundation.h> |
| 8 |
| 9 #include "base/bind.h" |
| 10 #include "base/files/file_path.h" |
| 11 #include "base/files/file_util.h" |
| 12 #include "base/location.h" |
| 13 #include "base/mac/foundation_util.h" |
| 14 #include "base/strings/sys_string_conversions.h" |
| 15 #include "components/prefs/pref_service.h" |
| 16 #include "google_apis/gaia/gaia_auth_util.h" |
| 17 #include "ios/chrome/browser/application_context.h" |
| 18 #include "ios/chrome/browser/browser_state/browser_state_info_cache.h" |
| 19 #include "ios/chrome/browser/chrome_constants.h" |
| 20 #include "ios/chrome/browser/chrome_paths_internal.h" |
| 21 #include "ios/chrome/browser/pref_names.h" |
| 22 #include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state_
manager.h" |
| 23 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" |
| 24 #import "ios/public/provider/chrome/browser/signin/chrome_identity.h" |
| 25 #include "ios/public/provider/chrome/browser/signin/chrome_identity_service.h" |
| 26 #include "ios/web/public/web_thread.h" |
| 27 |
| 28 namespace { |
| 29 |
| 30 ChromeBrowserStateRemovalController* g_chrome_browser_state_removal_helper = |
| 31 nullptr; |
| 32 |
| 33 NSString* const kPathToBrowserStateToKeepKey = @"PathToBrowserStateToKeep"; |
| 34 NSString* const kHasBrowserStateBeenRemovedKey = @"HasBrowserStateBeenRemoved"; |
| 35 |
| 36 const char kGmailDomain[] = "gmail.com"; |
| 37 |
| 38 // Removes from disk the directories used by the browser states in |
| 39 // |browser_states_paths|. |
| 40 void NukeBrowserStates(const std::vector<base::FilePath>& browser_states_path) { |
| 41 for (const base::FilePath& browser_state_path : browser_states_path) { |
| 42 // Delete both the browser state directory and its corresponding cache. |
| 43 base::FilePath cache_path; |
| 44 ios::GetUserCacheDirectory(browser_state_path, &cache_path); |
| 45 base::DeleteFile(browser_state_path, true); |
| 46 base::DeleteFile(cache_path, true); |
| 47 } |
| 48 } |
| 49 |
| 50 // Returns the GAIA Id of the given |browser_state_path| using the |info_cache|. |
| 51 std::string GetGaiaIdForBrowserState(const std::string& browser_state_path, |
| 52 BrowserStateInfoCache* info_cache) { |
| 53 base::FilePath path = info_cache->GetUserDataDir().Append(browser_state_path); |
| 54 size_t index = info_cache->GetIndexOfBrowserStateWithPath(path); |
| 55 if (index > info_cache->GetNumberOfBrowserStates()) |
| 56 return std::string(); |
| 57 return info_cache->GetGAIAIdOfBrowserStateAtIndex(index); |
| 58 } |
| 59 |
| 60 // Returns the email's domain of the identity associated with |gaia_id|. |
| 61 std::string GetDomainForGaiaId(const std::string& gaia_id) { |
| 62 ChromeIdentity* identity = ios::GetChromeBrowserProvider() |
| 63 ->GetChromeIdentityService() |
| 64 ->GetIdentityWithGaiaID(gaia_id); |
| 65 if (![identity userEmail]) |
| 66 return std::string(); |
| 67 return gaia::ExtractDomainName( |
| 68 gaia::SanitizeEmail(base::SysNSStringToUTF8([identity userEmail]))); |
| 69 } |
| 70 } |
| 71 |
| 72 ChromeBrowserStateRemovalController::ChromeBrowserStateRemovalController() |
| 73 : has_changed_last_used_browser_state_(false) {} |
| 74 |
| 75 ChromeBrowserStateRemovalController* |
| 76 ChromeBrowserStateRemovalController::GetInstance() { |
| 77 if (!g_chrome_browser_state_removal_helper) { |
| 78 g_chrome_browser_state_removal_helper = |
| 79 new ChromeBrowserStateRemovalController(); |
| 80 } |
| 81 return g_chrome_browser_state_removal_helper; |
| 82 } |
| 83 |
| 84 void ChromeBrowserStateRemovalController::RemoveBrowserStatesIfNecessary() { |
| 85 ApplicationContext* application_context = GetApplicationContext(); |
| 86 DCHECK(application_context); |
| 87 ios::ChromeBrowserStateManager* manager = |
| 88 application_context->GetChromeBrowserStateManager(); |
| 89 DCHECK(manager); |
| 90 BrowserStateInfoCache* info_cache = manager->GetBrowserStateInfoCache(); |
| 91 DCHECK(info_cache); |
| 92 |
| 93 std::string browser_state_to_keep = GetBrowserStatePathToKeep(); |
| 94 std::string browser_state_last_used = GetLastBrowserStatePathUsed(); |
| 95 if (browser_state_to_keep.empty()) { |
| 96 // If no browser state was marked as to keep, keep the last used one. |
| 97 browser_state_to_keep = browser_state_last_used; |
| 98 } |
| 99 if (browser_state_to_keep.empty()) { |
| 100 browser_state_to_keep = kIOSChromeInitialBrowserState; |
| 101 } |
| 102 if (browser_state_to_keep != browser_state_last_used) { |
| 103 std::string gaia_id = |
| 104 GetGaiaIdForBrowserState(browser_state_to_keep, info_cache); |
| 105 std::string last_used_gaia_id = |
| 106 GetGaiaIdForBrowserState(browser_state_last_used, info_cache); |
| 107 std::string last_used_domain = GetDomainForGaiaId(last_used_gaia_id); |
| 108 if (gaia_id.empty() && last_used_domain == kGmailDomain) { |
| 109 // If browser state to keep is not the last used one, wasn't |
| 110 // authenticated, and the last used browser state was a normal account |
| 111 // (domain starts with "gmail"), keep the last used browser state instead. |
| 112 browser_state_to_keep = browser_state_last_used; |
| 113 } |
| 114 } |
| 115 |
| 116 bool is_removing_browser_states = false; |
| 117 std::vector<base::FilePath> browser_states_to_nuke; |
| 118 for (size_t index = 0; index < info_cache->GetNumberOfBrowserStates(); |
| 119 ++index) { |
| 120 base::FilePath path = info_cache->GetPathOfBrowserStateAtIndex(index); |
| 121 if (path.BaseName().MaybeAsASCII() == browser_state_to_keep) { |
| 122 continue; |
| 123 } |
| 124 is_removing_browser_states = true; |
| 125 // Note: if there is more than 2 browser states (which should never be the |
| 126 // case), this might show the wrong GAIA Id. However, in this unlikely case, |
| 127 // there isn't really more that can be done. |
| 128 removed_browser_state_gaia_id_ = |
| 129 info_cache->GetGAIAIdOfBrowserStateAtIndex(index); |
| 130 browser_states_to_nuke.push_back(path); |
| 131 info_cache->RemoveBrowserState(path); |
| 132 } |
| 133 |
| 134 // Update the last used browser state if the old one was removed. |
| 135 if (browser_state_to_keep != browser_state_last_used) { |
| 136 has_changed_last_used_browser_state_ = true; |
| 137 SetLastBrowserStatePathUsed(browser_state_to_keep); |
| 138 } |
| 139 |
| 140 if (is_removing_browser_states) { |
| 141 SetHasBrowserStateBeenRemoved(true); |
| 142 web::WebThread::PostBlockingPoolTask( |
| 143 FROM_HERE, base::Bind(&NukeBrowserStates, browser_states_to_nuke)); |
| 144 } |
| 145 } |
| 146 |
| 147 bool ChromeBrowserStateRemovalController::HasBrowserStateBeenRemoved() { |
| 148 return [[NSUserDefaults standardUserDefaults] |
| 149 boolForKey:kHasBrowserStateBeenRemovedKey]; |
| 150 } |
| 151 |
| 152 void ChromeBrowserStateRemovalController::SetHasBrowserStateBeenRemoved( |
| 153 bool value) { |
| 154 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| 155 [defaults setBool:value forKey:kHasBrowserStateBeenRemovedKey]; |
| 156 [defaults synchronize]; |
| 157 } |
| 158 |
| 159 std::string ChromeBrowserStateRemovalController::GetBrowserStatePathToKeep() { |
| 160 return base::SysNSStringToUTF8([[NSUserDefaults standardUserDefaults] |
| 161 stringForKey:kPathToBrowserStateToKeepKey]); |
| 162 } |
| 163 |
| 164 std::string ChromeBrowserStateRemovalController::GetLastBrowserStatePathUsed() { |
| 165 return GetApplicationContext()->GetLocalState()->GetString( |
| 166 prefs::kBrowserStateLastUsed); |
| 167 } |
| 168 |
| 169 void ChromeBrowserStateRemovalController::SetLastBrowserStatePathUsed( |
| 170 const std::string& browser_state_path) { |
| 171 GetApplicationContext()->GetLocalState()->SetString( |
| 172 prefs::kBrowserStateLastUsed, browser_state_path); |
| 173 } |
OLD | NEW |