diff --git a/shell/platform/windows/uwptool_main.cc b/shell/platform/windows/uwptool_main.cc index f58071088f4f7..24bc41981d4c7 100644 --- a/shell/platform/windows/uwptool_main.cc +++ b/shell/platform/windows/uwptool_main.cc @@ -21,7 +21,7 @@ namespace { void PrintInstalledApps() { flutter::ApplicationStore app_store; for (const flutter::Application& app : app_store.GetInstalledApplications()) { - std::wcout << app.GetPackageId() << std::endl; + std::wcout << app.GetPackageFamily() << std::endl; } } @@ -31,9 +31,15 @@ void PrintInstalledApps() { // 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 LaunchApp(const std::wstring_view app_id, const std::wstring_view args) { - flutter::Application app(app_id); - return app.Launch(args); +int LaunchApp(const std::wstring_view package_family, + const std::wstring_view args) { + flutter::ApplicationStore app_store; + std::optional app = + app_store.GetInstalledApplication(package_family); + if (!app) { + return -1; + } + return app->Launch(args); } // Prints the command usage to stderr. @@ -66,8 +72,8 @@ int main(int argc, char** argv) { return 1; } - // Get the package ID. - std::string package_id = args[1]; + // Get the package family. + std::string package_family = args[1]; // Concatenate the remaining args, comma-separated. std::ostringstream app_args; @@ -77,16 +83,16 @@ int main(int argc, char** argv) { app_args << ","; } } - int process_id = LaunchApp(flutter::Utf16FromUtf8(package_id), + int process_id = LaunchApp(flutter::Utf16FromUtf8(package_family), flutter::Utf16FromUtf8(app_args.str())); if (process_id == -1) { - std::cerr << "error: Failed to launch app with package ID " << package_id - << std::endl; + std::cerr << "error: Failed to launch app with package family " + << package_family << std::endl; return 1; } // Write an informative message for the user to stderr. - std::cerr << "Launched app with package ID " << package_id + std::cerr << "Launched app with package family " << package_family << ". PID: " << std::endl; // Write the PID to stdout. The flutter tool reads this value in. std::cout << process_id << std::endl; diff --git a/shell/platform/windows/uwptool_utils.cc b/shell/platform/windows/uwptool_utils.cc index f3b8fefb00345..2fa58ed25e415 100644 --- a/shell/platform/windows/uwptool_utils.cc +++ b/shell/platform/windows/uwptool_utils.cc @@ -12,14 +12,16 @@ #include #include +#include #include #include #include namespace flutter { -Application::Application(const std::wstring_view package_id) - : package_id_(package_id) {} +Application::Application(const std::wstring_view package_family, + const std::wstring_view package_full_name) + : package_family_(package_family), package_full_name_(package_full_name) {} int Application::Launch(const std::wstring_view args) { // Create the ApplicationActivationManager. @@ -34,7 +36,7 @@ int Application::Launch(const std::wstring_view args) { // Launch the application. DWORD process_id; ACTIVATEOPTIONS options = AO_NONE; - std::wstring app_user_model_id = package_id_ + L"!App"; + 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)) { @@ -43,18 +45,34 @@ int Application::Launch(const std::wstring_view args) { return process_id; } -std::vector ApplicationStore::GetInstalledApplications() { +std::vector ApplicationStore::GetInstalledApplications() const { using winrt::Windows::ApplicationModel::Package; using winrt::Windows::Management::Deployment::PackageManager; // Find packages for the current user (default for empty string). PackageManager package_manager; - std::unordered_set package_ids; + std::vector apps; for (const Package& package : package_manager.FindPackagesForUser(L"")) { - package_ids.emplace(package.Id().FamilyName().c_str()); + apps.emplace_back(package.Id().FamilyName().c_str(), + package.Id().FullName().c_str()); } - std::vector apps(package_ids.begin(), package_ids.end()); return apps; } +std::optional ApplicationStore::GetInstalledApplication( + const std::wstring_view package_family) const { + using winrt::Windows::ApplicationModel::Package; + using winrt::Windows::Management::Deployment::PackageManager; + + // Find packages for the current user (default for empty string). + PackageManager package_manager; + std::vector apps; + for (const Package& package : + package_manager.FindPackagesForUser(L"", package_family)) { + return std::optional(Application(package.Id().FamilyName().c_str(), + package.Id().FullName().c_str())); + } + return std::nullopt; +} + } // namespace flutter diff --git a/shell/platform/windows/uwptool_utils.h b/shell/platform/windows/uwptool_utils.h index 9b6469aa5c08a..f2789871c1fc1 100644 --- a/shell/platform/windows/uwptool_utils.h +++ b/shell/platform/windows/uwptool_utils.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_UWPTOOL_UTILS_H_ #define FLUTTER_SHELL_PLATFORM_WINDOWS_UWPTOOL_UTILS_H_ +#include #include #include @@ -13,12 +14,16 @@ namespace flutter { // A UWP application. class Application { public: - explicit Application(const std::wstring_view package_id); + explicit Application(const std::wstring_view package_family, + const std::wstring_view package_full_name); Application(const Application& other) = default; Application& operator=(const Application& other) = default; - // Returns the package ID. - std::wstring GetPackageId() const { return package_id_; } + // Returns the package family. + std::wstring GetPackageFamily() const { return package_family_; } + + // Returns the package full name. + std::wstring GetPackageFullName() const { return package_full_name_; } // Launches the application with the specified list of launch arguments. // @@ -26,7 +31,8 @@ class Application { int Launch(const std::wstring_view args); private: - std::wstring package_id_; + std::wstring package_family_; + std::wstring package_full_name_; }; // The machine-local store of installed applications. @@ -39,7 +45,11 @@ class ApplicationStore { ApplicationStore& operator=(const ApplicationStore& other) = delete; // Returns a list of all installed application user model IDs. - std::vector GetInstalledApplications(); + std::vector GetInstalledApplications() const; + + // Returns a list of all installed application user model IDs. + std::optional GetInstalledApplication( + const std::wstring_view package_family) const; }; } // namespace flutter diff --git a/shell/platform/windows/uwptool_utils_unittests.cc b/shell/platform/windows/uwptool_utils_unittests.cc index 6ede6b1b354d5..5589cdfd43c21 100644 --- a/shell/platform/windows/uwptool_utils_unittests.cc +++ b/shell/platform/windows/uwptool_utils_unittests.cc @@ -26,10 +26,23 @@ TEST(ApplicationStore, GetInstalledApplications) { EXPECT_FALSE(apps.empty()); auto ms_pos = std::find_if(apps.begin(), apps.end(), [](const auto& app) { - return app.GetPackageId().rfind(L"Microsoft.", 0); + return app.GetPackageFamily().rfind(L"Microsoft.", 0); }); EXPECT_TRUE(ms_pos != apps.end()); } +// Verify that we can look up an app by family name. +TEST(ApplicationStore, GetInstalledApplication) { + ApplicationStore app_store; + std::vector apps = app_store.GetInstalledApplications(); + EXPECT_FALSE(apps.empty()); + + std::optional found_app = + app_store.GetInstalledApplication(apps[0].GetPackageFamily()); + ASSERT_TRUE(found_app != std::nullopt); + EXPECT_EQ(found_app->GetPackageFamily(), apps[0].GetPackageFamily()); + EXPECT_EQ(found_app->GetPackageFullName(), apps[0].GetPackageFullName()); +} + } // namespace testing } // namespace flutter