From c23d5920ac77f6c6274cf404da28ba5d6d49bb9d Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Thu, 20 May 2021 22:11:43 -0700 Subject: [PATCH] [uwptool] Move Launch, Uninstall to AppStore class This refactoring moves the Application Launch and Uninstall methods to the ApplicationStore class. This simplifies writing tests for Command classes since the Application class is now a plain old data class, and ApplicationStore can be replaced with a fake implementation for hermetic testing, while I'll do in a follow-up patch. Bug: https://github.com/flutter/flutter/issues/83072 --- shell/platform/windows/uwptool_commands.cc | 42 ++------ shell/platform/windows/uwptool_commands.h | 6 +- shell/platform/windows/uwptool_utils.cc | 116 +++++++++++---------- shell/platform/windows/uwptool_utils.h | 41 +++++--- 4 files changed, 102 insertions(+), 103 deletions(-) diff --git a/shell/platform/windows/uwptool_commands.cc b/shell/platform/windows/uwptool_commands.cc index 8a54ebee247ae..b524a398f37e1 100644 --- a/shell/platform/windows/uwptool_commands.cc +++ b/shell/platform/windows/uwptool_commands.cc @@ -31,7 +31,7 @@ int InstallCommand::Run(const std::vector& args) const { dependency_uris.push_back(flutter::Utf16FromUtf8(args[i])); } flutter::ApplicationStore app_store; - if (app_store.InstallApp(package_uri, dependency_uris)) { + if (app_store.Install(package_uri, dependency_uris)) { std::wcerr << L"Installed application " << package_uri << std::endl; return 0; } @@ -44,20 +44,9 @@ bool UninstallCommand::ValidateArgs( } int UninstallCommand::Run(const std::vector& args) const { - std::wstring package_family = flutter::Utf16FromUtf8(args[0]); - bool success = true; flutter::ApplicationStore app_store; - for (flutter::Application& app : app_store.GetApps(package_family)) { - if (app.Uninstall()) { - std::wcerr << L"Uninstalled application " << app.GetPackageFullName() - << std::endl; - } else { - std::wcerr << L"error: Failed to uninstall application " - << app.GetPackageFullName() << std::endl; - success = false; - } - } - return success ? 0 : 1; + std::wstring package_family = flutter::Utf16FromUtf8(args[0]); + return app_store.Uninstall(package_family) ? 0 : 1; } bool LaunchCommand::ValidateArgs(const std::vector& args) const { @@ -76,11 +65,13 @@ int LaunchCommand::Run(const std::vector& args) const { app_args << ","; } } - int process_id = LaunchApp(flutter::Utf16FromUtf8(package_family), - flutter::Utf16FromUtf8(app_args.str())); + flutter::ApplicationStore app_store; + int process_id = app_store.Launch(flutter::Utf16FromUtf8(package_family), + flutter::Utf16FromUtf8(app_args.str())); if (process_id == -1) { std::cerr << "error: Failed to launch app with package family " - << package_family << std::endl; + << package_family << " arguments [" << app_args.str() << "]" + << std::endl; return 1; } @@ -92,21 +83,4 @@ int LaunchCommand::Run(const std::vector& args) const { return 0; } -// Launches the app installed on the system with the specified package. -// -// Returns -1 if no matching app, or multiple matching apps are found, or if -// the app fails to launch. Otherwise, the process ID of the launched app is -// returned. -int LaunchCommand::LaunchApp(const std::wstring_view package_family, - const std::wstring_view args) const { - flutter::ApplicationStore app_store; - for (flutter::Application& app : app_store.GetApps(package_family)) { - int process_id = app.Launch(args); - if (process_id != -1) { - return process_id; - } - } - return -1; -} - } // namespace flutter diff --git a/shell/platform/windows/uwptool_commands.h b/shell/platform/windows/uwptool_commands.h index 2917c63efa411..07242516b38bd 100644 --- a/shell/platform/windows/uwptool_commands.h +++ b/shell/platform/windows/uwptool_commands.h @@ -73,7 +73,11 @@ class UninstallCommand : public Command { int Run(const std::vector& args) const override; }; -// Command that launches the specified application package. +// Launches the app installed on the system with the specified package. +// +// Returns -1 if no matching app, or multiple matching apps are found, or if +// the app fails to launch. Otherwise, the process ID of the launched app is +// returned. class LaunchCommand : public Command { public: LaunchCommand() diff --git a/shell/platform/windows/uwptool_utils.cc b/shell/platform/windows/uwptool_utils.cc index 95e936adf9f18..9ac41fbc042fb 100644 --- a/shell/platform/windows/uwptool_utils.cc +++ b/shell/platform/windows/uwptool_utils.cc @@ -20,58 +20,6 @@ namespace flutter { -Application::Application(const std::wstring_view package_name, - const std::wstring_view package_family, - const std::wstring_view package_full_name) - : package_name_(package_name), - package_family_(package_family), - package_full_name_(package_full_name) {} - -int Application::Launch(const std::wstring_view args) { - // Create the ApplicationActivationManager. - winrt::com_ptr activation_manager; - HRESULT hresult = ::CoCreateInstance( - CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC_SERVER, - IID_IApplicationActivationManager, activation_manager.put_void()); - if (FAILED(hresult)) { - return -1; - } - - // Launch the application. - DWORD process_id; - ACTIVATEOPTIONS options = AO_NONE; - std::wstring app_user_model_id = package_family_ + L"!App"; - hresult = activation_manager->ActivateApplication( - app_user_model_id.data(), args.data(), options, &process_id); - if (FAILED(hresult)) { - return -1; - } - return process_id; -} - -bool Application::Uninstall() { - using winrt::Windows::Foundation::AsyncStatus; - using winrt::Windows::Management::Deployment::PackageManager; - using winrt::Windows::Management::Deployment::RemovalOptions; - - PackageManager package_manager; - auto operation = package_manager.RemovePackageAsync( - package_full_name_, RemovalOptions::RemoveForAllUsers); - operation.get(); - - if (operation.Status() == AsyncStatus::Completed) { - return true; - } else if (operation.Status() == AsyncStatus::Canceled) { - return false; - } else if (operation.Status() == AsyncStatus::Error) { - auto result = operation.GetResults(); - std::wcerr << L"error: uninstall failed for package " << package_full_name_ - << L" with error: " << result.ErrorText().c_str() << std::endl; - return false; - } - return false; -} - std::vector ApplicationStore::GetApps() const { using winrt::Windows::ApplicationModel::Package; using winrt::Windows::Management::Deployment::PackageManager; @@ -112,7 +60,7 @@ std::vector ApplicationStore::GetApps( return apps; } -bool ApplicationStore::InstallApp( +bool ApplicationStore::Install( const std::wstring_view package_uri, const std::vector& dependency_uris) { using winrt::Windows::Foundation::AsyncStatus; @@ -145,4 +93,66 @@ bool ApplicationStore::InstallApp( return false; } +bool ApplicationStore::Uninstall(const std::wstring_view package_family) { + bool success = true; + for (const Application& app : GetApps(package_family)) { + if (Uninstall(app.GetPackageFullName())) { + std::wcerr << L"Uninstalled application " << app.GetPackageFullName() + << std::endl; + } else { + std::wcerr << L"error: Failed to uninstall application " + << app.GetPackageFullName() << std::endl; + success = false; + } + } + return success; +} + +bool ApplicationStore::UninstallPackage( + const std::wstring_view package_full_name) { + using winrt::Windows::Foundation::AsyncStatus; + using winrt::Windows::Management::Deployment::PackageManager; + using winrt::Windows::Management::Deployment::RemovalOptions; + + PackageManager package_manager; + auto operation = package_manager.RemovePackageAsync( + package_full_name, RemovalOptions::RemoveForAllUsers); + operation.get(); + + if (operation.Status() == AsyncStatus::Completed) { + return true; + } else if (operation.Status() == AsyncStatus::Canceled) { + return false; + } else if (operation.Status() == AsyncStatus::Error) { + auto result = operation.GetResults(); + std::wcerr << L"error: uninstall failed for package " << package_full_name + << L" with error: " << result.ErrorText().c_str() << std::endl; + return false; + } + return false; +} + +int ApplicationStore::Launch(const std::wstring_view package_family, + const std::wstring_view args) { + // Create the ApplicationActivationManager. + winrt::com_ptr activation_manager; + HRESULT hresult = ::CoCreateInstance( + CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC_SERVER, + IID_IApplicationActivationManager, activation_manager.put_void()); + if (FAILED(hresult)) { + return -1; + } + + // Launch the application. + DWORD process_id; + ACTIVATEOPTIONS options = AO_NONE; + std::wstring app_user_model_id = std::wstring(package_family) + L"!App"; + hresult = activation_manager->ActivateApplication( + app_user_model_id.data(), args.data(), options, &process_id); + if (FAILED(hresult)) { + return -1; + } + return process_id; +} + } // namespace flutter diff --git a/shell/platform/windows/uwptool_utils.h b/shell/platform/windows/uwptool_utils.h index 4ccfe90368b7a..21b116cb0ee81 100644 --- a/shell/platform/windows/uwptool_utils.h +++ b/shell/platform/windows/uwptool_utils.h @@ -14,9 +14,13 @@ namespace flutter { // A UWP application. class Application { public: - explicit Application(const std::wstring_view package_name, - const std::wstring_view package_family, - const std::wstring_view package_full_name); + Application(const std::wstring_view package_name, + const std::wstring_view package_family, + const std::wstring_view package_full_name) + : package_name_(package_name), + package_family_(package_family), + package_full_name_(package_full_name) {} + Application(const Application& other) = default; Application& operator=(const Application& other) = default; @@ -39,16 +43,6 @@ class Application { // package name, publisher, architecture and version information. std::wstring GetPackageFullName() const { return package_full_name_; } - // Launches the application with the specified list of launch arguments. - // - // Returns the process ID on success, or -1 on failure. - int Launch(const std::wstring_view args); - - // Uninstalls the application. - // - // Returns true on success. - bool Uninstall(); - private: std::wstring package_name_; std::wstring package_family_; @@ -75,8 +69,25 @@ class ApplicationStore { // // Installs the application located at package_uri with the specified // dependencies. - bool InstallApp(const std::wstring_view package_uri, - const std::vector& dependency_uris); + bool Install(const std::wstring_view package_uri, + const std::vector& dependency_uris); + + // Uninstalls all application packages in the specified package family. + // + // Returns true on success. + bool Uninstall(const std::wstring_view package_family); + + // Launches the application with the specified list of launch arguments. + // + // Returns the process ID on success, or -1 on failure. + int Launch(const std::wstring_view package_family, + const std::wstring_view args); + + private: + // Uninstalls the specified application package. + // + // Returns true on success. + bool UninstallPackage(const std::wstring_view package_full_name); }; } // namespace flutter