Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(588)

Side by Side Diff: chrome/browser/component_updater/sw_reporter_installer_win.cc

Issue 599653002: SRT Bubble (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR Comments. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/component_updater/sw_reporter_installer_win.h" 5 #include "chrome/browser/component_updater/sw_reporter_installer_win.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/base_paths.h" 10 #include "base/base_paths.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/files/file_path.h" 14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h" 15 #include "base/files/file_util.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
18 #include "base/metrics/sparse_histogram.h" 18 #include "base/metrics/sparse_histogram.h"
19 #include "base/path_service.h" 19 #include "base/path_service.h"
20 #include "base/prefs/pref_registry_simple.h" 20 #include "base/prefs/pref_registry_simple.h"
21 #include "base/prefs/pref_service.h" 21 #include "base/prefs/pref_service.h"
22 #include "base/process/kill.h" 22 #include "base/process/kill.h"
23 #include "base/process/launch.h" 23 #include "base/process/launch.h"
24 #include "base/task_runner_util.h" 24 #include "base/task_runner_util.h"
25 #include "base/threading/worker_pool.h" 25 #include "base/threading/worker_pool.h"
26 #include "base/time/time.h" 26 #include "base/time/time.h"
27 #include "base/win/registry.h" 27 #include "base/win/registry.h"
28 #include "chrome/browser/browser_process.h" 28 #include "chrome/browser/browser_process.h"
29 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" 29 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/safe_browsing/srt_global_error.h"
32 #include "chrome/browser/ui/browser_finder.h"
33 #include "chrome/browser/ui/global_error/global_error_service.h"
34 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
30 #include "chrome/common/pref_names.h" 35 #include "chrome/common/pref_names.h"
31 #include "components/component_updater/component_updater_paths.h" 36 #include "components/component_updater/component_updater_paths.h"
32 #include "components/component_updater/component_updater_service.h" 37 #include "components/component_updater/component_updater_service.h"
33 #include "components/component_updater/component_updater_utils.h" 38 #include "components/component_updater/component_updater_utils.h"
34 #include "components/component_updater/default_component_installer.h" 39 #include "components/component_updater/default_component_installer.h"
35 #include "components/component_updater/pref_names.h" 40 #include "components/component_updater/pref_names.h"
41 #include "components/pref_registry/pref_registry_syncable.h"
36 #include "content/public/browser/browser_thread.h" 42 #include "content/public/browser/browser_thread.h"
37 43
38 using content::BrowserThread; 44 using content::BrowserThread;
39 45
40 namespace component_updater { 46 namespace component_updater {
41 47
42 namespace { 48 namespace {
43 49
44 // These values are used to send UMA information and are replicated in the 50 // These values are used to send UMA information and are replicated in the
45 // histograms.xml file, so the order MUST NOT CHANGE. 51 // histograms.xml file, so the order MUST NOT CHANGE.
(...skipping 23 matching lines...) Expand all
69 0x5f, 0xea, 0xf0, 0x88, 0xf6, 0x97, 0x9b, 0xc7}; 75 0x5f, 0xea, 0xf0, 0x88, 0xf6, 0x97, 0x9b, 0xc7};
70 76
71 const base::FilePath::CharType kSwReporterExeName[] = 77 const base::FilePath::CharType kSwReporterExeName[] =
72 FILE_PATH_LITERAL("software_reporter_tool.exe"); 78 FILE_PATH_LITERAL("software_reporter_tool.exe");
73 79
74 // Where to fetch the reporter exit code in the registry. 80 // Where to fetch the reporter exit code in the registry.
75 const wchar_t kSoftwareRemovalToolRegistryKey[] = 81 const wchar_t kSoftwareRemovalToolRegistryKey[] =
76 L"Software\\Google\\Software Removal Tool"; 82 L"Software\\Google\\Software Removal Tool";
77 const wchar_t kExitCodeRegistryValueName[] = L"ExitCode"; 83 const wchar_t kExitCodeRegistryValueName[] = L"ExitCode";
78 84
85 // Exit codes that identify that a cleanup is needed.
86 const int kCleanupNeeded = 0;
87 const int kPostRebootCleanupNeeded = 4;
88
79 void ReportUmaStep(SwReporterUmaValue value) { 89 void ReportUmaStep(SwReporterUmaValue value) {
80 UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Step", value, SW_REPORTER_MAX); 90 UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Step", value, SW_REPORTER_MAX);
81 } 91 }
82 92
83 // This function is called on the UI thread to report the SwReporter exit code 93 // This function is called on the UI thread to report the SwReporter exit code
84 // and then clear it from the registry as well as clear the execution state 94 // and then clear it from the registry as well as clear the execution state
85 // from the local state. This could be called from an interruptible worker 95 // from the local state. This could be called from an interruptible worker
86 // thread so should be resilient to unexpected shutdown. 96 // thread so should be resilient to unexpected shutdown.
87 void ReportAndClearExitCode(int exit_code) { 97 void ReportAndClearExitCode(int exit_code, const std::string& version) {
gab 2014/09/24 16:22:36 Augment method comment with |version|.
MAD 2014/09/24 20:40:35 Done.
88 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.ExitCode", exit_code); 98 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.ExitCode", exit_code);
89 99
100 if (exit_code == kPostRebootCleanupNeeded || exit_code == kCleanupNeeded) {
101 Browser* browser =
102 chrome::FindLastActiveWithHostDesktopType(chrome::GetActiveDesktop());
gab 2014/09/24 16:22:36 I don't think this is what you want. This may be N
MAD 2014/09/24 20:40:35 The problem is that I don't have a profile here, s
103 if (browser) {
104 Profile* profile = browser->profile();
105 DCHECK(profile);
106 const std::string prompt_state =
107 profile->GetPrefs()->GetString(prefs::kSwReporterPromptState);
108 // Don't show the prompt again if it's been shown before.
109 if (prompt_state.empty()) {
110 profile->GetPrefs()->SetString(prefs::kSwReporterPromptState, version);
gab 2014/09/24 16:22:36 Only set this pref if we actually end up showing t
MAD 2014/09/24 20:40:35 No, because we still create the global error which
111 GlobalErrorService* global_error_service =
112 GlobalErrorServiceFactory::GetForProfile(profile);
113 SRTGlobalError* global_error = new SRTGlobalError(global_error_service);
114 global_error_service->AddGlobalError(global_error);
gab 2014/09/24 16:22:36 This gives ownership of |global_error|, make this
MAD 2014/09/24 20:40:35 If I release it here, I won't be able to use it be
115
116 // Do not try to show bubble if another GlobalError is already showing
117 // one.
118 const GlobalErrorService::GlobalErrorList& global_errors(
119 global_error_service->errors());
120 GlobalErrorService::GlobalErrorList::const_iterator it;
121 for (it = global_errors.begin(); it != global_errors.end(); ++it) {
122 if ((*it)->GetBubbleView())
robertshield 2014/09/24 13:02:12 Just to double check: GetBubbleView() should retur
MAD 2014/09/24 20:40:35 Yes.
123 break;
124 }
125 if (it == global_errors.end())
126 global_error->ShowBubbleView(browser);
gab 2014/09/24 16:22:36 This is not safe as you gave up ownership of |glob
MAD 2014/09/24 20:40:35 But then if we release it above, we still can't us
127 }
128 }
129 }
130
90 base::win::RegKey srt_key( 131 base::win::RegKey srt_key(
91 HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_WRITE); 132 HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_WRITE);
92 srt_key.DeleteValue(kExitCodeRegistryValueName); 133 srt_key.DeleteValue(kExitCodeRegistryValueName);
93 } 134 }
94 135
95 // This function is called from a worker thread to launch the SwReporter and 136 // This function is called from a worker thread to launch the SwReporter and
96 // wait for termination to collect its exit code. This task could be interrupted 137 // wait for termination to collect its exit code. This task could be interrupted
97 // by a shutdown at anytime, so it shouldn't depend on anything external that 138 // by a shutdown at anytime, so it shouldn't depend on anything external that
98 // could be shutdown beforehand. 139 // could be shutdown beforehand.
99 void LaunchAndWaitForExit(const base::FilePath& exe_path) { 140 void LaunchAndWaitForExit(const base::FilePath& exe_path,
141 const std::string& version) {
100 const base::CommandLine reporter_command_line(exe_path); 142 const base::CommandLine reporter_command_line(exe_path);
101 base::ProcessHandle scan_reporter_process = base::kNullProcessHandle; 143 base::ProcessHandle scan_reporter_process = base::kNullProcessHandle;
102 if (!base::LaunchProcess(reporter_command_line, 144 if (!base::LaunchProcess(reporter_command_line,
103 base::LaunchOptions(), 145 base::LaunchOptions(),
104 &scan_reporter_process)) { 146 &scan_reporter_process)) {
105 ReportUmaStep(SW_REPORTER_FAILED_TO_START); 147 ReportUmaStep(SW_REPORTER_FAILED_TO_START);
106 return; 148 return;
107 } 149 }
108 ReportUmaStep(SW_REPORTER_START_EXECUTION); 150 ReportUmaStep(SW_REPORTER_START_EXECUTION);
109 151
110 int exit_code = -1; 152 int exit_code = -1;
111 bool success = base::WaitForExitCode(scan_reporter_process, &exit_code); 153 bool success = base::WaitForExitCode(scan_reporter_process, &exit_code);
112 DCHECK(success); 154 DCHECK(success);
113 base::CloseProcessHandle(scan_reporter_process); 155 base::CloseProcessHandle(scan_reporter_process);
114 scan_reporter_process = base::kNullProcessHandle; 156 scan_reporter_process = base::kNullProcessHandle;
115 // It's OK if this doesn't complete, the work will continue on next startup. 157 // It's OK if this doesn't complete, the work will continue on next startup.
116 BrowserThread::PostTask(BrowserThread::UI, 158 BrowserThread::PostTask(
117 FROM_HERE, 159 BrowserThread::UI,
118 base::Bind(&ReportAndClearExitCode, exit_code));
119 }
120
121 void ExecuteReporter(const base::FilePath& install_dir) {
122 base::WorkerPool::PostTask(
123 FROM_HERE, 160 FROM_HERE,
124 base::Bind(&LaunchAndWaitForExit, install_dir.Append(kSwReporterExeName)), 161 base::Bind(&ReportAndClearExitCode, exit_code, version));
125 true);
126 } 162 }
127 163
128 class SwReporterInstallerTraits : public ComponentInstallerTraits { 164 class SwReporterInstallerTraits : public ComponentInstallerTraits {
129 public: 165 public:
130 explicit SwReporterInstallerTraits(PrefService* prefs) : prefs_(prefs) {} 166 explicit SwReporterInstallerTraits(PrefService* prefs) : prefs_(prefs) {}
131 167
132 virtual ~SwReporterInstallerTraits() {} 168 virtual ~SwReporterInstallerTraits() {}
133 169
134 virtual bool VerifyInstallation(const base::FilePath& dir) const { 170 virtual bool VerifyInstallation(const base::FilePath& dir) const {
135 return base::PathExists(dir.Append(kSwReporterExeName)); 171 return base::PathExists(dir.Append(kSwReporterExeName));
(...skipping 18 matching lines...) Expand all
154 190
155 // A previous run may have results in the registry, so check and report 191 // A previous run may have results in the registry, so check and report
156 // them if present. 192 // them if present.
157 base::win::RegKey srt_key( 193 base::win::RegKey srt_key(
158 HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_READ); 194 HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_READ);
159 DWORD exit_code; 195 DWORD exit_code;
160 if (srt_key.Valid() && 196 if (srt_key.Valid() &&
161 srt_key.ReadValueDW(kExitCodeRegistryValueName, &exit_code) == 197 srt_key.ReadValueDW(kExitCodeRegistryValueName, &exit_code) ==
162 ERROR_SUCCESS) { 198 ERROR_SUCCESS) {
163 ReportUmaStep(SW_REPORTER_REGISTRY_EXIT_CODE); 199 ReportUmaStep(SW_REPORTER_REGISTRY_EXIT_CODE);
164 ReportAndClearExitCode(exit_code); 200 ReportAndClearExitCode(exit_code, version.GetString());
165 } 201 }
166 202
167 // If we can't access local state, we can't see when we last ran, so 203 // If we can't access local state, we can't see when we last ran, so
168 // just exit without running. 204 // just exit without running.
169 if (!g_browser_process || !g_browser_process->local_state()) 205 if (!g_browser_process || !g_browser_process->local_state())
170 return; 206 return;
171 207
172 // Run the reporter if it hasn't been triggered in the 208 // Run the reporter if it hasn't been triggered in the
173 // kDaysBetweenSwReporterRuns days. 209 // kDaysBetweenSwReporterRuns days.
174 const base::Time last_time_triggered = base::Time::FromInternalValue( 210 const base::Time last_time_triggered = base::Time::FromInternalValue(
175 g_browser_process->local_state()->GetInt64( 211 g_browser_process->local_state()->GetInt64(
176 prefs::kSwReporterLastTimeTriggered)); 212 prefs::kSwReporterLastTimeTriggered));
177 if ((base::Time::Now() - last_time_triggered).InDays() >= 213 if ((base::Time::Now() - last_time_triggered).InDays() >=
178 kDaysBetweenSwReporterRuns) { 214 kDaysBetweenSwReporterRuns) {
179 g_browser_process->local_state()->SetInt64( 215 g_browser_process->local_state()->SetInt64(
180 prefs::kSwReporterLastTimeTriggered, 216 prefs::kSwReporterLastTimeTriggered,
181 base::Time::Now().ToInternalValue()); 217 base::Time::Now().ToInternalValue());
182 218
183 ExecuteReporter(install_dir); 219 base::WorkerPool::PostTask(
220 FROM_HERE,
221 base::Bind(&LaunchAndWaitForExit,
222 install_dir.Append(kSwReporterExeName),
223 version.GetString()),
224 true);
184 } 225 }
185 } 226 }
186 227
187 virtual base::FilePath GetBaseDirectory() const { return install_dir(); } 228 virtual base::FilePath GetBaseDirectory() const { return install_dir(); }
188 229
189 virtual void GetHash(std::vector<uint8>* hash) const { GetPkHash(hash); } 230 virtual void GetHash(std::vector<uint8>* hash) const { GetPkHash(hash); }
190 231
191 virtual std::string GetName() const { return "Software Reporter Tool"; } 232 virtual std::string GetName() const { return "Software Reporter Tool"; }
192 233
193 static base::FilePath install_dir() { 234 static base::FilePath install_dir() {
(...skipping 22 matching lines...) Expand all
216 PrefService* prefs_; 257 PrefService* prefs_;
217 static wchar_t version_dir_[_MAX_PATH]; 258 static wchar_t version_dir_[_MAX_PATH];
218 }; 259 };
219 260
220 wchar_t SwReporterInstallerTraits::version_dir_[] = {}; 261 wchar_t SwReporterInstallerTraits::version_dir_[] = {};
221 262
222 } // namespace 263 } // namespace
223 264
224 void RegisterSwReporterComponent(ComponentUpdateService* cus, 265 void RegisterSwReporterComponent(ComponentUpdateService* cus,
225 PrefService* prefs) { 266 PrefService* prefs) {
226 // The Sw reporter shouldn't run if the user isn't reporting metrics.
227 if (!ChromeMetricsServiceAccessor::IsMetricsReportingEnabled())
228 return;
229
230 // Install the component. 267 // Install the component.
231 scoped_ptr<ComponentInstallerTraits> traits( 268 scoped_ptr<ComponentInstallerTraits> traits(
232 new SwReporterInstallerTraits(prefs)); 269 new SwReporterInstallerTraits(prefs));
233 // |cus| will take ownership of |installer| during installer->Register(cus). 270 // |cus| will take ownership of |installer| during installer->Register(cus).
234 DefaultComponentInstaller* installer = 271 DefaultComponentInstaller* installer =
235 new DefaultComponentInstaller(traits.Pass()); 272 new DefaultComponentInstaller(traits.Pass());
236 installer->Register(cus); 273 installer->Register(cus);
237 } 274 }
238 275
239 void RegisterPrefsForSwReporter(PrefRegistrySimple* registry) { 276 void RegisterPrefsForSwReporter(PrefRegistrySimple* registry) {
240 registry->RegisterInt64Pref(prefs::kSwReporterLastTimeTriggered, 0); 277 registry->RegisterInt64Pref(prefs::kSwReporterLastTimeTriggered, 0);
241 } 278 }
242 279
280 void RegisterProfilePrefsForSwReporter(
281 user_prefs::PrefRegistrySyncable* registry) {
282 registry->RegisterStringPref(
283 prefs::kSwReporterPromptState,
284 "",
285 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
286 }
287
243 } // namespace component_updater 288 } // namespace component_updater
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698