#include <windows.h>
#include <shellapi.h>
#include <memory>
#include <string_view>
#include "base/files/file_path.h"
#include "base/json/json_file_value_serializer.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/strcat_win.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.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/brand_behaviors.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h"
#include "chrome/installer/util/install_util.h"
#include "components/metrics/metrics_pref_names.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 {
constexpr std::wstring_view kUninstallSurveyUrl(
L"https://support.google.com/chrome?p=chrome_uninstall_survey");
bool NavigateToUrlWithHttps(const std::wstring& url) {
SHELLEXECUTEINFO info = {sizeof(info)};
info.fMask = SEE_MASK_NOASYNC;
info.lpVerb = L"open";
info.lpFile = url.c_str();
info.nShow = SW_SHOWNORMAL;
if (::ShellExecuteEx(&info))
return true;
PLOG(ERROR) << "Failed to launch default browser for uninstall survey";
return false;
}
void NavigateToUrlWithIExplore(const std::wstring& url) {
base::FilePath iexplore;
if (!base::PathService::Get(base::DIR_PROGRAM_FILES, &iexplore))
return;
iexplore = iexplore.AppendASCII("Internet Explorer");
iexplore = iexplore.AppendASCII("iexplore.exe");
std::wstring command = L"\"" + iexplore.value() + L"\" " + url;
int pid = 0;
base::win::WmiLaunchProcess(command, &pid);
}
bool IsMetricsEnabled(const base::FilePath& file_path) {
JSONFileValueDeserializer json_deserializer(file_path);
std::unique_ptr<base::Value> root =
json_deserializer.Deserialize(nullptr, nullptr);
if (!root || !root->is_dict())
return false;
const std::optional<bool> value = root->GetDict().FindBoolByDottedPath(
metrics::prefs::kMetricsReportingEnabled);
return value.value_or(false);
}
}
void UpdateInstallStatus() {
GoogleUpdateSettings::UpdateInstallStatus();
}
std::wstring GetDistributionData() {
std::wstring 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);
std::wstring 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"&");
}
std::wstring 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"&");
}
std::wstring ap_value;
client_state_key.ReadValue(google_update::kRegApField, &ap_value);
result.append(google_update::kRegApField);
result.append(L"=");
result.append(ap_value);
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.ToWString());
}
return result;
}
void DoPostUninstallOperations(const base::Version& version,
const base::FilePath& local_data_path,
const std::wstring& distribution_data) {
const base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
base::win::OSInfo::VersionNumber version_number = os_info->version_number();
std::wstring os_version =
base::StrCat({base::NumberToWString(version_number.major), L".",
base::NumberToWString(version_number.minor), L".",
base::NumberToWString(version_number.build)});
const std::wstring survey_url = std::wstring(kUninstallSurveyUrl);
#if DCHECK_IS_ON()
const size_t pos = survey_url.find(L'?');
DCHECK_NE(pos, std::wstring::npos);
DCHECK_EQ(survey_url.find(L'?', pos + 1), std::wstring::npos);
DCHECK_NE(survey_url.back(), L'&');
#endif
auto url = base::StrCat({survey_url, L"&crversion=",
base::ASCIIToWide(version.GetString()), L"&os=",
os_version});
if (!distribution_data.empty() && IsMetricsEnabled(local_data_path)) {
url += L"&";
url += distribution_data;
}
if (os_info->version() < base::win::Version::WIN10 ||
!NavigateToUrlWithHttps(url)) {
NavigateToUrlWithIExplore(url);
}
}
}