Commit 00d80f6b authored by Greg Thompson's avatar Greg Thompson Committed by Commit Bot

Reland "Move DoPostUninstallOperations from BrowserDistribution into setup."

This is a reland of ea06ab2f.

Original CL:
> Showing the uninstall survey is a brand-specific behavior. This CL
> introduces a new setup/brand_behaviors.h file that declares various
> operations that vary by brand. DoPostUninstallOperations and
> GetDistributionData (its helper function) both reside in brand-specific
> implementation files that are selected at build time.
>
> This also allowed moving the uninstall metrics code from installer/util
> into installer/setup where it really belongs.
>
> I have also taken the liberty to gently modernize some of the moved
> code.
>
> BUG=879568
>
> Change-Id: I25d9c205d46ffb14454193fcc28ae5803502bf29
> Reviewed-on: https://chromium-review.googlesource.com/1200862
> Reviewed-by: Robert Sesek <rsesek@chromium.org>
> Reviewed-by: Brian White <bcwhite@chromium.org>
> Reviewed-by: Samuel Huang <huangs@chromium.org>
> Commit-Queue: Greg Thompson <grt@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#588537}
> (cherry picked from commit ea06ab2f)

BUG=879568
TBR=rsesek@chromium.org,bcwhite@chromium.org,huangs@chromium.org

