3#include <QCoreApplication>
5#include <QJsonDocument>
8#include <QLoggingCategory>
14#include "ParameterPlugin.h"
15#include "PasswordStore.h"
16#include "RabbitCommonEncrypt.h"
17#include "RabbitCommonDir.h"
19static constexpr int KEYCHAIN_TIMEOUT_MS = 2000;
20static Q_LOGGING_CATEGORY(log,
"WebBrowser.PasswordStore")
25 qDebug(log) << Q_FUNC_INFO;
28CPasswordStore::~CPasswordStore()
30 qDebug(log) << Q_FUNC_INFO;
33static QString ServiceName()
36 return "io.github.KangLin/RabbitRemoteControl";
40QVariantMap CPasswordStore::getCredentials(
const QString &host)
43 if (host.isEmpty())
return result;
45 const QString key = ServiceName() + QStringLiteral(
"autofill/%1").arg(host);
46 auto pJob =
new QKeychain::ReadPasswordJob(ServiceName());
47 bool check = connect(pJob, &QKeychain::ReadPasswordJob::finished,
48 this, [
this, pJob, host]() {
49 if (pJob->error() != QKeychain::NoError) {
50 qDebug(log) <<
"ReadPasswordJob error for" << host <<
":"
51 << pJob->errorString();
54 QString text = pJob->textData();
55 if (!text.isEmpty()) {
58 QJsonDocument doc = QJsonDocument::fromJson(text.toUtf8());
60 QJsonObject obj = doc.object();
61 if (obj.contains(QStringLiteral(
"username")))
62 result[
"username"] = obj.value(QStringLiteral(
"username")).toString();
63 if (obj.contains(QStringLiteral(
"password")))
64 result[
"password"] = obj.value(QStringLiteral(
"password")).toString();
67 result[
"password"] = text;
69 qDebug(log) <<
"Get credentials for" << host;
70 emit this->sigCredentialsReady(host, result);
80void CPasswordStore::saveCredentials(
81 const QString &host,
const QString &username,
const QString &password)
83 if (host.isEmpty() || username.isEmpty())
return;
85 const QString key = ServiceName() + QStringLiteral(
"autofill/%1").arg(host);
88 obj.insert(QStringLiteral(
"username"), username);
89 obj.insert(QStringLiteral(
"password"), password);
90 const QString payload =
91 QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact));
92 auto pJob =
new QKeychain::WritePasswordJob(ServiceName());
93 bool check = connect(pJob, &QKeychain::WritePasswordJob::finished,
94 [
this, host, pJob]() {
95 if (pJob->error() != QKeychain::NoError) {
96 qDebug(log) <<
"Saved credentials error for" << host <<
":"
97 << pJob->errorString();
100 emit this->credentialsSaved(host);
101 qDebug(log) <<
"Saved credentials for" << host;
105 pJob->setTextData(payload);
109QVariantMap CPasswordStore::getCredentials(
const QString &host)
112 if (host.isEmpty())
return result;
115 szFile = RabbitCommon::CDir::Instance()->GetDirUserData()
116 + QDir::separator() +
"WebCredentialsStore.ini";
117 QSettings set(szFile, QSettings::IniFormat);
118 const QString key = QStringLiteral(
"autofill/%1").arg(host);
120 int nRet = m_pPara->LoadPassword(
"Password", key, text, set);
121 if (!nRet && !text.isEmpty()) {
123 QJsonDocument doc = QJsonDocument::fromJson(text.toUtf8());
124 if (doc.isObject()) {
125 QJsonObject obj = doc.object();
126 if (obj.contains(QStringLiteral(
"username")))
127 result[
"username"] = obj.value(QStringLiteral(
"username")).toString();
128 if (obj.contains(QStringLiteral(
"password")))
129 result[
"password"] = obj.value(QStringLiteral(
"password")).toString();
132 result[
"password"] = text;
134 emit sigCredentialsReady(host, result);
136 qCritical(log) <<
"Get credentials fail:" << host;
141void CPasswordStore::saveCredentials(
142 const QString &host,
const QString &username,
const QString &password)
144 if (host.isEmpty() || username.isEmpty())
return;
147 szFile = RabbitCommon::CDir::Instance()->GetDirUserData()
148 + QDir::separator() +
"WebCredentialsStore.ini";
149 QSettings set(szFile, QSettings::IniFormat);
151 const QString key = QStringLiteral(
"autofill/%1").arg(host);
153 obj.insert(QStringLiteral(
"username"), username);
154 obj.insert(QStringLiteral(
"password"), password);
155 const QString payload = QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact));
156 m_pPara->SavePassword(key, payload, set, m_pPara->GetAutoFillUserAndPassword());
157 emit credentialsSaved(host);