feat: add app extra/unset env config
to fix #8667 you can - subpath:"/FoxitReader" appExtraEnvironments : "QT_QPA_PLATFORM=xcb" - subpath:"/FoxitReader" appEnvironmentsBlacklist : "QT_QPA_PLATFORM" ``` dde-dconfig set -a org.deepin.dde.application-manager -r org.deepin.dde.application-manager -k appExtraEnvironments -s "/FoxitReader" -v "[\"QT_QPA_PLATFORM=xcb\"]" dde-dconfig set -a org.deepin.dde.application-manager -r org.deepin.dde.application-manager -k appEnvironmentsBlacklist -s "/FoxitReader" -v "[\"QT_QPA_PLATFORM\"]" ``` Issue: https://github.com/linuxdeepin/developer-center/issues/8667
This commit is contained in:
parent
006f80d681
commit
50a0ad53ec
@ -138,10 +138,13 @@
|
||||
1. `uid` (type u):
|
||||
The user id as who is that application will be run.
|
||||
This option might request a polikit authentication.
|
||||
2. `env` (type s):
|
||||
2. `env` (type as):
|
||||
passing some specific environment variables to Launch
|
||||
this application, eg. 'LANG=en_US;PATH=xxx:yyy;'
|
||||
3. `path` (type s):
|
||||
this application without them, eg. '[LANG=en_US, PATH=xxx:yyy]'
|
||||
3. `unsetEnv` (type as):
|
||||
passed environment variables will be ignored when
|
||||
launching this application, eg. '[LANG, PATH]'
|
||||
4. `path` (type s):
|
||||
set this application's working directory, please pass
|
||||
absolute directory path.
|
||||
NOTE:
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <thread>
|
||||
#include "constant.h"
|
||||
#include "types.h"
|
||||
@ -140,6 +141,7 @@ int processExecStart(msg_ptr &msg, const std::deque<std::string_view> &execArgs)
|
||||
DBusValueType getPropType(std::string_view key)
|
||||
{
|
||||
static std::unordered_map<std::string_view, DBusValueType> map{{"Environment", DBusValueType::ArrayOfString},
|
||||
{"UnsetEnvironment", DBusValueType::ArrayOfString},
|
||||
{"WorkingDirectory", DBusValueType::String},
|
||||
{"ExecSearchPath", DBusValueType::ArrayOfString}};
|
||||
|
||||
@ -150,7 +152,7 @@ DBusValueType getPropType(std::string_view key)
|
||||
return DBusValueType::String; // fallback to string
|
||||
}
|
||||
|
||||
int appendPropValue(msg_ptr &msg, DBusValueType type, std::string_view value)
|
||||
int appendPropValue(msg_ptr &msg, DBusValueType type, const std::list<std::string_view> &value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -165,9 +167,11 @@ int appendPropValue(msg_ptr &msg, DBusValueType type, std::string_view value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret = handler->appendValue(std::string{value}); ret < 0) {
|
||||
sd_journal_perror("append property's variant value failed.");
|
||||
return ret;
|
||||
for (const auto &v : value) {
|
||||
if (ret = handler->appendValue(std::string{v}); ret < 0) {
|
||||
sd_journal_perror("append property's variant value failed.");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret = handler->closeVariant(); ret < 0) {
|
||||
@ -178,13 +182,12 @@ int appendPropValue(msg_ptr &msg, DBusValueType type, std::string_view value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int processKVPair(msg_ptr &msg, const std::map<std::string_view, std::string_view> &props)
|
||||
int processKVPair(msg_ptr &msg, const std::map<std::string_view, std::list<std::string_view>> &props)
|
||||
{
|
||||
int ret;
|
||||
if (!props.empty()) {
|
||||
for (auto [key, value] : props) {
|
||||
std::string keyStr{key};
|
||||
std::string valueStr{value};
|
||||
if (ret = sd_bus_message_open_container(msg, SD_BUS_TYPE_STRUCT, "sv"); ret < 0) {
|
||||
sd_journal_perror("open struct of properties failed.");
|
||||
return ret;
|
||||
@ -195,7 +198,7 @@ int processKVPair(msg_ptr &msg, const std::map<std::string_view, std::string_vie
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret = appendPropValue(msg, getPropType(key), valueStr); ret < 0) {
|
||||
if (ret = appendPropValue(msg, getPropType(key), value); ret < 0) {
|
||||
sd_journal_perror("append value of property failed.");
|
||||
return ret;
|
||||
}
|
||||
@ -212,7 +215,7 @@ int processKVPair(msg_ptr &msg, const std::map<std::string_view, std::string_vie
|
||||
std::string cmdParse(msg_ptr &msg, std::deque<std::string_view> cmdLines)
|
||||
{
|
||||
std::string serviceName{"internalError"};
|
||||
std::map<std::string_view, std::string_view> props;
|
||||
std::map<std::string_view, std::list<std::string_view>> props;
|
||||
while (!cmdLines.empty()) { // NOTE: avoid stl exception
|
||||
auto str = cmdLines.front();
|
||||
if (str.size() < 2) {
|
||||
@ -249,7 +252,7 @@ std::string cmdParse(msg_ptr &msg, std::deque<std::string_view> cmdLines)
|
||||
cmdLines.pop_front();
|
||||
continue;
|
||||
}
|
||||
props[key] = kvStr.substr(splitIndex + 1);
|
||||
props[key].push_back(kvStr.substr(splitIndex + 1));
|
||||
cmdLines.pop_front();
|
||||
continue;
|
||||
}
|
||||
@ -265,18 +268,19 @@ std::string cmdParse(msg_ptr &msg, std::deque<std::string_view> cmdLines)
|
||||
serviceName = "invalidInput";
|
||||
return serviceName;
|
||||
}
|
||||
int ret;
|
||||
if (props.find("unitName") == props.cend()) {
|
||||
sd_journal_perror("unitName doesn't exists.");
|
||||
serviceName = "invalidInput";
|
||||
return serviceName;
|
||||
}
|
||||
if (ret = sd_bus_message_append(msg, "s", props["unitName"].data()); ret < 0) { // unitName
|
||||
|
||||
int ret;
|
||||
if (ret = sd_bus_message_append(msg, "s", props["unitName"].front().data()); ret < 0) { // unitName
|
||||
sd_journal_perror("append unitName failed.");
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
serviceName = props["unitName"];
|
||||
serviceName = props["unitName"].front();
|
||||
props.erase("unitName");
|
||||
|
||||
if (ret = sd_bus_message_append(msg, "s", "replace"); ret < 0) { // start mode
|
||||
|
@ -3,6 +3,7 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "variantValue.h"
|
||||
#include "constant.h"
|
||||
#include <sstream>
|
||||
|
||||
std::unique_ptr<VariantValue> creatValueHandler(msg_ptr &msg, DBusValueType type)
|
||||
@ -34,29 +35,21 @@ int StringValue::appendValue(std::string &&value) noexcept
|
||||
|
||||
int ASValue::openVariant() noexcept
|
||||
{
|
||||
return sd_bus_message_open_container(msgRef(), SD_BUS_TYPE_VARIANT, "as");
|
||||
if (int ret = sd_bus_message_open_container(msgRef(), SD_BUS_TYPE_VARIANT, "as"); ret < 0)
|
||||
return ret;
|
||||
|
||||
return sd_bus_message_open_container(msgRef(), SD_BUS_TYPE_ARRAY, "s");
|
||||
}
|
||||
|
||||
int ASValue::closeVariant() noexcept
|
||||
{
|
||||
if (int ret = sd_bus_message_close_container(msgRef()); ret < 0)
|
||||
return ret;
|
||||
|
||||
return sd_bus_message_close_container(msgRef());
|
||||
}
|
||||
|
||||
int ASValue::appendValue(std::string &&value) noexcept
|
||||
{
|
||||
std::string envs{std::move(value)};
|
||||
std::istringstream stream{envs};
|
||||
int ret{0};
|
||||
|
||||
if (ret = sd_bus_message_open_container(msgRef(), SD_BUS_TYPE_ARRAY, "s"); ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (std::string line; std::getline(stream, line, ';');) {
|
||||
if (ret = sd_bus_message_append(msgRef(), "s", line.data()); ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(msgRef());
|
||||
return sd_bus_message_append(msgRef(), "s", value.data());
|
||||
}
|
||||
|
@ -70,5 +70,7 @@ install(FILES ${CMAKE_CURRENT_LIST_DIR}/hooks.d/debFix.sh
|
||||
)
|
||||
|
||||
dtk_add_config_meta_files(APPID ${APPLICATION_SERVICEID}
|
||||
FILES ${CMAKE_CURRENT_LIST_DIR}/dsg/configs/dde-application-manager/org.deepin.dde.am.json
|
||||
FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/dsg/configs/dde-application-manager/org.deepin.dde.am.json
|
||||
${CMAKE_CURRENT_LIST_DIR}/dsg/configs/dde-application-manager/org.deepin.dde.application-manager.json
|
||||
)
|
||||
|
@ -0,0 +1,26 @@
|
||||
{
|
||||
"magic": "dsg.config.meta",
|
||||
"version": "1.0",
|
||||
"contents": {
|
||||
"appExtraEnvironments": {
|
||||
"value": [],
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Launching app with extra environments",
|
||||
"name[zh_CN]": "启动应用时附加额外环境变量",
|
||||
"description": "Launching app with extra environments",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "public"
|
||||
},
|
||||
"appEnvironmentsBlacklist": {
|
||||
"value": [],
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Ignore blacklisted environment variables before launching app",
|
||||
"name[zh_CN]": "启动应用时取消某些环境变量",
|
||||
"description": "Ignore blacklisted environment variables before launching app",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "public"
|
||||
}
|
||||
}
|
||||
}
|
@ -65,4 +65,8 @@ constexpr auto ApplicationManagerHookDir = u8"/deepin/dde-application-manager/ho
|
||||
|
||||
constexpr auto ApplicationManagerToolsConfig = u8"org.deepin.dde.am";
|
||||
|
||||
constexpr auto ApplicationManagerConfig = u8"org.deepin.dde.application-manager";
|
||||
constexpr auto AppExtraEnvironments = u8"appExtraEnvironments";
|
||||
constexpr auto AppEnvironmentsBlacklist = u8"appEnvironmentsBlacklist";
|
||||
|
||||
#endif
|
||||
|
@ -24,6 +24,7 @@ target_link_libraries(
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::DBus
|
||||
Qt${QT_VERSION_MAJOR}::Concurrent
|
||||
Dtk6::Core
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "launchoptions.h"
|
||||
#include "desktopentry.h"
|
||||
#include "desktopfileparser.h"
|
||||
#include "config.h"
|
||||
#include <QUuid>
|
||||
#include <QStringList>
|
||||
#include <QList>
|
||||
@ -31,22 +32,50 @@
|
||||
#include <qtmetamacros.h>
|
||||
#include <utility>
|
||||
#include <wordexp.h>
|
||||
#include <DConfig>
|
||||
|
||||
static inline void appendEnvs(const QVariant &var, QStringList &envs)
|
||||
{
|
||||
if (var.canConvert(QMetaType::QStringList)) {
|
||||
envs.append(var.value<QStringList>());
|
||||
} else if (var.canConvert(QMetaType::QString)) {
|
||||
envs.append(var.value<QString>().split(";", Qt::SkipEmptyParts));
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationService::appendExtraEnvironments(QVariantMap &runtimeOptions) const noexcept
|
||||
{
|
||||
QStringList envs;
|
||||
DCORE_USE_NAMESPACE
|
||||
QStringList envs, unsetEnvs;
|
||||
const QString &env = environ();
|
||||
if (!env.isEmpty())
|
||||
envs.append(env);
|
||||
|
||||
if (auto it = runtimeOptions.find("env"); it != runtimeOptions.cend()) {
|
||||
envs.append(it->value<QString>());
|
||||
appendEnvs(*it, envs);
|
||||
}
|
||||
|
||||
if (auto it = runtimeOptions.find("unsetEnv"); it != runtimeOptions.cend()) {
|
||||
appendEnvs(*it, unsetEnvs);
|
||||
}
|
||||
|
||||
std::unique_ptr<DConfig> config(DConfig::create(ApplicationServiceID, ApplicationManagerConfig,
|
||||
QString("/%1").arg((id())))); // $appid as subpath
|
||||
if (config->isValid()){
|
||||
const QStringList &extraEnvs = config->value(AppExtraEnvironments).toStringList();
|
||||
if (!extraEnvs.isEmpty())
|
||||
envs.append(extraEnvs);
|
||||
|
||||
const QStringList &envsBlacklist = config->value(AppEnvironmentsBlacklist).toStringList();
|
||||
if (!envsBlacklist.isEmpty())
|
||||
unsetEnvs.append(envsBlacklist);
|
||||
}
|
||||
|
||||
// it's useful for App to get itself AppId.
|
||||
envs.append(QString{"DSG_APP_ID=%1"}.arg(id()));
|
||||
|
||||
runtimeOptions.insert("env", envs.join(';'));
|
||||
runtimeOptions.insert("env", envs);
|
||||
runtimeOptions.insert("unsetEnv", unsetEnvs);
|
||||
}
|
||||
|
||||
ApplicationService::ApplicationService(DesktopFile source,
|
||||
|
@ -17,6 +17,8 @@ QStringList generateCommand(const QVariantMap &props) noexcept
|
||||
options.emplace_back(std::make_unique<setUserLaunchOption>(value));
|
||||
} else if (key == setEnvLaunchOption::key()) {
|
||||
options.emplace_back(std::make_unique<setEnvLaunchOption>(value));
|
||||
} else if (key == unsetEnvLaunchOption::key()) {
|
||||
options.emplace_back(std::make_unique<unsetEnvLaunchOption>(value));
|
||||
} else if (key == hookLaunchOption::key()) {
|
||||
options.emplace_back(std::make_unique<hookLaunchOption>(value));
|
||||
} else if (key == setWorkingPathLaunchOption::key()) {
|
||||
@ -100,16 +102,6 @@ QStringList splitLaunchOption::generateCommandLine() const noexcept
|
||||
return QStringList{m_val.toString()};
|
||||
}
|
||||
|
||||
QStringList setEnvLaunchOption::generateCommandLine() const noexcept
|
||||
{
|
||||
auto str = m_val.toString();
|
||||
if (str.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return QStringList{QString{"--Environment=%1"}.arg(str)};
|
||||
}
|
||||
|
||||
QStringList setWorkingPathLaunchOption::generateCommandLine() const noexcept
|
||||
{
|
||||
auto str = m_val.toString();
|
||||
@ -120,13 +112,18 @@ QStringList setWorkingPathLaunchOption::generateCommandLine() const noexcept
|
||||
return QStringList{QString{"--WorkingDirectory=%1"}.arg(str)};
|
||||
}
|
||||
|
||||
QStringList builtInSearchExecOption::generateCommandLine() const noexcept
|
||||
QStringList StringListLaunchOption::generateCommandLine() const noexcept
|
||||
{
|
||||
auto list = m_val.toStringList();
|
||||
if (list.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto content = list.join(';');
|
||||
return QStringList{QString{"--ExecSearchPath=%1"}.arg(content)};
|
||||
QStringList ret;
|
||||
const QString ok = optionKey();
|
||||
for (const auto &ov : list) {
|
||||
ret << QString{"%1=%2"}.arg(ok).arg(ov);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -27,6 +27,14 @@ protected:
|
||||
LaunchOption() = default;
|
||||
};
|
||||
|
||||
struct StringListLaunchOption : public LaunchOption
|
||||
{
|
||||
using LaunchOption::LaunchOption;
|
||||
[[nodiscard]] QStringList generateCommandLine() const noexcept override;
|
||||
protected:
|
||||
[[nodiscard]] virtual const QString optionKey() const noexcept = 0;
|
||||
};
|
||||
|
||||
struct setUserLaunchOption : public LaunchOption
|
||||
{
|
||||
using LaunchOption::LaunchOption;
|
||||
@ -43,9 +51,9 @@ struct setUserLaunchOption : public LaunchOption
|
||||
[[nodiscard]] QStringList generateCommandLine() const noexcept override;
|
||||
};
|
||||
|
||||
struct setEnvLaunchOption : public LaunchOption
|
||||
struct setEnvLaunchOption : public StringListLaunchOption
|
||||
{
|
||||
using LaunchOption::LaunchOption;
|
||||
using StringListLaunchOption::StringListLaunchOption;
|
||||
[[nodiscard]] const QString &type() const noexcept override
|
||||
{
|
||||
static QString tp{systemdOption};
|
||||
@ -56,7 +64,10 @@ struct setEnvLaunchOption : public LaunchOption
|
||||
static QString env{"env"};
|
||||
return env;
|
||||
}
|
||||
[[nodiscard]] QStringList generateCommandLine() const noexcept override;
|
||||
protected:
|
||||
[[nodiscard]] virtual const QString optionKey() const noexcept {
|
||||
return QString("--Environment");
|
||||
}
|
||||
};
|
||||
|
||||
struct splitLaunchOption : public LaunchOption
|
||||
@ -110,9 +121,9 @@ struct setWorkingPathLaunchOption : public LaunchOption
|
||||
[[nodiscard]] QStringList generateCommandLine() const noexcept override;
|
||||
};
|
||||
|
||||
struct builtInSearchExecOption : public LaunchOption
|
||||
struct builtInSearchExecOption : public StringListLaunchOption
|
||||
{
|
||||
using LaunchOption::LaunchOption;
|
||||
using StringListLaunchOption::StringListLaunchOption;
|
||||
[[nodiscard]] const QString &type() const noexcept override
|
||||
{
|
||||
static QString tp{systemdOption};
|
||||
@ -123,7 +134,29 @@ struct builtInSearchExecOption : public LaunchOption
|
||||
static QString key{"_builtIn_searchExec"};
|
||||
return key;
|
||||
}
|
||||
[[nodiscard]] QStringList generateCommandLine() const noexcept override;
|
||||
protected:
|
||||
[[nodiscard]] virtual const QString optionKey() const noexcept {
|
||||
return QString("--ExecSearchPath");
|
||||
}
|
||||
};
|
||||
|
||||
struct unsetEnvLaunchOption : public StringListLaunchOption
|
||||
{
|
||||
using StringListLaunchOption::StringListLaunchOption;
|
||||
[[nodiscard]] const QString &type() const noexcept override
|
||||
{
|
||||
static QString tp{systemdOption};
|
||||
return tp;
|
||||
}
|
||||
[[nodiscard]] static const QString &key() noexcept
|
||||
{
|
||||
static QString env{"unsetEnv"};
|
||||
return env;
|
||||
}
|
||||
protected:
|
||||
[[nodiscard]] virtual const QString optionKey() const noexcept {
|
||||
return QString("--UnsetEnvironment");
|
||||
}
|
||||
};
|
||||
|
||||
QStringList generateCommand(const QVariantMap &props) noexcept;
|
||||
|
Loading…
Reference in New Issue
Block a user