| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  | #include "application_manager.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-15 12:10:42 +08:00
										 |  |  | #include <QDBusMessage>
 | 
					
						
							|  |  |  | #include <QDBusConnectionInterface>
 | 
					
						
							|  |  |  | #include <QDBusConnection>
 | 
					
						
							|  |  |  | #include <QDebug>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  | #include <iostream>
 | 
					
						
							|  |  |  | #include <map>
 | 
					
						
							|  |  |  | #include <mutex>
 | 
					
						
							|  |  |  | #include <thread>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../../modules/methods/basic.h"
 | 
					
						
							|  |  |  | #include "../../modules/methods/instance.hpp"
 | 
					
						
							|  |  |  | #include "../../modules/methods/quit.hpp"
 | 
					
						
							|  |  |  | #include "../../modules/methods/registe.hpp"
 | 
					
						
							|  |  |  | #include "../../modules/methods/task.hpp"
 | 
					
						
							|  |  |  | #include "../../modules/socket/server.h"
 | 
					
						
							|  |  |  | #include "application.h"
 | 
					
						
							|  |  |  | #include "application_instance.h"
 | 
					
						
							|  |  |  | #include "applicationinstanceadaptor.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  | class ApplicationManagerPrivate : public QObject | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |     Q_OBJECT | 
					
						
							|  |  |  |     ApplicationManager *q_ptr = nullptr; | 
					
						
							|  |  |  |     Q_DECLARE_PUBLIC(ApplicationManager); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |     QList<QSharedPointer<Application>> applications; | 
					
						
							|  |  |  |     Socket::Server server; | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |     std::multimap<std::string, QSharedPointer<ApplicationInstance>> tasks; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     ApplicationManagerPrivate(ApplicationManager *parent) : QObject(parent), q_ptr(parent) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |         const QString socketPath{QString("/run/user/%1/deepin-application-manager.socket").arg(getuid())}; | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |         connect(&server, &Socket::Server::onReadyRead, this, &ApplicationManagerPrivate::recvClientData, Qt::QueuedConnection); | 
					
						
							|  |  |  |         server.listen(socketPath.toStdString()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ~ApplicationManagerPrivate() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     void recvClientData(int socket, const std::vector<char> &data) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         std::string tmp; | 
					
						
							|  |  |  |         for (char c : data) { | 
					
						
							|  |  |  |             tmp += c; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         QByteArray jsonArray = data.data(); | 
					
						
							|  |  |  |         Methods::Basic basic; | 
					
						
							|  |  |  |         Methods::fromJson(jsonArray, basic); | 
					
						
							|  |  |  |         QByteArray tmpArray; | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |         do { | 
					
						
							|  |  |  |             if (basic.type == "instance") { | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |                 Methods::Instance instance; | 
					
						
							|  |  |  |                 Methods::fromJson(jsonArray, instance); | 
					
						
							|  |  |  |                 auto find = tasks.find(instance.hash.toStdString()); | 
					
						
							|  |  |  |                 if (find != tasks.end()) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     Methods::Task task = find->second->taskInfo(); | 
					
						
							|  |  |  |                     Methods::toJson(tmpArray, task); | 
					
						
							|  |  |  |                     write(socket, tmpArray.toStdString()); | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |                     tasks.erase(find); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (basic.type == "quit") { | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |                 Methods::Quit quit; | 
					
						
							|  |  |  |                 Methods::fromJson(jsonArray, quit); | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |                 server.close(socket); | 
					
						
							|  |  |  |                 std::cout << "client quit" << std::endl; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (basic.type == "registe") { | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |                 Methods::Registe registe; | 
					
						
							|  |  |  |                 Methods::fromJson(jsonArray, registe); | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |                 Methods::Registe result; | 
					
						
							|  |  |  |                 result.state = false; | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |                 // std::lock_guard<std::mutex> lock(task_mutex);
 | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |                 for (auto it = tasks.begin(); it != tasks.end(); ++it) { | 
					
						
							|  |  |  |                     result.state = true; | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |                     result.hash = QString::fromStdString(it->first); | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |                 Methods::toJson(tmpArray, result); | 
					
						
							|  |  |  |                 write(socket, tmpArray.toStdString()); | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |             write(socket, jsonArray.toStdString()); | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |         } while (false); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void write(int socket, const std::vector<char> &data) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         std::vector<char> tmp = data; | 
					
						
							|  |  |  |         tmp.push_back('\0'); | 
					
						
							|  |  |  |         server.write(socket, tmp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void write(int socket, const std::string &data) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         std::vector<char> result; | 
					
						
							|  |  |  |         std::copy(data.cbegin(), data.cend(), std::back_inserter(result)); | 
					
						
							|  |  |  |         return write(socket, result); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void write(int socket, const char c) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return write(socket, std::vector<char>(c)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-15 12:10:42 +08:00
										 |  |  | ApplicationManager::ApplicationManager(QObject *parent) | 
					
						
							|  |  |  |  : QObject(parent) | 
					
						
							|  |  |  |  , dd_ptr(new ApplicationManagerPrivate(this)) | 
					
						
							|  |  |  |  , startManager(new StartManager(this)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     connect(startManager, &StartManager::autostartChanged, this, &ApplicationManager::AutostartChanged); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ApplicationManager::~ApplicationManager() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplicationManager::addApplication(const QList<QSharedPointer<Application>> &list) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_D(ApplicationManager); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d->applications = list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QDBusObjectPath ApplicationManager::GetInformation(const QString &id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_D(ApplicationManager); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-15 12:10:42 +08:00
										 |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |     for (const QSharedPointer<Application> &app : d->applications) { | 
					
						
							|  |  |  |         if (app->id() == id) { | 
					
						
							|  |  |  |             return app->path(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<QDBusObjectPath> ApplicationManager::GetInstances(const QString &id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_D(const ApplicationManager); | 
					
						
							| 
									
										
										
										
											2022-05-15 12:10:42 +08:00
										 |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (const auto &app : d->applications) { | 
					
						
							|  |  |  |         if (app->id() == id) { | 
					
						
							|  |  |  |             return app->instances(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QDBusObjectPath ApplicationManager::Run(const QString &id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_D(ApplicationManager); | 
					
						
							| 
									
										
										
										
											2022-05-15 12:10:42 +08:00
										 |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 创建一个实例
 | 
					
						
							|  |  |  |     for (const QSharedPointer<Application> &app : d->applications) { | 
					
						
							|  |  |  |         if (app->id() == id) { | 
					
						
							|  |  |  |             // 创建任务所需的数据,并记录到任务队列,等待 loader 消耗
 | 
					
						
							| 
									
										
										
										
											2022-04-24 14:52:13 +08:00
										 |  |  |             QSharedPointer<ApplicationInstance> instance{app->createInstance()}; | 
					
						
							|  |  |  |             const std::string hash{instance->hash().toStdString()}; | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  |             connect(instance.get(), &ApplicationInstance::taskFinished, this, [=] { | 
					
						
							|  |  |  |                 for (auto it = d->tasks.begin(); it != d->tasks.end(); ++it) { | 
					
						
							|  |  |  |                     if (it->first == hash) { | 
					
						
							|  |  |  |                         d->tasks.erase(it); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |             d->tasks.insert(std::make_pair(hash, instance)); | 
					
						
							|  |  |  |             return instance->path(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-15 12:10:42 +08:00
										 |  |  | bool ApplicationManager::AddAutostart(QString fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return startManager->addAutostart(fileName); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ApplicationManager::RemoveAutostart(QString fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return startManager->removeAutostart(fileName); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QStringList ApplicationManager::AutostartList() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return startManager->autostartList(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString ApplicationManager::DumpMemRecord() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return startManager->dumpMemRecord(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ApplicationManager::IsAutostart(QString fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return startManager->isAutostart(fileName); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ApplicationManager::IsMemSufficient() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return startManager->isMemSufficient(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplicationManager::LaunchApp(QString desktopFile, uint32_t timestamp, QStringList files) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     startManager->launchApp(desktopFile, timestamp, files); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplicationManager::LaunchAppAction(QString desktopFile, QString action, uint32_t timestamp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     startManager->launchAppAction(desktopFile, action, timestamp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplicationManager::LaunchAppWithOptions(QString desktopFile, uint32_t timestamp, QStringList files, QMap<QString, QString> options) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     startManager->launchAppWithOptions(desktopFile, timestamp, files, options); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplicationManager::RunCommand(QString exe, QStringList args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     startManager->runCommand(exe, args); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplicationManager::RunCommandWithOptions(QString exe, QStringList args, QMap<QString, QString> options) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     startManager->runCommandWithOptions(exe, args, options); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplicationManager::TryAgain(bool launch) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!checkDMsgUid()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     startManager->tryAgain(launch); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  | QList<QDBusObjectPath> ApplicationManager::instances() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_D(const ApplicationManager); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<QDBusObjectPath> result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (const auto &app : d->applications) { | 
					
						
							|  |  |  |         result += app->instances(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<QDBusObjectPath> ApplicationManager::list() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_D(const ApplicationManager); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<QDBusObjectPath> result; | 
					
						
							|  |  |  |     for (const QSharedPointer<Application> &app : d->applications) { | 
					
						
							|  |  |  |         result << app->path(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-15 12:10:42 +08:00
										 |  |  | bool ApplicationManager::checkDMsgUid() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDBusReply<uint> reply = connection().interface()->serviceUid(message().service()); | 
					
						
							|  |  |  |     return reply.isValid() && (reply.value() == getuid()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 17:56:27 +08:00
										 |  |  | #include "application_manager.moc"
 |