• 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/resettable_settings_snapshot.h"
6 
7 #include "base/json/json_writer.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/feedback/feedback_data.h"
14 #include "chrome/browser/feedback/feedback_util.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/search_engines/template_url_service.h"
17 #include "chrome/browser/search_engines/template_url_service_factory.h"
18 #include "chrome/common/chrome_version_info.h"
19 #include "chrome/common/pref_names.h"
20 #include "grit/generated_resources.h"
21 #include "grit/google_chrome_strings.h"
22 #include "ui/base/l10n/l10n_util.h"
23 
24 namespace {
25 
26 // Feedback bucket labels.
27 const char kProfileResetPromptBucket[] = "SamplingOfSettingsResetPrompt";
28 const char kProfileResetWebUIBucket[] = "ProfileResetReport";
29 
30 // Dictionary keys for feedback report.
31 const char kDefaultSearchEnginePath[] = "default_search_engine";
32 const char kEnabledExtensions[] = "enabled_extensions";
33 const char kHomepageIsNewTabPage[] = "homepage_is_ntp";
34 const char kHomepagePath[] = "homepage";
35 const char kStartupTypePath[] = "startup_type";
36 const char kStartupURLPath[] = "startup_urls";
37 
38 template <class StringType>
AddPair(ListValue * list,const base::string16 & key,const StringType & value)39 void AddPair(ListValue* list,
40              const base::string16& key,
41              const StringType& value) {
42   DictionaryValue* results = new DictionaryValue();
43   results->SetString("key", key);
44   results->SetString("value", value);
45   list->Append(results);
46 }
47 
48 }  // namespace
49 
ResettableSettingsSnapshot(Profile * profile)50 ResettableSettingsSnapshot::ResettableSettingsSnapshot(Profile* profile)
51     : startup_(SessionStartupPref::GetStartupPref(profile)) {
52   // URLs are always stored sorted.
53   std::sort(startup_.urls.begin(), startup_.urls.end());
54 
55   PrefService* prefs = profile->GetPrefs();
56   DCHECK(prefs);
57   homepage_ = prefs->GetString(prefs::kHomePage);
58   homepage_is_ntp_ = prefs->GetBoolean(prefs::kHomePageIsNewTabPage);
59 
60   TemplateURLService* service =
61       TemplateURLServiceFactory::GetForProfile(profile);
62   DCHECK(service);
63   TemplateURL* dse = service->GetDefaultSearchProvider();
64   if (dse)
65     dse_url_ = dse->url();
66 
67   ExtensionService* extension_service = profile->GetExtensionService();
68   DCHECK(extension_service);
69   const ExtensionSet* enabled_ext = extension_service->extensions();
70   enabled_extensions_.reserve(enabled_ext->size());
71 
72   for (ExtensionSet::const_iterator it = enabled_ext->begin();
73        it != enabled_ext->end(); ++it)
74     enabled_extensions_.push_back(std::make_pair((*it)->id(), (*it)->name()));
75 
76   // ExtensionSet is sorted but it seems to be an implementation detail.
77   std::sort(enabled_extensions_.begin(), enabled_extensions_.end());
78 }
79 
~ResettableSettingsSnapshot()80 ResettableSettingsSnapshot::~ResettableSettingsSnapshot() {}
81 
Subtract(const ResettableSettingsSnapshot & snapshot)82 void ResettableSettingsSnapshot::Subtract(
83     const ResettableSettingsSnapshot& snapshot) {
84   ExtensionList extensions = base::STLSetDifference<ExtensionList>(
85       enabled_extensions_, snapshot.enabled_extensions_);
86   enabled_extensions_.swap(extensions);
87 }
88 
FindDifferentFields(const ResettableSettingsSnapshot & snapshot) const89 int ResettableSettingsSnapshot::FindDifferentFields(
90     const ResettableSettingsSnapshot& snapshot) const {
91   int bit_mask = 0;
92 
93   if (startup_.type != snapshot.startup_.type ||
94       startup_.urls != snapshot.startup_.urls)
95     bit_mask |= STARTUP_MODE;
96 
97   if (homepage_is_ntp_ != snapshot.homepage_is_ntp_ ||
98       homepage_ != snapshot.homepage_)
99     bit_mask |= HOMEPAGE;
100 
101   if (dse_url_ != snapshot.dse_url_)
102     bit_mask |= DSE_URL;
103 
104   if (enabled_extensions_ != snapshot.enabled_extensions_)
105     bit_mask |= EXTENSIONS;
106 
107   COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 15,
108                  add_new_field_here);
109 
110   return bit_mask;
111 }
112 
SerializeSettingsReport(const ResettableSettingsSnapshot & snapshot,int field_mask)113 std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot,
114                                     int field_mask) {
115   DictionaryValue dict;
116 
117   if (field_mask & ResettableSettingsSnapshot::STARTUP_MODE) {
118     ListValue* list = new ListValue;
119     const std::vector<GURL>& urls = snapshot.startup_urls();
120     for (std::vector<GURL>::const_iterator i = urls.begin();
121          i != urls.end(); ++i)
122       list->AppendString(i->spec());
123     dict.Set(kStartupURLPath, list);
124     dict.SetInteger(kStartupTypePath, snapshot.startup_type());
125   }
126 
127   if (field_mask & ResettableSettingsSnapshot::HOMEPAGE) {
128     dict.SetString(kHomepagePath, snapshot.homepage());
129     dict.SetBoolean(kHomepageIsNewTabPage, snapshot.homepage_is_ntp());
130   }
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 ResettableSettingsSnapshot::ExtensionList& extensions =
138         snapshot.enabled_extensions();
139     for (ResettableSettingsSnapshot::ExtensionList::const_iterator i =
140          extensions.begin(); i != extensions.end(); ++i) {
141       // Replace "\"" to simplify server-side analysis.
142       std::string ext_name;
143       base::ReplaceChars(i->second, "\"", "\'", &ext_name);
144       list->AppendString(i->first + ";" + ext_name);
145     }
146     dict.Set(kEnabledExtensions, list);
147   }
148 
149   COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 15,
150                  serialize_new_field_here);
151 
152   std::string json;
153   base::JSONWriter::Write(&dict, &json);
154   return json;
155 }
156 
SendSettingsFeedback(const std::string & report,Profile * profile,SnapshotCaller caller)157 void SendSettingsFeedback(const std::string& report,
158                           Profile* profile,
159                           SnapshotCaller caller) {
160   scoped_refptr<FeedbackData> feedback_data = new FeedbackData();
161   std::string bucket;
162   switch (caller) {
163     case PROFILE_RESET_WEBUI:
164       bucket = kProfileResetWebUIBucket;
165       break;
166     case PROFILE_RESET_PROMPT:
167       bucket = kProfileResetPromptBucket;
168       break;
169   }
170   feedback_data->set_category_tag(bucket);
171   feedback_data->set_description(report);
172 
173   feedback_data->set_image(scoped_ptr<std::string>(new std::string));
174   feedback_data->set_profile(profile);
175 
176   feedback_data->set_page_url("");
177   feedback_data->set_user_email("");
178 
179   feedback_util::SendReport(feedback_data);
180 }
181 
GetReadableFeedback(Profile * profile)182 ListValue* GetReadableFeedback(Profile* profile) {
183   DCHECK(profile);
184   ListValue* list = new ListValue;
185   AddPair(list, l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_LOCALE),
186           g_browser_process->GetApplicationLocale());
187   AddPair(list,
188           l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_USER_AGENT),
189           content::GetUserAgent(GURL()));
190   chrome::VersionInfo version_info;
191   std::string version = version_info.Version();
192   version += chrome::VersionInfo::GetVersionStringModifier();
193   AddPair(list,
194           l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
195           version);
196 
197   // Add snapshot data.
198   ResettableSettingsSnapshot snapshot(profile);
199   const std::vector<GURL>& urls = snapshot.startup_urls();
200   std::string startup_urls;
201   for (std::vector<GURL>::const_iterator i = urls.begin();
202        i != urls.end(); ++i) {
203     (startup_urls += i->host()) += ' ';
204   }
205   if (!startup_urls.empty()) {
206     startup_urls.erase(startup_urls.end() - 1);
207     AddPair(list,
208             l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_STARTUP_URLS),
209             startup_urls);
210   }
211 
212   base::string16 startup_type;
213   switch (snapshot.startup_type()) {
214     case SessionStartupPref::DEFAULT:
215       startup_type = l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_NEWTAB);
216       break;
217     case SessionStartupPref::LAST:
218       startup_type = l10n_util::GetStringUTF16(
219           IDS_OPTIONS_STARTUP_RESTORE_LAST_SESSION);
220       break;
221     case SessionStartupPref::URLS:
222       startup_type = l10n_util::GetStringUTF16(IDS_OPTIONS_STARTUP_SHOW_PAGES);
223       break;
224     default:
225       break;
226   }
227   AddPair(list,
228           l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_STARTUP_TYPE),
229           startup_type);
230 
231   if (!snapshot.homepage().empty()) {
232     AddPair(list,
233             l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_HOMEPAGE),
234             snapshot.homepage());
235   }
236 
237   int is_ntp_message_id = snapshot.homepage_is_ntp() ?
238       IDS_RESET_PROFILE_SETTINGS_HOMEPAGE_IS_NTP_TRUE :
239       IDS_RESET_PROFILE_SETTINGS_HOMEPAGE_IS_NTP_FALSE;
240   AddPair(list,
241           l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_HOMEPAGE_IS_NTP),
242           l10n_util::GetStringUTF16(is_ntp_message_id));
243 
244   TemplateURLService* service =
245       TemplateURLServiceFactory::GetForProfile(profile);
246   DCHECK(service);
247   TemplateURL* dse = service->GetDefaultSearchProvider();
248   if (dse) {
249     AddPair(list,
250             l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_DSE),
251             TemplateURLService::GenerateSearchURL(dse).host());
252   }
253 
254   const ResettableSettingsSnapshot::ExtensionList& extensions =
255       snapshot.enabled_extensions();
256   std::string extension_names;
257   for (ResettableSettingsSnapshot::ExtensionList::const_iterator i =
258        extensions.begin(); i != extensions.end(); ++i) {
259     (extension_names += i->second) += '\n';
260   }
261   if (!extension_names.empty()) {
262     extension_names.erase(extension_names.end() - 1);
263     AddPair(list,
264             l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_EXTENSIONS),
265             extension_names);
266   }
267   return list;
268 }
269