| // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/profile_resetter/resettable_settings_snapshot.h" |
| |
| #include "base/json/json_writer.h" |
| #include "base/prefs/pref_service.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/feedback/feedback_data.h" |
| #include "chrome/browser/feedback/feedback_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/search_engines/template_url_service.h" |
| #include "chrome/browser/search_engines/template_url_service_factory.h" |
| #include "chrome/common/pref_names.h" |
| |
| namespace { |
| |
| // Feedback bucket label. |
| const char kProfileResetFeedbackBucket[] = "ProfileResetReport"; |
| |
| // Dictionary keys for feedback report. |
| const char kDefaultSearchEnginePath[] = "default_search_engine"; |
| const char kEnabledExtensions[] = "enabled_extensions"; |
| const char kHomepageIsNewTabPage[] = "homepage_is_ntp"; |
| const char kHomepagePath[] = "homepage"; |
| const char kStartupTypePath[] = "startup_type"; |
| const char kStartupURLPath[] = "startup_urls"; |
| |
| } // namespace |
| |
| ResettableSettingsSnapshot::ResettableSettingsSnapshot(Profile* profile) |
| : startup_(SessionStartupPref::GetStartupPref(profile)) { |
| // URLs are always stored sorted. |
| std::sort(startup_.urls.begin(), startup_.urls.end()); |
| |
| PrefService* prefs = profile->GetPrefs(); |
| DCHECK(prefs); |
| homepage_ = prefs->GetString(prefs::kHomePage); |
| homepage_is_ntp_ = prefs->GetBoolean(prefs::kHomePageIsNewTabPage); |
| |
| TemplateURLService* service = |
| TemplateURLServiceFactory::GetForProfile(profile); |
| DCHECK(service); |
| TemplateURL* dse = service->GetDefaultSearchProvider(); |
| if (dse) |
| dse_url_ = dse->url(); |
| |
| ExtensionService* extension_service = profile->GetExtensionService(); |
| DCHECK(extension_service); |
| const ExtensionSet* enabled_ext = extension_service->extensions(); |
| enabled_extensions_.reserve(enabled_ext->size()); |
| |
| for (ExtensionSet::const_iterator it = enabled_ext->begin(); |
| it != enabled_ext->end(); ++it) |
| enabled_extensions_.push_back((*it)->id()); |
| |
| // ExtensionSet is sorted but it seems to be an implementation detail. |
| std::sort(enabled_extensions_.begin(), enabled_extensions_.end()); |
| } |
| |
| ResettableSettingsSnapshot::~ResettableSettingsSnapshot() {} |
| |
| void ResettableSettingsSnapshot::Subtract( |
| const ResettableSettingsSnapshot& snapshot) { |
| std::vector<GURL> urls; |
| std::set_difference(startup_.urls.begin(), startup_.urls.end(), |
| snapshot.startup_.urls.begin(), |
| snapshot.startup_.urls.end(), |
| std::back_inserter(urls)); |
| startup_.urls.swap(urls); |
| |
| std::vector<std::string> extensions; |
| std::set_difference(enabled_extensions_.begin(), enabled_extensions_.end(), |
| snapshot.enabled_extensions_.begin(), |
| snapshot.enabled_extensions_.end(), |
| std::back_inserter(extensions)); |
| enabled_extensions_.swap(extensions); |
| } |
| |
| int ResettableSettingsSnapshot::FindDifferentFields( |
| const ResettableSettingsSnapshot& snapshot) const { |
| int bit_mask = 0; |
| |
| if (startup_.urls != snapshot.startup_.urls) { |
| bit_mask |= STARTUP_URLS; |
| } |
| |
| if (startup_.type != snapshot.startup_.type) |
| bit_mask |= STARTUP_TYPE; |
| |
| if (homepage_ != snapshot.homepage_) |
| bit_mask |= HOMEPAGE; |
| |
| if (homepage_is_ntp_ != snapshot.homepage_is_ntp_) |
| bit_mask |= HOMEPAGE_IS_NTP; |
| |
| if (dse_url_ != snapshot.dse_url_) |
| bit_mask |= DSE_URL; |
| |
| if (enabled_extensions_ != snapshot.enabled_extensions_) |
| bit_mask |= EXTENSIONS; |
| |
| COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63, |
| add_new_field_here); |
| |
| return bit_mask; |
| } |
| |
| std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot, |
| int field_mask) { |
| DictionaryValue dict; |
| |
| if (field_mask & ResettableSettingsSnapshot::STARTUP_URLS) { |
| ListValue* list = new ListValue; |
| const std::vector<GURL>& urls = snapshot.startup_urls(); |
| for (std::vector<GURL>::const_iterator i = urls.begin(); |
| i != urls.end(); ++i) |
| list->AppendString(i->spec()); |
| dict.Set(kStartupURLPath, list); |
| } |
| |
| if (field_mask & ResettableSettingsSnapshot::STARTUP_TYPE) |
| dict.SetInteger(kStartupTypePath, snapshot.startup_type()); |
| |
| if (field_mask & ResettableSettingsSnapshot::HOMEPAGE) |
| dict.SetString(kHomepagePath, snapshot.homepage()); |
| |
| if (field_mask & ResettableSettingsSnapshot::HOMEPAGE_IS_NTP) |
| dict.SetBoolean(kHomepageIsNewTabPage, snapshot.homepage_is_ntp()); |
| |
| if (field_mask & ResettableSettingsSnapshot::DSE_URL) |
| dict.SetString(kDefaultSearchEnginePath, snapshot.dse_url()); |
| |
| if (field_mask & ResettableSettingsSnapshot::EXTENSIONS) { |
| ListValue* list = new ListValue; |
| const std::vector<std::string>& extensions = snapshot.enabled_extensions(); |
| for (std::vector<std::string>::const_iterator i = extensions.begin(); |
| i != extensions.end(); ++i) |
| list->AppendString(*i); |
| dict.Set(kEnabledExtensions, list); |
| } |
| |
| COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63, |
| serialize_new_field_here); |
| |
| std::string json; |
| base::JSONWriter::Write(&dict, &json); |
| return json; |
| } |
| |
| void SendSettingsFeedback(const std::string& report, Profile* profile) { |
| scoped_refptr<FeedbackData> feedback_data = new FeedbackData(); |
| feedback_data->set_category_tag(kProfileResetFeedbackBucket); |
| feedback_data->set_description(report); |
| |
| feedback_data->set_image(ScreenshotDataPtr()); |
| feedback_data->set_profile(profile); |
| |
| feedback_data->set_page_url(""); |
| feedback_data->set_user_email(""); |
| |
| FeedbackUtil::SendReport(feedback_data); |
| } |