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