• 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/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 
ResetShortcutsOnFileThread()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 
ProfileResetter(Profile * profile)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 
~ProfileResetter()74 ProfileResetter::~ProfileResetter() {
75   if (cookies_remover_)
76     cookies_remover_->RemoveObserver(this);
77 }
78 
Reset(ProfileResetter::ResettableFlags resettable_flags,scoped_ptr<BrandcodedDefaultSettings> master_settings,bool accepted_send_feedback,const base::Closure & callback)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 
IsActive() const130 bool ProfileResetter::IsActive() const {
131   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
132   return pending_reset_flags_ != 0;
133 }
134 
MarkAsDone(Resettable resettable)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 
ResetDefaultSearchEngine()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 
ResetHomepage()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 
ResetContentSettings()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 
ResetCookiesAndSiteData()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 
ResetExtensions()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 
ResetStartupPages()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 
ResetPinnedTabs()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 
ResetShortcuts()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 
OnTemplateURLServiceLoaded()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 
OnBrowsingDataRemoverDone()324 void ProfileResetter::OnBrowsingDataRemoverDone() {
325   cookies_remover_ = NULL;
326   MarkAsDone(COOKIES_AND_SITE_DATA);
327 }
328 
GetChromeLaunchShortcuts(const scoped_refptr<SharedCancellationFlag> & cancel)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