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

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

Issue 856393005: Re-prompt Chrome users to run the SRT when a finch param changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Final nit Created 5 years, 10 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
« no previous file with comments | « no previous file | chrome/browser/prefs/chrome_pref_service_factory.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <stdint.h> 7 #include <stdint.h>
8
9 #include <map>
8 #include <string> 10 #include <string>
9 #include <vector> 11 #include <vector>
10 12
11 #include "base/base_paths.h" 13 #include "base/base_paths.h"
12 #include "base/bind.h" 14 #include "base/bind.h"
13 #include "base/bind_helpers.h" 15 #include "base/bind_helpers.h"
14 #include "base/command_line.h" 16 #include "base/command_line.h"
15 #include "base/files/file_path.h" 17 #include "base/files/file_path.h"
16 #include "base/files/file_util.h" 18 #include "base/files/file_util.h"
17 #include "base/logging.h" 19 #include "base/logging.h"
(...skipping 17 matching lines...) Expand all
35 #include "chrome/browser/ui/global_error/global_error_service.h" 37 #include "chrome/browser/ui/global_error/global_error_service.h"
36 #include "chrome/browser/ui/global_error/global_error_service_factory.h" 38 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
37 #include "chrome/common/pref_names.h" 39 #include "chrome/common/pref_names.h"
38 #include "components/component_updater/component_updater_paths.h" 40 #include "components/component_updater/component_updater_paths.h"
39 #include "components/component_updater/component_updater_service.h" 41 #include "components/component_updater/component_updater_service.h"
40 #include "components/component_updater/default_component_installer.h" 42 #include "components/component_updater/default_component_installer.h"
41 #include "components/component_updater/pref_names.h" 43 #include "components/component_updater/pref_names.h"
42 #include "components/pref_registry/pref_registry_syncable.h" 44 #include "components/pref_registry/pref_registry_syncable.h"
43 #include "components/update_client/update_client.h" 45 #include "components/update_client/update_client.h"
44 #include "components/update_client/utils.h" 46 #include "components/update_client/utils.h"
47 #include "components/variations/variations_associated_data.h"
45 #include "content/public/browser/browser_thread.h" 48 #include "content/public/browser/browser_thread.h"
46 49
47 using content::BrowserThread; 50 using content::BrowserThread;
48 51
49 namespace component_updater { 52 namespace component_updater {
50 53
51 namespace { 54 namespace {
52 55
53 // These values are used to send UMA information and are replicated in the 56 // These values are used to send UMA information and are replicated in the
54 // histograms.xml file, so the order MUST NOT CHANGE. 57 // histograms.xml file, so the order MUST NOT CHANGE.
(...skipping 30 matching lines...) Expand all
85 L"Software\\Google\\Software Removal Tool"; 88 L"Software\\Google\\Software Removal Tool";
86 const wchar_t kCleanerSuffixRegistryKey[] = L"Cleaner"; 89 const wchar_t kCleanerSuffixRegistryKey[] = L"Cleaner";
87 const wchar_t kExitCodeRegistryValueName[] = L"ExitCode"; 90 const wchar_t kExitCodeRegistryValueName[] = L"ExitCode";
88 const wchar_t kVersionRegistryValueName[] = L"Version"; 91 const wchar_t kVersionRegistryValueName[] = L"Version";
89 const wchar_t kStartTimeRegistryValueName[] = L"StartTime"; 92 const wchar_t kStartTimeRegistryValueName[] = L"StartTime";
90 const wchar_t kEndTimeRegistryValueName[] = L"EndTime"; 93 const wchar_t kEndTimeRegistryValueName[] = L"EndTime";
91 94
92 // Field trial strings. 95 // Field trial strings.
93 const char kSRTPromptTrialName[] = "SRTPromptFieldTrial"; 96 const char kSRTPromptTrialName[] = "SRTPromptFieldTrial";
94 const char kSRTPromptOnGroup[] = "On"; 97 const char kSRTPromptOnGroup[] = "On";
98 const char kSRTPromptSeedParamName[] = "Seed";
95 99
96 // Exit codes that identify that a cleanup is needed. 100 // Exit codes that identify that a cleanup is needed.
97 const int kCleanupNeeded = 0; 101 const int kCleanupNeeded = 0;
98 const int kNothingFound = 2; 102 const int kNothingFound = 2;
99 const int kPostRebootCleanupNeeded = 4; 103 const int kPostRebootCleanupNeeded = 4;
100 const int kDelayedPostRebootCleanupNeeded = 15; 104 const int kDelayedPostRebootCleanupNeeded = 15;
101 105
102 void ReportUmaStep(SwReporterUmaValue value) { 106 void ReportUmaStep(SwReporterUmaValue value) {
103 UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Step", value, SW_REPORTER_MAX); 107 UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Step", value, SW_REPORTER_MAX);
104 } 108 }
(...skipping 25 matching lines...) Expand all
130 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MajorVersion", major_version); 134 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MajorVersion", major_version);
131 } 135 }
132 136
133 // This function is called on the UI thread to report the SwReporter exit code 137 // This function is called on the UI thread to report the SwReporter exit code
134 // and then clear it from the registry as well as clear the execution state 138 // and then clear it from the registry as well as clear the execution state
135 // from the local state. This could be called from an interruptible worker 139 // from the local state. This could be called from an interruptible worker
136 // thread so should be resilient to unexpected shutdown. |version| is provided 140 // thread so should be resilient to unexpected shutdown. |version| is provided
137 // so the kSwReporterPromptVersion prefs can be set. 141 // so the kSwReporterPromptVersion prefs can be set.
138 void ReportAndClearExitCode(int exit_code, const std::string& version) { 142 void ReportAndClearExitCode(int exit_code, const std::string& version) {
139 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.ExitCode", exit_code); 143 UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.ExitCode", exit_code);
144 base::win::RegKey srt_key(HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey,
145 KEY_WRITE);
146 srt_key.DeleteValue(kExitCodeRegistryValueName);
147
140 if (g_browser_process && g_browser_process->local_state()) { 148 if (g_browser_process && g_browser_process->local_state()) {
141 g_browser_process->local_state()->SetInteger(prefs::kSwReporterLastExitCode, 149 g_browser_process->local_state()->SetInteger(prefs::kSwReporterLastExitCode,
142 exit_code); 150 exit_code);
143 } 151 }
144 152
145 if ((exit_code == kPostRebootCleanupNeeded || exit_code == kCleanupNeeded) && 153 if ((exit_code != kPostRebootCleanupNeeded && exit_code != kCleanupNeeded) ||
146 base::FieldTrialList::FindFullName(kSRTPromptTrialName) == 154 base::FieldTrialList::FindFullName(kSRTPromptTrialName) !=
147 kSRTPromptOnGroup) { 155 kSRTPromptOnGroup) {
148 // Find the last active browser, which may be NULL, in which case we won't 156 return;
149 // show the prompt this time and will wait until the next run of the 157 }
150 // reporter. We can't use other ways of finding a browser because we don't 158 // Find the last active browser, which may be NULL, in which case we won't
151 // have a profile. 159 // show the prompt this time and will wait until the next run of the
152 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop(); 160 // reporter. We can't use other ways of finding a browser because we don't
153 Browser* browser = chrome::FindLastActiveWithHostDesktopType(desktop_type); 161 // have a profile.
154 if (browser) { 162 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
155 Profile* profile = browser->profile(); 163 Browser* browser = chrome::FindLastActiveWithHostDesktopType(desktop_type);
156 // Don't show the prompt again if it's been shown before for this profile. 164 if (!browser)
157 DCHECK(profile); 165 return;
158 const std::string prompt_version =
159 profile->GetPrefs()->GetString(prefs::kSwReporterPromptVersion);
160 if (prompt_version.empty()) {
161 profile->GetPrefs()->SetString(prefs::kSwReporterPromptVersion,
162 version);
163 profile->GetPrefs()->SetInteger(prefs::kSwReporterPromptReason,
164 exit_code);
165 // Now that we have a profile, make sure we have a tabbed browser since
166 // we need to anchor the bubble to the toolbar's wrench menu. Create one
167 // if none exist already.
168 if (browser->type() != Browser::TYPE_TABBED) {
169 browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
170 if (!browser)
171 browser = new Browser(Browser::CreateParams(profile, desktop_type));
172 }
173 GlobalErrorService* global_error_service =
174 GlobalErrorServiceFactory::GetForProfile(profile);
175 SRTGlobalError* global_error = new SRTGlobalError(global_error_service);
176 // |global_error_service| takes ownership of |global_error| and keeps it
177 // alive until RemoveGlobalError() is called, and even then, the object
178 // is not destroyed, the caller of RemoveGlobalError is responsible to
179 // destroy it, and in the case of the SRTGlobalError, it deletes itself
180 // but only after the bubble has been interacted with.
181 global_error_service->AddGlobalError(global_error);
182 166
183 // Do not try to show bubble if another GlobalError is already showing 167 Profile* profile = browser->profile();
184 // one. The bubble will be shown once the others have been dismissed. 168 DCHECK(profile);
185 const GlobalErrorService::GlobalErrorList& global_errors( 169
186 global_error_service->errors()); 170 PrefService* prefs = profile->GetPrefs();
187 GlobalErrorService::GlobalErrorList::const_iterator it; 171 DCHECK(prefs);
188 for (it = global_errors.begin(); it != global_errors.end(); ++it) { 172
189 if ((*it)->GetBubbleView()) 173 // Don't show the prompt again if it's been shown before for this profile
190 break; 174 // and for the current Finch seed.
191 } 175 std::map<std::string, std::string> params;
192 if (it == global_errors.end()) 176 variations::GetVariationParams(kSRTPromptTrialName, &params);
193 global_error->ShowBubbleView(browser); 177 const std::string previous_prompt_seed =
194 } 178 prefs->GetString(prefs::kSwReporterPromptSeed);
195 } 179 std::map<std::string, std::string>::const_iterator seed_iter(
180 params.find(std::string(kSRTPromptSeedParamName)));
181 bool valid_incoming_seed =
182 seed_iter != params.end() && !seed_iter->second.empty();
183 if (valid_incoming_seed && seed_iter->second == previous_prompt_seed)
184 return;
185
186 // If we don't have a new seed, and have shown the prompt before, don't show
187 // it again.
188 const std::string prompt_version =
189 prefs->GetString(prefs::kSwReporterPromptVersion);
190 if (!valid_incoming_seed && !prompt_version.empty())
191 return;
192
193 if (valid_incoming_seed)
194 prefs->SetString(prefs::kSwReporterPromptSeed, seed_iter->second);
195 prefs->SetString(prefs::kSwReporterPromptVersion, version);
196 prefs->SetInteger(prefs::kSwReporterPromptReason, exit_code);
197
198 // Make sure we have a tabbed browser since we need to anchor the bubble to
199 // the toolbar's wrench menu. Create one if none exist already.
200 if (browser->type() != Browser::TYPE_TABBED) {
201 browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
202 if (!browser)
203 browser = new Browser(Browser::CreateParams(profile, desktop_type));
196 } 204 }
205 GlobalErrorService* global_error_service =
206 GlobalErrorServiceFactory::GetForProfile(profile);
207 SRTGlobalError* global_error = new SRTGlobalError(global_error_service);
197 208
198 base::win::RegKey srt_key( 209 // |global_error_service| takes ownership of |global_error| and keeps it
199 HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_WRITE); 210 // alive until RemoveGlobalError() is called, and even then, the object
200 srt_key.DeleteValue(kExitCodeRegistryValueName); 211 // is not destroyed, the caller of RemoveGlobalError is responsible to
212 // destroy it, and in the case of the SRTGlobalError, it deletes itself
213 // but only after the bubble has been interacted with.
214 global_error_service->AddGlobalError(global_error);
215
216 // Do not try to show bubble if another GlobalError is already showing
217 // one. The bubble will be shown once the others have been dismissed.
218 const GlobalErrorService::GlobalErrorList& global_errors(
219 global_error_service->errors());
220 GlobalErrorService::GlobalErrorList::const_iterator it;
221 for (it = global_errors.begin(); it != global_errors.end(); ++it) {
222 if ((*it)->GetBubbleView())
223 break;
224 }
225 if (it == global_errors.end())
226 global_error->ShowBubbleView(browser);
201 } 227 }
202 228
203 // This function is called from a worker thread to launch the SwReporter and 229 // This function is called from a worker thread to launch the SwReporter and
204 // wait for termination to collect its exit code. This task could be interrupted 230 // wait for termination to collect its exit code. This task could be interrupted
205 // by a shutdown at anytime, so it shouldn't depend on anything external that 231 // by a shutdown at anytime, so it shouldn't depend on anything external that
206 // could be shutdown beforehand. 232 // could be shutdown beforehand.
207 void LaunchAndWaitForExit(const base::FilePath& exe_path, 233 void LaunchAndWaitForExit(const base::FilePath& exe_path,
208 const std::string& version) { 234 const std::string& version) {
209 const base::CommandLine reporter_command_line(exe_path); 235 const base::CommandLine reporter_command_line(exe_path);
210 base::Process scan_reporter_process = 236 base::Process scan_reporter_process =
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 } 428 }
403 429
404 void RegisterPrefsForSwReporter(PrefRegistrySimple* registry) { 430 void RegisterPrefsForSwReporter(PrefRegistrySimple* registry) {
405 registry->RegisterInt64Pref(prefs::kSwReporterLastTimeTriggered, 0); 431 registry->RegisterInt64Pref(prefs::kSwReporterLastTimeTriggered, 0);
406 registry->RegisterIntegerPref(prefs::kSwReporterLastExitCode, -1); 432 registry->RegisterIntegerPref(prefs::kSwReporterLastExitCode, -1);
407 } 433 }
408 434
409 void RegisterProfilePrefsForSwReporter( 435 void RegisterProfilePrefsForSwReporter(
410 user_prefs::PrefRegistrySyncable* registry) { 436 user_prefs::PrefRegistrySyncable* registry) {
411 registry->RegisterIntegerPref( 437 registry->RegisterIntegerPref(
412 prefs::kSwReporterPromptReason, 438 prefs::kSwReporterPromptReason, -1,
413 -1,
414 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 439 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
415 440
416 registry->RegisterStringPref( 441 registry->RegisterStringPref(
417 prefs::kSwReporterPromptVersion, 442 prefs::kSwReporterPromptVersion, "",
418 "", 443 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
444
445 registry->RegisterStringPref(
446 prefs::kSwReporterPromptSeed, "",
419 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 447 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
420 } 448 }
421 449
422 } // namespace component_updater 450 } // namespace component_updater
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/prefs/chrome_pref_service_factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698