forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
uwptool is a helper tool used by the flutter command-line tool. It can be thought of as analogous to adb for Android or libimobiledevice for iOS. Its core functions are: * List installed apps. (included in this patch) * Launch an app with a set of launch arguments. (included in this patch) * Install an app (included in a later patch). * Uninstall an app (included in a later patch). Part of flutter/flutter#81756
- Loading branch information
Showing
7 changed files
with
282 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include <Windows.h> | ||
#include <winrt/base.h> | ||
|
||
#include <algorithm> | ||
#include <iostream> | ||
#include <sstream> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "flutter/fml/command_line.h" | ||
#include "flutter/shell/platform/windows/string_conversion.h" | ||
#include "flutter/shell/platform/windows/uwptool_utils.h" | ||
|
||
namespace { | ||
|
||
// Prints a list of installed UWP apps to stdout. | ||
void PrintInstalledApps() { | ||
flutter::ApplicationStore app_store; | ||
for (const flutter::Application& app : app_store.GetInstalledApplications()) { | ||
std::wcout << app.GetPackageId() << std::endl; | ||
} | ||
} | ||
|
||
// Launches the app installed on the system whose Application User Model ID is | ||
// prefixed with app_id, with the specified arguments list. | ||
// | ||
// 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); | ||
DWORD process_id = app.Launch(args); | ||
if (process_id == -1) { | ||
std::wcerr << L"Failed to launch app " << app.GetPackageId() << std::endl; | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
// Prints the command usage to stderr. | ||
void PrintUsage() { | ||
std::cerr << "usage: uwptool COMMAND [APP_ID]" << std::endl; | ||
std::cerr << "commands:" << std::endl; | ||
std::cerr << " listapps list installed applications" << std::endl; | ||
std::cerr << " launch launch an application" << std::endl; | ||
} | ||
|
||
} // namespace | ||
|
||
int main(int argc, char** argv) { | ||
winrt::init_apartment(); | ||
|
||
auto command_line = fml::CommandLineFromArgcArgv(argc, argv); | ||
if (command_line.positional_args().size() < 1) { | ||
PrintUsage(); | ||
return 1; | ||
} | ||
|
||
const std::vector<std::string>& args = command_line.positional_args(); | ||
std::string command = args[0]; | ||
if (command == "listapps") { | ||
PrintInstalledApps(); | ||
return 0; | ||
} else if (command == "launch") { | ||
if (command_line.positional_args().size() < 1) { | ||
PrintUsage(); | ||
return 1; | ||
} | ||
|
||
// Get the package ID. | ||
std::string package_id = args[1]; | ||
|
||
// Concatenate the remaining args, space-separated. | ||
std::ostringstream app_args; | ||
for (int i = 2; i < args.size(); ++i) { | ||
app_args << args[i]; | ||
if (i < args.size() - 1) { | ||
app_args << " "; | ||
} | ||
} | ||
return LaunchApp(flutter::Utf16FromUtf8(package_id), | ||
flutter::Utf16FromUtf8(app_args.str())); | ||
} | ||
|
||
std::cerr << "Unknown command: " << command << std::endl; | ||
PrintUsage(); | ||
return 1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/shell/platform/windows/uwptool_utils.h" | ||
|
||
#include <Windows.h> | ||
#include <Winreg.h> | ||
#include <shobjidl_core.h> | ||
#include <winrt/base.h> | ||
|
||
#include <string> | ||
#include <unordered_set> | ||
#include <vector> | ||
|
||
namespace flutter { | ||
|
||
Application::Application(const std::wstring_view package_id) | ||
: package_id_(package_id) {} | ||
|
||
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_id_ + L"!App"; | ||
hresult = activation_manager->ActivateApplication( | ||
app_user_model_id.data(), args.data(), options, &process_id); | ||
if (FAILED(hresult)) { | ||
return -1; | ||
} | ||
return process_id; | ||
} | ||
|
||
std::vector<Application> ApplicationStore::GetInstalledApplications() { | ||
constexpr wchar_t kMappingsKey[] = | ||
L"\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion" | ||
L"\\AppModel\\Repository\\Families"; | ||
RegistryKey mappings_key(HKEY_CLASSES_ROOT, kMappingsKey, KEY_READ); | ||
if (!mappings_key.IsValid()) { | ||
return {}; | ||
} | ||
|
||
std::unordered_set<std::wstring> package_ids; | ||
for (const std::wstring& subkey_name : mappings_key.GetSubKeyNames()) { | ||
package_ids.emplace(subkey_name); | ||
} | ||
std::vector<Application> apps(package_ids.begin(), package_ids.end()); | ||
return apps; | ||
} | ||
|
||
} // namespace flutter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_UWPTOOL_UTILS_H_ | ||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_UWPTOOL_UTILS_H_ | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
#include "flutter/shell/platform/windows/registry.h" | ||
|
||
namespace flutter { | ||
|
||
// A UWP application. | ||
class Application { | ||
public: | ||
explicit Application(const std::wstring_view package_id); | ||
Application(const Application& other) = default; | ||
Application& operator=(const Application& other) = default; | ||
|
||
// Returns the application user model ID. | ||
std::wstring GetPackageId() const { return package_id_; } | ||
|
||
// Launches the application with the specified list of launch arguments. | ||
int Launch(const std::wstring_view args); | ||
|
||
private: | ||
std::wstring package_id_; | ||
}; | ||
|
||
// The machine-local store of installed applications. | ||
class ApplicationStore { | ||
public: | ||
ApplicationStore() = default; | ||
|
||
// Prevent copying. | ||
ApplicationStore(const ApplicationStore& other) = delete; | ||
ApplicationStore& operator=(const ApplicationStore& other) = delete; | ||
|
||
// Returns a list of all installed application user model IDs. | ||
std::vector<Application> GetInstalledApplications(); | ||
}; | ||
|
||
} // namespace flutter | ||
|
||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_UWPTOOL_UTILS_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/shell/platform/windows/uwptool_utils.h" | ||
|
||
#include <algorithm> | ||
#include <iostream> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "gtest/gtest.h" | ||
|
||
namespace flutter { | ||
namespace testing { | ||
|
||
// TODO(cbracken): write registry values to be tested, then cleanup, refactor | ||
// to support a mock registry. | ||
// https://github.com/flutter/flutter/issues/82095 | ||
|
||
// Verify that at least one Microsoft app (e.g. Microsoft.WindowsCalculator) is | ||
// installed and can be found. | ||
TEST(ApplicationStore, GetInstalledApplications) { | ||
ApplicationStore app_store; | ||
std::vector<Application> apps = app_store.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); | ||
}); | ||
EXPECT_TRUE(ms_pos != apps.end()); | ||
} | ||
|
||
} // namespace testing | ||
} // namespace flutter |