OLD | NEW |
| (Empty) |
1 // Copyright 2014 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/safe_browsing/srt_global_error_win.h" | |
6 | |
7 #include "base/base_paths.h" | |
8 #include "base/bind.h" | |
9 #include "base/bind_helpers.h" | |
10 #include "base/callback.h" | |
11 #include "base/command_line.h" | |
12 #include "base/files/file_path.h" | |
13 #include "base/files/file_util.h" | |
14 #include "base/path_service.h" | |
15 #include "base/process/launch.h" | |
16 #include "base/strings/string_number_conversions.h" | |
17 #include "base/task_scheduler/post_task.h" | |
18 #include "chrome/app/chrome_command_ids.h" | |
19 #include "chrome/browser/browser_process.h" | |
20 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" | |
21 #include "chrome/browser/safe_browsing/srt_client_info_win.h" | |
22 #include "chrome/browser/safe_browsing/srt_field_trial_win.h" | |
23 #include "chrome/browser/ui/browser.h" | |
24 #include "chrome/browser/ui/browser_finder.h" | |
25 #include "chrome/browser/ui/global_error/global_error_service.h" | |
26 #include "chrome/common/channel_info.h" | |
27 #include "chrome/grit/chromium_strings.h" | |
28 #include "chrome/grit/generated_resources.h" | |
29 #include "chrome/installer/util/install_util.h" | |
30 #include "components/chrome_cleaner/public/constants/constants.h" | |
31 #include "components/component_updater/pref_names.h" | |
32 #include "components/prefs/pref_service.h" | |
33 #include "components/version_info/version_info.h" | |
34 #include "ui/base/l10n/l10n_util.h" | |
35 | |
36 namespace safe_browsing { | |
37 | |
38 namespace { | |
39 | |
40 // Used as a backup plan in case the SRT executable was not successfully | |
41 // downloaded or run. | |
42 const char kSRTDownloadURL[] = | |
43 "https://www.google.com/chrome/srt/?chrome-prompt=1"; | |
44 | |
45 // The extension to use to replace the temporary one created when the SRT was | |
46 // downloaded. | |
47 const base::FilePath::CharType kExecutableExtension[] = L"exe"; | |
48 | |
49 bool MaybeExecuteSRTFromBlockingPool( | |
50 const base::FilePath& downloaded_path, | |
51 bool metrics_enabled, | |
52 bool sber_enabled, | |
53 chrome_cleaner::ChromePromptValue prompt_value) { | |
54 DCHECK(!downloaded_path.empty()); | |
55 | |
56 if (base::PathExists(downloaded_path)) { | |
57 base::FilePath executable_path( | |
58 downloaded_path.ReplaceExtension(kExecutableExtension)); | |
59 if (base::ReplaceFile(downloaded_path, executable_path, nullptr)) { | |
60 base::CommandLine srt_command_line(executable_path); | |
61 srt_command_line.AppendSwitchASCII( | |
62 chrome_cleaner::kChromePromptSwitch, | |
63 base::IntToString(static_cast<int>(prompt_value))); | |
64 srt_command_line.AppendSwitchASCII(chrome_cleaner::kChromeVersionSwitch, | |
65 version_info::GetVersionNumber()); | |
66 srt_command_line.AppendSwitchASCII(chrome_cleaner::kChromeChannelSwitch, | |
67 base::IntToString(ChannelAsInt())); | |
68 | |
69 base::FilePath chrome_exe_path; | |
70 PathService::Get(base::FILE_EXE, &chrome_exe_path); | |
71 srt_command_line.AppendSwitchPath(chrome_cleaner::kChromeExePathSwitch, | |
72 chrome_exe_path); | |
73 if (!InstallUtil::IsPerUserInstall()) | |
74 srt_command_line.AppendSwitch( | |
75 chrome_cleaner::kChromeSystemInstallSwitch); | |
76 | |
77 if (metrics_enabled) { | |
78 srt_command_line.AppendSwitch(chrome_cleaner::kUmaUserSwitch); | |
79 srt_command_line.AppendSwitch( | |
80 chrome_cleaner::kEnableCrashReportingSwitch); | |
81 } | |
82 | |
83 if (sber_enabled) | |
84 srt_command_line.AppendSwitch( | |
85 chrome_cleaner::kExtendedSafeBrowsingEnabledSwitch); | |
86 | |
87 base::Process srt_process( | |
88 base::LaunchProcess(srt_command_line, base::LaunchOptions())); | |
89 return srt_process.IsValid(); | |
90 } | |
91 } | |
92 return false; | |
93 } | |
94 | |
95 void DeleteFilesFromBlockingPool(const base::FilePath& downloaded_path) { | |
96 base::DeleteFile(downloaded_path, false); | |
97 base::DeleteFile(downloaded_path.ReplaceExtension(kExecutableExtension), | |
98 false); | |
99 } | |
100 | |
101 } // namespace | |
102 | |
103 // SRTGlobalError ------------------------------------------------------------ | |
104 | |
105 SRTGlobalError::SRTGlobalError(GlobalErrorService* global_error_service, | |
106 const base::FilePath& downloaded_path) | |
107 : global_error_service_(global_error_service), | |
108 downloaded_path_(downloaded_path) { | |
109 DCHECK(global_error_service_); | |
110 } | |
111 | |
112 SRTGlobalError::~SRTGlobalError() { | |
113 if (!interacted_) { | |
114 base::PostTaskWithTraits( | |
115 FROM_HERE, base::TaskTraits().MayBlock().WithPriority( | |
116 base::TaskPriority::BACKGROUND), | |
117 base::Bind(&DeleteFilesFromBlockingPool, downloaded_path_)); | |
118 } | |
119 } | |
120 | |
121 bool SRTGlobalError::HasMenuItem() { | |
122 return true; | |
123 } | |
124 | |
125 int SRTGlobalError::MenuItemCommandID() { | |
126 return IDC_SHOW_SRT_BUBBLE; | |
127 } | |
128 | |
129 base::string16 SRTGlobalError::MenuItemLabel() { | |
130 return l10n_util::GetStringUTF16(IDS_SRT_MENU_ITEM); | |
131 } | |
132 | |
133 void SRTGlobalError::ExecuteMenuItem(Browser* browser) { | |
134 RecordSRTPromptHistogram(SRT_PROMPT_SHOWN_FROM_MENU); | |
135 bubble_shown_from_menu_ = true; | |
136 ShowBubbleView(browser); | |
137 } | |
138 | |
139 void SRTGlobalError::ShowBubbleView(Browser* browser) { | |
140 RecordSRTPromptHistogram(SRT_PROMPT_SHOWN); | |
141 GlobalErrorWithStandardBubble::ShowBubbleView(browser); | |
142 } | |
143 | |
144 bool SRTGlobalError::ShouldShowCloseButton() const { | |
145 return true; | |
146 } | |
147 | |
148 base::string16 SRTGlobalError::GetBubbleViewTitle() { | |
149 return l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_TITLE); | |
150 } | |
151 | |
152 std::vector<base::string16> SRTGlobalError::GetBubbleViewMessages() { | |
153 std::vector<base::string16> messages; | |
154 messages.push_back(l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_TEXT)); | |
155 return messages; | |
156 } | |
157 | |
158 base::string16 SRTGlobalError::GetBubbleViewAcceptButtonLabel() { | |
159 return downloaded_path_.empty() | |
160 ? l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_DOWNLOAD_BUTTON_TEXT) | |
161 : l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_RUN_BUTTON_TEXT); | |
162 } | |
163 | |
164 bool SRTGlobalError::ShouldAddElevationIconToAcceptButton() { | |
165 return !downloaded_path_.empty() && SRTPromptNeedsElevationIcon(); | |
166 } | |
167 | |
168 base::string16 SRTGlobalError::GetBubbleViewCancelButtonLabel() { | |
169 // Show the dismiss button only if the bubble was shown from the menu. | |
170 return bubble_shown_from_menu_ | |
171 ? l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_DISMISS) | |
172 : base::string16(); | |
173 } | |
174 | |
175 void SRTGlobalError::OnBubbleViewDidClose(Browser* browser) { | |
176 if (!interacted_) { | |
177 // If user didn't interact with the bubble, it means they used the generic | |
178 // close bubble button. | |
179 RecordSRTPromptHistogram(SRT_PROMPT_CLOSED); | |
180 g_browser_process->local_state()->SetBoolean( | |
181 prefs::kSwReporterPendingPrompt, true); | |
182 } | |
183 } | |
184 | |
185 void SRTGlobalError::BubbleViewAcceptButtonPressed(Browser* browser) { | |
186 OnUserinteractionStarted(SRT_PROMPT_ACCEPTED); | |
187 MaybeExecuteSRT(); | |
188 } | |
189 | |
190 void SRTGlobalError::BubbleViewCancelButtonPressed(Browser* browser) { | |
191 OnUserinteractionStarted(SRT_PROMPT_DENIED); | |
192 base::PostTaskWithTraits( | |
193 FROM_HERE, base::TaskTraits().MayBlock().WithPriority( | |
194 base::TaskPriority::BACKGROUND), | |
195 base::Bind(&DeleteFilesFromBlockingPool, downloaded_path_)); | |
196 OnUserinteractionDone(); | |
197 } | |
198 | |
199 bool SRTGlobalError::ShouldCloseOnDeactivate() const { | |
200 return false; | |
201 } | |
202 | |
203 void SRTGlobalError::MaybeExecuteSRT() { | |
204 if (downloaded_path_.empty()) { | |
205 FallbackToDownloadPage(); | |
206 return; | |
207 } | |
208 // At this point, this object owns itself, since ownership has been taken back | |
209 // from the global_error_service_ in the call to OnUserInteractionStarted. | |
210 // This means that it is safe to use base::Unretained here. | |
211 base::PostTaskWithTraitsAndReplyWithResult( | |
212 FROM_HERE, | |
213 base::TaskTraits().MayBlock().WithPriority( | |
214 base::TaskPriority::BACKGROUND), | |
215 base::Bind( | |
216 &MaybeExecuteSRTFromBlockingPool, downloaded_path_, | |
217 ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled(), | |
218 SafeBrowsingExtendedReportingEnabled(), | |
219 bubble_shown_from_menu_ | |
220 ? chrome_cleaner::ChromePromptValue::kShownFromMenu | |
221 : chrome_cleaner::ChromePromptValue::kPrompted), | |
222 base::Bind( | |
223 [](SRTGlobalError* self, bool success) { | |
224 if (success) | |
225 self->OnUserinteractionDone(); | |
226 else | |
227 self->FallbackToDownloadPage(); | |
228 }, | |
229 base::Unretained(this))); | |
230 } | |
231 | |
232 void SRTGlobalError::FallbackToDownloadPage() { | |
233 RecordSRTPromptHistogram(SRT_PROMPT_FALLBACK); | |
234 | |
235 Browser* browser = chrome::FindLastActive(); | |
236 if (browser) { | |
237 browser->OpenURL( | |
238 content::OpenURLParams(GURL(kSRTDownloadURL), content::Referrer(), | |
239 WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
240 ui::PAGE_TRANSITION_LINK, false)); | |
241 } | |
242 | |
243 base::PostTaskWithTraits( | |
244 FROM_HERE, base::TaskTraits().MayBlock().WithPriority( | |
245 base::TaskPriority::BACKGROUND), | |
246 base::Bind(&DeleteFilesFromBlockingPool, downloaded_path_)); | |
247 OnUserinteractionDone(); | |
248 } | |
249 | |
250 void SRTGlobalError::OnUserinteractionStarted( | |
251 SRTPromptHistogramValue histogram_value) { | |
252 // This is for cases where the UI doesn't go away quickly enough and user | |
253 // might click on the button more than once, or more than one button. | |
254 if (interacted_) | |
255 return; | |
256 RecordSRTPromptHistogram(histogram_value); | |
257 interacted_ = true; | |
258 if (global_error_service_) { | |
259 global_error_service_->RemoveGlobalError(this).release(); | |
260 global_error_service_ = nullptr; | |
261 } | |
262 } | |
263 | |
264 void SRTGlobalError::OnUserinteractionDone() { | |
265 DCHECK(interacted_); | |
266 // Once the user interacted with the bubble, we can forget about any pending | |
267 // prompt. | |
268 g_browser_process->local_state()->SetBoolean(prefs::kSwReporterPendingPrompt, | |
269 false); | |
270 delete this; | |
271 } | |
272 | |
273 } // namespace safe_browsing | |
OLD | NEW |