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