Skip to content

Commit

Permalink
[uwptool] Move Launch, Uninstall to AppStore class (flutter#26315)
Browse files Browse the repository at this point in the history
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: flutter/flutter#83072
  • Loading branch information
cbracken committed May 21, 2021
1 parent 2f067fc commit cb3ee34
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 103 deletions.
42 changes: 8 additions & 34 deletions shell/platform/windows/uwptool_commands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ int InstallCommand::Run(const std::vector<std::string>& 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;
}
Expand All @@ -44,20 +44,9 @@ bool UninstallCommand::ValidateArgs(
}

int UninstallCommand::Run(const std::vector<std::string>& 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<std::string>& args) const {
Expand All @@ -76,11 +65,13 @@ int LaunchCommand::Run(const std::vector<std::string>& 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;
}

Expand All @@ -92,21 +83,4 @@ int LaunchCommand::Run(const std::vector<std::string>& 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
6 changes: 5 additions & 1 deletion shell/platform/windows/uwptool_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,11 @@ class UninstallCommand : public Command {
int Run(const std::vector<std::string>& 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()
Expand Down
116 changes: 63 additions & 53 deletions shell/platform/windows/uwptool_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<IApplicationActivationManager> 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<Application> ApplicationStore::GetApps() const {
using winrt::Windows::ApplicationModel::Package;
using winrt::Windows::Management::Deployment::PackageManager;
Expand Down Expand Up @@ -112,7 +60,7 @@ std::vector<Application> ApplicationStore::GetApps(
return apps;
}

bool ApplicationStore::InstallApp(
bool ApplicationStore::Install(
const std::wstring_view package_uri,
const std::vector<std::wstring>& dependency_uris) {
using winrt::Windows::Foundation::AsyncStatus;
Expand Down Expand Up @@ -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<IApplicationActivationManager> 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
41 changes: 26 additions & 15 deletions shell/platform/windows/uwptool_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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_;
Expand All @@ -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<std::wstring>& dependency_uris);
bool Install(const std::wstring_view package_uri,
const std::vector<std::wstring>& 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
Expand Down

0 comments on commit cb3ee34

Please sign in to comment.