Commit c99ec168 authored by Yusuf Sengul's avatar Yusuf Sengul Committed by Commit Bot

Add uninstall registries for GCPW

Bug: 1129714
Change-Id: Ibd98640f75a306c327f11c5aca1d81acd334f4a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2417551
Commit-Queue: Yusuf Sengul <yusufsn@google.com>
Reviewed-by: default avatarRakesh Soma <rakeshsoma@google.com>
Cr-Commit-Position: refs/heads/master@{#812955}
parent 98efd1be
......@@ -57,6 +57,23 @@ const wchar_t kRegUsageStatsName[] = L"usagestats";
const wchar_t kRegUpdateTracksName[] = L"ap";
const wchar_t kRegVersionName[] = L"pv";
const wchar_t kRegUninstall[] =
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
const wchar_t kRegUninstallProduct[] = L"GCPW";
const wchar_t kRegUninstallString[] = L"UninstallString";
const wchar_t kRegUninstallDisplayName[] = L"DisplayName";
const wchar_t kRegInstallLocation[] = L"InstallLocation";
const wchar_t kRegDisplayIcon[] = L"DisplayIcon";
const wchar_t kRegNoModify[] = L"NoModify";
const wchar_t kRegNoRepair[] = L"NoRepair";
const wchar_t kRegPublisherName[] = L"Publisher";
const wchar_t kRegVersion[] = L"Version";
const wchar_t kRegDisplayVersion[] = L"DisplayVersion";
const wchar_t kRegInstallDate[] = L"InstallDate";
const wchar_t kRegVersionMajor[] = L"VersionMajor";
const wchar_t kRegVersionMinor[] = L"VersionMinor";
const wchar_t kRegPublisher[] = L"Google LLC";
// Chrome is being opened to show the credential provider logon page. This
// page is always shown in incognito mode.
const char kGcpwSigninSwitch[] = "gcpw-signin";
......
......@@ -81,6 +81,23 @@ extern const wchar_t kRegUsageStatsName[];
extern const wchar_t kRegUpdateTracksName[];
extern const wchar_t kRegVersionName[];
// Registry keys to list GCPW in add/remove programs on Windows.
extern const wchar_t kRegUninstall[];
extern const wchar_t kRegUninstallProduct[];
extern const wchar_t kRegUninstallString[];
extern const wchar_t kRegUninstallDisplayName[];
extern const wchar_t kRegInstallLocation[];
extern const wchar_t kRegDisplayIcon[];
extern const wchar_t kRegNoModify[];
extern const wchar_t kRegNoRepair[];
extern const wchar_t kRegPublisherName[];
extern const wchar_t kRegVersion[];
extern const wchar_t kRegDisplayVersion[];
extern const wchar_t kRegInstallDate[];
extern const wchar_t kRegVersionMajor[];
extern const wchar_t kRegVersionMinor[];
extern const wchar_t kRegPublisher[];
// These are command line switches passed to chrome to start it as a process
// used as a logon stub.
extern const char kGcpwSigninSwitch[];
......
......@@ -296,6 +296,41 @@ HRESULT SetGlobalFlagForTesting(const base::string16& name, DWORD value) {
return SetMachineRegDWORD(kGcpRootKeyName, name, value);
}
HRESULT SetUpdaterClientsAppPathFlag(const base::string16& name, DWORD value) {
base::win::RegKey key;
LONG sts = key.Create(HKEY_LOCAL_MACHINE, kRegUpdaterClientsAppPath,
KEY_WRITE | KEY_WOW64_32KEY);
if (sts != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(sts);
sts = key.WriteValue(name.c_str(), value);
if (sts != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(sts);
return S_OK;
}
HRESULT GetUpdaterClientsAppPathFlag(const base::string16& name, DWORD* value) {
base::win::RegKey key;
LONG sts = key.Open(HKEY_LOCAL_MACHINE, kRegUpdaterClientsAppPath,
KEY_READ | KEY_WOW64_32KEY);
if (sts != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(sts);
sts = key.ReadValueDW(name.c_str(), value);
if (sts != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(sts);
return S_OK;
}
DWORD GetUpdaterClientsAppPathFlagOrDefault(const base::string16& reg_key,
const DWORD& default_value) {
DWORD value;
HRESULT hr = GetUpdaterClientsAppPathFlag(reg_key, &value);
return SUCCEEDED(hr) ? value : default_value;
}
HRESULT GetUserProperty(const base::string16& sid,
const base::string16& name,
DWORD* value) {
......
......@@ -65,6 +65,17 @@ DWORD GetGlobalFlagOrDefault(const base::string16& reg_key,
// Sets global DWORD flag.
HRESULT SetGlobalFlag(const base::string16& name, DWORD value);
// Sets the client flag under |kRegUpdaterClientsAppPath|.
HRESULT SetUpdaterClientsAppPathFlag(const base::string16&, DWORD value);
// Gets client DWORD flag from |kRegUpdaterClientsAppPath|.
HRESULT GetUpdaterClientsAppPathFlag(const base::string16& name, DWORD* value);
// Gets client DWORD flag under |kRegUpdaterClientsAppPath|. Returns
// |default_value| if no value is set or there was an error fetching the flag.
DWORD GetUpdaterClientsAppPathFlagOrDefault(const base::string16& reg_key,
const DWORD& default_value);
// Sets global base::string16 flag.
HRESULT SetGlobalFlag(const base::string16& name, const base::string16& value);
......
......@@ -22,12 +22,16 @@ source_set("common") {
"gcpw_files.h",
"setup_lib.cc",
"setup_lib.h",
"setup_utils.cc",
"setup_utils.h",
]
public_deps = [ "//base" ]
deps = [
"../extension:common",
"../gaiacp:common",
"../gaiacp:util",
"//chrome/common:version_header",
"//chrome/credential_provider/gaiacp:string_resources",
"//chrome/installer/util:with_no_strings",
]
}
......
......@@ -16,7 +16,7 @@
#include "chrome/credential_provider/common/gcp_strings.h"
#include "chrome/credential_provider/gaiacp/gcp_crash_reporter_client.h"
#include "chrome/credential_provider/gaiacp/gcp_crash_reporting_utils.h"
#include "chrome/credential_provider/setup/setup_lib.h"
#include "chrome/credential_provider/setup/setup_utils.h"
#include "components/crash/core/app/crashpad.h"
#include "components/crash/core/common/crash_key.h"
#include "components/crash/core/common/crash_keys.h"
......
......@@ -39,6 +39,7 @@
#include "chrome/credential_provider/gaiacp/reg_utils.h"
#include "chrome/credential_provider/setup/gcp_installer_crash_reporting.h"
#include "chrome/credential_provider/setup/setup_lib.h"
#include "chrome/credential_provider/setup/setup_utils.h"
#include "components/crash/core/app/crash_switches.h"
#include "components/crash/core/app/run_as_crashpad_handler_win.h"
#include "content/public/common/content_switches.h"
......@@ -179,6 +180,9 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
std::string parent_handle_str = cmdline->GetSwitchValueASCII(
credential_provider::switches::kParentHandle);
credential_provider::StandaloneInstallerConfigurator::Get()
->ConfigureInstallationType(*cmdline);
if (is_uninstall) {
// If this is a user invoked uninstall, copy the exe to the temp directory
// and rerun it from there. Append a new arg so that setup knows it is not
......
......@@ -33,6 +33,7 @@
#include "chrome/credential_provider/gaiacp/logging.h"
#include "chrome/credential_provider/gaiacp/reg_utils.h"
#include "chrome/credential_provider/setup/gcpw_files.h"
#include "chrome/credential_provider/setup/setup_utils.h"
#include "chrome/installer/util/delete_after_reboot_helper.h"
namespace credential_provider {
......@@ -157,31 +158,6 @@ HRESULT UnregisterDlls(const base::FilePath& dest_path,
} // namespace
namespace switches {
// These are command line switches to the setup program.
// Indicates the handle of the parent setup process when setup relaunches itself
// during uninstall.
const char kParentHandle[] = "parent-handle";
// Indicates the full path to the GCP installation to delete. This switch is
// only used during uninstall.
const char kInstallPath[] = "install-path";
// Indicates to setup that it is being run to inunstall GCP. If this switch
// is not present the assumption is to install GCP.
const char kUninstall[] = "uninstall";
// Command line arguments used to either enable or disable stats and crash
// dump collection. When either of these command line args is used setup
// will perform the requested action and exit without trying to install or
// uninstall anything. Disable takes precedence over enable.
const char kEnableStats[] = "enable-stats";
const char kDisableStats[] = "disable-stats";
} // namespace switches
DWORD InstallGCPWExtension(const base::FilePath& extension_exe_path) {
credential_provider::extension::OSServiceManager* service_manager =
credential_provider::extension::OSServiceManager::Get();
......@@ -306,7 +282,7 @@ HRESULT DoInstall(const base::FilePath& installer_path,
// through.
}
hr = WriteCredentialProviderRegistryValues();
hr = WriteCredentialProviderRegistryValues(dest_path);
if (FAILED(hr)) {
LOGFN(ERROR) << "WriteCredentialProviderRegistryValues failed hr="
<< putHR(hr);
......@@ -355,6 +331,13 @@ HRESULT DoUninstall(const base::FilePath& installer_path,
if (base::IsDirectoryEmpty(dest_path.DirName()))
has_failures |= !base::DeleteFile(dest_path.DirName());
StandaloneInstallerConfigurator* installer_config =
StandaloneInstallerConfigurator::Get();
if (installer_config->IsStandaloneInstallation()) {
has_failures |= FAILED(HRESULT_FROM_WIN32(
StandaloneInstallerConfigurator::Get()->RemoveUninstallKey()));
}
// TODO(rogerta): ask user to reboot if anything went wrong during uninstall.
return has_failures ? E_UNEXPECTED : S_OK;
......@@ -464,17 +447,25 @@ HRESULT WriteUninstallRegistryValues(const base::FilePath& setup_exe) {
return HRESULT_FROM_WIN32(status);
}
HRESULT WriteCredentialProviderRegistryValues() {
HRESULT WriteCredentialProviderRegistryValues(
const base::FilePath& install_path) {
HRESULT hr =
StandaloneInstallerConfigurator::Get()->AddUninstallKey(install_path);
if (FAILED(hr)) {
LOGFN(ERROR) << "AddUninstallKey hr=" << putHR(hr);
return hr;
}
base::win::RegKey key;
LONG status = key.Create(HKEY_LOCAL_MACHINE, kGcpRootKeyName, KEY_SET_VALUE);
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to create " << kGcpRootKeyName
<< " hr=" << putHR(hr);
return hr;
}
return HRESULT_FROM_WIN32(status);
return S_OK;
}
} // namespace credential_provider
......@@ -20,16 +20,6 @@ struct FakesForTesting;
// Define command line swtiches for setup.
namespace switches {
extern const char kParentHandle[];
extern const char kInstallPath[];
extern const char kUninstall[];
extern const char kEnableStats[];
extern const char kDisableStats[];
} // namespace switches
// Installs GCPW Extension service. If there is an already GCPW extension, it is
// stopped and deleted initially.
DWORD InstallGCPWExtension(const base::FilePath& extension_exe_path);
......@@ -65,7 +55,8 @@ int EnableStatsCollection(const base::CommandLine& cmdline);
HRESULT WriteUninstallRegistryValues(const base::FilePath& setup_exe);
// Writes the registry entries Credential Provider uses at runtime.
HRESULT WriteCredentialProviderRegistryValues();
HRESULT WriteCredentialProviderRegistryValues(
const base::FilePath& install_path);
} // namespace credential_provider
......
// Copyright 2020 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/credential_provider/setup/setup_utils.h"
#include <Windows.h>
#include <string>
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
#include "chrome/common/chrome_version.h"
#include "chrome/credential_provider/common/gcp_strings.h"
#include "chrome/credential_provider/gaiacp/gaia_resources.h"
#include "chrome/credential_provider/gaiacp/gcp_utils.h"
#include "chrome/credential_provider/gaiacp/logging.h"
#include "chrome/credential_provider/gaiacp/reg_utils.h"
#include "chrome/credential_provider/setup/gcpw_files.h"
namespace credential_provider {
namespace switches {
const char kParentHandle[] = "parent-handle";
const char kInstallPath[] = "install-path";
const char kUninstall[] = "uninstall";
const char kEnableStats[] = "enable-stats";
const char kDisableStats[] = "disable-stats";
const char kStandaloneInstall[] = "standalone";
} // namespace switches
StandaloneInstallerConfigurator::StandaloneInstallerConfigurator()
: is_standalone_installation_(false) {}
StandaloneInstallerConfigurator::~StandaloneInstallerConfigurator() {}
// static
StandaloneInstallerConfigurator**
StandaloneInstallerConfigurator::GetInstanceStorage() {
static StandaloneInstallerConfigurator* instance =
new StandaloneInstallerConfigurator();
return &instance;
}
// static
StandaloneInstallerConfigurator* StandaloneInstallerConfigurator::Get() {
return *GetInstanceStorage();
}
// Sets the installer source for GCPW. When installed through standalone
// installer, |kStandaloneInstall| switch is present in the commandline
// arguments.
void StandaloneInstallerConfigurator::ConfigureInstallationType(
const base::CommandLine& cmdline) {
base::string16 standalone_install16 =
base::UTF8ToUTF16(switches::kStandaloneInstall);
if (cmdline.HasSwitch(switches::kStandaloneInstall)) {
is_standalone_installation_ = true;
HRESULT hr = SetUpdaterClientsAppPathFlag(standalone_install16, 1);
if (FAILED(hr))
LOGFN(ERROR) << "SetGlobalFlag failed" << putHR(hr);
} else if (GetUpdaterClientsAppPathFlag(standalone_install16, 0)) {
is_standalone_installation_ = true;
}
}
base::string16 StandaloneInstallerConfigurator::GetCurrentDate() {
static const wchar_t kDateFormat[] = L"yyyyMMdd";
wchar_t date_str[base::size(kDateFormat)] = {0};
int len = GetDateFormatW(LOCALE_INVARIANT, 0, nullptr, kDateFormat, date_str,
base::size(date_str));
if (len) {
--len; // Subtract terminating \0.
} else {
LOGFN(ERROR) << "GetDateFormat failed";
return L"";
}
return base::string16(date_str, len);
}
bool StandaloneInstallerConfigurator::IsStandaloneInstallation() const {
return is_standalone_installation_;
}
HRESULT StandaloneInstallerConfigurator::AddUninstallKey(
const base::FilePath& install_path) {
LOGFN(VERBOSE);
if (!is_standalone_installation_)
return S_OK;
std::wstring uninstall_reg = kRegUninstall;
uninstall_reg.append(L"\\");
uninstall_reg.append(kRegUninstallProduct);
base::win::RegKey key;
LONG status =
key.Create(HKEY_LOCAL_MACHINE, uninstall_reg.c_str(), KEY_SET_VALUE);
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to create " << uninstall_reg << " hr=" << putHR(hr);
return hr;
}
base::CommandLine uninstall_string(
install_path.Append(kCredentialProviderSetupExe));
uninstall_string.AppendSwitch(switches::kUninstall);
status = key.WriteValue(kRegUninstallString,
uninstall_string.GetCommandLineString().c_str());
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegUninstallString
<< " hr=" << putHR(hr);
return hr;
}
status = key.WriteValue(kRegUninstallDisplayName,
GetStringResource(IDS_PROJNAME_BASE).c_str());
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegUninstallDisplayName
<< " hr=" << putHR(hr);
return hr;
}
status = key.WriteValue(kRegInstallLocation, install_path.value().c_str());
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegInstallLocation
<< " hr=" << putHR(hr);
return hr;
}
status = key.WriteValue(
kRegDisplayIcon,
(install_path.Append(kCredentialProviderSetupExe).value() + L",0")
.c_str());
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegDisplayIcon
<< " hr=" << putHR(hr);
return hr;
}
status = key.WriteValue(kRegNoModify, 1);
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegNoModify << " hr=" << putHR(hr);
return hr;
}
status = key.WriteValue(kRegNoRepair, 1);
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegNoRepair << " hr=" << putHR(hr);
return hr;
}
status = key.WriteValue(kRegPublisherName, kRegPublisher);
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegPublisherName
<< " hr=" << putHR(hr);
return hr;
}
status = key.WriteValue(kRegInstallDate, GetCurrentDate().c_str());
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegInstallDate
<< " hr=" << putHR(hr);
return hr;
}
base::Version version(CHROME_VERSION_STRING);
status = key.WriteValue(kRegVersion,
base::ASCIIToUTF16(version.GetString()).c_str());
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegVersion << " hr=" << putHR(hr);
return hr;
}
status = key.WriteValue(kRegDisplayVersion,
base::ASCIIToUTF16(version.GetString()).c_str());
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegDisplayVersion
<< " hr=" << putHR(hr);
return hr;
}
const std::vector<uint32_t>& version_components = version.components();
if (version_components.size() == 4) {
status = key.WriteValue(kRegVersionMajor,
static_cast<DWORD>(version_components[2]));
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegVersionMajor
<< " hr=" << putHR(hr);
return hr;
}
status = key.WriteValue(kRegVersionMinor,
static_cast<DWORD>(version_components[3]));
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to write " << kRegVersionMinor
<< " hr=" << putHR(hr);
return hr;
}
}
return S_OK;
}
HRESULT StandaloneInstallerConfigurator::RemoveUninstallKey() {
LOGFN(VERBOSE);
base::win::RegKey key;
LONG status = key.Create(HKEY_LOCAL_MACHINE, kRegUninstall, KEY_SET_VALUE);
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to create " << kRegUninstall << " hr=" << putHR(hr);
return hr;
}
status = key.DeleteKey(kRegUninstallProduct);
if (status != ERROR_SUCCESS) {
HRESULT hr = HRESULT_FROM_WIN32(status);
LOGFN(ERROR) << "Unable to delete " << kRegUninstallProduct
<< " hr=" << putHR(hr);
return hr;
}
return S_OK;
}
} // namespace credential_provider
// Copyright 2020 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.
#ifndef CHROME_CREDENTIAL_PROVIDER_SETUP_SETUP_UTILS_H_
#define CHROME_CREDENTIAL_PROVIDER_SETUP_SETUP_UTILS_H_
#include <string>
#include "base/command_line.h"
#include "base/files/file.h"
#include "base/win/windows_types.h"
namespace credential_provider {
namespace switches {
// These are command line switches to the setup program.
// Indicates the handle of the parent setup process when setup relaunches itself
// during uninstall.
extern const char kParentHandle[];
// Indicates the full path to the GCP installation to delete. This switch is
// only used during uninstall.
extern const char kInstallPath[];
// Indicates to setup that it is being run to inunstall GCP. If this switch
// is not present the assumption is to install GCP.
extern const char kUninstall[];
// Command line arguments used to either enable or disable stats and crash
// dump collection. When either of these command line args is used setup
// will perform the requested action and exit without trying to install or
// uninstall anything. Disable takes precedence over enable.
extern const char kEnableStats[];
extern const char kDisableStats[];
extern const char kStandaloneInstall[];
} // namespace switches
class StandaloneInstallerConfigurator {
public:
// Used to retrieve singleton instance of the StandaloneInstallerConfigurator.
static StandaloneInstallerConfigurator* Get();
void ConfigureInstallationType(const base::CommandLine& cmdline);
HRESULT AddUninstallKey(const base::FilePath& install_path);
HRESULT RemoveUninstallKey();
bool IsStandaloneInstallation() const;
private:
StandaloneInstallerConfigurator();
virtual ~StandaloneInstallerConfigurator();
// Returns the storage used for the instance pointer.
static StandaloneInstallerConfigurator** GetInstanceStorage();
base::string16 GetCurrentDate();
bool is_standalone_installation_;
};
bool IsStandaloneInstallation(const base::CommandLine& command_line);
} // namespace credential_provider
#endif // CHROME_CREDENTIAL_PROVIDER_SETUP_SETUP_UTILS_H_
......@@ -44,6 +44,7 @@ test("gcp_unittests") {
"../setup:common",
"//base",
"//chrome/common:non_code_constants",
"//chrome/common:version_header",
"//chrome/test:credential_provider_test_utils",
"//content/public/browser",
"//google_apis",
......
......@@ -5,6 +5,7 @@
#include <atlbase.h>
#include <atlcom.h>
#include <atlcomcli.h>
#include <datetimeapi.h>
#include <lmerr.h>
#include <unknwn.h>
#include <wrl/client.h>
......@@ -23,6 +24,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/syslog_logging.h"
#include "base/test/scoped_path_override.h"
#include "base/test/test_reg_util_win.h"
......@@ -30,6 +32,7 @@
#include "base/win/scoped_com_initializer.h"
#include "base/win/win_util.h"
#include "build/build_config.h"
#include "chrome/common/chrome_version.h"
#include "chrome/credential_provider/common/gcp_strings.h"
#include "chrome/credential_provider/extension/extension_strings.h"
#include "chrome/credential_provider/gaiacp/gaia_credential_provider.h"
......@@ -38,6 +41,7 @@
#include "chrome/credential_provider/gaiacp/reg_utils.h"
#include "chrome/credential_provider/setup/gcpw_files.h"
#include "chrome/credential_provider/setup/setup_lib.h"
#include "chrome/credential_provider/setup/setup_utils.h"
#include "chrome/credential_provider/test/gcp_fakes.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -88,9 +92,96 @@ class GcpSetupTest : public ::testing::Test {
FakesForTesting* fakes_for_testing() { return &fakes_; }
std::wstring uninstall_reg_key() {
std::wstring uninstall_reg = kRegUninstall;
uninstall_reg.append(L"\\");
uninstall_reg.append(kRegUninstallProduct);
return uninstall_reg;
}
void assert_addremove_reg_exists() {
base::win::RegKey uninstall_key;
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.Open(HKEY_LOCAL_MACHINE,
uninstall_reg_key().c_str(), KEY_ALL_ACCESS));
base::string16 uninstall_args;
base::string16 display_name;
base::string16 install_location;
base::string16 display_icon;
base::string16 install_date;
DWORD no_modify;
DWORD no_repair;
base::string16 publisher_name;
base::string16 version_str;
base::string16 display_version;
DWORD version_major;
DWORD version_minor;
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValue(kRegUninstallString, &uninstall_args));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValue(kRegUninstallDisplayName, &display_name));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValue(kRegInstallLocation, &install_location));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValue(kRegDisplayIcon, &display_icon));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValue(kRegInstallDate, &install_date));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValueDW(kRegNoModify, &no_modify));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValueDW(kRegNoRepair, &no_repair));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValue(kRegPublisherName, &publisher_name));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValue(kRegVersion, &version_str));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValue(kRegDisplayVersion, &display_version));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValueDW(kRegVersionMajor, &version_major));
ASSERT_EQ(ERROR_SUCCESS,
uninstall_key.ReadValueDW(kRegVersionMinor, &version_minor));
base::CommandLine uninstall_cmdline(
installed_path().Append(kCredentialProviderSetupExe));
uninstall_cmdline.AppendSwitch(switches::kUninstall);
ASSERT_EQ(uninstall_args, uninstall_cmdline.GetCommandLineString().c_str());
ASSERT_EQ(display_name, GetStringResource(IDS_PROJNAME_BASE));
ASSERT_EQ(install_location, installed_path().value());
ASSERT_EQ(publisher_name, kRegPublisher);
base::FilePath setup_exe =
installed_path().Append(kCredentialProviderSetupExe);
ASSERT_EQ(display_icon, (setup_exe.value() + L",0").c_str());
ASSERT_EQ(install_date, GetCurrentDateForTesting());
ASSERT_EQ(no_modify, (DWORD)1);
ASSERT_EQ(no_repair, (DWORD)1);
base::Version version(CHROME_VERSION_STRING);
ASSERT_EQ(version_str, base::ASCIIToUTF16(version.GetString()));
ASSERT_EQ(display_version, base::ASCIIToUTF16(version.GetString()));
const std::vector<uint32_t>& version_components = version.components();
ASSERT_EQ(version_major, static_cast<DWORD>(version_components[2]));
ASSERT_EQ(version_minor, static_cast<DWORD>(version_components[3]));
}
private:
void SetUp() override;
base::string16 GetCurrentDateForTesting() {
static const wchar_t kDateFormat[] = L"yyyyMMdd";
wchar_t date_str[base::size(kDateFormat)] = {0};
int len = GetDateFormatW(LOCALE_INVARIANT, 0, nullptr, kDateFormat,
date_str, base::size(date_str));
if (len) {
--len; // Subtract terminating \0.
} else {
return L"";
}
return base::string16(date_str, len);
}
void GetModulePathAndProductVersion(base::FilePath* module_path,
base::string16* product_version);
......@@ -439,11 +530,27 @@ TEST_F(GcpSetupTest, LaunchGcpAfterInstall) {
ExpectAllFilesToExist(false, old_version);
}
TEST_F(GcpSetupTest, DoUninstall) {
class GcpInstallerTest : public GcpSetupTest,
public ::testing::WithParamInterface<int> {};
TEST_P(GcpInstallerTest, DoUninstall) {
int standalone_installer = GetParam();
logging::ResetEventSourceForTesting();
if (standalone_installer) {
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitch(switches::kStandaloneInstall);
StandaloneInstallerConfigurator::Get()->ConfigureInstallationType(
command_line);
}
ASSERT_EQ(S_OK,
DoInstall(module_path(), product_version(), fakes_for_testing()));
if (standalone_installer)
assert_addremove_reg_exists();
CreateSentinelFileToSimulateCrash(product_version());
logging::ResetEventSourceForTesting();
......@@ -460,8 +567,15 @@ TEST_F(GcpSetupTest, DoUninstall) {
EXPECT_TRUE(fake_scoped_lsa_policy_factory()
->private_data()[kLsaKeyGaiaUsername]
.empty());
base::win::RegKey uninstall_key;
EXPECT_NE(ERROR_SUCCESS,
uninstall_key.Open(HKEY_LOCAL_MACHINE, uninstall_reg_key().c_str(),
KEY_ALL_ACCESS));
}
INSTANTIATE_TEST_SUITE_P(All, GcpInstallerTest, ::testing::Values(0, 1));
TEST_F(GcpSetupTest, DoUninstallWithExtension) {
logging::ResetEventSourceForTesting();
......@@ -491,6 +605,8 @@ TEST_F(GcpSetupTest, DoUninstallWithExtension) {
}
TEST_F(GcpSetupTest, ValidLsaWithNoExistingUser) {
logging::ResetEventSourceForTesting();
// Create the default user so that name is not taken when the user is created.
CComBSTR sid;
DWORD error;
......@@ -503,7 +619,6 @@ TEST_F(GcpSetupTest, ValidLsaWithNoExistingUser) {
L"gaia1";
fake_scoped_lsa_policy_factory()->private_data()[kLsaKeyGaiaPassword] =
L"password";
logging::ResetEventSourceForTesting();
ASSERT_EQ(S_OK,
DoInstall(module_path(), product_version(), fakes_for_testing()));
......@@ -581,7 +696,7 @@ TEST_F(GcpSetupTest, EnableDisableStats) {
EXPECT_EQ(0u, value);
}
TEST_F(GcpSetupTest, WriteUninstallStrings) {
TEST_F(GcpSetupTest, WriteUninstallStringsForMSI) {
base::win::RegKey key;
ASSERT_EQ(ERROR_SUCCESS,
......@@ -616,12 +731,25 @@ TEST_F(GcpSetupTest, WriteCredentialProviderRegistryValues) {
ASSERT_NE(ERROR_SUCCESS,
key.Open(HKEY_LOCAL_MACHINE, kGcpRootKeyName, KEY_ALL_ACCESS));
base::win::RegKey uninstall_key;
ASSERT_NE(ERROR_SUCCESS,
uninstall_key.Open(HKEY_LOCAL_MACHINE, uninstall_reg_key().c_str(),
KEY_ALL_ACCESS));
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitch(switches::kStandaloneInstall);
StandaloneInstallerConfigurator::Get()->ConfigureInstallationType(
command_line);
// Write GCPW registry keys.
ASSERT_EQ(S_OK, WriteCredentialProviderRegistryValues());
ASSERT_EQ(S_OK, WriteCredentialProviderRegistryValues(installed_path()));
// Verify keys were created.
ASSERT_EQ(ERROR_SUCCESS,
key.Open(HKEY_LOCAL_MACHINE, kGcpRootKeyName, KEY_ALL_ACCESS));
assert_addremove_reg_exists();
}
TEST_F(GcpSetupTest, DoInstallWritesUninstallStrings) {
......
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