• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/browser_process.h"
13 #include "chrome/browser/browsing_data/browsing_data_helper.h"
14 #include "chrome/browser/content_settings/host_content_settings_map.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/google/google_url_tracker_factory.h"
17 #include "chrome/browser/profile_resetter/brandcoded_default_settings.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
20 #include "chrome/browser/search_engines/template_url_service.h"
21 #include "chrome/browser/search_engines/template_url_service_factory.h"
22 #include "chrome/browser/ui/browser.h"
23 #include "chrome/browser/ui/browser_iterator.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/installer/util/browser_distribution.h"
27 #include "components/google/core/browser/google_pref_names.h"
28 #include "components/google/core/browser/google_url_tracker.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/browser/component_updater/sw_reporter_installer_win.h"
37 #include "chrome/installer/util/shell_util.h"
38 
39 namespace {
40 
ResetShortcutsOnFileThread()41 void ResetShortcutsOnFileThread() {
42   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
43   // Get full path of chrome.
44   base::FilePath chrome_exe;
45   if (!PathService::Get(base::FILE_EXE, &chrome_exe))
46     return;
47   BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
48       BrowserDistribution::CHROME_BROWSER);
49   for (int location = ShellUtil::SHORTCUT_LOCATION_FIRST;
50        location < ShellUtil::NUM_SHORTCUT_LOCATIONS; ++location) {
51     ShellUtil::ShortcutListMaybeRemoveUnknownArgs(
52         static_cast<ShellUtil::ShortcutLocation>(location),
53         dist,
54         ShellUtil::CURRENT_USER,
55         chrome_exe,
56         true,
57         NULL,
58         NULL);
59   }
60 }
61 
62 }  // namespace
63 #endif  // defined(OS_WIN)
64 
ProfileResetter(Profile * profile)65 ProfileResetter::ProfileResetter(Profile* profile)
66     : profile_(profile),
67       template_url_service_(TemplateURLServiceFactory::GetForProfile(profile_)),
68       pending_reset_flags_(0),
69       cookies_remover_(NULL),
70       weak_ptr_factory_(this) {
71   DCHECK(CalledOnValidThread());
72   DCHECK(profile_);
73 }
74 
~ProfileResetter()75 ProfileResetter::~ProfileResetter() {
76   if (cookies_remover_)
77     cookies_remover_->RemoveObserver(this);
78 }
79 
Reset(ProfileResetter::ResettableFlags resettable_flags,scoped_ptr<BrandcodedDefaultSettings> master_settings,bool accepted_send_feedback,const base::Closure & callback)80 void ProfileResetter::Reset(
81     ProfileResetter::ResettableFlags resettable_flags,
82     scoped_ptr<BrandcodedDefaultSettings> master_settings,
83     bool accepted_send_feedback,
84     const base::Closure& callback) {
85   DCHECK(CalledOnValidThread());
86   DCHECK(master_settings);
87 
88   // We should never be called with unknown flags.
89   CHECK_EQ(static_cast<ResettableFlags>(0), resettable_flags & ~ALL);
90 
91   // We should never be called when a previous reset has not finished.
92   CHECK_EQ(static_cast<ResettableFlags>(0), pending_reset_flags_);
93 
94   if (!resettable_flags) {
95     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
96                                      callback);
97     return;
98   }
99 
100   master_settings_.swap(master_settings);
101   callback_ = callback;
102 
103   // These flags are set to false by the individual reset functions.
104   pending_reset_flags_ = resettable_flags;
105 
106   struct {
107     Resettable flag;
108     void (ProfileResetter::*method)();
109   } flagToMethod[] = {
110         {DEFAULT_SEARCH_ENGINE, &ProfileResetter::ResetDefaultSearchEngine},
111         {HOMEPAGE, &ProfileResetter::ResetHomepage},
112         {CONTENT_SETTINGS, &ProfileResetter::ResetContentSettings},
113         {COOKIES_AND_SITE_DATA, &ProfileResetter::ResetCookiesAndSiteData},
114         {EXTENSIONS, &ProfileResetter::ResetExtensions},
115         {STARTUP_PAGES, &ProfileResetter::ResetStartupPages},
116         {PINNED_TABS, &ProfileResetter::ResetPinnedTabs},
117         {SHORTCUTS, &ProfileResetter::ResetShortcuts},
118     };
119 
120   ResettableFlags reset_triggered_for_flags = 0;
121   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flagToMethod); ++i) {
122     if (resettable_flags & flagToMethod[i].flag) {
123       reset_triggered_for_flags |= flagToMethod[i].flag;
124       (this->*flagToMethod[i].method)();
125     }
126   }
127 
128 // When the user resets any of their settings on Windows and agreed to sending
129 // feedback, run the software reporter tool to see if it could find the reason
130 // why the user wanted a reset.
131 #if defined(OS_WIN)
132   // The browser process and / or local_state can be NULL when running tests.
133   if (accepted_send_feedback && g_browser_process &&
134       g_browser_process->local_state() &&
135       g_browser_process->local_state()->GetBoolean(
136           prefs::kMetricsReportingEnabled)) {
137     ExecuteSwReporter(g_browser_process->component_updater(),
138                       g_browser_process->local_state());
139   }
140 #endif
141 
142   DCHECK_EQ(resettable_flags, reset_triggered_for_flags);
143 }
144 
IsActive() const145 bool ProfileResetter::IsActive() const {
146   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
147   return pending_reset_flags_ != 0;
148 }
149 
MarkAsDone(Resettable resettable)150 void ProfileResetter::MarkAsDone(Resettable resettable) {
151   DCHECK(CalledOnValidThread());
152 
153   // Check that we are never called twice or unexpectedly.
154   CHECK(pending_reset_flags_ & resettable);
155 
156   pending_reset_flags_ &= ~resettable;
157 
158   if (!pending_reset_flags_) {
159     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
160                                      callback_);
161     callback_.Reset();
162     master_settings_.reset();
163     template_url_service_sub_.reset();
164   }
165 }
166 
ResetDefaultSearchEngine()167 void ProfileResetter::ResetDefaultSearchEngine() {
168   DCHECK(CalledOnValidThread());
169   DCHECK(template_url_service_);
170   // If TemplateURLServiceFactory is ready we can clean it right now.
171   // Otherwise, load it and continue from ProfileResetter::Observe.
172   if (template_url_service_->loaded()) {
173     PrefService* prefs = profile_->GetPrefs();
174     DCHECK(prefs);
175     TemplateURLPrepopulateData::ClearPrepopulatedEnginesInPrefs(
176         profile_->GetPrefs());
177     scoped_ptr<base::ListValue> search_engines(
178         master_settings_->GetSearchProviderOverrides());
179     if (search_engines) {
180       // This Chrome distribution channel provides a custom search engine. We
181       // must reset to it.
182       ListPrefUpdate update(prefs, prefs::kSearchProviderOverrides);
183       update->Swap(search_engines.get());
184     }
185 
186     template_url_service_->RepairPrepopulatedSearchEngines();
187 
188     // Reset Google search URL.
189     prefs->ClearPref(prefs::kLastPromptedGoogleURL);
190     const TemplateURL* default_search_provider =
191         template_url_service_->GetDefaultSearchProvider();
192     if (default_search_provider &&
193         default_search_provider->HasGoogleBaseURLs(
194             template_url_service_->search_terms_data())) {
195       GoogleURLTracker* tracker =
196           GoogleURLTrackerFactory::GetForProfile(profile_);
197       if (tracker)
198         tracker->RequestServerCheck(true);
199     }
200 
201     MarkAsDone(DEFAULT_SEARCH_ENGINE);
202   } else {
203     template_url_service_sub_ =
204         template_url_service_->RegisterOnLoadedCallback(
205             base::Bind(&ProfileResetter::OnTemplateURLServiceLoaded,
206                        weak_ptr_factory_.GetWeakPtr()));
207     template_url_service_->Load();
208   }
209 }
210 
ResetHomepage()211 void ProfileResetter::ResetHomepage() {
212   DCHECK(CalledOnValidThread());
213   PrefService* prefs = profile_->GetPrefs();
214   DCHECK(prefs);
215   std::string homepage;
216   bool homepage_is_ntp, show_home_button;
217 
218   if (master_settings_->GetHomepage(&homepage))
219     prefs->SetString(prefs::kHomePage, homepage);
220 
221   if (master_settings_->GetHomepageIsNewTab(&homepage_is_ntp))
222     prefs->SetBoolean(prefs::kHomePageIsNewTabPage, homepage_is_ntp);
223   else
224     prefs->ClearPref(prefs::kHomePageIsNewTabPage);
225 
226   if (master_settings_->GetShowHomeButton(&show_home_button))
227     prefs->SetBoolean(prefs::kShowHomeButton, show_home_button);
228   else
229     prefs->ClearPref(prefs::kShowHomeButton);
230   MarkAsDone(HOMEPAGE);
231 }
232 
ResetContentSettings()233 void ProfileResetter::ResetContentSettings() {
234   DCHECK(CalledOnValidThread());
235   PrefService* prefs = profile_->GetPrefs();
236   HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
237 
238   for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
239     map->ClearSettingsForOneType(static_cast<ContentSettingsType>(type));
240     if (HostContentSettingsMap::IsSettingAllowedForType(
241             prefs,
242             CONTENT_SETTING_DEFAULT,
243             static_cast<ContentSettingsType>(type)))
244       map->SetDefaultContentSetting(static_cast<ContentSettingsType>(type),
245                                     CONTENT_SETTING_DEFAULT);
246   }
247   MarkAsDone(CONTENT_SETTINGS);
248 }
249 
ResetCookiesAndSiteData()250 void ProfileResetter::ResetCookiesAndSiteData() {
251   DCHECK(CalledOnValidThread());
252   DCHECK(!cookies_remover_);
253 
254   cookies_remover_ = BrowsingDataRemover::CreateForUnboundedRange(profile_);
255   cookies_remover_->AddObserver(this);
256   int remove_mask = BrowsingDataRemover::REMOVE_SITE_DATA |
257                     BrowsingDataRemover::REMOVE_CACHE;
258   PrefService* prefs = profile_->GetPrefs();
259   DCHECK(prefs);
260   // Don't try to clear LSO data if it's not supported.
261   if (!prefs->GetBoolean(prefs::kClearPluginLSODataEnabled))
262     remove_mask &= ~BrowsingDataRemover::REMOVE_PLUGIN_DATA;
263   cookies_remover_->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
264 }
265 
ResetExtensions()266 void ProfileResetter::ResetExtensions() {
267   DCHECK(CalledOnValidThread());
268 
269   std::vector<std::string> brandcode_extensions;
270   master_settings_->GetExtensions(&brandcode_extensions);
271 
272   ExtensionService* extension_service = profile_->GetExtensionService();
273   DCHECK(extension_service);
274   extension_service->DisableUserExtensions(brandcode_extensions);
275 
276   MarkAsDone(EXTENSIONS);
277 }
278 
ResetStartupPages()279 void ProfileResetter::ResetStartupPages() {
280   DCHECK(CalledOnValidThread());
281   PrefService* prefs = profile_->GetPrefs();
282   DCHECK(prefs);
283   scoped_ptr<base::ListValue> url_list(
284       master_settings_->GetUrlsToRestoreOnStartup());
285   if (url_list)
286     ListPrefUpdate(prefs, prefs::kURLsToRestoreOnStartup)->Swap(url_list.get());
287 
288   int restore_on_startup;
289   if (master_settings_->GetRestoreOnStartup(&restore_on_startup))
290     prefs->SetInteger(prefs::kRestoreOnStartup, restore_on_startup);
291   else
292     prefs->ClearPref(prefs::kRestoreOnStartup);
293 
294   prefs->SetBoolean(prefs::kRestoreOnStartupMigrated, true);
295   MarkAsDone(STARTUP_PAGES);
296 }
297 
ResetPinnedTabs()298 void ProfileResetter::ResetPinnedTabs() {
299   // Unpin all the tabs.
300   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
301     if (it->is_type_tabbed() && it->profile() == profile_) {
302       TabStripModel* tab_model = it->tab_strip_model();
303       // Here we assume that indexof(any mini tab) < indexof(any normal tab).
304       // If we unpin the tab, it can be moved to the right. Thus traversing in
305       // reverse direction is correct.
306       for (int i = tab_model->count() - 1; i >= 0; --i) {
307         if (tab_model->IsTabPinned(i) && !tab_model->IsAppTab(i))
308           tab_model->SetTabPinned(i, false);
309       }
310     }
311   }
312   MarkAsDone(PINNED_TABS);
313 }
314 
ResetShortcuts()315 void ProfileResetter::ResetShortcuts() {
316 #if defined(OS_WIN)
317   content::BrowserThread::PostTaskAndReply(
318       content::BrowserThread::FILE,
319       FROM_HERE,
320       base::Bind(&ResetShortcutsOnFileThread),
321       base::Bind(&ProfileResetter::MarkAsDone,
322                  weak_ptr_factory_.GetWeakPtr(),
323                  SHORTCUTS));
324 #else
325   MarkAsDone(SHORTCUTS);
326 #endif
327 }
328 
OnTemplateURLServiceLoaded()329 void ProfileResetter::OnTemplateURLServiceLoaded() {
330   // TemplateURLService has loaded. If we need to clean search engines, it's
331   // time to go on.
332   DCHECK(CalledOnValidThread());
333   template_url_service_sub_.reset();
334   if (pending_reset_flags_ & DEFAULT_SEARCH_ENGINE)
335     ResetDefaultSearchEngine();
336 }
337 
OnBrowsingDataRemoverDone()338 void ProfileResetter::OnBrowsingDataRemoverDone() {
339   cookies_remover_ = NULL;
340   MarkAsDone(COOKIES_AND_SITE_DATA);
341 }
342 
GetChromeLaunchShortcuts(const scoped_refptr<SharedCancellationFlag> & cancel)343 std::vector<ShortcutCommand> GetChromeLaunchShortcuts(
344     const scoped_refptr<SharedCancellationFlag>& cancel) {
345   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
346 #if defined(OS_WIN)
347   // Get full path of chrome.
348   base::FilePath chrome_exe;
349   if (!PathService::Get(base::FILE_EXE, &chrome_exe))
350     return std::vector<ShortcutCommand>();
351   BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
352       BrowserDistribution::CHROME_BROWSER);
353   std::vector<ShortcutCommand> shortcuts;
354   for (int location = ShellUtil::SHORTCUT_LOCATION_FIRST;
355        location < ShellUtil::NUM_SHORTCUT_LOCATIONS; ++location) {
356     if (cancel && cancel->data.IsSet())
357       break;
358     ShellUtil::ShortcutListMaybeRemoveUnknownArgs(
359         static_cast<ShellUtil::ShortcutLocation>(location),
360         dist,
361         ShellUtil::CURRENT_USER,
362         chrome_exe,
363         false,
364         cancel,
365         &shortcuts);
366   }
367   return shortcuts;
368 #else
369   return std::vector<ShortcutCommand>();
370 #endif
371 }
372