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 "base/prefs/pref_service.h" 8 #include "chrome/browser/browsing_data/browsing_data_helper.h" 9 #include "chrome/browser/content_settings/host_content_settings_map.h" 10 #include "chrome/browser/extensions/extension_service.h" 11 #include "chrome/browser/extensions/extension_system.h" 12 #include "chrome/browser/google/google_url_tracker.h" 13 #include "chrome/browser/profile_resetter/brandcoded_default_settings.h" 14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/search_engines/search_terms_data.h" 16 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" 17 #include "chrome/browser/search_engines/template_url_service.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 "content/public/browser/browser_thread.h" 24 #include "extensions/browser/management_policy.h" 25 26 ProfileResetter::ProfileResetter(Profile* profile) 27 : profile_(profile), 28 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile_)), 29 pending_reset_flags_(0), 30 cookies_remover_(NULL) { 31 DCHECK(CalledOnValidThread()); 32 DCHECK(profile_); 33 } 34 35 ProfileResetter::~ProfileResetter() { 36 if (cookies_remover_) 37 cookies_remover_->RemoveObserver(this); 38 } 39 40 void ProfileResetter::Reset( 41 ProfileResetter::ResettableFlags resettable_flags, 42 scoped_ptr<BrandcodedDefaultSettings> master_settings, 43 const base::Closure& callback) { 44 DCHECK(CalledOnValidThread()); 45 DCHECK(master_settings); 46 47 // We should never be called with unknown flags. 48 CHECK_EQ(static_cast<ResettableFlags>(0), resettable_flags & ~ALL); 49 50 // We should never be called when a previous reset has not finished. 51 CHECK_EQ(static_cast<ResettableFlags>(0), pending_reset_flags_); 52 53 if (!resettable_flags) { 54 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 55 callback); 56 return; 57 } 58 59 master_settings_.swap(master_settings); 60 callback_ = callback; 61 62 // These flags are set to false by the individual reset functions. 63 pending_reset_flags_ = resettable_flags; 64 65 struct { 66 Resettable flag; 67 void (ProfileResetter::*method)(); 68 } flagToMethod [] = { 69 { DEFAULT_SEARCH_ENGINE, &ProfileResetter::ResetDefaultSearchEngine }, 70 { HOMEPAGE, &ProfileResetter::ResetHomepage }, 71 { CONTENT_SETTINGS, &ProfileResetter::ResetContentSettings }, 72 { COOKIES_AND_SITE_DATA, &ProfileResetter::ResetCookiesAndSiteData }, 73 { EXTENSIONS, &ProfileResetter::ResetExtensions }, 74 { STARTUP_PAGES, &ProfileResetter::ResetStartupPages }, 75 { PINNED_TABS, &ProfileResetter::ResetPinnedTabs }, 76 }; 77 78 ResettableFlags reset_triggered_for_flags = 0; 79 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flagToMethod); ++i) { 80 if (resettable_flags & flagToMethod[i].flag) { 81 reset_triggered_for_flags |= flagToMethod[i].flag; 82 (this->*flagToMethod[i].method)(); 83 } 84 } 85 86 DCHECK_EQ(resettable_flags, reset_triggered_for_flags); 87 } 88 89 bool ProfileResetter::IsActive() const { 90 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 91 return pending_reset_flags_ != 0; 92 } 93 94 void ProfileResetter::MarkAsDone(Resettable resettable) { 95 DCHECK(CalledOnValidThread()); 96 97 // Check that we are never called twice or unexpectedly. 98 CHECK(pending_reset_flags_ & resettable); 99 100 pending_reset_flags_ &= ~resettable; 101 102 if (!pending_reset_flags_) { 103 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 104 callback_); 105 callback_.Reset(); 106 master_settings_.reset(); 107 template_url_service_sub_.reset(); 108 } 109 } 110 111 void ProfileResetter::ResetDefaultSearchEngine() { 112 DCHECK(CalledOnValidThread()); 113 DCHECK(template_url_service_); 114 // If TemplateURLServiceFactory is ready we can clean it right now. 115 // Otherwise, load it and continue from ProfileResetter::Observe. 116 if (template_url_service_->loaded()) { 117 PrefService* prefs = profile_->GetPrefs(); 118 DCHECK(prefs); 119 TemplateURLPrepopulateData::ClearPrepopulatedEnginesInPrefs(profile_); 120 scoped_ptr<ListValue> search_engines( 121 master_settings_->GetSearchProviderOverrides()); 122 if (search_engines) { 123 // This Chrome distribution channel provides a custom search engine. We 124 // must reset to it. 125 ListPrefUpdate update(prefs, prefs::kSearchProviderOverrides); 126 update->Swap(search_engines.get()); 127 } 128 129 template_url_service_->RepairPrepopulatedSearchEngines(); 130 131 // Reset Google search URL. 132 prefs->ClearPref(prefs::kLastPromptedGoogleURL); 133 const TemplateURL* default_search_provider = 134 template_url_service_->GetDefaultSearchProvider(); 135 if (default_search_provider && 136 default_search_provider->url_ref().HasGoogleBaseURLs()) 137 GoogleURLTracker::RequestServerCheck(profile_, true); 138 139 MarkAsDone(DEFAULT_SEARCH_ENGINE); 140 } else { 141 template_url_service_sub_ = 142 template_url_service_->RegisterOnLoadedCallback( 143 base::Bind(&ProfileResetter::OnTemplateURLServiceLoaded, 144 base::Unretained(this))); 145 template_url_service_->Load(); 146 } 147 } 148 149 void ProfileResetter::ResetHomepage() { 150 DCHECK(CalledOnValidThread()); 151 PrefService* prefs = profile_->GetPrefs(); 152 DCHECK(prefs); 153 std::string homepage; 154 bool homepage_is_ntp, show_home_button; 155 156 if (master_settings_->GetHomepage(&homepage)) 157 prefs->SetString(prefs::kHomePage, homepage); 158 159 if (master_settings_->GetHomepageIsNewTab(&homepage_is_ntp)) 160 prefs->SetBoolean(prefs::kHomePageIsNewTabPage, homepage_is_ntp); 161 else 162 prefs->ClearPref(prefs::kHomePageIsNewTabPage); 163 164 if (master_settings_->GetShowHomeButton(&show_home_button)) 165 prefs->SetBoolean(prefs::kShowHomeButton, show_home_button); 166 else 167 prefs->ClearPref(prefs::kShowHomeButton); 168 MarkAsDone(HOMEPAGE); 169 } 170 171 void ProfileResetter::ResetContentSettings() { 172 DCHECK(CalledOnValidThread()); 173 PrefService* prefs = profile_->GetPrefs(); 174 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); 175 176 for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) { 177 map->ClearSettingsForOneType(static_cast<ContentSettingsType>(type)); 178 if (HostContentSettingsMap::IsSettingAllowedForType( 179 prefs, 180 CONTENT_SETTING_DEFAULT, 181 static_cast<ContentSettingsType>(type))) 182 map->SetDefaultContentSetting(static_cast<ContentSettingsType>(type), 183 CONTENT_SETTING_DEFAULT); 184 } 185 MarkAsDone(CONTENT_SETTINGS); 186 } 187 188 void ProfileResetter::ResetCookiesAndSiteData() { 189 DCHECK(CalledOnValidThread()); 190 DCHECK(!cookies_remover_); 191 192 cookies_remover_ = BrowsingDataRemover::CreateForUnboundedRange(profile_); 193 cookies_remover_->AddObserver(this); 194 int remove_mask = BrowsingDataRemover::REMOVE_SITE_DATA | 195 BrowsingDataRemover::REMOVE_CACHE; 196 PrefService* prefs = profile_->GetPrefs(); 197 DCHECK(prefs); 198 // Don't try to clear LSO data if it's not supported. 199 if (!prefs->GetBoolean(prefs::kClearPluginLSODataEnabled)) 200 remove_mask &= ~BrowsingDataRemover::REMOVE_PLUGIN_DATA; 201 cookies_remover_->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB); 202 } 203 204 void ProfileResetter::ResetExtensions() { 205 DCHECK(CalledOnValidThread()); 206 207 std::vector<std::string> brandcode_extensions; 208 master_settings_->GetExtensions(&brandcode_extensions); 209 210 ExtensionService* extension_service = profile_->GetExtensionService(); 211 DCHECK(extension_service); 212 extension_service->DisableUserExtensions(brandcode_extensions); 213 214 MarkAsDone(EXTENSIONS); 215 } 216 217 void ProfileResetter::ResetStartupPages() { 218 DCHECK(CalledOnValidThread()); 219 PrefService* prefs = profile_->GetPrefs(); 220 DCHECK(prefs); 221 scoped_ptr<ListValue> url_list(master_settings_->GetUrlsToRestoreOnStartup()); 222 if (url_list) 223 ListPrefUpdate(prefs, prefs::kURLsToRestoreOnStartup)->Swap(url_list.get()); 224 225 int restore_on_startup; 226 if (master_settings_->GetRestoreOnStartup(&restore_on_startup)) 227 prefs->SetInteger(prefs::kRestoreOnStartup, restore_on_startup); 228 else 229 prefs->ClearPref(prefs::kRestoreOnStartup); 230 231 prefs->SetBoolean(prefs::kRestoreOnStartupMigrated, true); 232 MarkAsDone(STARTUP_PAGES); 233 } 234 235 void ProfileResetter::ResetPinnedTabs() { 236 // Unpin all the tabs. 237 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 238 if (it->is_type_tabbed() && it->profile() == profile_) { 239 TabStripModel* tab_model = it->tab_strip_model(); 240 // Here we assume that indexof(any mini tab) < indexof(any normal tab). 241 // If we unpin the tab, it can be moved to the right. Thus traversing in 242 // reverse direction is correct. 243 for (int i = tab_model->count() - 1; i >= 0; --i) { 244 if (tab_model->IsTabPinned(i) && !tab_model->IsAppTab(i)) 245 tab_model->SetTabPinned(i, false); 246 } 247 } 248 } 249 MarkAsDone(PINNED_TABS); 250 } 251 252 void ProfileResetter::OnTemplateURLServiceLoaded() { 253 // TemplateURLService has loaded. If we need to clean search engines, it's 254 // time to go on. 255 DCHECK(CalledOnValidThread()); 256 template_url_service_sub_.reset(); 257 if (pending_reset_flags_ & DEFAULT_SEARCH_ENGINE) 258 ResetDefaultSearchEngine(); 259 } 260 261 void ProfileResetter::OnBrowsingDataRemoverDone() { 262 cookies_remover_ = NULL; 263 MarkAsDone(COOKIES_AND_SITE_DATA); 264 } 265