Change-Id: I089f50e1a24d447936bb034bddc9cba5ee0afa7f
Reviewed-on: https://chromium-review.googlesource.com/1206431
Commit-Queue: Greg Thompson <grt@chromium.org>
Reviewed-by: default avatarGreg Thompson <grt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#588817}
parent 83fe1805
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# found in the LICENSE file. # found in the LICENSE file.
import("//build/buildflag_header.gni") import("//build/buildflag_header.gni")
import("//build/config/chrome_build.gni")
import("//chrome/installer/setup/buildflags.gni") import("//chrome/installer/setup/buildflags.gni")
import("//chrome/process_version_rc_template.gni") import("//chrome/process_version_rc_template.gni")
import("//testing/test.gni") import("//testing/test.gni")
...@@ -33,12 +34,17 @@ if (is_win) { ...@@ -33,12 +34,17 @@ if (is_win) {
":buildflags", ":buildflags",
":lib", ":lib",
":setup_exe_version", ":setup_exe_version",
"//base",
"//build/win:default_exe_manifest", "//build/win:default_exe_manifest",
"//chrome/common:constants",
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
"//chrome/installer/util:with_rc_strings",
"//chrome_elf:constants",
"//components/crash/content/app:app", "//components/crash/content/app:app",
"//components/crash/content/app:crash_export_thunks", "//components/crash/content/app:crash_export_thunks",
"//components/crash/content/app:run_as_crashpad_handler", "//components/crash/content/app:run_as_crashpad_handler",
"//content/public/common:static_switches", "//content/public/common:static_switches",
"//rlz:rlz_lib",
] ]
libs = [ "netapi32.lib" ] libs = [ "netapi32.lib" ]
...@@ -46,8 +52,10 @@ if (is_win) { ...@@ -46,8 +52,10 @@ if (is_win) {
static_library("lib") { static_library("lib") {
sources = [ sources = [
"${branding_path_component}_behaviors.cc",
"archive_patch_helper.cc", "archive_patch_helper.cc",
"archive_patch_helper.h", "archive_patch_helper.h",
"brand_behaviors.h",
"install.cc", "install.cc",
"install.h", "install.h",
"install_worker.cc", "install_worker.cc",
...@@ -70,6 +78,8 @@ if (is_win) { ...@@ -70,6 +78,8 @@ if (is_win) {
"setup_singleton.h", "setup_singleton.h",
"setup_util.cc", "setup_util.cc",
"setup_util.h", "setup_util.h",
"uninstall_metrics.cc",
"uninstall_metrics.h",
"update_active_setup_version_work_item.cc", "update_active_setup_version_work_item.cc",
"update_active_setup_version_work_item.h", "update_active_setup_version_work_item.h",
"user_experiment.cc", "user_experiment.cc",
...@@ -81,20 +91,23 @@ if (is_win) { ...@@ -81,20 +91,23 @@ if (is_win) {
public_deps = [ public_deps = [
":buildflags", ":buildflags",
"//base", "//base",
"//chrome/installer/util:with_rc_strings",
]
deps = [
"//chrome/common:constants", "//chrome/common:constants",
"//chrome/common:version_header", "//chrome/common:version_header",
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
"//chrome/installer/util:with_rc_strings",
"//chrome_elf:constants",
"//components/base32", "//components/base32",
"//components/crash/content/app", "//components/crash/content/app",
"//components/crash/core/common", "//components/crash/core/common",
"//components/metrics",
"//components/zucchini:zucchini_io", "//components/zucchini:zucchini_io",
"//components/zucchini:zucchini_lib", "//components/zucchini:zucchini_lib",
"//courgette:courgette_lib", "//courgette:courgette_lib",
"//rlz:rlz_lib",
"//third_party/bspatch", "//third_party/bspatch",
"//third_party/zlib", "//third_party/crashpad/crashpad/client",
"//third_party/crashpad/crashpad/util",
"//ui/base:fullscreen_win", "//ui/base:fullscreen_win",
] ]
} }
...@@ -118,6 +131,7 @@ if (is_win) { ...@@ -118,6 +131,7 @@ if (is_win) {
"setup_singleton_unittest.cc", "setup_singleton_unittest.cc",
"setup_util_unittest.cc", "setup_util_unittest.cc",
"setup_util_unittest.h", "setup_util_unittest.h",
"uninstall_metrics_unittest.cc",
"update_active_setup_version_work_item_unittest.cc", "update_active_setup_version_work_item_unittest.cc",
"user_experiment_unittest.cc", "user_experiment_unittest.cc",
"user_hive_visitor_unittest.cc", "user_hive_visitor_unittest.cc",
...@@ -129,6 +143,8 @@ if (is_win) { ...@@ -129,6 +143,8 @@ if (is_win) {
"//base:i18n", "//base:i18n",
"//base/allocator:buildflags", "//base/allocator:buildflags",
"//base/test:test_support", "//base/test:test_support",
"//chrome/common:constants",
"//chrome/common:version_header",
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
"//chrome/install_static/test:test_support", "//chrome/install_static/test:test_support",
"//chrome/installer/mini_installer:unit_tests", "//chrome/installer/mini_installer:unit_tests",
......
...@@ -2,8 +2,10 @@ include_rules = [ ...@@ -2,8 +2,10 @@ include_rules = [
"+chrome_elf/chrome_elf_constants.h", "+chrome_elf/chrome_elf_constants.h",
"+chrome/install_static", "+chrome/install_static",
"+components/base32", "+components/base32",
"+components/metrics",
"+components/zucchini", "+components/zucchini",
"+courgette", "+courgette",
"+third_party/crashpad",
] ]
specific_include_rules = { specific_include_rules = {
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Declares functions that implement brand-specific behavior. The definitions
// reside in brand-specific files that are only compiled when their respective
// branding is in use at build time.
#ifndef CHROME_INSTALLER_SETUP_BRAND_BEHAVIORS_H_
#define CHROME_INSTALLER_SETUP_BRAND_BEHAVIORS_H_
#include "base/strings/string16.h"
namespace base {
class FilePath;
class Version;
} // namespace base
namespace installer {
// Returns an opaque string holding data relating to the browser being
// uninstalled. This function is called before the product's Clients key is
// deleted. This blob is later passed to DoPostUninstallOperations.
base::string16 GetDistributionData();
// Performs brand-specific operations following unintsallation of the browser.
// |version| is the version of the browser being uninstalled. |local_data_path|
// |is a backup of the Local State file of the user performing the uninstall
// |operation. |distribution_data| is the string generated by
// |GetDistributionData().
void DoPostUninstallOperations(const base::Version& version,
const base::FilePath& local_data_path,
const base::string16& distribution_data);
} // namespace installer
#endif // CHROME_INSTALLER_SETUP_BRAND_BEHAVIORS_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/installer/setup/brand_behaviors.h"
namespace installer {
base::string16 GetDistributionData() {
return base::string16();
}
void DoPostUninstallOperations(const base::Version& version,
const base::FilePath& local_data_path,
const base::string16& distribution_data) {}
} // namespace installer
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/installer/setup/brand_behaviors.h"
#include <windows.h>
#include <shellapi.h>
#include <memory>
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/version.h"
#include "base/win/registry.h"
#include "base/win/windows_version.h"
#include "base/win/wmi.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/install_static/install_util.h"
#include "chrome/installer/setup/uninstall_metrics.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"
#include "third_party/crashpad/crashpad/client/settings.h"
#include "third_party/crashpad/crashpad/util/misc/uuid.h"
namespace installer {
namespace {
// Substitutes the locale parameter in |url| with whatever Google Update tells
// us is the locale. In case we fail to find the locale, we use US English.
base::string16 LocalizeUrl(const wchar_t* url) {
base::string16 language;
if (!GoogleUpdateSettings::GetLanguage(&language))
language = L"en-US"; // Default to US English.
return base::ReplaceStringPlaceholders(url, language, nullptr);
}
base::string16 GetUninstallSurveyUrl() {
static constexpr wchar_t kSurveyUrl[] =
L"https://support.google.com/chrome/contact/chromeuninstall3?hl=$1";
return LocalizeUrl(kSurveyUrl);
}
bool NavigateToUrlWithEdge(const base::string16& url) {
base::string16 protocol_url = L"microsoft-edge:" + url;
SHELLEXECUTEINFO info = {sizeof(info)};
info.fMask = SEE_MASK_NOASYNC;
info.lpVerb = L"open";
info.lpFile = protocol_url.c_str();
info.nShow = SW_SHOWNORMAL;
if (::ShellExecuteEx(&info))
return true;
PLOG(ERROR) << "Failed to launch Edge for uninstall survey";
return false;
}
void NavigateToUrlWithIExplore(const base::string16& url) {
base::FilePath iexplore;
if (!base::PathService::Get(base::DIR_PROGRAM_FILES, &iexplore))
return;
iexplore = iexplore.AppendASCII("Internet Explorer");
iexplore = iexplore.AppendASCII("iexplore.exe");
base::string16 command = L"\"" + iexplore.value() + L"\" " + url;
int pid = 0;
// The reason we use WMI to launch the process is because the uninstall
// process runs inside a Job object controlled by the shell. As long as there
// are processes running, the shell will not close the uninstall applet. WMI
// allows us to escape from the Job object so the applet will close.
base::win::WmiLaunchProcess(command, &pid);
}
} // namespace
// Returns a string holding the following URL query parameters:
// - brand
// - client
// - ap
// - crash_client_id
base::string16 GetDistributionData() {
base::string16 result;
base::win::RegKey client_state_key(
install_static::IsSystemInstall() ? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER,
install_static::GetClientStateKeyPath().c_str(),
KEY_QUERY_VALUE | KEY_WOW64_32KEY);
base::string16 brand_value;
if (client_state_key.ReadValue(google_update::kRegRLZBrandField,
&brand_value) == ERROR_SUCCESS) {
result.append(google_update::kRegRLZBrandField);
result.append(L"=");
result.append(brand_value);
result.append(L"&");
}
base::string16 client_value;
if (client_state_key.ReadValue(google_update::kRegClientField,
&client_value) == ERROR_SUCCESS) {
result.append(google_update::kRegClientField);
result.append(L"=");
result.append(client_value);
result.append(L"&");
}
base::string16 ap_value;
// If we fail to read the ap key, send up "&ap=" anyway to indicate
// that this was probably a stable channel release.
client_state_key.ReadValue(google_update::kRegApField, &ap_value);
result.append(google_update::kRegApField);
result.append(L"=");
result.append(ap_value);
// Crash client id.
// While it would be convenient to use the path service to get
// chrome::DIR_CRASH_DUMPS, that points to the dump location for the installer
// rather than for the browser. For per-user installs they are the same, yet
// for system-level installs the installer uses the system temp directory (see
// setup/installer_crash_reporting.cc's ConfigureCrashReporting).
// TODO(grt): use install_static::GetDefaultCrashDumpLocation (with an option
// to suppress creating the directory) once setup.exe uses
// install_static::InstallDetails.
base::FilePath crash_dir;
if (chrome::GetDefaultUserDataDirectory(&crash_dir)) {
crash_dir = crash_dir.Append(FILE_PATH_LITERAL("Crashpad"));
crashpad::UUID client_id;
std::unique_ptr<crashpad::CrashReportDatabase> database(
crashpad::CrashReportDatabase::InitializeWithoutCreating(crash_dir));
if (database && database->GetSettings()->GetClientID(&client_id))
result.append(L"&crash_client_id=").append(client_id.ToString16());
}
return result;
}
// Launches Edge or IE to show the uninstall survey. The following URL query
// params are included unconditionally in the survey URL:
// - crversion: the version of Chrome being uninstalled
// - os: Major.Minor.Build of the OS version
// If the user is sending crash reports and usage statistics to Google, the
// uninstall metrics read from |local_data_path| and the query params in
// |distribution_data| are included in the URL.
void DoPostUninstallOperations(const base::Version& version,
const base::FilePath& local_data_path,
const base::string16& distribution_data) {
// Send the Chrome version and OS version as params to the form. It would be
// nice to send the locale, too, but I don't see an easy way to get that in
// the existing code. It's something we can add later, if needed. We depend
// on installed_version.GetString() not having spaces or other characters that
// need escaping: 0.2.13.4. Should that change, we will need to escape the
// string before using it in a URL.
const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
base::win::OSInfo::VersionNumber version_number = os_info->version_number();
base::string16 os_version =
base::StringPrintf(L"%d.%d.%d", version_number.major,
version_number.minor, version_number.build);
const base::string16 survey_url = GetUninstallSurveyUrl();
#if DCHECK_IS_ON()
// The URL is expected to have a query part and not end with '&'.
const size_t pos = survey_url.find(L'?');
DCHECK_NE(pos, base::string16::npos);
DCHECK_EQ(survey_url.find(L'?', pos + 1), base::string16::npos);
DCHECK_NE(survey_url.back(), L'&');
#endif
auto url = base::StringPrintf(L"%ls&crversion=%ls&os=%ls", survey_url.c_str(),
base::ASCIIToUTF16(version.GetString()).c_str(),
os_version.c_str());
base::string16 uninstall_metrics;
if (ExtractUninstallMetricsFromFile(local_data_path, &uninstall_metrics)) {
DCHECK_EQ(uninstall_metrics.front(), L'&');
DCHECK_NE(uninstall_metrics.back(), L'&');
DCHECK_EQ(uninstall_metrics.find(L'?'), base::string16::npos);
// The user has opted into anonymous usage data collection, so append
// metrics and distribution data.
url += uninstall_metrics;
if (!distribution_data.empty()) {
url += L"&";
url += distribution_data;
}
}
if (os_info->version() < base::win::VERSION_WIN10 ||
!NavigateToUrlWithEdge(url)) {
NavigateToUrlWithIExplore(url);
}
}
} // namespace installer
...@@ -19,6 +19,9 @@ const wchar_t kInstallSourceChromeDir[] = L"Chrome-bin"; ...@@ -19,6 +19,9 @@ const wchar_t kInstallSourceChromeDir[] = L"Chrome-bin";
const wchar_t kMediaPlayerRegPath[] = const wchar_t kMediaPlayerRegPath[] =
L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList"; L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList";
// Local State preference names.
const char kUninstallMetricsName[] = "uninstall_metrics";
const char kCourgette[] = "courgette"; const char kCourgette[] = "courgette";
const char kBsdiff[] = "bsdiff"; const char kBsdiff[] = "bsdiff";
#if BUILDFLAG(ZUCCHINI) #if BUILDFLAG(ZUCCHINI)
......
...@@ -21,6 +21,8 @@ extern const wchar_t kInstallSourceChromeDir[]; ...@@ -21,6 +21,8 @@ extern const wchar_t kInstallSourceChromeDir[];
extern const wchar_t kMediaPlayerRegPath[]; extern const wchar_t kMediaPlayerRegPath[];
extern const char kUninstallMetricsName[];
// The range of error values among the installer, Courgette, BSDiff and // The range of error values among the installer, Courgette, BSDiff and
// Zucchini overlap. These offset values disambiguate between different sets // Zucchini overlap. These offset values disambiguate between different sets
// of errors by shifting the values up with the specified offset. // of errors by shifting the values up with the specified offset.
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_result_codes.h" #include "chrome/common/chrome_result_codes.h"
#include "chrome/install_static/install_util.h" #include "chrome/install_static/install_util.h"
#include "chrome/installer/setup/brand_behaviors.h"
#include "chrome/installer/setup/install.h" #include "chrome/installer/setup/install.h"
#include "chrome/installer/setup/install_worker.h" #include "chrome/installer/setup/install_worker.h"
#include "chrome/installer/setup/installer_state.h" #include "chrome/installer/setup/installer_state.h"
...@@ -883,7 +884,7 @@ InstallStatus UninstallProduct(const InstallationState& original_state, ...@@ -883,7 +884,7 @@ InstallStatus UninstallProduct(const InstallationState& original_state,
// Note that we must retrieve the distribution-specific data before deleting // Note that we must retrieve the distribution-specific data before deleting
// product.GetVersionKey(). // product.GetVersionKey().
base::string16 distribution_data(browser_dist->GetDistributionData(reg_root)); base::string16 distribution_data(GetDistributionData());
// Remove Control Panel uninstall link. // Remove Control Panel uninstall link.
// Assert that this is only called with the one relevant distribution. // Assert that this is only called with the one relevant distribution.
...@@ -1020,8 +1021,8 @@ InstallStatus UninstallProduct(const InstallationState& original_state, ...@@ -1020,8 +1021,8 @@ InstallStatus UninstallProduct(const InstallationState& original_state,
if (!force_uninstall && product_state) { if (!force_uninstall && product_state) {
VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; VLOG(1) << "Uninstallation complete. Launching post-uninstall operations.";
browser_dist->DoPostUninstallOperations(product_state->version(), DoPostUninstallOperations(product_state->version(), backup_state_file,
backup_state_file, distribution_data); distribution_data);
} }
// Try and delete the preserved local state once the post-install // Try and delete the preserved local state once the post-install
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/installer/util/uninstall_metrics.h" #include "chrome/installer/setup/uninstall_metrics.h"
#include <memory> #include <memory>
#include <string> #include <string>
...@@ -10,36 +10,36 @@ ...@@ -10,36 +10,36 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/json/json_file_value_serializer.h" #include "base/json/json_file_value_serializer.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "chrome/installer/util/util_constants.h" #include "chrome/installer/setup/setup_constants.h"
#include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_pref_names.h"
namespace installer { namespace installer {
namespace { namespace {
// Given a DictionaryValue containing a set of uninstall metrics, // Appends an URL query parameter to |metrics| for each item in
// this builds a URL parameter list of all the contained metrics. // |uninstall_metrics_dict|. Returns true if |metrics| was modified; otherwise,
// Returns true if at least one uninstall metric was found in // false.
// uninstall_metrics_dict, false otherwise. bool BuildUninstallMetricsString(const base::Value& uninstall_metrics_dict,
bool BuildUninstallMetricsString( base::string16* metrics) {
const base::DictionaryValue* uninstall_metrics_dict, DCHECK(uninstall_metrics_dict.is_dict());
base::string16* metrics) { DCHECK(metrics);
DCHECK(NULL != metrics);
bool has_values = false; bool has_values = false;
for (base::DictionaryValue::Iterator iter(*uninstall_metrics_dict); for (const auto& item : uninstall_metrics_dict.DictItems()) {
!iter.IsAtEnd();
iter.Advance()) {
has_values = true; has_values = true;
metrics->append(L"&"); metrics->push_back(L'&');
metrics->append(base::UTF8ToWide(iter.key())); metrics->append(base::UTF8ToWide(item.first));
metrics->append(L"="); metrics->push_back(L'=');
std::string value; if (item.second.is_string())
iter.value().GetAsString(&value); metrics->append(base::UTF8ToWide(item.second.GetString()));
metrics->append(base::UTF8ToWide(value)); else
NOTREACHED() << item.second.type();
} }
return has_values; return has_values;
...@@ -47,30 +47,24 @@ bool BuildUninstallMetricsString( ...@@ -47,30 +47,24 @@ bool BuildUninstallMetricsString(
} // namespace } // namespace
bool ExtractUninstallMetrics(const base::DictionaryValue& root, bool ExtractUninstallMetrics(const base::Value& root,
base::string16* uninstall_metrics_string) { base::string16* uninstall_metrics_string) {
// Make sure that the user wants us reporting metrics. If not, don't DCHECK(root.is_dict());
// add our uninstall metrics. // Make sure that the user wants us reporting metrics. If not, don't add our
bool metrics_reporting_enabled = false; // uninstall metrics.
if (!root.GetBoolean(metrics::prefs::kMetricsReportingEnabled, auto path =
&metrics_reporting_enabled) || base::SplitStringPiece(metrics::prefs::kMetricsReportingEnabled, ".",
!metrics_reporting_enabled) { base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
return false; const auto* value = root.FindPathOfType(path, base::Value::Type::BOOLEAN);
} if (!value || !value->GetBool())
const base::DictionaryValue* uninstall_metrics_dict = NULL;
if (!root.HasKey(installer::kUninstallMetricsName) ||
!root.GetDictionary(installer::kUninstallMetricsName,
&uninstall_metrics_dict)) {
return false; return false;
}
if (!BuildUninstallMetricsString(uninstall_metrics_dict, value = root.FindKeyOfType(installer::kUninstallMetricsName,
uninstall_metrics_string)) { base::Value::Type::DICTIONARY);
if (!value)
return false; return false;
}
return true; return BuildUninstallMetricsString(*value, uninstall_metrics_string);
} }
bool ExtractUninstallMetricsFromFile(const base::FilePath& file_path, bool ExtractUninstallMetricsFromFile(const base::FilePath& file_path,
...@@ -78,17 +72,16 @@ bool ExtractUninstallMetricsFromFile(const base::FilePath& file_path, ...@@ -78,17 +72,16 @@ bool ExtractUninstallMetricsFromFile(const base::FilePath& file_path,
JSONFileValueDeserializer json_deserializer(file_path); JSONFileValueDeserializer json_deserializer(file_path);
std::string json_error_string; std::string json_error_string;
std::unique_ptr<base::Value> root = json_deserializer.Deserialize(NULL, NULL); std::unique_ptr<base::Value> root =
if (!root.get()) json_deserializer.Deserialize(nullptr, nullptr);
if (!root)
return false; return false;
// Preferences should always have a dictionary root. // Preferences should always have a dictionary root.
if (!root->is_dict()) if (!root->is_dict())
return false; return false;
return ExtractUninstallMetrics( return ExtractUninstallMetrics(*root, uninstall_metrics_string);
*static_cast<base::DictionaryValue*>(root.get()),
uninstall_metrics_string);
} }
} // namespace installer } // namespace installer
...@@ -2,20 +2,20 @@ ...@@ -2,20 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_INSTALLER_UTIL_UNINSTALL_METRICS_H_ #ifndef CHROME_INSTALLER_SETUP_UNINSTALL_METRICS_H_
#define CHROME_INSTALLER_UTIL_UNINSTALL_METRICS_H_ #define CHROME_INSTALLER_SETUP_UNINSTALL_METRICS_H_
#include "base/strings/string16.h" #include "base/strings/string16.h"
namespace base { namespace base {
class DictionaryValue;
class FilePath; class FilePath;
} class Value;
} // namespace base
namespace installer { namespace installer {
// Extracts uninstall metrics from the given JSON value. // Extracts uninstall metrics from the given JSON value.
bool ExtractUninstallMetrics(const base::DictionaryValue& root, bool ExtractUninstallMetrics(const base::Value& root,
base::string16* uninstall_metrics); base::string16* uninstall_metrics);
// Extracts uninstall metrics from the JSON file located at file_path. // Extracts uninstall metrics from the JSON file located at file_path.
...@@ -28,4 +28,4 @@ bool ExtractUninstallMetricsFromFile(const base::FilePath& file_path, ...@@ -28,4 +28,4 @@ bool ExtractUninstallMetricsFromFile(const base::FilePath& file_path,
} // namespace installer } // namespace installer
#endif // CHROME_INSTALLER_UTIL_UNINSTALL_METRICS_H_ #endif // CHROME_INSTALLER_SETUP_UNINSTALL_METRICS_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/installer/util/uninstall_metrics.h" #include "chrome/installer/setup/uninstall_metrics.h"
#include <memory> #include <memory>
#include <string> #include <string>
...@@ -51,9 +51,7 @@ TEST(UninstallMetricsTest, TestExtractUninstallMetrics) { ...@@ -51,9 +51,7 @@ TEST(UninstallMetricsTest, TestExtractUninstallMetrics) {
ASSERT_TRUE(root.get()); ASSERT_TRUE(root.get());
base::string16 uninstall_metrics_string; base::string16 uninstall_metrics_string;
EXPECT_TRUE( EXPECT_TRUE(ExtractUninstallMetrics(*root, &uninstall_metrics_string));
ExtractUninstallMetrics(*static_cast<base::DictionaryValue*>(root.get()),
&uninstall_metrics_string));
EXPECT_EQ(expected_url_string, uninstall_metrics_string); EXPECT_EQ(expected_url_string, uninstall_metrics_string);
} }
......
...@@ -87,8 +87,6 @@ static_library("with_no_strings") { ...@@ -87,8 +87,6 @@ static_library("with_no_strings") {
"self_cleaning_temp_dir.h", "self_cleaning_temp_dir.h",
"shell_util.cc", "shell_util.cc",
"shell_util.h", "shell_util.h",
"uninstall_metrics.cc",
"uninstall_metrics.h",
] ]
deps += [ deps += [
...@@ -104,8 +102,6 @@ static_library("with_no_strings") { ...@@ -104,8 +102,6 @@ static_library("with_no_strings") {
"//courgette:courgette_lib", "//courgette:courgette_lib",
"//crypto", "//crypto",
"//rlz/buildflags", "//rlz/buildflags",
"//third_party/bspatch",
"//third_party/crashpad/crashpad/client",
"//third_party/icu", "//third_party/icu",
"//third_party/lzma_sdk", "//third_party/lzma_sdk",
] ]
...@@ -316,7 +312,6 @@ if (is_win) { ...@@ -316,7 +312,6 @@ if (is_win) {
"shell_util_unittest.cc", "shell_util_unittest.cc",
"test_app_registration_data.cc", "test_app_registration_data.cc",
"test_app_registration_data.h", "test_app_registration_data.h",
"uninstall_metrics_unittest.cc",
"work_item_list_unittest.cc", "work_item_list_unittest.cc",
"work_item_mocks.cc", "work_item_mocks.cc",
"work_item_mocks.h", "work_item_mocks.h",
...@@ -330,6 +325,7 @@ if (is_win) { ...@@ -330,6 +325,7 @@ if (is_win) {
"//base:i18n", "//base:i18n",
"//base/test:test_support", "//base/test:test_support",
"//chrome:other_version", "//chrome:other_version",
"//chrome/common:constants",
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
"//chrome/install_static/test:test_support", "//chrome/install_static/test:test_support",
"//chrome/installer/setup:lib", "//chrome/installer/setup:lib",
......
...@@ -7,5 +7,4 @@ include_rules = [ ...@@ -7,5 +7,4 @@ include_rules = [
"+components/base32", "+components/base32",
"+components/metrics", "+components/metrics",
"+third_party/crashpad",
] ]
...@@ -81,11 +81,6 @@ base::string16 BrowserDistribution::GetVersionKey() const { ...@@ -81,11 +81,6 @@ base::string16 BrowserDistribution::GetVersionKey() const {
return app_reg_data_->GetVersionKey(); return app_reg_data_->GetVersionKey();
} }
void BrowserDistribution::DoPostUninstallOperations(
const base::Version& version, const base::FilePath& local_data_path,
const base::string16& distribution_data) {
}
base::string16 BrowserDistribution::GetDisplayName() { base::string16 BrowserDistribution::GetDisplayName() {
return GetShortcutName(); return GetShortcutName();
} }
...@@ -117,10 +112,6 @@ base::string16 BrowserDistribution::GetLongAppDescription() { ...@@ -117,10 +112,6 @@ base::string16 BrowserDistribution::GetLongAppDescription() {
return app_description; return app_description;
} }
base::string16 BrowserDistribution::GetDistributionData(HKEY root_key) {
return L"";
}
void BrowserDistribution::UpdateInstallStatus(bool system_install, void BrowserDistribution::UpdateInstallStatus(bool system_install,
installer::ArchiveType archive_type, installer::ArchiveType archive_type,
installer::InstallStatus install_status) { installer::InstallStatus install_status) {
......
...@@ -8,24 +8,13 @@ ...@@ -8,24 +8,13 @@
#define CHROME_INSTALLER_UTIL_BROWSER_DISTRIBUTION_H_ #define CHROME_INSTALLER_UTIL_BROWSER_DISTRIBUTION_H_
#include <memory> #include <memory>
#include <string>
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "build/build_config.h"
#include "chrome/installer/util/util_constants.h" #include "chrome/installer/util/util_constants.h"
#if defined(OS_WIN)
#include <windows.h> // NOLINT
#endif
class AppRegistrationData; class AppRegistrationData;
namespace base {
class FilePath;
class Version;
}
class BrowserDistribution { class BrowserDistribution {
public: public:
enum Subfolder { enum Subfolder {
...@@ -43,11 +32,6 @@ class BrowserDistribution { ...@@ -43,11 +32,6 @@ class BrowserDistribution {
base::string16 GetStateMediumKey() const; base::string16 GetStateMediumKey() const;
base::string16 GetVersionKey() const; base::string16 GetVersionKey() const;
virtual void DoPostUninstallOperations(
const base::Version& version,
const base::FilePath& local_data_path,
const base::string16& distribution_data);
// Returns the localized display name of this distribution. // Returns the localized display name of this distribution.
virtual base::string16 GetDisplayName(); virtual base::string16 GetDisplayName();
...@@ -64,10 +48,6 @@ class BrowserDistribution { ...@@ -64,10 +48,6 @@ class BrowserDistribution {
virtual base::string16 GetLongAppDescription(); virtual base::string16 GetLongAppDescription();
#if defined(OS_WIN)
virtual base::string16 GetDistributionData(HKEY root_key);
#endif
virtual void UpdateInstallStatus(bool system_install, virtual void UpdateInstallStatus(bool system_install,
installer::ArchiveType archive_type, installer::ArchiveType archive_type,
installer::InstallStatus install_status); installer::InstallStatus install_status);
......
...@@ -7,194 +7,26 @@ ...@@ -7,194 +7,26 @@
#include "chrome/installer/util/google_chrome_distribution.h" #include "chrome/installer/util/google_chrome_distribution.h"
#include <windows.h>
#include <msi.h>
#include <shellapi.h>
#include <memory>
#include <utility> #include <utility>
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
#include "base/win/windows_version.h"
#include "base/win/wmi.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/install_static/install_util.h" #include "chrome/install_static/install_util.h"
#include "chrome/installer/util/app_registration_data.h" #include "chrome/installer/util/app_registration_data.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h" #include "chrome/installer/util/google_update_settings.h"
#include "chrome/installer/util/install_util.h" #include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/installer_util_strings.h" #include "chrome/installer/util/installer_util_strings.h"
#include "chrome/installer/util/l10n_string_util.h" #include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/uninstall_metrics.h"
#include "chrome/installer/util/updating_app_registration_data.h" #include "chrome/installer/util/updating_app_registration_data.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"
#include "third_party/crashpad/crashpad/client/settings.h"
namespace {
// Substitute the locale parameter in uninstall URL with whatever
// Google Update tells us is the locale. In case we fail to find
// the locale, we use US English.
base::string16 LocalizeUrl(const wchar_t* url) {
base::string16 language;
if (!GoogleUpdateSettings::GetLanguage(&language))
language = L"en-US"; // Default to US English.
return base::ReplaceStringPlaceholders(url, language, NULL);
}
base::string16 GetUninstallSurveyUrl() {
const wchar_t kSurveyUrl[] = L"https://support.google.com/chrome/"
L"contact/chromeuninstall3?hl=$1";
return LocalizeUrl(kSurveyUrl);
}
bool NavigateToUrlWithEdge(const base::string16& url) {
base::string16 protocol_url = L"microsoft-edge:" + url;
SHELLEXECUTEINFO info = { sizeof(info) };
info.fMask = SEE_MASK_NOASYNC;
info.lpVerb = L"open";
info.lpFile = protocol_url.c_str();
info.nShow = SW_SHOWNORMAL;
if (::ShellExecuteEx(&info))
return true;
PLOG(ERROR) << "Failed to launch Edge for uninstall survey";
return false;
}
void NavigateToUrlWithIExplore(const base::string16& url) {
base::FilePath iexplore;
if (!base::PathService::Get(base::DIR_PROGRAM_FILES, &iexplore))
return;
iexplore = iexplore.AppendASCII("Internet Explorer");
iexplore = iexplore.AppendASCII("iexplore.exe");
base::string16 command = L"\"" + iexplore.value() + L"\" " + url;
int pid = 0;
// The reason we use WMI to launch the process is because the uninstall
// process runs inside a Job object controlled by the shell. As long as there
// are processes running, the shell will not close the uninstall applet. WMI
// allows us to escape from the Job object so the applet will close.
base::win::WmiLaunchProcess(command, &pid);
}
} // namespace
GoogleChromeDistribution::GoogleChromeDistribution() GoogleChromeDistribution::GoogleChromeDistribution()
: BrowserDistribution(std::make_unique<UpdatingAppRegistrationData>( : BrowserDistribution(std::make_unique<UpdatingAppRegistrationData>(
install_static::GetAppGuid())) {} install_static::GetAppGuid())) {}
void GoogleChromeDistribution::DoPostUninstallOperations(
const base::Version& version,
const base::FilePath& local_data_path,
const base::string16& distribution_data) {
// Send the Chrome version and OS version as params to the form.
// It would be nice to send the locale, too, but I don't see an
// easy way to get that in the existing code. It's something we
// can add later, if needed.
// We depend on installed_version.GetString() not having spaces or other
// characters that need escaping: 0.2.13.4. Should that change, we will
// need to escape the string before using it in a URL.
const base::string16 kVersionParam = L"crversion";
const base::string16 kOSParam = L"os";
const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
base::win::OSInfo::VersionNumber version_number = os_info->version_number();
base::string16 os_version =
base::StringPrintf(L"%d.%d.%d", version_number.major,
version_number.minor, version_number.build);
base::string16 url = GetUninstallSurveyUrl() + L"&" + kVersionParam + L"=" +
base::ASCIIToUTF16(version.GetString()) + L"&" +
kOSParam + L"=" + os_version;
base::string16 uninstall_metrics;
if (installer::ExtractUninstallMetricsFromFile(local_data_path,
&uninstall_metrics)) {
// The user has opted into anonymous usage data collection, so append
// metrics and distribution data.
url += uninstall_metrics;
if (!distribution_data.empty()) {
url += L"&";
url += distribution_data;
}
}
if (os_info->version() >= base::win::VERSION_WIN10 &&
NavigateToUrlWithEdge(url)) {
return;
}
NavigateToUrlWithIExplore(url);
}
base::string16 GoogleChromeDistribution::GetPublisherName() { base::string16 GoogleChromeDistribution::GetPublisherName() {
const base::string16& publisher_name = const base::string16& publisher_name =
installer::GetLocalizedString(IDS_ABOUT_VERSION_COMPANY_NAME_BASE); installer::GetLocalizedString(IDS_ABOUT_VERSION_COMPANY_NAME_BASE);
return publisher_name; return publisher_name;
} }
base::string16 GoogleChromeDistribution::GetDistributionData(HKEY root_key) {
base::string16 sub_key(google_update::kRegPathClientState);
sub_key.append(L"\\");
sub_key.append(install_static::GetAppGuid());
base::win::RegKey client_state_key(
root_key, sub_key.c_str(), KEY_READ | KEY_WOW64_32KEY);
base::string16 result;
base::string16 brand_value;
if (client_state_key.ReadValue(google_update::kRegRLZBrandField,
&brand_value) == ERROR_SUCCESS) {
result = google_update::kRegRLZBrandField;
result.append(L"=");
result.append(brand_value);
result.append(L"&");
}
base::string16 client_value;
if (client_state_key.ReadValue(google_update::kRegClientField,
&client_value) == ERROR_SUCCESS) {
result.append(google_update::kRegClientField);
result.append(L"=");
result.append(client_value);
result.append(L"&");
}
base::string16 ap_value;
// If we fail to read the ap key, send up "&ap=" anyway to indicate
// that this was probably a stable channel release.
client_state_key.ReadValue(google_update::kRegApField, &ap_value);
result.append(google_update::kRegApField);
result.append(L"=");
result.append(ap_value);
// Crash client id.
// While it would be convenient to use the path service to get
// chrome::DIR_CRASH_DUMPS, that points to the dump location for the installer
// rather than for the browser. For per-user installs they are the same, yet
// for system-level installs the installer uses the system temp directory (see
// setup/installer_crash_reporting.cc's ConfigureCrashReporting).
// TODO(grt): use install_static::GetDefaultCrashDumpLocation (with an option
// to suppress creating the directory) once setup.exe uses
// install_static::InstallDetails.
base::FilePath crash_dir;
if (chrome::GetDefaultUserDataDirectory(&crash_dir)) {
crash_dir = crash_dir.Append(FILE_PATH_LITERAL("Crashpad"));
crashpad::UUID client_id;
std::unique_ptr<crashpad::CrashReportDatabase> database(
crashpad::CrashReportDatabase::InitializeWithoutCreating(crash_dir));
if (database && database->GetSettings()->GetClientID(&client_id))
result.append(L"&crash_client_id=").append(client_id.ToString16());
}
return result;
}
// This method checks if we need to change "ap" key in Google Update to try // This method checks if we need to change "ap" key in Google Update to try
// full installer as fall back method in case incremental installer fails. // full installer as fall back method in case incremental installer fails.
// - If incremental installer fails we append a magic string ("-full"), if // - If incremental installer fails we append a magic string ("-full"), if
......
...@@ -12,27 +12,8 @@ ...@@ -12,27 +12,8 @@
class GoogleChromeDistribution : public BrowserDistribution { class GoogleChromeDistribution : public BrowserDistribution {
public: public:
// Opens the Google Chrome uninstall survey window.
// version refers to the version of Chrome being uninstalled.
// local_data_path is the path of the file containing json metrics that
// will be parsed. If this file indicates that the user has opted in to
// providing anonymous usage data, then some additional statistics will
// be added to the survey url.
// distribution_data contains Google Update related data that will be
// concatenated to the survey url if the file in local_data_path indicates
// the user has opted in to providing anonymous usage data.
void DoPostUninstallOperations(
const base::Version& version,
const base::FilePath& local_data_path,
const base::string16& distribution_data) override;
base::string16 GetPublisherName() override; base::string16 GetPublisherName() override;
// This method reads data from the Google Update ClientState key for
// potential use in the uninstall survey. It must be called before the
// key returned by GetVersionKey() is deleted.
base::string16 GetDistributionData(HKEY root_key) override;
void UpdateInstallStatus( void UpdateInstallStatus(
bool system_install, bool system_install,
installer::ArchiveType archive_type, installer::ArchiveType archive_type,
......
...@@ -203,7 +203,6 @@ const wchar_t kSetupExe[] = L"setup.exe"; ...@@ -203,7 +203,6 @@ const wchar_t kSetupExe[] = L"setup.exe";
const wchar_t kUninstallStringField[] = L"UninstallString"; const wchar_t kUninstallStringField[] = L"UninstallString";
const wchar_t kUninstallArgumentsField[] = L"UninstallArguments"; const wchar_t kUninstallArgumentsField[] = L"UninstallArguments";
const wchar_t kUninstallDisplayNameField[] = L"DisplayName"; const wchar_t kUninstallDisplayNameField[] = L"DisplayName";
const char kUninstallMetricsName[] = "uninstall_metrics";
const wchar_t kUninstallInstallationDate[] = L"installation_date"; const wchar_t kUninstallInstallationDate[] = L"installation_date";
// Google Update installer result API. // Google Update installer result API.
......
...@@ -216,7 +216,6 @@ extern const wchar_t kSetupExe[]; ...@@ -216,7 +216,6 @@ extern const wchar_t kSetupExe[];
extern const wchar_t kUninstallArgumentsField[]; extern const wchar_t kUninstallArgumentsField[];
extern const wchar_t kUninstallDisplayNameField[]; extern const wchar_t kUninstallDisplayNameField[];
extern const wchar_t kUninstallInstallationDate[]; extern const wchar_t kUninstallInstallationDate[];
extern const char kUninstallMetricsName[];
extern const wchar_t kUninstallStringField[]; extern const wchar_t kUninstallStringField[];
// Google Update installer result API. // Google Update installer result API.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment