Home | History | Annotate | Download | only in profile_resetter
      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