feat(dock): add app launch event reporting for taskbar icons#1606
Open
Ivy233 wants to merge 1 commit into
Open
feat(dock): add app launch event reporting for taskbar icons#1606Ivy233 wants to merge 1 commit into
Ivy233 wants to merge 1 commit into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: Ivy233 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
35405ee to
0b79013
Compare
|
TAG Bot New tag: 2.0.43 |
0b79013 to
2e0b988
Compare
deepin pr auto review这份代码实现了一个应用启动时长上报器,通过 D-Bus 查询应用实例信息,结合 但在语法逻辑、代码质量、性能和安全性方面存在一些需要改进的地方。以下是详细的审查意见: 1. 语法与逻辑问题
2. 代码性能
3. 代码安全
4. 代码质量与可维护性
改进后的代码示例针对以上核心问题,以下是修改后的 // ... 头部保持不变,建议修改年份 ...
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
namespace {
// ... 常量定义增加 ...
constexpr auto kAmService = "org.desktopspec.ApplicationManager1";
constexpr auto kApplicationIface = "org.desktopspec.ApplicationManager1.Application";
constexpr auto kInstanceIface = "org.desktopspec.ApplicationManager1.Instance";
constexpr int kLinglongCacheTTLSeconds = 1800;
constexpr int kDebCacheTTLSeconds = 1800;
constexpr int kDbusTimeoutMs = 1000;
constexpr int kSubprocessTimeoutMs = 3000;
QList<InstanceInfo> queryInstances(const QString &desktopId)
{
QList<InstanceInfo> result;
auto appPath = QStringLiteral("/org/desktopspec/ApplicationManager1/%1").arg(escapeToObjectPath(desktopId));
QDBusInterface appIface(QString::fromUtf8(kAmService),
appPath,
QStringLiteral("org.freedesktop.DBus.Properties"),
QDBusConnection::sessionBus());
appIface.setTimeout(kDbusTimeoutMs);
QDBusReply<QVariant> reply = appIface.call(QStringLiteral("Get"),
QString::fromUtf8(kApplicationIface),
QStringLiteral("Instances"));
if (!reply.isValid()) {
qCDebug(launchDurationReporter) << "[DockIconTiming] queryInstances failed for" << desktopId << ":" << reply.error().message();
return result;
}
const auto paths = qdbus_cast<QList<QDBusObjectPath>>(reply.value());
for (const auto &path : paths) {
QDBusInterface instIface(QString::fromUtf8(kAmService),
path.path(),
QStringLiteral("org.freedesktop.DBus.Properties"),
QDBusConnection::sessionBus());
instIface.setTimeout(kDbusTimeoutMs);
InstanceInfo info;
info.instanceId = path.path().section(QLatin1Char('/'), -1);
// 优化:使用 QDBusReply 简化提取逻辑
QDBusReply<QVariant> launchTypeReply = instIface.call(QStringLiteral("Get"),
QString::fromUtf8(kInstanceIface),
QStringLiteral("LaunchType"));
if (launchTypeReply.isValid()) {
info.launchType = launchTypeReply.value().toString();
}
if (info.launchType.isEmpty()) {
info.launchType = QStringLiteral("unknown");
}
result.append(info);
}
return result;
}
QHash<QString, QString> loadAllLinglongVersions()
{
QHash<QString, QString> result;
QProcess proc;
// 建议:如果 ll-cli 支持 --json,请使用 JSON 解析代替字符串分割
proc.start(QStringLiteral("ll-cli"), {QStringLiteral("list"), QStringLiteral("--type"), QStringLiteral("app")});
if (!proc.waitForFinished(kSubprocessTimeoutMs)) {
qCWarning(launchDurationReporter) << "ll-cli list timeout";
proc.kill();
proc.waitForFinished();
return result;
}
if (proc.exitCode() != 0) {
qCWarning(launchDurationReporter) << "ll-cli list failed, exitCode:" << proc.exitCode();
return result;
}
QString output = QString::fromUtf8(proc.readAllStandardOutput());
QStringList lines = output.split(QLatin1Char('\n'), Qt::SkipEmptyParts);
// Skip header line
for (int i = 1; i < lines.size(); ++i) {
// 优化:使用正则匹配连续空格,防止单元格内包含空格导致错位
QStringList columns = lines[i].simplified().split(QRegularExpression("\\s+"));
if (columns.size() >= 3) {
QString name = columns[1];
QString version = columns[2];
if (!name.isEmpty()) {
result.insert(name, version);
}
}
}
return result;
}
// 正则表达式验证包名合法性,防止注入或异常字符
static bool isValidDesktopId(const QString &desktopId) {
static QRegularExpression validNameRegex("^[a-z0-9][a-z0-9+.-]+$");
return validNameRegex.match(desktopId).hasMatch();
}
} // namespace
namespace dock {
// ... 构造和析构保持不变 ...
void LaunchDurationReporter::reportWindowAppeared(const QString &desktopId)
{
if (desktopId.isEmpty() || !isValidDesktopId(desktopId)) {
return;
}
// 不需要接收 future 则不接收,避免 Q_UNUSED
QtConcurrent::run(&m_workerPool, [this, desktopId]() {
auto instances = queryInstances(desktopId);
QString uniqueId;
QString launchType = QStringLiteral("unknown");
if (!instances.isEmpty()) {
const auto &latest = instances.constLast();
uniqueId = latest.instanceId;
launchType = latest.launchType;
}
if (uniqueId.isEmpty()) {
return;
}
QString version;
QString pakType;
{
QMutexLocker locker(&m_cacheMutex);
qint64 currentTime = QDateTime::currentSecsSinceEpoch();
if ((currentTime - m_linglongCacheTime) > kLinglongCacheTTLSeconds) {
m_linglongCache = loadAllLinglongVersions();
m_linglongCacheTime = currentTime;
}
if (m_linglongCache.contains(desktopId)) {
version = m_linglongCache.value(desktopId);
pakType = QStringLiteral("linglong");
} else if (m_debCache.contains(desktopId)) {
const auto &entry = m_debCache.value(desktopId);
if ((currentTime - entry.timestamp) <= kDebCacheTTLSeconds) {
version = entry.version;
pakType = entry.pakType;
}
}
}
if (pakType.isEmpty()) {
QProcess proc;
proc.start(QStringLiteral("dpkg-query"), {QStringLiteral("-W"), QStringLiteral("-f=${Version}"), desktopId});
proc.waitForFinished(kDbusTimeoutMs); // 复用超时常量
if (proc.exitCode() == 0) {
version = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
pakType = QStringLiteral("deb");
} else {
qCDebug(launchDurationReporter) << "dpkg-query failed for" << desktopId << "exitCode:" << proc.exitCode();
pakType = QStringLiteral("unknown");
}
QMutexLocker locker(&m_cacheMutex);
m_debCache.insert(desktopId, {version, pakType, QDateTime::currentSecsSinceEpoch()});
}
QMetaObject::invokeMethod(this, [this, desktopId, uniqueId, launchType, version, pakType]() {
doReport(desktopId, uniqueId, launchType, version, pakType);
}, Qt::QueuedConnection);
});
}
// ... doReport 保持不变 ...
} // namespace dock |
Use AM.Identify(pidfd) for precise per-window instance mapping, read X-linglong from desktop files, and query dpkg/linglong for package version info. Report the data via DDE EventLogger (event ID 1000610003). 使用 pidfd 精准匹配窗口与 AM 实例,从桌面文件读取玲珑包名, 通过 dpkg/玲珑查询包版本信息,并通过 DDE EventLogger 上报数据。 Log: 新增任务栏图标启动时长上报 PMS: TASK-389405
2e0b988 to
31355d0
Compare
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Log: Report app launch events when taskbar icons appear for analytics
Influence:
feat(dock): 添加任务栏图标出现时的应用启动事件上报
Log: 任务栏图标出现时上报应用启动事件用于分析
Influence:
PMS: TASK-389405