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