| // Copyright 2022 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_WIN_APP_COMMAND_RUNNER_H_ |
| #define CHROME_UPDATER_WIN_APP_COMMAND_RUNNER_H_ |
| |
| #include <windows.h> |
| |
| #include <optional> |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/span.h" |
| #include "base/files/file_path.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/process/process.h" |
| #include "chrome/updater/updater_scope.h" |
| #include "chrome/updater/util/win_util.h" |
| |
| namespace updater { |
| |
| // AppCommandRunner loads and runs a pre-registered command line from the |
| // registry. |
| class AppCommandRunner { |
| public: |
| AppCommandRunner(); |
| AppCommandRunner(const AppCommandRunner&); |
| AppCommandRunner& operator=(const AppCommandRunner&); |
| ~AppCommandRunner(); |
| |
| // Creates an instance of `AppCommandRunner` object corresponding to `app_id` |
| // and `command_id`. |
| static HResultOr<AppCommandRunner> LoadAppCommand( |
| UpdaterScope scope, |
| const std::wstring& app_id, |
| const std::wstring& command_id); |
| |
| // Loads and returns a vector of `AppCommandRunner` objects corresponding to |
| // "AutoRunOnOsUpgradeAppCommands" for `app_id`. |
| static std::vector<AppCommandRunner> LoadAutoRunOnOsUpgradeAppCommands( |
| UpdaterScope scope, |
| const std::wstring& app_id); |
| |
| // Runs the AppCommand with the provided `substitutions` and populates |
| // `process` if successful. |
| HRESULT Run(base::span<const std::wstring> substitutions, |
| base::Process& process) const; |
| |
| private: |
| // Starts a process with separate `executable` and `parameters` components. |
| // `executable` needs to be an absolute path. |
| static HRESULT StartProcess(const base::FilePath& executable, |
| const std::wstring& parameters, |
| base::Process& process); |
| |
| // Separates a command line in `command_format` into an `executable` and |
| // `parameters`. `executable` needs to be an absolute path, and additionally |
| // needs to be under %programfiles% for System `scope`. Parameters on the |
| // command line can be either hardcoded or placeholders from `%1` to `%9`. |
| static HRESULT GetAppCommandFormatComponents( |
| UpdaterScope scope, |
| std::wstring command_format, |
| base::FilePath& executable, |
| std::vector<std::wstring>& parameters); |
| |
| // Formats a single `parameter` using |
| // `base::internal::DoReplaceStringPlaceholders`. Any placeholder `%N` in |
| // `parameter` is replaced with substitutions[N - 1]. Any literal `%` needs to |
| // be escaped with a `%`. |
| // |
| // Returns `std::nullopt` if: |
| // * a placeholder %N is encountered where N > substitutions.size(). |
| // * a literal `%` is not escaped with a `%`. |
| static std::optional<std::wstring> FormatParameter( |
| const std::wstring& parameter, |
| base::span<const std::wstring> substitutions); |
| |
| // Formats a vector of `parameters` using the provided `substitutions` and |
| // returns a resultant command line. Any placeholder `%N` in `parameters` is |
| // replaced with substitutions[N - 1]. Any literal `%` needs to be escaped |
| // with a `%`. |
| // |
| // The parameters are quoted after substitution if necessary so that each |
| // parameter will be interpreted as a single command-line parameter according |
| // to the rules for ::CommandLineToArgvW. |
| // |
| // Returns `std::nullopt` if: |
| // * a placeholder %N is encountered where N > substitutions.size(). |
| // * a literal `%` is not escaped with a `%`. |
| static std::optional<std::wstring> FormatAppCommandLine( |
| const std::vector<std::wstring>& parameters, |
| base::span<const std::wstring> substitutions); |
| |
| // Helper method that calls `FormatAppCommandLine` and then `StartProcess`. |
| static HRESULT ExecuteAppCommand(const base::FilePath& executable, |
| const std::vector<std::wstring>& parameters, |
| base::span<const std::wstring> substitutions, |
| base::Process& process); |
| |
| base::FilePath executable_; |
| std::vector<std::wstring> parameters_; |
| |
| FRIEND_TEST_ALL_PREFIXES(AppCommandFormatComponentsInvalidPathsTest, |
| TestCases); |
| FRIEND_TEST_ALL_PREFIXES(AppCommandFormatComponentsProgramFilesPathsTest, |
| TestCases); |
| FRIEND_TEST_ALL_PREFIXES(AppCommandFormatParameterTest, TestCases); |
| FRIEND_TEST_ALL_PREFIXES(AppCommandFormatComponentsAndCommandLineTest, |
| TestCases); |
| FRIEND_TEST_ALL_PREFIXES(AppCommandExecuteTest, TestCases); |
| }; |
| |
| } // namespace updater |
| |
| #endif // CHROME_UPDATER_WIN_APP_COMMAND_RUNNER_H_ |