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/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