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/resettable_settings_snapshot.h" 6 7 #include "base/json/json_writer.h" 8 #include "base/prefs/pref_service.h" 9 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/feedback/feedback_data.h" 11 #include "chrome/browser/feedback/feedback_util.h" 12 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/search_engines/template_url_service.h" 14 #include "chrome/browser/search_engines/template_url_service_factory.h" 15 #include "chrome/common/pref_names.h" 16 17 namespace { 18 19 // Feedback bucket label. 20 const char kProfileResetFeedbackBucket[] = "ProfileResetReport"; 21 22 // Dictionary keys for feedback report. 23 const char kDefaultSearchEnginePath[] = "default_search_engine"; 24 const char kEnabledExtensions[] = "enabled_extensions"; 25 const char kHomepageIsNewTabPage[] = "homepage_is_ntp"; 26 const char kHomepagePath[] = "homepage"; 27 const char kStartupTypePath[] = "startup_type"; 28 const char kStartupURLPath[] = "startup_urls"; 29 30 } // namespace 31 32 ResettableSettingsSnapshot::ResettableSettingsSnapshot(Profile* profile) 33 : startup_(SessionStartupPref::GetStartupPref(profile)) { 34 // URLs are always stored sorted. 35 std::sort(startup_.urls.begin(), startup_.urls.end()); 36 37 PrefService* prefs = profile->GetPrefs(); 38 DCHECK(prefs); 39 homepage_ = prefs->GetString(prefs::kHomePage); 40 homepage_is_ntp_ = prefs->GetBoolean(prefs::kHomePageIsNewTabPage); 41 42 TemplateURLService* service = 43 TemplateURLServiceFactory::GetForProfile(profile); 44 DCHECK(service); 45 TemplateURL* dse = service->GetDefaultSearchProvider(); 46 if (dse) 47 dse_url_ = dse->url(); 48 49 ExtensionService* extension_service = profile->GetExtensionService(); 50 DCHECK(extension_service); 51 const ExtensionSet* enabled_ext = extension_service->extensions(); 52 enabled_extensions_.reserve(enabled_ext->size()); 53 54 for (ExtensionSet::const_iterator it = enabled_ext->begin(); 55 it != enabled_ext->end(); ++it) 56 enabled_extensions_.push_back((*it)->id()); 57 58 // ExtensionSet is sorted but it seems to be an implementation detail. 59 std::sort(enabled_extensions_.begin(), enabled_extensions_.end()); 60 } 61 62 ResettableSettingsSnapshot::~ResettableSettingsSnapshot() {} 63 64 void ResettableSettingsSnapshot::Subtract( 65 const ResettableSettingsSnapshot& snapshot) { 66 std::vector<GURL> urls; 67 std::set_difference(startup_.urls.begin(), startup_.urls.end(), 68 snapshot.startup_.urls.begin(), 69 snapshot.startup_.urls.end(), 70 std::back_inserter(urls)); 71 startup_.urls.swap(urls); 72 73 std::vector<std::string> extensions; 74 std::set_difference(enabled_extensions_.begin(), enabled_extensions_.end(), 75 snapshot.enabled_extensions_.begin(), 76 snapshot.enabled_extensions_.end(), 77 std::back_inserter(extensions)); 78 enabled_extensions_.swap(extensions); 79 } 80 81 int ResettableSettingsSnapshot::FindDifferentFields( 82 const ResettableSettingsSnapshot& snapshot) const { 83 int bit_mask = 0; 84 85 if (startup_.urls != snapshot.startup_.urls) { 86 bit_mask |= STARTUP_URLS; 87 } 88 89 if (startup_.type != snapshot.startup_.type) 90 bit_mask |= STARTUP_TYPE; 91 92 if (homepage_ != snapshot.homepage_) 93 bit_mask |= HOMEPAGE; 94 95 if (homepage_is_ntp_ != snapshot.homepage_is_ntp_) 96 bit_mask |= HOMEPAGE_IS_NTP; 97 98 if (dse_url_ != snapshot.dse_url_) 99 bit_mask |= DSE_URL; 100 101 if (enabled_extensions_ != snapshot.enabled_extensions_) 102 bit_mask |= EXTENSIONS; 103 104 COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63, 105 add_new_field_here); 106 107 return bit_mask; 108 } 109 110 std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot, 111 int field_mask) { 112 DictionaryValue dict; 113 114 if (field_mask & ResettableSettingsSnapshot::STARTUP_URLS) { 115 ListValue* list = new ListValue; 116 const std::vector<GURL>& urls = snapshot.startup_urls(); 117 for (std::vector<GURL>::const_iterator i = urls.begin(); 118 i != urls.end(); ++i) 119 list->AppendString(i->spec()); 120 dict.Set(kStartupURLPath, list); 121 } 122 123 if (field_mask & ResettableSettingsSnapshot::STARTUP_TYPE) 124 dict.SetInteger(kStartupTypePath, snapshot.startup_type()); 125 126 if (field_mask & ResettableSettingsSnapshot::HOMEPAGE) 127 dict.SetString(kHomepagePath, snapshot.homepage()); 128 129 if (field_mask & ResettableSettingsSnapshot::HOMEPAGE_IS_NTP) 130 dict.SetBoolean(kHomepageIsNewTabPage, snapshot.homepage_is_ntp()); 131 132 if (field_mask & ResettableSettingsSnapshot::DSE_URL) 133 dict.SetString(kDefaultSearchEnginePath, snapshot.dse_url()); 134 135 if (field_mask & ResettableSettingsSnapshot::EXTENSIONS) { 136 ListValue* list = new ListValue; 137 const std::vector<std::string>& extensions = snapshot.enabled_extensions(); 138 for (std::vector<std::string>::const_iterator i = extensions.begin(); 139 i != extensions.end(); ++i) 140 list->AppendString(*i); 141 dict.Set(kEnabledExtensions, list); 142 } 143 144 COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63, 145 serialize_new_field_here); 146 147 std::string json; 148 base::JSONWriter::Write(&dict, &json); 149 return json; 150 } 151 152 void SendSettingsFeedback(const std::string& report, Profile* profile) { 153 scoped_refptr<FeedbackData> feedback_data = new FeedbackData(); 154 feedback_data->set_category_tag(kProfileResetFeedbackBucket); 155 feedback_data->set_description(report); 156 157 feedback_data->set_image(ScreenshotDataPtr()); 158 feedback_data->set_profile(profile); 159 160 feedback_data->set_page_url(""); 161 feedback_data->set_user_email(""); 162 163 FeedbackUtil::SendReport(feedback_data); 164 } 165