1 // Copyright (c) 2013 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/profile_resetter/profile_resetter.h" 6 7 #include <string> 8 9 #include "base/prefs/pref_service.h" 10 #include "base/prefs/scoped_user_pref_update.h" 11 #include "base/synchronization/cancellation_flag.h" 12 #include "chrome/browser/browsing_data/browsing_data_helper.h" 13 #include "chrome/browser/content_settings/host_content_settings_map.h" 14 #include "chrome/browser/extensions/extension_service.h" 15 #include "chrome/browser/google/google_url_tracker_factory.h" 16 #include "chrome/browser/profile_resetter/brandcoded_default_settings.h" 17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/search_engines/template_url_service_factory.h" 19 #include "chrome/browser/ui/browser.h" 20 #include "chrome/browser/ui/browser_iterator.h" 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" 22 #include "chrome/common/pref_names.h" 23 #include "chrome/installer/util/browser_distribution.h" 24 #include "components/google/core/browser/google_pref_names.h" 25 #include "components/google/core/browser/google_url_tracker.h" 26 #include "components/search_engines/search_engines_pref_names.h" 27 #include "components/search_engines/template_url_prepopulate_data.h" 28 #include "components/search_engines/template_url_service.h" 29 #include "content/public/browser/browser_thread.h" 30 #include "extensions/browser/extension_system.h" 31 #include "extensions/browser/management_policy.h" 32 33 #if defined(OS_WIN) 34 #include "base/base_paths.h" 35 #include "base/path_service.h" 36 #include "chrome/installer/util/shell_util.h" 37 38 namespace { 39 40 void ResetShortcutsOnFileThread() { 41 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 42 // Get full path of chrome. 43 base::FilePath chrome_exe; 44 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) 45 return; 46 BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( 47 BrowserDistribution::CHROME_BROWSER); 48 for (int location = ShellUtil::SHORTCUT_LOCATION_FIRST; 49 location < ShellUtil::NUM_SHORTCUT_LOCATIONS; ++location) { 50 ShellUtil::ShortcutListMaybeRemoveUnknownArgs( 51 static_cast<ShellUtil::ShortcutLocation>(location), 52 dist, 53 ShellUtil::CURRENT_USER, 54 chrome_exe, 55 true, 56 NULL, 57 NULL); 58 } 59 } 60 61 } // namespace 62 #endif // defined(OS_WIN) 63 64 ProfileResetter::ProfileResetter(Profile* profile) 65 : profile_(profile), 66 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile_)), 67 pending_reset_flags_(0), 68 cookies_remover_(NULL), 69 weak_ptr_factory_(this) { 70 DCHECK(CalledOnValidThread()); 71 DCHECK(profile_); 72 } 73 74 ProfileResetter::~ProfileResetter() { 75 if (cookies_remover_) 76 cookies_remover_->RemoveObserver(this); 77 } 78 79 void ProfileResetter::Reset( 80 ProfileResetter::ResettableFlags resettable_flags, 81 scoped_ptr<BrandcodedDefaultSettings> master_settings, 82 bool accepted_send_feedback, 83 const base::Closure& callback) { 84 DCHECK(CalledOnValidThread()); 85 DCHECK(master_settings); 86 87 // We should never be called with unknown flags. 88 CHECK_EQ(static_cast<ResettableFlags>(0), resettable_flags & ~ALL); 89 90 // We should never be called when a previous reset has not finished. 91 CHECK_EQ(static_cast<ResettableFlags>(0), pending_reset_flags_); 92 93 if (!resettable_flags) { 94 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 95 callback); 96 return; 97 } 98 99 master_settings_.swap(master_settings); 100 callback_ = callback; 101 102 // These flags are set to false by the individual reset functions. 103 pending_reset_flags_ = resettable_flags; 104 105 struct { 106 Resettable flag; 107 void (ProfileResetter::*method)(); 108 } flagToMethod[] = { 109 {DEFAULT_SEARCH_ENGINE, &ProfileResetter::ResetDefaultSearchEngine}, 110 {HOMEPAGE, &ProfileResetter::ResetHomepage}, 111 {CONTENT_SETTINGS, &ProfileResetter::ResetContentSettings}, 112 {COOKIES_AND_SITE_DATA, &ProfileResetter::ResetCookiesAndSiteData}, 113 {EXTENSIONS, &ProfileResetter::ResetExtensions}, 114 {STARTUP_PAGES, &ProfileResetter::ResetStartupPages}, 115 {PINNED_TABS, &ProfileResetter::ResetPinnedTabs}, 116 {SHORTCUTS, &ProfileResetter::ResetShortcuts}, 117 }; 118 119 ResettableFlags reset_triggered_for_flags = 0; 120 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flagToMethod); ++i) { 121 if (resettable_flags & flagToMethod[i].flag) { 122 reset_triggered_for_flags |= flagToMethod[i].flag; 123 (this->*flagToMethod[i].method)(); 124 } 125 } 126 127 DCHECK_EQ(resettable_flags, reset_triggered_for_flags); 128 } 129 130 bool ProfileResetter::IsActive() const { 131 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 132 return pending_reset_flags_ != 0; 133 } 134 135 void ProfileResetter::MarkAsDone(Resettable resettable) { 136 DCHECK(CalledOnValidThread()); 137 138 // Check that we are never called twice or unexpectedly. 139 CHECK(pending_reset_flags_ & resettable); 140 141 pending_reset_flags_ &= ~resettable; 142 143 if (!pending_reset_flags_) { 144 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 145 callback_); 146 callback_.Reset(); 147 master_settings_.reset(); 148 template_url_service_sub_.reset(); 149 } 150 } 151 152 void ProfileResetter::ResetDefaultSearchEngine() { 153 DCHECK(CalledOnValidThread()); 154 DCHECK(template_url_service_); 155 // If TemplateURLServiceFactory is ready we can clean it right now. 156 // Otherwise, load it and continue from ProfileResetter::Observe. 157 if (template_url_service_->loaded()) { 158 PrefService* prefs = profile_->GetPrefs(); 159 DCHECK(prefs); 160 TemplateURLPrepopulateData::ClearPrepopulatedEnginesInPrefs( 161 profile_->GetPrefs()); 162 scoped_ptr<base::ListValue> search_engines( 163 master_settings_->GetSearchProviderOverrides()); 164 if (search_engines) { 165 // This Chrome distribution channel provides a custom search engine. We 166 // must reset to it. 167 ListPrefUpdate update(prefs, prefs::kSearchProviderOverrides); 168 update->Swap(search_engines.get()); 169 } 170 171 template_url_service_->RepairPrepopulatedSearchEngines(); 172 173 // Reset Google search URL. 174 prefs->ClearPref(prefs::kLastPromptedGoogleURL); 175 const TemplateURL* default_search_provider = 176 template_url_service_->GetDefaultSearchProvider(); 177 if (default_search_provider && 178 default_search_provider->HasGoogleBaseURLs( 179 template_url_service_->search_terms_data())) { 180 GoogleURLTracker* tracker = 181 GoogleURLTrackerFactory::GetForProfile(profile_); 182 if (tracker) 183 tracker->RequestServerCheck(true); 184 } 185 186 MarkAsDone(DEFAULT_SEARCH_ENGINE); 187 } else { 188 template_url_service_sub_ = 189 template_url_service_->RegisterOnLoadedCallback( 190 base::Bind(&ProfileResetter::OnTemplateURLServiceLoaded, 191 weak_ptr_factory_.GetWeakPtr())); 192 template_url_service_->Load(); 193 } 194 } 195 196 void ProfileResetter::ResetHomepage() { 197 DCHECK(CalledOnValidThread()); 198 PrefService* prefs = profile_->GetPrefs(); 199 DCHECK(prefs); 200 std::string homepage; 201 bool homepage_is_ntp, show_home_button; 202 203 if (master_settings_->GetHomepage(&homepage)) 204 prefs->SetString(prefs::kHomePage, homepage); 205 206 if (master_settings_->GetHomepageIsNewTab(&homepage_is_ntp)) 207 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, homepage_is_ntp); 208 else 209 prefs->ClearPref(prefs::kHomePageIsNewTabPage); 210 211 if (master_settings_->GetShowHomeButton(&show_home_button)) 212 prefs->SetBoolean(prefs::kShowHomeButton, show_home_button); 213 else 214 prefs->ClearPref(prefs::kShowHomeButton); 215 MarkAsDone(HOMEPAGE); 216 } 217 218 void ProfileResetter::ResetContentSettings() { 219 DCHECK(CalledOnValidThread()); 220 PrefService* prefs = profile_->GetPrefs(); 221 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); 222 223 for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) { 224 map->ClearSettingsForOneType(static_cast<ContentSettingsType>(type)); 225 if (HostContentSettingsMap::IsSettingAllowedForType( 226 prefs, 227 CONTENT_SETTING_DEFAULT, 228 static_cast<ContentSettingsType>(type))) 229 map->SetDefaultContentSetting(static_cast<ContentSettingsType>(type), 230 CONTENT_SETTING_DEFAULT); 231 } 232 MarkAsDone(CONTENT_SETTINGS); 233 } 234 235 void ProfileResetter::ResetCookiesAndSiteData() { 236 DCHECK(CalledOnValidThread()); 237 DCHECK(!cookies_remover_); 238 239 cookies_remover_ = BrowsingDataRemover::CreateForUnboundedRange(profile_); 240 cookies_remover_->AddObserver(this); 241 int remove_mask = BrowsingDataRemover::REMOVE_SITE_DATA | 242 BrowsingDataRemover::REMOVE_CACHE; 243 PrefService* prefs = profile_->GetPrefs(); 244 DCHECK(prefs); 245 // Don't try to clear LSO data if it's not supported. 246 if (!prefs->GetBoolean(prefs::kClearPluginLSODataEnabled)) 247 remove_mask &= ~BrowsingDataRemover::REMOVE_PLUGIN_DATA; 248 cookies_remover_->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB); 249 } 250 251 void ProfileResetter::ResetExtensions() { 252 DCHECK(CalledOnValidThread()); 253 254 std::vector<std::string> brandcode_extensions; 255 master_settings_->GetExtensions(&brandcode_extensions); 256 257 ExtensionService* extension_service = 258 extensions::ExtensionSystem::Get(profile_)->extension_service(); 259 DCHECK(extension_service); 260 extension_service->DisableUserExtensions(brandcode_extensions); 261 262 MarkAsDone(EXTENSIONS); 263 } 264 265 void ProfileResetter::ResetStartupPages() { 266 DCHECK(CalledOnValidThread()); 267 PrefService* prefs = profile_->GetPrefs(); 268 DCHECK(prefs); 269 scoped_ptr<base::ListValue> url_list( 270 master_settings_->GetUrlsToRestoreOnStartup()); 271 if (url_list) 272 ListPrefUpdate(prefs, prefs::kURLsToRestoreOnStartup)->Swap(url_list.get()); 273 274 int restore_on_startup; 275 if (master_settings_->GetRestoreOnStartup(&restore_on_startup)) 276 prefs->SetInteger(prefs::kRestoreOnStartup, restore_on_startup); 277 else 278 prefs->ClearPref(prefs::kRestoreOnStartup); 279 280 prefs->SetBoolean(prefs::kRestoreOnStartupMigrated, true); 281 MarkAsDone(STARTUP_PAGES); 282 } 283 284 void ProfileResetter::ResetPinnedTabs() { 285 // Unpin all the tabs. 286 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 287 if (it->is_type_tabbed() && it->profile() == profile_) { 288 TabStripModel* tab_model = it->tab_strip_model(); 289 // Here we assume that indexof(any mini tab) < indexof(any normal tab). 290 // If we unpin the tab, it can be moved to the right. Thus traversing in 291 // reverse direction is correct. 292 for (int i = tab_model->count() - 1; i >= 0; --i) { 293 if (tab_model->IsTabPinned(i) && !tab_model->IsAppTab(i)) 294 tab_model->SetTabPinned(i, false); 295 } 296 } 297 } 298 MarkAsDone(PINNED_TABS); 299 } 300 301 void ProfileResetter::ResetShortcuts() { 302 #if defined(OS_WIN) 303 content::BrowserThread::PostTaskAndReply( 304 content::BrowserThread::FILE, 305 FROM_HERE, 306 base::Bind(&ResetShortcutsOnFileThread), 307 base::Bind(&ProfileResetter::MarkAsDone, 308 weak_ptr_factory_.GetWeakPtr(), 309 SHORTCUTS)); 310 #else 311 MarkAsDone(SHORTCUTS); 312 #endif 313 } 314 315 void ProfileResetter::OnTemplateURLServiceLoaded() { 316 // TemplateURLService has loaded. If we need to clean search engines, it's 317 // time to go on. 318 DCHECK(CalledOnValidThread()); 319 template_url_service_sub_.reset(); 320 if (pending_reset_flags_ & DEFAULT_SEARCH_ENGINE) 321 ResetDefaultSearchEngine(); 322 } 323 324 void ProfileResetter::OnBrowsingDataRemoverDone() { 325 cookies_remover_ = NULL; 326 MarkAsDone(COOKIES_AND_SITE_DATA); 327 } 328 329 std::vector<ShortcutCommand> GetChromeLaunchShortcuts( 330 const scoped_refptr<SharedCancellationFlag>& cancel) { 331 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 332 #if defined(OS_WIN) 333 // Get full path of chrome. 334 base::FilePath chrome_exe; 335 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) 336 return std::vector<ShortcutCommand>(); 337 BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( 338 BrowserDistribution::CHROME_BROWSER); 339 std::vector<ShortcutCommand> shortcuts; 340 for (int location = ShellUtil::SHORTCUT_LOCATION_FIRST; 341 location < ShellUtil::NUM_SHORTCUT_LOCATIONS; ++location) { 342 if (cancel && cancel->data.IsSet()) 343 break; 344 ShellUtil::ShortcutListMaybeRemoveUnknownArgs( 345 static_cast<ShellUtil::ShortcutLocation>(location), 346 dist, 347 ShellUtil::CURRENT_USER, 348 chrome_exe, 349 false, 350 cancel, 351 &shortcuts); 352 } 353 return shortcuts; 354 #else 355 return std::vector<ShortcutCommand>(); 356 #endif 357 } 358