blob: 667be1084bfbc8838f8804c32fb7f54e4b84b274 [file] [log] [blame]
// Copyright 2017 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_BROWSER_CONFLICTS_INSTALLED_PROGRAMS_WIN_H_
#define CHROME_BROWSER_CONFLICTS_INSTALLED_PROGRAMS_WIN_H_
#include <memory>
#include <utility>
#include <vector>
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/strings/string16.h"
class MsiUtil;
// This class inspects the user's installed programs and builds a mapping of
// files to its associated program.
//
// Installed programs are found by searching the
// "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" registry key and
// its variants. There are 2 cases that are covered:
//
// 1 - If the program's installer did its due dilligence, it populated the
// "InstallLocation" registry key with the directory where it was installed,
// and all the files under that directory are assumed to be owned by this
// program.
//
// In the event of 2 conflicting "InstallLocation", both are ignored as this
// method doesn't let us know for sure who is the owner of any enclosing
// files.
//
// 2 - If the program's entry is a valid MSI Product GUID, the complete list of
// associated file is used to exactly match a given file to a program.
//
// If multiple products installed the same file as the same component,
// Windows keeps a reference count of that component so that the file
// doesn't get removed if one of them is uninstalled. So both programs are
// returned by GetInstalledPrograms().
//
// Note: Programs may be skipped and so would not be returned by
// GetInstalledPrograms() for the following reasons:
// - The program is owned by Microsoft.
// - The uninstall entry is marked as a system component.
// - The uninstall entry has no display name.
// - The uninstall entry has no UninstallString.
//
// This class is not thread safe and should be only accessed on the same
// sequence.
class InstalledPrograms {
public:
struct ProgramInfo {
ProgramInfo(base::string16 name,
HKEY registry_root,
base::string16 registry_key_path,
REGSAM registry_wow64_access);
~ProgramInfo();
base::string16 name;
// Holds the path to the uninstall entry in the registry.
HKEY registry_root;
base::string16 registry_key_path;
REGSAM registry_wow64_access;
};
// The guts of the class, this structure is populated on a background sequence
// and moved back to this instance after initialization.
struct ProgramsData {
ProgramsData();
~ProgramsData();
// Programs are stored in this vector because multiple entries in
// |installed_files| could point to the same one. This is to avoid
// duplicating them.
std::vector<ProgramInfo> programs;
// Contains all the files from programs installed via Microsoft Installer.
// The second part of the pair is the index into |programs|.
std::vector<std::pair<base::FilePath, size_t>> installed_files;
// For some programs, the best information available is the directory of the
// installation. The compare functor treats file paths where one is the
// parent of the other as equal.
// The second part of the pair is the index into |programs|.
std::vector<std::pair<base::FilePath, size_t>> install_directories;
};
InstalledPrograms();
~InstalledPrograms();
// Initializes this class on a background sequence.
void Initialize(base::OnceClosure on_initialized_callback);
// Given a |file|, checks if it matches an installed program on the user's
// machine and appends all the matching programs to |programs|. Do not call
// this before the initialization is done.
bool GetInstalledPrograms(const base::FilePath& file,
std::vector<ProgramInfo>* programs) const;
protected:
// Protected so that tests can subclass InstalledPrograms and access it.
void Initialize(base::OnceClosure on_initialized_callback,
std::unique_ptr<MsiUtil> msi_util);
private:
bool GetProgramsFromInstalledFiles(const base::FilePath& file,
std::vector<ProgramInfo>* programs) const;
bool GetProgramsFromInstallDirectories(
const base::FilePath& file,
std::vector<ProgramInfo>* programs) const;
// Takes the result from the initialization and moves it to this instance,
// then calls |on_initialized_callback| to indicate that the initialization
// is done.
void OnInitializationDone(base::OnceClosure on_initialized_callback,
std::unique_ptr<ProgramsData> programs_data);
// Used to assert that initialization was completed before calling
// GetInstalledPrograms().
bool initialized_;
std::unique_ptr<ProgramsData> programs_data_;
// Make sure this class isn't accessed via multiple sequences.
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<InstalledPrograms> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(InstalledPrograms);
};
#endif // CHROME_BROWSER_CONFLICTS_INSTALLED_PROGRAMS_WIN_H_