1 // Copyright 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/ui/webui/settings/reset_settings_handler.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "base/metrics/user_metrics.h"
13 #include "base/strings/string16.h"
14 #include "base/time/time.h"
15 #include "base/values.h"
16 #include "build/build_config.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/google/google_brand.h"
19 #include "chrome/browser/net/system_network_context_manager.h"
20 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
21 #include "chrome/browser/profile_resetter/brandcode_config_fetcher.h"
22 #include "chrome/browser/profile_resetter/brandcoded_default_settings.h"
23 #include "chrome/browser/profile_resetter/profile_resetter.h"
24 #include "chrome/browser/profile_resetter/resettable_settings_snapshot.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/common/url_constants.h"
27 #include "chrome/grit/generated_resources.h"
28 #include "components/prefs/pref_service.h"
29 #include "content/public/browser/web_ui.h"
30 #include "content/public/browser/web_ui_data_source.h"
31 #include "services/network/public/mojom/url_loader_factory.mojom.h"
32 #include "ui/base/l10n/l10n_util.h"
33
34 #if defined(OS_CHROMEOS)
35 #include "chrome/browser/browser_process.h"
36 #include "chrome/browser/browser_process_platform_part.h"
37 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
38 #include "chrome/browser/chromeos/reset/metrics.h"
39 #include "chrome/common/pref_names.h"
40 #include "components/user_manager/user_manager.h"
41 #endif // defined(OS_CHROMEOS)
42
43 #if defined(OS_WIN)
44 #include "chrome/browser/profile_resetter/triggered_profile_resetter.h"
45 #include "chrome/browser/profile_resetter/triggered_profile_resetter_factory.h"
46 #endif // defined(OS_WIN)
47
48 namespace settings {
49
50 namespace {
51
52 reset_report::ChromeResetReport::ResetRequestOrigin
ResetRequestOriginFromString(const std::string & request_origin)53 ResetRequestOriginFromString(const std::string& request_origin) {
54 static const char kOriginUserClick[] = "userclick";
55 static const char kOriginTriggeredReset[] = "triggeredreset";
56
57 if (request_origin == ResetSettingsHandler::kCctResetSettingsHash)
58 return reset_report::ChromeResetReport::RESET_REQUEST_ORIGIN_CCT;
59 if (request_origin == kOriginUserClick)
60 return reset_report::ChromeResetReport::RESET_REQUEST_ORIGIN_USER_CLICK;
61 if (request_origin == kOriginTriggeredReset) {
62 return reset_report::ChromeResetReport::
63 RESET_REQUEST_ORIGIN_TRIGGERED_RESET;
64 }
65 if (!request_origin.empty())
66 NOTREACHED();
67
68 return reset_report::ChromeResetReport::RESET_REQUEST_ORIGIN_UNKNOWN;
69 }
70
71 } // namespace
72
73 const char ResetSettingsHandler::kCctResetSettingsHash[] = "cct";
74
ResetSettingsHandler(Profile * profile)75 ResetSettingsHandler::ResetSettingsHandler(Profile* profile)
76 : profile_(profile) {
77 google_brand::GetBrand(&brandcode_);
78 }
79
~ResetSettingsHandler()80 ResetSettingsHandler::~ResetSettingsHandler() {}
81
Create(content::WebUIDataSource * html_source,Profile * profile)82 ResetSettingsHandler* ResetSettingsHandler::Create(
83 content::WebUIDataSource* html_source, Profile* profile) {
84 #if defined(OS_CHROMEOS)
85 // TODO(crbug.com/891905): Centralize powerwash restriction checks.
86 bool allow_powerwash = false;
87 policy::BrowserPolicyConnectorChromeOS* connector =
88 g_browser_process->platform_part()->browser_policy_connector_chromeos();
89 allow_powerwash =
90 !connector->IsEnterpriseManaged() &&
91 !user_manager::UserManager::Get()->IsLoggedInAsGuest() &&
92 !user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser() &&
93 !user_manager::UserManager::Get()->IsLoggedInAsChildUser();
94 html_source->AddBoolean("allowPowerwash", allow_powerwash);
95 #endif // defined(OS_CHROMEOS)
96
97 bool show_reset_profile_banner = false;
98 static const int kBannerShowTimeInDays = 5;
99 const base::Time then = chrome_prefs::GetResetTime(profile);
100 if (!then.is_null()) {
101 show_reset_profile_banner =
102 (base::Time::Now() - then).InDays() < kBannerShowTimeInDays;
103 }
104 html_source->AddBoolean("showResetProfileBanner", show_reset_profile_banner);
105
106 return new ResetSettingsHandler(profile);
107 }
108
OnJavascriptDisallowed()109 void ResetSettingsHandler::OnJavascriptDisallowed() {
110 callback_weak_ptr_factory_.InvalidateWeakPtrs();
111 }
112
RegisterMessages()113 void ResetSettingsHandler::RegisterMessages() {
114 web_ui()->RegisterMessageCallback(
115 "performResetProfileSettings",
116 base::BindRepeating(&ResetSettingsHandler::HandleResetProfileSettings,
117 base::Unretained(this)));
118 web_ui()->RegisterMessageCallback(
119 "onShowResetProfileDialog",
120 base::BindRepeating(&ResetSettingsHandler::OnShowResetProfileDialog,
121 base::Unretained(this)));
122 web_ui()->RegisterMessageCallback(
123 "getReportedSettings",
124 base::BindRepeating(&ResetSettingsHandler::HandleGetReportedSettings,
125 base::Unretained(this)));
126 web_ui()->RegisterMessageCallback(
127 "onHideResetProfileDialog",
128 base::BindRepeating(&ResetSettingsHandler::OnHideResetProfileDialog,
129 base::Unretained(this)));
130 web_ui()->RegisterMessageCallback(
131 "onHideResetProfileBanner",
132 base::BindRepeating(&ResetSettingsHandler::OnHideResetProfileBanner,
133 base::Unretained(this)));
134 web_ui()->RegisterMessageCallback(
135 "getTriggeredResetToolName",
136 base::BindRepeating(
137 &ResetSettingsHandler::HandleGetTriggeredResetToolName,
138 base::Unretained(this)));
139 #if defined(OS_CHROMEOS)
140 web_ui()->RegisterMessageCallback(
141 "onPowerwashDialogShow",
142 base::BindRepeating(&ResetSettingsHandler::OnShowPowerwashDialog,
143 base::Unretained(this)));
144 #endif // defined(OS_CHROMEOS)
145 }
146
HandleResetProfileSettings(const base::ListValue * args)147 void ResetSettingsHandler::HandleResetProfileSettings(
148 const base::ListValue* args) {
149 AllowJavascript();
150
151 CHECK_EQ(3U, args->GetSize());
152 std::string callback_id;
153 CHECK(args->GetString(0, &callback_id));
154 bool send_settings = false;
155 CHECK(args->GetBoolean(1, &send_settings));
156 std::string request_origin_string;
157 CHECK(args->GetString(2, &request_origin_string));
158 reset_report::ChromeResetReport::ResetRequestOrigin request_origin =
159 ResetRequestOriginFromString(request_origin_string);
160
161 DCHECK(brandcode_.empty() || config_fetcher_);
162 if (config_fetcher_ && config_fetcher_->IsActive()) {
163 // Reset once the prefs are fetched.
164 config_fetcher_->SetCallback(base::Bind(&ResetSettingsHandler::ResetProfile,
165 base::Unretained(this), callback_id,
166 send_settings, request_origin));
167 } else {
168 ResetProfile(callback_id, send_settings, request_origin);
169 }
170 }
171
OnResetProfileSettingsDone(std::string callback_id,bool send_feedback,reset_report::ChromeResetReport::ResetRequestOrigin request_origin)172 void ResetSettingsHandler::OnResetProfileSettingsDone(
173 std::string callback_id,
174 bool send_feedback,
175 reset_report::ChromeResetReport::ResetRequestOrigin request_origin) {
176 ResolveJavascriptCallback(base::Value(callback_id), base::Value());
177 if (send_feedback && setting_snapshot_) {
178 ResettableSettingsSnapshot current_snapshot(profile_);
179 int difference = setting_snapshot_->FindDifferentFields(current_snapshot);
180 if (difference) {
181 setting_snapshot_->Subtract(current_snapshot);
182 std::unique_ptr<reset_report::ChromeResetReport> report_proto =
183 SerializeSettingsReportToProto(*setting_snapshot_, difference);
184 if (report_proto) {
185 report_proto->set_reset_request_origin(request_origin);
186 SendSettingsFeedbackProto(*report_proto, profile_);
187 }
188 }
189 }
190 setting_snapshot_.reset();
191 }
192
HandleGetReportedSettings(const base::ListValue * args)193 void ResetSettingsHandler::HandleGetReportedSettings(
194 const base::ListValue* args) {
195 AllowJavascript();
196
197 CHECK_EQ(1U, args->GetSize());
198 std::string callback_id;
199 CHECK(args->GetString(0, &callback_id));
200
201 setting_snapshot_->RequestShortcuts(
202 base::Bind(&ResetSettingsHandler::OnGetReportedSettingsDone,
203 callback_weak_ptr_factory_.GetWeakPtr(), callback_id));
204 }
205
OnGetReportedSettingsDone(std::string callback_id)206 void ResetSettingsHandler::OnGetReportedSettingsDone(std::string callback_id) {
207 std::unique_ptr<base::ListValue> list =
208 GetReadableFeedbackForSnapshot(profile_, *setting_snapshot_);
209 ResolveJavascriptCallback(base::Value(callback_id), *list);
210 }
211
OnShowResetProfileDialog(const base::ListValue * args)212 void ResetSettingsHandler::OnShowResetProfileDialog(
213 const base::ListValue* args) {
214 if (!GetResetter()->IsActive()) {
215 setting_snapshot_ = std::make_unique<ResettableSettingsSnapshot>(profile_);
216 }
217
218 if (brandcode_.empty())
219 return;
220 config_fetcher_ = std::make_unique<BrandcodeConfigFetcher>(
221 g_browser_process->system_network_context_manager()
222 ->GetURLLoaderFactory(),
223 base::Bind(&ResetSettingsHandler::OnSettingsFetched,
224 base::Unretained(this)),
225 GURL("https://tools.google.com/service/update2"), brandcode_);
226 }
227
OnHideResetProfileDialog(const base::ListValue * args)228 void ResetSettingsHandler::OnHideResetProfileDialog(
229 const base::ListValue* args) {
230 if (!GetResetter()->IsActive())
231 setting_snapshot_.reset();
232 }
233
OnHideResetProfileBanner(const base::ListValue * args)234 void ResetSettingsHandler::OnHideResetProfileBanner(
235 const base::ListValue* args) {
236 chrome_prefs::ClearResetTime(profile_);
237 }
238
OnSettingsFetched()239 void ResetSettingsHandler::OnSettingsFetched() {
240 DCHECK(config_fetcher_);
241 DCHECK(!config_fetcher_->IsActive());
242 // The master prefs is fetched. We are waiting for user pressing 'Reset'.
243 }
244
ResetProfile(const std::string & callback_id,bool send_settings,reset_report::ChromeResetReport::ResetRequestOrigin request_origin)245 void ResetSettingsHandler::ResetProfile(
246 const std::string& callback_id,
247 bool send_settings,
248 reset_report::ChromeResetReport::ResetRequestOrigin request_origin) {
249 CHECK(!GetResetter()->IsActive());
250
251 std::unique_ptr<BrandcodedDefaultSettings> default_settings;
252 if (config_fetcher_) {
253 DCHECK(!config_fetcher_->IsActive());
254 default_settings = config_fetcher_->GetSettings();
255 config_fetcher_.reset();
256 } else {
257 DCHECK(brandcode_.empty());
258 }
259
260 // If failed to fetch BrandcodedDefaultSettings or this is an organic
261 // installation, use default settings.
262 if (!default_settings)
263 default_settings = std::make_unique<BrandcodedDefaultSettings>();
264
265 GetResetter()->Reset(
266 ProfileResetter::ALL, std::move(default_settings),
267 base::Bind(&ResetSettingsHandler::OnResetProfileSettingsDone,
268 callback_weak_ptr_factory_.GetWeakPtr(), callback_id,
269 send_settings, request_origin));
270 base::RecordAction(base::UserMetricsAction("ResetProfile"));
271 UMA_HISTOGRAM_ENUMERATION(
272 "ProfileReset.ResetRequestOrigin", request_origin,
273 reset_report::ChromeResetReport::ResetRequestOrigin_MAX + 1);
274 }
275
GetResetter()276 ProfileResetter* ResetSettingsHandler::GetResetter() {
277 if (!resetter_)
278 resetter_ = std::make_unique<ProfileResetter>(profile_);
279 return resetter_.get();
280 }
281
HandleGetTriggeredResetToolName(const base::ListValue * args)282 void ResetSettingsHandler::HandleGetTriggeredResetToolName(
283 const base::ListValue* args) {
284 AllowJavascript();
285
286 CHECK_EQ(1U, args->GetSize());
287 const base::Value* callback_id;
288 CHECK(args->Get(0, &callback_id));
289
290 // Set up the localized strings for the triggered profile reset dialog.
291 // Custom reset tool names are supported on Windows only.
292 base::string16 reset_tool_name;
293 #if defined(OS_WIN)
294 Profile* profile = Profile::FromWebUI(web_ui());
295 TriggeredProfileResetter* triggered_profile_resetter =
296 TriggeredProfileResetterFactory::GetForBrowserContext(profile);
297 // TriggeredProfileResetter instance will be nullptr for incognito profiles.
298 if (triggered_profile_resetter) {
299 reset_tool_name = triggered_profile_resetter->GetResetToolName();
300
301 // Now that a reset UI has been shown, don't trigger again for this profile.
302 triggered_profile_resetter->ClearResetTrigger();
303 }
304 #endif // defined(OS_WIN)
305
306 if (reset_tool_name.empty()) {
307 reset_tool_name = l10n_util::GetStringUTF16(
308 IDS_TRIGGERED_RESET_PROFILE_SETTINGS_DEFAULT_TOOL_NAME);
309 }
310
311 base::Value string_value(reset_tool_name);
312 ResolveJavascriptCallback(*callback_id, string_value);
313 }
314
315 #if defined(OS_CHROMEOS)
OnShowPowerwashDialog(const base::ListValue * args)316 void ResetSettingsHandler::OnShowPowerwashDialog(
317 const base::ListValue* args) {
318 UMA_HISTOGRAM_ENUMERATION(
319 "Reset.ChromeOS.PowerwashDialogShown",
320 chromeos::reset::DIALOG_FROM_OPTIONS,
321 chromeos::reset::DIALOG_VIEW_TYPE_SIZE);
322 }
323 #endif // defined(OS_CHROMEOS)
324
325 } // namespace settings
326