// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_UPDATER_UTIL_UTIL_H_ #define CHROME_UPDATER_UTIL_UTIL_H_ #include <cmath> #include <concepts> #include <limits> #include <optional> #include <ostream> #include <string> #include <type_traits> #include <vector> #include "base/functional/callback_forward.h" #include "base/memory/ref_counted.h" #include "base/types/cxx23_to_underlying.h" #include "build/build_config.h" #include "chrome/updater/tag.h" #include "chrome/updater/updater_scope.h" class GURL; namespace base { class CommandLine; class FilePath; class Version; // Enables insertion of optional `base` types. Must be in the `base` namespace // for insertion into gTest expectations to work. template <class T> inline std::ostream& operator<<(std::ostream& os, const std::optional<T>& opt) { … } } // namespace base namespace updater { struct RegistrationRequest; // Converts an unsigned integral to a signed one. Returns -1 if the value is // out of the range of the target type. template <std::unsigned_integral T> [[nodiscard]] auto ToSignedIntegral(T value) { … } // Inserts an enum value as the underlying type. template <typename T> requires(std::is_enum_v<T>) inline std::ostream& operator<<(std::ostream& os, const T& e) { … } // Returns the versioned install directory under which the program stores its // executables. For example, on macOS this function may return // ~/Library/Google/GoogleUpdater/88.0.4293.0 (/Library for system). Does not // create the directory if it does not exist. std::optional<base::FilePath> GetVersionedInstallDirectory( UpdaterScope scope, const base::Version& version); // Simpler form of GetVersionedInstallDirectory for the currently running // version of the updater. std::optional<base::FilePath> GetVersionedInstallDirectory(UpdaterScope scope); // Returns the base install directory common to all versions of the updater. // Does not create the directory if it does not exist. std::optional<base::FilePath> GetInstallDirectory(UpdaterScope scope); // Returns the base path for discardable caches. Deleting a discardable cache // between runs of the updater may impair performance, cause a redownload, etc., // but otherwise not interfere with overall updater function. Cache contents // should only be stored in subpaths under this path. Does not create the // directory if it does not exist. std::optional<base::FilePath> GetCacheBaseDirectory(UpdaterScope scope); // Returns the path where CRXes cached for delta updates should be stored, // common to all versions of the updater. Does not create the directory if it // does not exist. std::optional<base::FilePath> GetCrxDiffCacheDirectory(UpdaterScope scope); #if BUILDFLAG(IS_MAC) // For example: ~/Library/Google/GoogleUpdater/88.0.4293.0/GoogleUpdater.app std::optional<base::FilePath> GetUpdaterAppBundlePath(UpdaterScope scope); #endif // BUILDFLAG(IS_MAC) // For user installations: // ~/Library/Google/GoogleUpdater/88.0.4293.0/GoogleUpdater.app/Contents/ // MacOS/GoogleUpdater // For system installations: // /Library/Google/GoogleUpdater/88.0.4293.0/GoogleUpdater.app/Contents/ // MacOS/GoogleUpdater std::optional<base::FilePath> GetUpdaterExecutablePath( UpdaterScope scope, const base::Version& version); // Simpler form of GetUpdaterExecutablePath for the currently running version // of the updater. std::optional<base::FilePath> GetUpdaterExecutablePath(UpdaterScope scope); // Returns a relative path to the executable from GetVersionedInstallDirectory. // "GoogleUpdater.app/Contents/MacOS/GoogleUpdater" on macOS. // "updater.exe" on Win. base::FilePath GetExecutableRelativePath(); // Returns the path to the crashpad database directory. The directory is not // created if it does not exist. std::optional<base::FilePath> GetCrashDatabasePath(UpdaterScope scope); // Returns the path to the crashpad database, creating it if it does not exist. std::optional<base::FilePath> EnsureCrashDatabasePath(UpdaterScope scope); // Contains the parsed values from the tag. The tag is provided as a command // line argument to the `--install` or the `--handoff` switch. struct TagParsingResult { … }; // These functions return {} if there was no tag at all. An error is set if the // tag fails to parse. TagParsingResult GetTagArgsForCommandLine( const base::CommandLine& command_line); TagParsingResult GetTagArgs(); std::optional<tagging::AppArgs> GetAppArgs(const std::string& app_id); std::string GetDecodedInstallDataFromAppArgs(const std::string& app_id); std::string GetInstallDataIndexFromAppArgs(const std::string& app_id); std::optional<base::FilePath> GetLogFilePath(UpdaterScope scope); // Initializes logging for an executable. void InitLogging(UpdaterScope updater_scope); // Returns HTTP user-agent value. std::string GetUpdaterUserAgent(); // Returns a new GURL by appending the given query parameter name and the // value. Unsafe characters in the name and the value are escaped like // %XX%XX. The original query component is preserved if it's present. // // Examples: // // AppendQueryParameter(GURL("http://example.com"), "name", "value").spec() // => "http://example.com?name=value" // AppendQueryParameter(GURL("http://example.com?x=y"), "name", "value").spec() // => "http://example.com?x=y&name=value" GURL AppendQueryParameter(const GURL& url, const std::string& name, const std::string& value); #if BUILDFLAG(IS_MAC) // Uses the builtin unzip utility within macOS /usr/bin/unzip to unzip instead // of using the configurator's UnzipperFactory. The UnzipperFactory utilizes the // //third_party/zlib/google, which has a bug that does not preserve the // permissions when it extracts the contents. For updates via zip or // differentials, use UnzipWithExe. bool UnzipWithExe(const base::FilePath& src_path, const base::FilePath& dest_path); // Read the file at path to confirm that the file at the path has the same // permissions as the given permissions mask. bool ConfirmFilePermissions(const base::FilePath& root_path, int kPermissionsMask); #endif // BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_WIN) // Returns the versioned task name prefix in the following format: // "{ProductName}Task{System/User}{UpdaterVersion}". // For instance: "ChromiumUpdaterTaskSystem92.0.0.1". std::wstring GetTaskNamePrefix(UpdaterScope scope); // Returns the versioned task display name in the following format: // "{ProductName} Task {System/User} {UpdaterVersion}". // For instance: "ChromiumUpdater Task System 92.0.0.1". std::wstring GetTaskDisplayName(UpdaterScope scope); // Parses the command line string in legacy format into `base::CommandLine`. // The string must be in format like: // program.exe /switch1 value1 /switch2 /switch3 value3 // Returns empty if a Chromium style switch is found. std::optional<base::CommandLine> CommandLineForLegacyFormat( const std::wstring& cmd_string); // Returns the command line for current process, either in legacy style, or // in Chromium style. base::CommandLine GetCommandLineLegacyCompatible(); #endif // BUILDFLAG(IS_WIN) // Writes the provided string prefixed with the UTF8 byte order mark to a // temporary file. The temporary file is created in the specified `directory`. std::optional<base::FilePath> WriteInstallerDataToTempFile( const base::FilePath& directory, const std::string& installer_data); // Creates and starts a thread pool for this process. void InitializeThreadPool(const char* name); // Returns whether the user currently running the program is the right user for // the scope. This can be useful to avoid installing system updaters that are // owned by non-root accounts, or avoiding the installation of a user level // updater as root. bool WrongUser(UpdaterScope scope); // Returns whether a user has previously accepted a EULA / ToS for at least one // of the listed apps. bool EulaAccepted(const std::vector<std::string>& app_ids); // Imports metadata from legacy updaters. bool MigrateLegacyUpdaters( UpdaterScope scope, base::RepeatingCallback<void(const RegistrationRequest&)> register_callback); // Delete everything other than `except` under `except.DirName()`. [[nodiscard]] bool DeleteExcept(const std::optional<base::FilePath>& except); // Returns the quotient of dividing two integer numbers (m/n) rounded up. template <typename T> requires(std::integral<T>) [[nodiscard]] constexpr T CeilingDivide(T m, T n) { … } // Returns a value in the [0, 100] range or -1 if the progress could not // be computed. [[nodiscard]] int GetDownloadProgress(int64_t downloaded_bytes, int64_t total_bytes); } // namespace updater #endif // CHROME_UPDATER_UTIL_UTIL_H_