Overview¶
Ubuntu App Launch is the abstraction that creates a consistent interface for managing apps on Ubuntu Touch. It is used by Unity8 and other programs to start and stop applications, as well as query which ones are currently open. It doesn’t have its own service or processes though, it relies on the system init daemon to manage the processes (currently systemd) but configures them in a way that they’re discoverable and usable by higher level applications.
Environment Variables¶
There are a few environment variables that can effect the behavior of UAL while it is running.
- UBUNTU_APP_LAUNCH_DEMANGLER
- Path to the UAL demangler tool that will get the Mir FD for trusted prompt session.
- UBUNTU_APP_LAUNCH_DISABLE_SNAPD_TIMEOUT
- Wait as long as Snapd wants to return data instead of erroring after 100ms.
- UBUNTU_APP_LAUNCH_LEGACY_ROOT
- Set the path that represents the root for legacy applications.
- UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH
- Path to the libertine launch utility for setting up libertine containers and XMir based legacy apps.
- UBUNTU_APP_LAUNCH_OOM_HELPER
- Path to the setuid helper that configures OOM values on application processes that we otherwise couldn’t, mostly this is for Oxide.
- UBUNTU_APP_LAUNCH_OOM_PROC_PATH
- Path to look for the files to set OOM values, defaults to /proc.
- UBUNTU_APP_LAUNCH_SNAP_BASEDIR
- The place where snaps are installed in the system, /snap is the default.
- UBUNTU_APP_LAUNCH_SNAP_LEGACY_EXEC
- A snappy command that is used to launch legacy applications in the current snap, to ensure the environment gets configured correctly, defaults to /snap/bin/unity8-session.legacy-exec
- UBUNTU_APP_LAUNCH_SNAPD_SOCKET
- Path to the snapd socket.
- UBUNTU_APP_LAUNCH_SYSTEMD_CGROUP_ROOT
- Path to the root of the cgroups that we should look in for PIDs. Defaults to /sys/fs/cgroup/systemd/.
- UBUNTU_APP_LAUNCH_SYSTEMD_PATH
- Path to the dbus bus that is used to talk to systemd. This allows us to talk to the user bus while Upstart is still setting up a session bus. Defaults to /run/user/$uid/bus.
- UBUNTU_APP_LAUNCH_SYSTEMD_NO_RESET
- Don’t reset the job after it fails. This makes it so it can’t be run again, but leaves debugging information around for investigation.
- UBUNTU_APP_LAUNCH_XMIR_HELPER
- Tool that helps to start XMir and sets the DISPLAY variable for applications
- UBUNTU_APP_LAUNCH_XMIR_PATH
- Specifies the location of the XMir binary to use
API Documentation¶
AppID¶
-
struct
ubuntu::app_launch::
AppID
¶ The set of information that is used to uniquely identify an application in Ubuntu.
Application ID’s are derived from the packaging system and the applications that are defined to work in it. It resolves down to a specific version of the package to resolve problems with upgrades and reduce race conditions that come from installing and removing them while trying to launch them. While it always resolves down to a specific version, there are functions avilable here that search in various ways for the current version so higher level apps can save just the package and application strings and discover the version when it is required.
Public Types
-
enum
ApplicationWildcard
¶ Control how the application list of a package is searched in the discover() functions.
Values:
-
FIRST_LISTED
¶ First application listed in the manifest
-
LAST_LISTED
¶ Last application listed in the manifest
-
ONLY_LISTED
¶ Only application listed in the manifest
-
-
enum
VersionWildcard
¶ Control how the versions are searched in the discover() set of functions
Values:
-
CURRENT_USER_VERSION
¶ The current installed version
-
Public Functions
-
operator std::string
() const¶ Turn the structure into a string. This is required for many older C based interfaces that work with AppID‘s, but is generally not recommended for anyting other than debug messages.
-
AppID
()¶ Empty constructor for an AppID. Makes coding with them easier, but generally there is nothing useful about an empty AppID.
-
AppID
(Package pkg, AppName app, Version ver)¶ Constructor for an AppID if all the information is known about the package. Provides a precise and fast way to create an AppID if all the information is already known.
- Parameters
package
: Name of the packageappname
: Name of the applicationversion
: Version of the package
Public Members
-
Package
package
¶ The package name of the application. Typically this is in the form of $app.$developer so it could be my-app.my-name, though other formats do exist and are used in the wild.
In the case of legacy applications this will be the empty string.
-
AppName
appname
¶ The string that uniquely identifies the application. This comes from the package manifest. In a Click package this is the string that exists under the “hooks” key in the JSON manifest.
-
Version
version
¶ Version of the package that is installed. This is always resolved when creating the struct.
- Note
- For snaps this is actually the ‘revision’ instead of the version since that is unique where ‘version’ is not.
Public Static Functions
-
AppID
parse
(const std::string &appid)¶ Parse a string and turn it into an AppID. This assumes that the string is in the form: __ and will return an empty AppID if not.
- Parameters
appid
: String with the concatenated AppID
-
AppID
find
(const std::string &sappid)¶ Find is a more tollerant version of parse(), it handles legacy applications, short AppIDs ($package_$app) and other forms of that are in common usage. It can be used, but is slower than parse() if you’ve got well formed data already.
- Note
- This will use the default registry instance, it is generally recommended to have your own instead of using the default.
- Parameters
sappid
: String with the concatenated AppID
Find is a more tollerant version of parse(), it handles legacy applications, short AppIDs ($package_$app) and other forms of that are in common usage. It can be used, but is slower than parse() if you’ve got well formed data already.
-
bool
valid
(const std::string &sappid)¶ Check to see whether a string is a valid AppID string
- Parameters
sappid
: String with the concatenated AppID
-
AppID
discover
(const std::string &package, ApplicationWildcard appwildcard = ApplicationWildcard::FIRST_LISTED, VersionWildcard versionwildcard = VersionWildcard::CURRENT_USER_VERSION)¶ Find the AppID for an application where you only know the package name.
- Note
- This will use the default registry instance, it is generally recommended to have your own instead of using the default.
- Parameters
package
: Name of the packageappwildcard
: Specification of how to search the manifest for appsversionwildcard
: Specification of how to search for the version
-
AppID
discover
(const std::string &package, const std::string &appname, VersionWildcard versionwildcard = VersionWildcard::CURRENT_USER_VERSION)¶ Find the AppID for an application where you know the package name and application name.
- Note
- This will use the default registry instance, it is generally recommended to have your own instead of using the default.
- Parameters
package
: Name of the packageappname
: Name of the applicationversionwildcard
: Specification of how to search for the version
-
AppID
discover
(const std::string &package, const std::string &appname, const std::string &version)¶ Create an AppID providing known strings of packages and names
- Note
- This will use the default registry instance, it is generally recommended to have your own instead of using the default.
- Parameters
package
: Name of the packageappname
: Name of the applicationversion
: Version of the package
Find the AppID for an application where you only know the package name.
- Parameters
registry
: Registry instance to use for persistant connectionspackage
: Name of the packageappwildcard
: Specification of how to search the manifest for appsversionwildcard
: Specification of how to search for the version
-
enum
Application¶
-
class
ubuntu::app_launch::
Application
¶ Class to represent an application, whether running or not, and query more information about it.
Generally the Application object represents an Application in the system. It hooks up all of it’s signals, finds out information about it and controls whether it is running or not. This class is what most users of Ubuntu App Launch will do the majority of their work.
Subclassed by ubuntu::app_launch::app_impls::Base
Public Functions
-
virtual
~Application
()¶
-
virtual AppID
appId
() = 0¶ Get the Application ID of this Application
-
virtual std::shared_ptr<Info>
info
() = 0¶ Get a Application::Info object to describe the metadata for this application
-
virtual bool
hasInstances
() = 0¶ A quick check to see if this application has any running instances
-
virtual std::vector<std::shared_ptr<Instance>>
instances
() = 0¶ Get a vector of the running instances of this application
-
virtual std::shared_ptr<Instance>
launch
(const std::vector<URL> &urls = {}) = 0¶ Start an application, optionally with URLs to pass to it.
- Parameters
urls
: A list of URLs to pass to the application command line
Public Static Functions
Function to create an Application object. It determines the type of application and returns a pointer to that application object. It uses the registry for shared connections and is given an AppID. To find the AppID for a given application use the AppID::discover() functions.
- Parameters
appid
: Application ID for the applicationregistry
: Shared registry to use
-
class
Info
¶ Information and metadata about the application for programs that are displaying the application to users.
The Info class has all the metadata including user visible strings and other nicities that users expect to see about applications. For most formats this is gotten from the Desktop file, but those may be in different locations depending on the packaging format.
Subclassed by ubuntu::app_launch::app_info::Desktop
Public Functions
-
virtual
~Info
()¶
-
virtual const Name &
name
() = 0¶ Name of the application
-
virtual const Description &
description
() = 0¶ Textual description of the application
-
virtual const IconPath &
iconPath
() = 0¶ Path to the icon that represents the application
-
virtual const DefaultDepartment &
defaultDepartment
() = 0¶ Default department of the application
-
virtual const IconPath &
screenshotPath
() = 0¶ Path to the screenshot of the application
-
virtual const Keywords &
keywords
() = 0¶ List of keywords for the application
-
virtual const Popularity &
popularity
() = 0¶ Get the relative popularity of the application, 0 is not popular
-
virtual Orientations
supportedOrientations
() = 0¶ Return which orientations are supported
-
virtual RotatesWindow
rotatesWindowContents
() = 0¶ Return whether the window contents can be rotated or not
-
virtual UbuntuLifecycle
supportsUbuntuLifecycle
() = 0¶
-
struct
Orientations
¶ Orientation and placement
Public Functions
-
bool
operator==
(const Orientations &b) const¶ Check to see if two Orientations are the same
-
bool
-
struct
Splash
¶ Information to be shown on the app splash screen
-
virtual
-
class
Instance
¶ Interface representing the information about a specific application running instance. This includes information on the PIDs that make up the Application::Instance.
Subclassed by ubuntu::app_launch::jobs::instance::Base
Public Functions
-
virtual
~Instance
()¶
-
virtual bool
isRunning
() = 0¶ Check to see if the instance is currently running. The object can exist even after the instance has stopped running.
-
virtual pid_t
primaryPid
() = 0¶ Get the primary PID for this Application::Instance, this will return zero when it is not running. The primary PID is the PID keeping the instance alive, when it exists the others get reaped.
-
virtual bool
hasPid
(pid_t pid) = 0¶ Check to see if a PID is in the cgroup for this application instance. Each application instance tracks all the PIDs that are currently being used
-
virtual std::vector<pid_t>
pids
() = 0¶ Check to see if a specific PID is part of this Application::Instance
-
virtual void
setOomAdjustment
(const oom::Score score) = 0¶ Sets the value of the OOM Adjust kernel property for the all of the processes this instance.
-
virtual const oom::Score
getOomAdjustment
() = 0¶ Gets the value of the OOM Adjust kernel property for the primary process of this instance.
- Note
- This function does not check all the processes and ensure they are consistent, it just checks the primary and assumes that.
-
virtual void
pause
() = 0¶ Pause, or send SIGSTOP, to the PIDs in this Application::Instance
-
virtual void
resume
() = 0¶ Resume, or send SIGCONT, to the PIDs in this Application::Instance
-
virtual void
stop
() = 0¶ Stop, or send SIGTERM, to the PIDs in this Application::Instance, if the PIDs do not respond to the SIGTERM they will be SIGKILL’d
-
virtual void
focus
() = 0¶ Signal the shell to focus the Application::Instance
-
virtual
-
virtual
Helper¶
-
class
ubuntu::app_launch::
Helper
¶ Class representing an untrusted helper in the system. Untrusted helpers are used by trusted helpers to get some amount of functionality from a package in the system. Typically this is via a Click hook in a Click package.
In order to setup a untrusted helper the trusted helper needs to install a small executable that gives the equivallent of a Desktop Exec string to the system. This is done by installing the executable in the
/usr/lib//ubuntu-app-launch/$(helper type)/exec-tool
. A simple example can be seen in URL Dispatcher’s URL Overlay helper. It is important to note that the helper will be confined with the apparmor profile associated with the AppID that is being used. For Click based applications this means that an untrusted helper should be its own stanza in the Click manifest with its ownapparmor
hook. This will configure the confinement for the helper.Many times an untrusted helper runs in a non-user-facing mode, it is important that UAL DOES NOT implement a lifecycle for the helper. It is the responsibility of the trusted helper to do that. Many times this is a timeout or other similar functionality. These are the tools to implement those in a reasonable fashion (services don’t have to worry about AppArmor, cgroups, or jobs) but it doesn’t not implement them by itself.
Subclassed by ubuntu::app_launch::helper_impls::Base
Public Functions
-
virtual bool
hasInstances
() = 0¶ Check to see if there are any instances of this untrusted helper
-
virtual std::vector<std::shared_ptr<Instance>>
instances
() = 0¶ Get the list of instances of this helper
-
virtual std::shared_ptr<Instance>
launch
(std::vector<URL> urls = {}) = 0¶ Launch an instance of a helper with an optional set of URLs that get passed to the helper.
- Parameters
urls
: List of URLs to passed to the untrusted helper
-
virtual std::shared_ptr<Instance>
launch
(MirPromptSession *session, std::vector<URL> urls = {}) = 0¶ Launch an instance of a helper that is run in a Mir Trusted Prompt session. The session should be created by the trusted helper using the Mir function
mir_connection_create_prompt_session_sync()
.- Parameters
session
: Mir trusted prompt sessionurls
: List of URLs to passed to the untrusted helper
-
virtual bool
Registry¶
-
class
ubuntu::app_launch::
Registry
¶ The application registry provides a central source for finding information about the applications in the system. This includes installed applications and running applications.
This class also holds onto shared resources for Ubuntu App Launch objects and functions. Generally speaking, there should only be one of them in the process. There are singleton functions, getDefault() and clearDefault(), which can be used to port applications from the old C API to the new C++ one but their use is discouraged.
Public Types
Public Functions
-
Registry
()¶
-
~Registry
()¶
-
void
clearManager
()¶ Remove the current manager on the registry
Public Static Functions
List the applications that are currently running, each will have a valid Application::Instance at call time, but that could change as soon as the call occurs.
- Parameters
registry
: Shared registry for the tracking
List all of the applications that are currently installed on the system. Queries the various packaging schemes that are supported to get thier list of applications.
- Parameters
registry
: Shared registry for the tracking
Get the signal object that is signaled when an application has been started.
- Note
- This signal handler is activated on the UAL thread
- Parameters
reg
: Registry to get the handler from
Get the signal object that is signaled when an application has stopped.
- Note
- This signal handler is activated on the UAL thread
- Parameters
reg
: Registry to get the handler from
Get the signal object that is signaled when an application has failed.
- Note
- This signal handler is activated on the UAL thread
- Parameters
reg
: Registry to get the handler from
Get the signal object that is signaled when an application has been paused.
- Note
- This signal handler is activated on the UAL thread
- Parameters
reg
: Registry to get the handler from
Get the signal object that is signaled when an application has been resumed.
- Note
- This signal handler is activated on the UAL thread
- Parameters
reg
: Registry to get the handler from
Get the signal object that is signaled when an application’s info has been updated.
- Note
- This signal handler is activated on the UAL thread
- Parameters
reg
: Registry to get the handler from
Set the manager of applications, which gives permissions for them to start and gain focus. In almost all cases this should be Unity8 as it will be controlling applications.
This function will failure if there is already a manager set.
Get a list of all the helpers for a given helper type
- Parameters
type
: Helper type stringregistry
: Shared registry for the tracking
Get the signal object that is signaled when helper has been started.
Get the signal object that is signaled when a helper has stopped.
Get the signal object that is signaled when a helper has failed.
-
std::shared_ptr<Registry>
getDefault
()¶ Use the Registry as a global singleton, this function will create a Registry object if one doesn’t exist. Use of this function is discouraged.
-
void
clearDefault
()¶ Clear the default. If you’re using the singleton interface in the Registry::getDefault() function you should call this as your service and/or tests exit to ensure you don’t get Valgrind errors.
-
class
Manager
¶ The Application Manager, almost always if you’re not Unity8, don’t use this API. Testing is a special case. Subclass this interface and implement these functions.
Each function here is being passed a function object that takes a boolean to reply. This will accept or reject the request. The function object can be copied to another thread and executed if needed.
The reply is required for the application to start. It will block (not currently implemented) until approval is given. If there are multiple requests sent they may be replied out of order if desired.
Public Functions
Application wishes to startup
- Note
- This signal handler is activated on the UAL thread
- Parameters
app
: Application requesting startupinstance
: Instance of the app, always valid but not useful unless mulit-instance app.reply
: Function object to reply if it is allowed to start
Application wishes to have focus. Usually this occurs when a URL for the application is activated and the running app is requested.
- Note
- This signal handler is activated on the UAL thread
- Parameters
app
: Application requesting focusinstance
: Instance of the app, always valid but not useful unless mulit-instance app.reply
: Function object to reply if it is allowed to focus
Application wishes to resume. Usually this occurs when a URL for the application is activated and the running app is requested.
- Note
- This signal handler is activated on the UAL thread
- Parameters
app
: Application requesting resumeinstance
: Instance of the app, always valid but not useful unless mulit-instance app.reply
: Function object to reply if it is allowed to resume
-
Implementation Details¶
Application Implementation Base¶
-
class
ubuntu::app_launch::app_impls::
Base
¶ Provides some helper functions that can be used by all implementations of application. Stores the registry pointer which everyone wants anyway.
Inherits from ubuntu::app_launch::Application
Subclassed by ubuntu::app_launch::app_impls::Legacy, ubuntu::app_launch::app_impls::Libertine, ubuntu::app_launch::app_impls::Snap
Public Functions
-
~Base
()¶
-
bool
hasInstances
()¶ A quick check to see if this application has any running instances
Generates an instance string based on the clock if we’re a multi-instance application.
-
virtual std::shared_ptr<Application::Instance>
findInstance
(const std::string &instanceid) = 0¶
-
std::shared_ptr<Application::Instance>
findInstance
(const pid_t &pid)¶ Get a a pointer to the running instances of this application based on the pid
- Parameters
pid
: The pid to find the instance of
Protected Attributes
Protected Static Functions
-
std::list<std::pair<std::string, std::string>>
confinedEnv
(const std::string &package, const std::string &pkgdir)¶ Function to create all the standard environment variables that we’re building for everyone. Mostly stuff involving paths.
- Parameters
package
: Name of the packagepkgdir
: Directory that the package lives in
-
Application Implementation Legacy¶
-
class
ubuntu::app_launch::app_impls::
Legacy
¶ Application Implementation for Legacy applications. These are applications that are typically installed as Debian packages on the base system. The standard place for them to put their desktop files is in /usr/share/applications though other directories may be used by setting the appropriate XDG environment variables. This implementation makes use of the GIO Desktop Appinfo functions which do caching of those files to make access faster.
AppIDs for legacy applications only include the Appname variable. Both the package and the version entries are empty strings. The appname variable is the filename of the desktop file describing the application with the ”.desktop” suffix.
More info: https://specifications.freedesktop.org/desktop-entry-spec/latest/
Inherits from ubuntu::app_launch::app_impls::Base
Public Functions
-
AppID
appId
()¶ Get the Application ID of this Application
-
std::shared_ptr<Application::Info>
info
()¶ Get a Application::Info object to describe the metadata for this application
-
std::vector<std::shared_ptr<Application::Instance>>
instances
()¶ Get a vector of the running instances of this application
-
std::shared_ptr<Application::Instance>
launch
(const std::vector<Application::URL> &urls = {})¶ Create an UpstartInstance for this AppID using the UpstartInstance launch function.
- Parameters
urls
: URLs to pass to the application
-
std::shared_ptr<Application::Instance>
launchTest
(const std::vector<Application::URL> &urls = {})¶ Create an UpstartInstance for this AppID using the UpstartInstance launch function with a testing environment.
- Parameters
urls
: URLs to pass to the application
-
std::shared_ptr<Application::Instance>
findInstance
(const std::string &instanceid)¶
Private Functions
-
std::list<std::pair<std::string, std::string>>
launchEnv
(const std::string &instance)¶ Grabs all the environment for a legacy app. Mostly this consists of the exec line and whether it needs XMir. Also we set the path if that is specified in the desktop file. We can also set an AppArmor profile if requested.
-
AppID
Application Implementation Libertine¶
-
class
ubuntu::app_launch::app_impls::
Libertine
¶ Application Implmentation for the Libertine container system. Libertine sets up containers that are read/write on a read only system, to all for more dynamic packaging systems (like deb) to work. This provides some compatibility for older applications or those who are only distributed in packaging systems requiring full system access.
Application IDs for Libertine applications have the package field as the name of the container. The appname is similar to that of the Legacy() implementation as the filename of the desktop file defining the application without the ”.desktop” suffix. UAL has no way to know the version, so it is always hard coded to “0.0”.
Libertine applications always are setup with XMir and started using the libertine-launch utility which configures the environment for the container.
More info: https://wiki.ubuntu.com/Touch/Libertine
Inherits from ubuntu::app_launch::app_impls::Base
Public Functions
-
AppID
appId
()¶ Get the Application ID of this Application
-
std::shared_ptr<Application::Info>
info
()¶ Get a Application::Info object to describe the metadata for this application
-
std::vector<std::shared_ptr<Application::Instance>>
instances
()¶ Get a vector of the running instances of this application
-
std::shared_ptr<Application::Instance>
launch
(const std::vector<Application::URL> &urls = {})¶
-
std::shared_ptr<Application::Instance>
launchTest
(const std::vector<Application::URL> &urls = {})¶
-
std::shared_ptr<Application::Instance>
findInstance
(const std::string &instanceid)¶
Private Functions
-
std::list<std::pair<std::string, std::string>>
launchEnv
()¶ Grabs all the environment variables for the application to launch in. It sets up the confinement ones and then adds in the APP_EXEC line and whether to use XMir.
This function adds ‘libertine-launch’ at the beginning of the Exec line with the container name as a parameter. The command can be overridden with the UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH environment variable.
-
AppID
Application Implementation Snappy¶
-
class
ubuntu::app_launch::app_impls::
Snap
¶ Class implementing a Applications that are installed in the system as Snaps. This class connects to snapd to get information on the interfaces of the installed snaps and sees if any of them are applicable to the user session. Currently that means if the command has the mir, unity8, unity7 or x11 interfaces.
For Application IDs snaps use a very similar scheme to Click packages. The package field is the name of the snap package, typically this is the overall application name. The appname is the command in the snap package, which needs to be associated with one of our supported interfaces and have a desktop file. Lastly the version field is actually the snap revision, this value changes even on updates between channels of the same version so it provides a greater amount of uniqueness.
Inherits from ubuntu::app_launch::app_impls::Base
Public Types
-
typedef std::tuple<app_info::Desktop::XMirEnable, Application::Info::UbuntuLifecycle>
InterfaceInfo
¶
Public Functions
Uses the findInterfaceInfo() function to find the interface if we don’t have one.
- Parameters
appid
: Application ID of the snapregistry
: Registry to use for persistent connections
Creates a Snap application object. Will throw exceptions if the AppID doesn’t resolve into a valid package or that package doesn’t have a desktop file that matches the app name.
- Parameters
appid
: Application ID of the snapregistry
: Registry to use for persistent connectionsinterfaceInfo
: Metadata gleaned from the snap’s interfaces
-
std::shared_ptr<Application::Info>
info
()¶ Returns a reference to the info for the snap
-
std::vector<std::shared_ptr<Application::Instance>>
instances
()¶ Get all of the instances of this snap package that are running
-
std::shared_ptr<Application::Instance>
launch
(const std::vector<Application::URL> &urls = {})¶ Create a new instance of this Snap
- Parameters
urls
: URLs to pass to the command
-
std::shared_ptr<Application::Instance>
launchTest
(const std::vector<Application::URL> &urls = {})¶ Create a new instance of this Snap with a testing environment setup for it.
- Parameters
urls
: URLs to pass to the command
-
std::shared_ptr<Application::Instance>
findInstance
(const std::string &instanceid)¶
Public Static Functions
Asks Snapd for the interfaces to determine which ones the application can support.
- Parameters
appid
: Application ID of the snapregistry
: Registry to use for persistent connections
Checks a PkgInfo structure to ensure that it matches the AppID
Private Functions
-
typedef std::tuple<app_info::Desktop::XMirEnable, Application::Info::UbuntuLifecycle>
Application Info Desktop¶
-
class
ubuntu::app_launch::app_info::
Desktop
¶ Inherits from ubuntu::app_launch::Application::Info
Subclassed by ubuntu::app_launch::app_impls::SnapInfo
Public Types
-
typedef TypeTagger<XMirEnableTag, bool>
XMirEnable
¶
-
typedef TypeTagger<ExecTag, std::string>
Exec
¶
-
typedef TypeTagger<SingleInstanceTag, bool>
SingleInstance
¶
Public Functions
-
const Application::Info::Name &
name
()¶ Name of the application
-
const Application::Info::Description &
description
()¶ Textual description of the application
-
const Application::Info::IconPath &
iconPath
()¶ Path to the icon that represents the application
-
const Application::Info::DefaultDepartment &
defaultDepartment
()¶ Default department of the application
-
const Application::Info::IconPath &
screenshotPath
()¶ Path to the screenshot of the application
-
const Application::Info::Keywords &
keywords
()¶ List of keywords for the application
-
const Application::Info::Popularity &
popularity
()¶ Get the relative popularity of the application, 0 is not popular
-
Application::Info::Splash
splash
()¶ Get information for the splash screen
-
Application::Info::Orientations
supportedOrientations
()¶ Return which orientations are supported
-
Application::Info::RotatesWindow
rotatesWindowContents
()¶ Return whether the window contents can be rotated or not
-
Application::Info::UbuntuLifecycle
supportsUbuntuLifecycle
()¶
-
virtual XMirEnable
xMirEnable
()¶
-
virtual SingleInstance
singleInstance
()¶
Protected Attributes
-
std::shared_ptr<GKeyFile>
_keyfile
¶
-
std::string
_basePath
¶
-
std::string
_rootDir
¶
-
Application::Info::Name
_name
¶
-
Application::Info::Description
_description
¶
-
Application::Info::IconPath
_iconPath
¶
-
Application::Info::DefaultDepartment
_defaultDepartment
¶
-
Application::Info::IconPath
_screenshotPath
¶
-
Application::Info::Keywords
_keywords
¶
-
Application::Info::Popularity
_popularity
¶
-
Application::Info::Splash
_splashInfo
¶
-
Application::Info::Orientations
_supportedOrientations
¶
-
Application::Info::RotatesWindow
_rotatesWindow
¶
-
Application::Info::UbuntuLifecycle
_ubuntuLifecycle
¶
-
XMirEnable
_xMirEnable
¶
-
SingleInstance
_singleInstance
¶
-
typedef TypeTagger<XMirEnableTag, bool>
Application Info Snap¶
-
class
ubuntu::app_launch::app_impls::
SnapInfo
¶ Subclassing the desktop info object so that we can override a couple of properties with interface definitions. This may grow as we add more fields to the desktop spec that come from Snappy interfaces.
Inherits from ubuntu::app_launch::app_info::Desktop
Public Functions
-
Exec
execLine
()¶ Figures out the exec line for a snappy command. We’re not using the Exec in the desktop file exactly, but assuming that it is kinda what we want to be run. So we’re replacing that with the script, which we have to use as we can’t get the command that is in the snap metadata as Snapd won’t give it to us. So we’re parsing the Exec line and replacing the first entry. Then putting it back together again.
-
Exec
Application Icon Finder¶
-
class
ubuntu::app_launch::
IconFinder
¶ Class to search for available application icons and select the best option.
This object attempts to find the highest resolution icon based on the freedesktop icon theme specification found at: https://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html It parses the theme file for the hicolor theme and identifies all possible directories in the global scope and the local scope.
Public Functions
-
IconFinder
(std::string basePath)¶ Create an IconFinder
- Parameters
basePath
: the root directory to begin searching for themes
-
virtual
~IconFinder
()¶
-
Application::Info::IconPath
find
(const std::string &iconName)¶ Find the optimal icon for the given icon name.
Finds an icon in the search paths that we have for this path
- Parameters
iconName
: name of or path to application icon
Private Static Functions
-
bool
hasImageExtension
(const char *filename)¶ Check to see if this is an icon name or an icon filename
-
std::string
findExistingIcon
(const std::string &path, const std::string &iconName)¶ Check in a given path if there is an existing file in it that satifies our name
-
std::list<IconFinder::ThemeSubdirectory>
validDirectories
(const std::string &themePath, gchar *directory, int size)¶ Create a directory item if the directory exists
Take the data in a directory stanza and turn it into an actual directory
Parse a theme file’s various stanzas for each directory
-
std::list<IconFinder::ThemeSubdirectory>
themeFileSearchPaths
(const std::string &themePath)¶ Try to get theme subdirectories using .theme file in the given theme path if it exists
-
std::list<IconFinder::ThemeSubdirectory>
themeDirSearchPaths
(const std::string &basePath)¶ Look into a theme directory and see if we can use the subdirectories as icon folders. This is a fallback, and is sadly inefficient.
-
std::list<IconFinder::ThemeSubdirectory>
iconsFromThemePath
(const gchar *themeDir)¶ Gets all search paths from a given theme directory via theme file or manually scanning the directory.
-
std::list<IconFinder::ThemeSubdirectory>
getSearchPaths
(const std::string &basePath)¶ Gets search paths based on common icon directories including themes and pixmaps.
-
struct
ThemeSubdirectory
¶
-
Application Storage Base¶
-
class
ubuntu::app_launch::app_store::
Base
¶ Inherits from ubuntu::app_launch::info_watcher::Base
Subclassed by ubuntu::app_launch::app_store::Legacy, ubuntu::app_launch::app_store::Libertine, ubuntu::app_launch::app_store::Snap
Application Storage Legacy¶
-
class
ubuntu::app_launch::app_store::
Legacy
¶ Inherits from ubuntu::app_launch::app_store::Base
Public Functions
-
Legacy
()¶
-
~Legacy
()¶
Ensure the package is empty
- Parameters
package
: Container nameregistry
: persistent connections to use
Looks for an application by looking through the system and user application directories to find the desktop file.
- Parameters
package
: Container nameappname
: Application name to look forregistry
: persistent connections to use
We don’t really have a way to implement this for Legacy, any search wouldn’t really make sense. We just throw an error.
- Parameters
package
: Container namecard
: Application search pathsregistry
: persistent connections to use
Function to return an empty string
- Parameters
package
: Container name (unused)appname
: Application name (unused)registry
: persistent connections to use (unused)
Checks the AppID by ensuring the version and package are empty then looks for the application.
- Parameters
appid
: AppID to checkregistry
: persistent connections to use
-
Application Storage Libertine¶
-
class
ubuntu::app_launch::app_store::
Libertine
¶ Inherits from ubuntu::app_launch::app_store::Base
Public Functions
-
Libertine
()¶
-
~Libertine
()¶
Verify a package name by getting the list of containers from liblibertine and ensuring it is in that list.
- Parameters
package
: Container nameregistry
: persistent connections to use
Gets the list of applications from the container using liblibertine and see if is in that list.
- Parameters
package
: Container nameappname
: Application name to look forregistry
: persistent connections to use
We don’t really have a way to implement this for Libertine, any search wouldn’t really make sense. We just throw an error.
- Parameters
package
: Container namecard
: Application search pathsregistry
: persistent connections to use
Function to return “0.0”
- Parameters
package
: Container name (unused)appname
: Application name (unused)registry
: persistent connections to use (unused)
Checks the AppID by making sure the version is “0.0” and then calling verifyAppname() to check the rest.
- Parameters
appid
: AppID to checkregistry
: persistent connections to use
-
Application Storage Snap¶
-
class
ubuntu::app_launch::app_store::
Snap
¶ Inherits from ubuntu::app_launch::app_store::Base
Public Functions
-
Snap
()¶
-
~Snap
()¶
Look to see if a package is a valid Snap package name
- Parameters
package
: Package nameregistry
: Registry to use for persistent connections
Look to see if an appname is a valid for a Snap package
- Parameters
package
: Package nameappname
: Command nameregistry
: Registry to use for persistent connections
Look for an application name on a Snap package based on a wildcard type.
- Parameters
package
: Package namecard
: Wildcard to use for finding the appnameregistry
: Registry to use for persistent connections
Look for a version of a Snap package
- Parameters
package
: Package nameappname
: Not used for snapsregistry
: Registry to use for persistent connections
Checks if an AppID could be a snap. Note it doesn’t look for a desktop file just the package, app and version. This is done to make the lookup quickly, as this function can be used to select which backend to use and we want to reject quickly.
- Parameters
appid
: Application ID of the snapregistry
: Registry to use for persistent connections
Lists all the Snappy apps that are using one of our supported interfaces. Also makes sure they’re valid.
- Parameters
registry
: Registry to use for persistent connections
-
Helper Implementation Base¶
-
class
ubuntu::app_launch::helper_impls::
Base
¶ Inherits from ubuntu::app_launch::Helper
Public Functions
-
bool
hasInstances
()¶ Check to see if there are any instances of this untrusted helper
-
std::vector<std::shared_ptr<Helper::Instance>>
instances
()¶ Get the list of instances of this helper
Private Functions
-
std::list<std::pair<std::string, std::string>>
defaultEnv
()¶ Sets up the executable environment variable based on the appid and the type of helper. We look for the exec-tool, but if we can’t find it we’re cool with that and we just execute the helper. If we do find an exec-tool we’ll use that to fill in the parameters. For legacy appid’s we’ll allow the exec-tool to set everything.
-
bool
Jobs Manager Base¶
-
class
ubuntu::app_launch::jobs::manager::
Base
¶ Subclassed by ubuntu::app_launch::jobs::manager::SystemD
Public Functions
-
~Base
()¶
-
virtual std::shared_ptr<Application::Instance>
launch
(const AppID &appId, const std::string &job, const std::string &instance, const std::vector<Application::URL> &urls, launchMode mode, std::function<std::list<std::pair<std::string, std::string>>(void)> &getenv) = 0¶
-
virtual std::shared_ptr<Application::Instance>
existing
(const AppID &appId, const std::string &job, const std::string &instance, const std::vector<Application::URL> &urls) = 0¶
-
std::list<std::shared_ptr<Application>>
runningApps
()¶ Get application objects for all of the applications based on the appids associated with the application jobs
-
std::list<std::shared_ptr<Helper>>
runningHelpers
(const Helper::Type &type)¶ Get application objects for all of the applications based on the appids associated with the application jobs
-
virtual std::list<std::string>
runningAppIds
(const std::list<std::string> &jobs) = 0¶
-
virtual std::vector<std::shared_ptr<instance::Base>>
instances
(const AppID &appID, const std::string &job) = 0¶
-
const std::list<std::string> &
getAllApplicationJobs
() const¶
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&> &
appStarted
()¶
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&> &
appStopped
()¶
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, Registry::FailureType> &
appFailed
()¶
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, const std::vector<pid_t>&> &
appPaused
()¶ Grab the signal object for application paused. If we’re not already listing for those signals this sets up a listener for them.
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, const std::vector<pid_t>&> &
appResumed
()¶ Grab the signal object for application resumed. If we’re not already listing for those signals this sets up a listener for them.
-
core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&> &
helperStarted
(Helper::Type type)¶
-
core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&> &
helperStopped
(Helper::Type type)¶
-
core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&, Registry::FailureType> &
helperFailed
(Helper::Type type)¶
-
virtual core::Signal<const std::string&, const std::string&, const std::string&> &
jobStarted
() = 0¶
-
virtual core::Signal<const std::string&, const std::string&, const std::string&> &
jobStopped
() = 0¶
-
virtual core::Signal<const std::string&, const std::string&, const std::string&, Registry::FailureType> &
jobFailed
() = 0¶
Set the manager for the registry. This includes tracking the pointer as well as setting up the signals to call back into the manager. The signals are only setup once per registry even if the manager is cleared and changed again. They will just be no-op’s in those cases.
-
void
clearManager
()¶ Clear the manager pointer
Public Static Functions
Should determine which jobs backend to use, but we only have one right now.
Protected Attributes
-
std::list<std::string>
allApplicationJobs_
¶ A set of all the job names used by applications
-
std::shared_ptr<GDBusConnection>
dbus_
¶ The DBus connection we’re connecting to
-
std::shared_ptr<Registry::Manager>
manager_
¶ Application manager instance
Private Functions
Core handler for pause and resume events. Includes turning the GVariant pid list into a std::vector and getting the application object.
Private Members
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>
sig_appStarted
¶ Signal object for applications started
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>
sig_appStopped
¶ Signal object for applications stopped
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, Registry::FailureType>
sig_appFailed
¶ Signal object for applications failed
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, const std::vector<pid_t>&>
sig_appPaused
¶ Signal object for applications paused
-
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, const std::vector<pid_t>&>
sig_appResumed
¶ Signal object for applications resumed
-
std::map<std::string, std::shared_ptr<core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&>>>
sig_helpersStarted
¶
-
std::map<std::string, std::shared_ptr<core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&>>>
sig_helpersStopped
¶
-
std::map<std::string, std::shared_ptr<core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&, Registry::FailureType>>>
sig_helpersFailed
¶
-
ManagedDBusSignalConnection
handle_managerSignalFocus
= { DBusSignalUnsubscriber{}}¶ GDBus signal watcher handle for app focused signal
-
ManagedDBusSignalConnection
handle_managerSignalResume
= { DBusSignalUnsubscriber{}}¶ GDBus signal watcher handle for app resumed signal
-
ManagedDBusSignalConnection
handle_managerSignalStarting
= { DBusSignalUnsubscriber{}}¶ GDBus signal watcher handle for app starting signal
-
ManagedDBusSignalConnection
handle_appPaused
= { DBusSignalUnsubscriber{}}¶ GDBus signal watcher handle for app paused signal
-
ManagedDBusSignalConnection
handle_appResumed
= { DBusSignalUnsubscriber{}}¶ GDBus signal watcher handle for app resumed signal
-
std::once_flag
flag_managerSignals
¶ Variable to track to see if signal handlers are installed for the manager signals of focused, resumed and starting
-
std::once_flag
flag_appStarted
¶ Variable to track to see if signal handlers are installed for application started
-
std::once_flag
flag_appStopped
¶ Variable to track to see if signal handlers are installed for application stopped
-
std::once_flag
flag_appFailed
¶ Variable to track to see if signal handlers are installed for application failed
-
std::once_flag
flag_appPaused
¶ Variable to track to see if signal handlers are installed for application paused
-
std::once_flag
flag_appResumed
¶ Variable to track to see if signal handlers are installed for application resumed
Private Static Functions
Take the GVariant of parameters and turn them into an application and and instance. Easier to read in the smaller function
Register for a signal for the manager. All of the signals needed this same code so it got pulled out into a function. Takes the same of the signal, the registry that we’re using and a function to call after we’ve messaged all the parameters into being something C++-ish.
-
Jobs Instance Base¶
-
class
ubuntu::app_launch::jobs::instance::
Base
¶ Inherits from ubuntu::app_launch::Application::Instance
Subclassed by ubuntu::app_launch::jobs::instance::SystemD
Public Functions
-
virtual
~Base
()¶
-
bool
isRunning
()¶ Checks to see if we have a primary PID for the instance
-
bool
hasPid
(pid_t pid)¶ Looks at the PIDs in the instance cgroup and checks to see if is in the set.
- Parameters
pid
: PID to look for
-
void
pause
()¶ Pauses this application by sending SIGSTOP to all the PIDs in the cgroup and tells Zeitgeist that we’ve left the application.
-
void
resume
()¶ Resumes this application by sending SIGCONT to all the PIDs in the cgroup and tells Zeitgeist that we’re accessing the application.
-
void
focus
()¶ Focuses this application by sending SIGCONT to all the PIDs in the cgroup and tells the Shell to focus the application.
-
const std::string &
getInstanceId
()¶
-
void
setOomAdjustment
(const oom::Score score)¶ Sets the OOM adjustment by getting the list of PIDs and writing the value to each of their files in proc
- Parameters
score
: OOM Score to set
-
const oom::Score
getOomAdjustment
()¶ Figures out the path to the primary PID of the application and then reads its OOM adjustment file.
Protected Functions
-
std::vector<pid_t>
forAllPids
(std::function<void(pid_t)> eachPid)¶ Go through the list of PIDs calling a function and handling the issue with getting PIDs being a racey condition.
- Parameters
eachPid
: Function to run on each PID
Protected Attributes
-
const AppID
appId_
¶ Application ID
-
const std::string
job_
¶ Upstart job name
-
const std::string
instance_
¶ Instance ID environment value, empty if none
-
std::vector<Application::URL>
urls_
¶ The URLs that this was launched for. Only valid on launched jobs, we should look at perhaps changing that.
Protected Static Functions
Send a signal that we’ve change the application. Do this on the registry thread in an idle so that we don’t block anyone.
- Parameters
pids
: List of PIDs to turn into variants to sendsignal
: Name of the DBus signal to send
-
void
signalToPid
(pid_t pid, int signal)¶ Sends a signal to a PID with a warning if we can’t send it. We could throw an exception, but we can’t handle it usefully anyway
- Parameters
pid
: PID to send the signal tosignal
: signal to send
-
void
oomValueToPid
(pid_t pid, const oom::Score oomvalue)¶ Writes an OOM value to proc, assuming we have a string in the outer loop
- Parameters
pid
: PID to change the OOM value ofoomvalue
: OOM value to set
-
void
oomValueToPidHelper
(pid_t pid, const oom::Score oomvalue)¶ Use a setuid root helper for setting the oom value of Chromium instances
- Parameters
pid
: PID to change the OOM value ofoomvalue
: OOM value to set
-
std::string
pidToOomPath
(pid_t pid)¶ Get the path to the PID’s OOM adjust path, with allowing for an override for testing using the environment variable UBUNTU_APP_LAUNCH_OOM_PROC_PATH
- Parameters
pid
: PID to build path for
-
GCharVUPtr
urlsToStrv
(const std::vector<Application::URL> &urls)¶ Reformat a C++ vector of URLs into a C GStrv of strings
- Parameters
urls
: Vector of URLs to make into C strings
-
virtual
Registry Implementation¶
-
class
ubuntu::app_launch::Registry::
Impl
¶ Private implementation of the Registry object.
Public Functions
-
virtual
~Impl
()¶
-
void
clearManager
()¶
-
std::shared_ptr<IconFinder>
getIconFinder
(std::string basePath)¶
-
void
zgSendEvent
(AppID appid, const std::string &eventtype)¶ Send an event to Zietgeist using the registry thread so that the callback comes back in the right place.
-
const std::string &
oomHelper
() const¶
Public Members
-
GLib::ContextThread
thread
¶ Shared context thread for events and background tasks that UAL subtasks are doing
-
std::shared_ptr<GDBusConnection>
_dbus
¶ DBus shared connection for the session bus
Public Static Functions
Helper function for printing JSON objects to debug output
Helper function for printing JSON nodes to debug output
-
void
watchingAppStarting
(bool rWatching)¶ Variable to track if this program is watching app startup so that we can know to not wait on the response to that.
-
bool
isWatchingAppStarting
()¶ Accessor for the internal variable to know whether an app is watching for app startup
Protected Attributes
-
std::shared_ptr<info_watcher::Zeitgeist>
zgWatcher_
¶ ZG Info Watcher
-
std::once_flag
zgWatcherOnce_
¶ Init checker for ZG Watcher
Private Members
-
std::shared_ptr<ZeitgeistLog>
zgLog_
¶ Shared instance of the Zeitgeist Log
-
std::unordered_map<std::string, std::shared_ptr<IconFinder>>
_iconFinders
¶ All of our icon finders based on the path that they’re looking into
-
std::list<std::shared_ptr<app_store::Base>>
_appStores
¶ Application stores
-
core::Signal<const std::shared_ptr<Application>&>
sig_appInfoUpdated
¶ Signal for application info changing
-
std::once_flag
flag_appInfoUpdated
¶ Flag to see if we’ve initialized the info watcher list
-
std::list<std::pair<std::shared_ptr<info_watcher::Base>, core::ScopedConnection>>
infoWatchers_
¶ List of info watchers along with a signal handle to our connection to their update signal
-
virtual
Snapd Info¶
-
class
ubuntu::app_launch::snapd::
Info
¶ Class that implements the connection to Snapd allowing us to get info from it in a C++ friendly way.
Public Functions
-
Info
()¶ Initializes the info object which mostly means checking what is overridden by environment variables (mostly for testing) and making sure there is a snapd socket available to us.
-
virtual
~Info
()¶
-
std::shared_ptr<Info::PkgInfo>
pkgInfo
(const AppID::Package &package) const¶ Gets package information out of snapd by using the REST interface and turning the JSON object into a C++ Struct
- Parameters
package
: Name of the package to look for
Private Functions
-
std::shared_ptr<JsonNode>
snapdJson
(const std::string &endpoint) const¶ Asks the snapd process for some JSON. This function parses the basic response JSON that snapd returns and will error if a return code error is in the JSON. It then passes on the “result” part of the response to the caller.
- Parameters
endpoint
: End of the URL to pass to snapd
-
void
forAllPlugs
(std::function<void(JsonObject *plugobj)> plugfunc) const¶ Looks through all the plugs in the interfaces and runs a function based on them. Avoids pulling objects out of the parsed JSON structure from Snappy and making sure they have the same lifecycle as the parser object which seems to destroy them when it dies.
- Parameters
plugfunc
: Function to execute on each plug
Private Members
-
std::string
snapdSocket
¶ Path to the socket of snapd
-
std::string
snapBasedir
¶ Directory to use as the base for all snap packages when making paths. This can be overridden with UBUNTU_APP_LAUNCH_SNAP_BASEDIR
-
bool
snapdExists
= false¶ Result of a check at init to see if the socket is available. If not all functions will return null results.
-
struct
PkgInfo
¶ Information that we can get from snapd about a package
Public Members
-
std::string
name
¶ Name of the package
-
std::string
version
¶ Version string provided by the package
-
std::string
revision
¶ Numerical always incrementing revision of the package
-
std::string
directory
¶ Directory that the snap is uncompressed into
-
std::set<std::string>
appnames
¶ List of appnames in the snap
-
std::string
-
Type Tagger¶
- template <typename Tag, typename T>
-
class
ubuntu::app_launch::
TypeTagger
¶ A small template to make it clearer when special types are being used.
The TypeTagger a small piece of C++ so that we can have custom types for things in the Ubuntu App Launch API that should be handled in special ways, but really have basic types at their core. In this way there is explicit code to convert these items into their fundamental type so that is obvious and can be easily searched for.
Public Functions
-
const T &
value
() const¶ Getter to get the fundamental type out of the TypeTagger wrapper
-
operator T
() const¶ Getter to get the fundamental type out of the TypeTagger wrapper
-
bool
operator==
(const TypeTagger<Tag, T> &b) const¶
-
bool
operator==
(const T &b) const¶
-
~TypeTagger
()¶
Public Static Functions
-
static TypeTagger<Tag, T>
from_raw
(const T &value)¶ Function to build a TypeTagger object from a fundamental type
Private Functions
-
TypeTagger
(const T &value)¶ Private constructor used by from_raw()
Private Members
-
T
_value
¶ The memory allocation for the fundamental type
-
const T &
Quality¶
Merge Requirements¶
This documents the expections that the project has on what both submitters and reviewers should ensure that they’ve done for a merge into the project.
Submitter Responsibilities¶
- Ensure the project compiles and the test suite executes without error
- Ensure that non-obvious code has comments explaining it
Reviewer Responsibilities¶
- Did the Jenkins build compile? Pass? Run unit tests successfully?
- Are there appropriate tests to cover any new functionality?
- If this MR effects application startup:
- Run test case: ubuntu-app-launch/click-app
- Run test case: ubuntu-app-launch/legacy-app
- Run test case: ubuntu-app-launch/secondary-activation
- If this MR effect untrusted-helpers:
- Run test case: ubuntu-app-launch/helper-run