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.
5 #include "chrome/browser/safe_browsing/srt_global_error_win.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/command_line.h"
11 #include "base/files/file_util.h"
12 #include "base/process/launch.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "chrome/app/chrome_command_ids.h"
16 #include "chrome/browser/safe_browsing/srt_field_trial_win.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_finder.h"
19 #include "chrome/browser/ui/global_error/global_error_service.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "grit/chromium_strings.h"
22 #include "grit/generated_resources.h"
23 #include "ui/base/l10n/l10n_util.h"
25 using base::SingleThreadTaskRunner
;
26 using base::ThreadTaskRunnerHandle
;
27 using content::BrowserThread
;
31 // Used as a backup plan in case the SRT executable was not successfully
33 const char kSRTDownloadURL
[] =
34 "https://www.google.com/chrome/srt/?chrome-prompt=1";
36 // The extension to use to replace the temporary one created when the SRT was
38 const base::FilePath::CharType kExecutableExtension
[] = L
"exe";
40 // A switch to add to the command line when executing the SRT.
41 const char kChromePromptSwitch
[] = "chrome-prompt";
43 void MaybeExecuteSRTFromBlockingPool(
44 const base::FilePath
& downloaded_path
,
45 const scoped_refptr
<SingleThreadTaskRunner
>& task_runner
,
46 const base::Closure
& success_callback
,
47 const base::Closure
& failure_callback
) {
48 DCHECK(!downloaded_path
.empty());
50 if (base::PathExists(downloaded_path
)) {
51 base::FilePath
executable_path(
52 downloaded_path
.ReplaceExtension(kExecutableExtension
));
53 if (base::ReplaceFile(downloaded_path
, executable_path
, NULL
)) {
54 base::CommandLine
srt_command_line(executable_path
);
55 srt_command_line
.AppendSwitch(kChromePromptSwitch
);
56 base::Process
srt_process(
57 base::LaunchProcess(srt_command_line
, base::LaunchOptions()));
58 if (srt_process
.IsValid()) {
59 task_runner
->PostTask(FROM_HERE
, success_callback
);
65 task_runner
->PostTask(FROM_HERE
, failure_callback
);
68 void DeleteFilesFromBlockingPool(const base::FilePath
& downloaded_path
) {
69 base::DeleteFile(downloaded_path
, false);
70 base::DeleteFile(downloaded_path
.ReplaceExtension(kExecutableExtension
),
76 // SRTGlobalError ------------------------------------------------------------
78 SRTGlobalError::SRTGlobalError(GlobalErrorService
* global_error_service
,
79 const base::FilePath
& downloaded_path
)
80 : global_error_service_(global_error_service
),
81 downloaded_path_(downloaded_path
) {
82 DCHECK(global_error_service_
);
85 SRTGlobalError::~SRTGlobalError() {
88 bool SRTGlobalError::HasMenuItem() {
92 int SRTGlobalError::MenuItemCommandID() {
93 return IDC_SHOW_SRT_BUBBLE
;
96 base::string16
SRTGlobalError::MenuItemLabel() {
97 return l10n_util::GetStringUTF16(IDS_SRT_MENU_ITEM
);
100 void SRTGlobalError::ExecuteMenuItem(Browser
* browser
) {
101 ShowBubbleView(browser
);
104 void SRTGlobalError::ShowBubbleView(Browser
* browser
) {
105 safe_browsing::RecordSRTPromptHistogram(safe_browsing::SRT_PROMPT_SHOWN
);
106 GlobalErrorWithStandardBubble::ShowBubbleView(browser
);
109 base::string16
SRTGlobalError::GetBubbleViewTitle() {
110 return l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_TITLE
);
113 std::vector
<base::string16
> SRTGlobalError::GetBubbleViewMessages() {
114 std::vector
<base::string16
> messages
;
115 messages
.push_back(l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_TEXT
));
119 base::string16
SRTGlobalError::GetBubbleViewAcceptButtonLabel() {
120 return downloaded_path_
.empty()
121 ? l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_DOWNLOAD_BUTTON_TEXT
)
122 : l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_RUN_BUTTON_TEXT
);
125 bool SRTGlobalError::ShouldAddElevationIconToAcceptButton() {
126 return !downloaded_path_
.empty() &&
127 safe_browsing::SRTPromptNeedsElevationIcon();
130 base::string16
SRTGlobalError::GetBubbleViewCancelButtonLabel() {
131 return l10n_util::GetStringUTF16(IDS_SRT_BUBBLE_DISMISS
);
134 void SRTGlobalError::OnBubbleViewDidClose(Browser
* browser
) {
137 void SRTGlobalError::BubbleViewAcceptButtonPressed(Browser
* browser
) {
138 safe_browsing::RecordSRTPromptHistogram(safe_browsing::SRT_PROMPT_ACCEPTED
);
139 global_error_service_
->RemoveGlobalError(this);
143 void SRTGlobalError::BubbleViewCancelButtonPressed(Browser
* browser
) {
144 safe_browsing::RecordSRTPromptHistogram(safe_browsing::SRT_PROMPT_DENIED
);
145 global_error_service_
->RemoveGlobalError(this);
147 BrowserThread::PostBlockingPoolTask(
148 FROM_HERE
, base::Bind(&DeleteFilesFromBlockingPool
, downloaded_path_
));
152 bool SRTGlobalError::ShouldCloseOnDeactivate() const {
156 void SRTGlobalError::MaybeExecuteSRT() {
157 if (downloaded_path_
.empty()) {
158 FallbackToDownloadPage();
161 // At this point, this object owns itself, since ownership has been taken back
162 // from the global_error_service_ in the call to RemoveGlobalError. This means
163 // that it is safe to use base::Unretained here.
164 BrowserThread::PostBlockingPoolTask(
165 FROM_HERE
, base::Bind(&MaybeExecuteSRTFromBlockingPool
, downloaded_path_
,
166 base::ThreadTaskRunnerHandle::Get(),
167 base::Bind(&SRTGlobalError::DestroySelf
,
168 base::Unretained(this)),
169 base::Bind(&SRTGlobalError::FallbackToDownloadPage
,
170 base::Unretained(this))));
173 void SRTGlobalError::FallbackToDownloadPage() {
174 safe_browsing::RecordSRTPromptHistogram(safe_browsing::SRT_PROMPT_FALLBACK
);
176 chrome::HostDesktopType desktop_type
= chrome::GetActiveDesktop();
177 Browser
* browser
= chrome::FindLastActiveWithHostDesktopType(desktop_type
);
179 browser
->OpenURL(content::OpenURLParams(
180 GURL(kSRTDownloadURL
), content::Referrer(), NEW_FOREGROUND_TAB
,
181 ui::PAGE_TRANSITION_LINK
, false));
184 BrowserThread::PostBlockingPoolTask(
185 FROM_HERE
, base::Bind(&DeleteFilesFromBlockingPool
, downloaded_path_
));
189 void SRTGlobalError::DestroySelf() {