Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/browser/BrowserService.cpp')
-rw-r--r--src/browser/BrowserService.cpp437
1 files changed, 217 insertions, 220 deletions
diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp
index 42def203a..1f54e33ca 100644
--- a/src/browser/BrowserService.cpp
+++ b/src/browser/BrowserService.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
- * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
+ * Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,8 +26,10 @@
#include <QUuid>
#include "BrowserAccessControlDialog.h"
+#include "BrowserAction.h"
#include "BrowserEntryConfig.h"
#include "BrowserEntrySaveDialog.h"
+#include "BrowserHost.h"
#include "BrowserService.h"
#include "BrowserSettings.h"
#include "core/Database.h"
@@ -39,16 +41,14 @@
#include "gui/MainWindow.h"
#include "gui/MessageBox.h"
#ifdef Q_OS_MACOS
-#include "gui/macutils/MacUtils.h"
+#include "gui/osutils/macutils/MacUtils.h"
#endif
const QString BrowserService::KEEPASSXCBROWSER_NAME = QStringLiteral("KeePassXC-Browser Settings");
const QString BrowserService::KEEPASSXCBROWSER_OLD_NAME = QStringLiteral("keepassxc-browser Settings");
-const QString BrowserService::ASSOCIATE_KEY_PREFIX = QStringLiteral("KPXC_BROWSER_");
static const QString KEEPASSXCBROWSER_GROUP_NAME = QStringLiteral("KeePassXC-Browser Passwords");
static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
// These are for the settings and password conversion
-const QString BrowserService::LEGACY_ASSOCIATE_KEY_PREFIX = QStringLiteral("Public Key: ");
static const QString KEEPASSHTTP_NAME = QStringLiteral("KeePassHttp Settings");
static const QString KEEPASSHTTP_GROUP_NAME = QStringLiteral("KeePassHttp Passwords");
// Extra entry related options saved in custom data
@@ -58,34 +58,45 @@ const QString BrowserService::OPTION_ONLY_HTTP_AUTH = QStringLiteral("BrowserOnl
// Multiple URL's
const QString BrowserService::ADDITIONAL_URL = QStringLiteral("KP2A_URL");
-BrowserService::BrowserService(DatabaseTabWidget* parent)
- : m_dbTabWidget(parent)
+Q_GLOBAL_STATIC(BrowserService, s_browserService);
+
+BrowserService::BrowserService()
+ : QObject()
+ , m_browserHost(new BrowserHost)
, m_dialogActive(false)
, m_bringToFrontRequested(false)
, m_prevWindowState(WindowState::Normal)
, m_keepassBrowserUUID(Tools::hexToUuid("de887cc3036343b8974b5911b8816224"))
{
- // Don't connect the signals when used from DatabaseSettingsWidgetBrowser (parent is nullptr)
- if (m_dbTabWidget) {
- connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*)));
- connect(
- m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*)));
- connect(m_dbTabWidget,
- SIGNAL(activateDatabaseChanged(DatabaseWidget*)),
- this,
- SLOT(activateDatabaseChanged(DatabaseWidget*)));
+ connect(m_browserHost, &BrowserHost::clientMessageReceived, this, &BrowserService::processClientMessage);
+ setEnabled(browserSettings()->isEnabled());
+}
+
+BrowserService* BrowserService::instance()
+{
+ return s_browserService;
+}
+
+void BrowserService::setEnabled(bool enabled)
+{
+ if (enabled) {
+ // Update KeePassXC/keepassxc-proxy binary paths to Native Messaging scripts
+ if (browserSettings()->updateBinaryPath()) {
+ browserSettings()->updateBinaryPaths();
+ }
+
+ m_browserHost->start();
+ } else {
+ m_browserHost->stop();
}
}
bool BrowserService::isDatabaseOpened() const
{
- DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget();
- if (!dbWidget) {
- return false;
+ if (m_currentDatabaseWidget) {
+ return !m_currentDatabaseWidget->isLocked();
}
-
- return dbWidget->currentMode() == DatabaseWidget::Mode::ViewMode
- || dbWidget->currentMode() == DatabaseWidget::Mode::EditMode;
+ return false;
}
bool BrowserService::openDatabase(bool triggerUnlock)
@@ -94,19 +105,14 @@ bool BrowserService::openDatabase(bool triggerUnlock)
return false;
}
- DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget();
- if (!dbWidget) {
- return false;
- }
-
- if (dbWidget->currentMode() == DatabaseWidget::Mode::ViewMode
- || dbWidget->currentMode() == DatabaseWidget::Mode::EditMode) {
+ if (m_currentDatabaseWidget && !m_currentDatabaseWidget->isLocked()) {
return true;
}
if (triggerUnlock) {
m_bringToFrontRequested = true;
- raiseWindow(true);
+ updateWindowState();
+ emit requestUnlock();
}
return false;
@@ -114,19 +120,20 @@ bool BrowserService::openDatabase(bool triggerUnlock)
void BrowserService::lockDatabase()
{
- if (thread() != QThread::currentThread()) {
- QMetaObject::invokeMethod(this, "lockDatabase", Qt::BlockingQueuedConnection);
- }
-
- DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget();
- if (!dbWidget) {
- return;
+ if (m_currentDatabaseWidget) {
+ m_currentDatabaseWidget->lock();
}
+}
- if (dbWidget->currentMode() == DatabaseWidget::Mode::ViewMode
- || dbWidget->currentMode() == DatabaseWidget::Mode::EditMode) {
- dbWidget->lock();
+QString BrowserService::getDatabaseHash(bool legacy)
+{
+ if (legacy) {
+ return QCryptographicHash::hash(
+ (browserService()->getDatabaseRootUuid() + browserService()->getDatabaseRecycleBinUuid()).toUtf8(),
+ QCryptographicHash::Sha256)
+ .toHex();
}
+ return QCryptographicHash::hash(getDatabaseRootUuid().toUtf8(), QCryptographicHash::Sha256).toHex();
}
QString BrowserService::getDatabaseRootUuid()
@@ -180,9 +187,9 @@ QJsonArray BrowserService::getChildrenFromGroup(Group* group)
return groupList;
}
-QJsonObject BrowserService::getDatabaseGroups(const QSharedPointer<Database>& selectedDb)
+QJsonObject BrowserService::getDatabaseGroups()
{
- auto db = selectedDb ? selectedDb : getDatabase();
+ auto db = getDatabase();
if (!db) {
return {};
}
@@ -208,15 +215,6 @@ QJsonObject BrowserService::getDatabaseGroups(const QSharedPointer<Database>& se
QJsonObject BrowserService::createNewGroup(const QString& groupName)
{
- QJsonObject result;
- if (thread() != QThread::currentThread()) {
- QMetaObject::invokeMethod(this,
- "createNewGroup",
- Qt::BlockingQueuedConnection,
- Q_RETURN_ARG(QJsonObject, result),
- Q_ARG(QString, groupName));
- return result;
- }
auto db = getDatabase();
if (!db) {
@@ -232,6 +230,7 @@ QJsonObject BrowserService::createNewGroup(const QString& groupName)
// Group already exists
if (group) {
+ QJsonObject result;
result["name"] = group->name();
result["uuid"] = Tools::uuidToHex(group->uuid());
return result;
@@ -245,7 +244,7 @@ QJsonObject BrowserService::createNewGroup(const QString& groupName)
MessageBox::Yes | MessageBox::No);
if (dialogResult != MessageBox::Yes) {
- return result;
+ return {};
}
QString name, uuid;
@@ -279,6 +278,7 @@ QJsonObject BrowserService::createNewGroup(const QString& groupName)
previousGroup = tempGroup;
}
+ QJsonObject result;
result["name"] = name;
result["uuid"] = uuid;
return result;
@@ -286,25 +286,18 @@ QJsonObject BrowserService::createNewGroup(const QString& groupName)
QString BrowserService::storeKey(const QString& key)
{
- QString id;
-
- if (thread() != QThread::currentThread()) {
- QMetaObject::invokeMethod(
- this, "storeKey", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, id), Q_ARG(QString, key));
- return id;
- }
-
auto db = getDatabase();
if (!db) {
return {};
}
bool contains;
- MessageBox::Button dialogResult = MessageBox::Cancel;
+ auto dialogResult = MessageBox::Cancel;
+ QString id;
do {
QInputDialog keyDialog;
- connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), &keyDialog, SLOT(reject()));
+ connect(m_currentDatabaseWidget, SIGNAL(databaseLocked()), &keyDialog, SLOT(reject()));
keyDialog.setWindowTitle(tr("KeePassXC: New key association request"));
keyDialog.setLabelText(tr("You have received an association request for the following database:\n%1\n\n"
"Give the connection a unique name or ID, for example:\nchrome-laptop.")
@@ -324,7 +317,7 @@ QString BrowserService::storeKey(const QString& key)
return {};
}
- contains = db->metadata()->customData()->contains(ASSOCIATE_KEY_PREFIX + id);
+ contains = db->metadata()->customData()->contains(CustomData::BrowserKeyPrefix + id);
if (contains) {
dialogResult = MessageBox::warning(nullptr,
tr("KeePassXC: Overwrite existing key?"),
@@ -337,7 +330,9 @@ QString BrowserService::storeKey(const QString& key)
} while (contains && dialogResult == MessageBox::Cancel);
hideWindow();
- db->metadata()->customData()->set(ASSOCIATE_KEY_PREFIX + id, key);
+ db->metadata()->customData()->set(CustomData::BrowserKeyPrefix + id, key);
+ db->metadata()->customData()->set(QString("%1_%2").arg(CustomData::Created, id),
+ Clock::currentDateTime().toString(Qt::SystemLocaleShortDate));
return id;
}
@@ -348,31 +343,17 @@ QString BrowserService::getKey(const QString& id)
return {};
}
- return db->metadata()->customData()->value(ASSOCIATE_KEY_PREFIX + id);
+ return db->metadata()->customData()->value(CustomData::BrowserKeyPrefix + id);
}
-QJsonArray BrowserService::findMatchingEntries(const QString& id,
+QJsonArray BrowserService::findMatchingEntries(const QString& dbid,
const QString& url,
const QString& submitUrl,
const QString& realm,
const StringPairList& keyList,
const bool httpAuth)
{
- QJsonArray result;
- if (thread() != QThread::currentThread()) {
- QMetaObject::invokeMethod(this,
- "findMatchingEntries",
- Qt::BlockingQueuedConnection,
- Q_RETURN_ARG(QJsonArray, result),
- Q_ARG(QString, id),
- Q_ARG(QString, url),
- Q_ARG(QString, submitUrl),
- Q_ARG(QString, realm),
- Q_ARG(StringPairList, keyList),
- Q_ARG(bool, httpAuth));
- return result;
- }
-
+ Q_UNUSED(dbid);
const bool alwaysAllowAccess = browserSettings()->alwaysAllowAccess();
const bool ignoreHttpAuth = browserSettings()->httpAuthPermission();
const QString host = QUrl(url).host();
@@ -417,23 +398,25 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id,
}
// Confirm entries
- if (confirmEntries(pwEntriesToConfirm, url, host, submitUrl, realm, httpAuth)) {
- pwEntries.append(pwEntriesToConfirm);
+ QList<Entry*> selectedEntriesToConfirm = confirmEntries(pwEntriesToConfirm, url, host, submitHost, realm, httpAuth);
+ if (!selectedEntriesToConfirm.isEmpty()) {
+ pwEntries.append(selectedEntriesToConfirm);
}
if (pwEntries.isEmpty()) {
- return QJsonArray();
+ return {};
}
// Ensure that database is not locked when the popup was visible
if (!isDatabaseOpened()) {
- return QJsonArray();
+ return {};
}
// Sort results
pwEntries = sortEntries(pwEntries, host, submitUrl);
// Fill the list
+ QJsonArray result;
for (auto* entry : pwEntries) {
result.append(prepareEntry(entry));
}
@@ -441,7 +424,7 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id,
return result;
}
-void BrowserService::addEntry(const QString& id,
+void BrowserService::addEntry(const QString& dbid,
const QString& login,
const QString& password,
const QString& url,
@@ -451,21 +434,8 @@ void BrowserService::addEntry(const QString& id,
const QString& groupUuid,
const QSharedPointer<Database>& selectedDb)
{
- if (thread() != QThread::currentThread()) {
- QMetaObject::invokeMethod(this,
- "addEntry",
- Qt::BlockingQueuedConnection,
- Q_ARG(QString, id),
- Q_ARG(QString, login),
- Q_ARG(QString, password),
- Q_ARG(QString, url),
- Q_ARG(QString, submitUrl),
- Q_ARG(QString, realm),
- Q_ARG(QString, group),
- Q_ARG(QString, groupUuid),
- Q_ARG(QSharedPointer<Database>, selectedDb));
- }
-
+ // TODO: select database based on this key id
+ Q_UNUSED(dbid);
auto db = selectedDb ? selectedDb : selectedDatabase();
if (!db) {
return;
@@ -507,37 +477,25 @@ void BrowserService::addEntry(const QString& id,
config.save(entry);
}
-BrowserService::ReturnValue BrowserService::updateEntry(const QString& id,
- const QString& uuid,
- const QString& login,
- const QString& password,
- const QString& url,
- const QString& submitUrl)
+bool BrowserService::updateEntry(const QString& dbid,
+ const QString& uuid,
+ const QString& login,
+ const QString& password,
+ const QString& url,
+ const QString& submitUrl)
{
- ReturnValue result = ReturnValue::Error;
- if (thread() != QThread::currentThread()) {
- QMetaObject::invokeMethod(this,
- "updateEntry",
- Qt::BlockingQueuedConnection,
- Q_RETURN_ARG(ReturnValue, result),
- Q_ARG(QString, id),
- Q_ARG(QString, uuid),
- Q_ARG(QString, login),
- Q_ARG(QString, password),
- Q_ARG(QString, url),
- Q_ARG(QString, submitUrl));
- }
-
+ // TODO: select database based on this key id
+ Q_UNUSED(dbid);
auto db = selectedDatabase();
if (!db) {
- return ReturnValue::Error;
+ return false;
}
Entry* entry = db->rootGroup()->findEntryByUuid(Tools::hexToUuid(uuid));
if (!entry) {
// If entry is not found for update, add a new one to the selected database
- addEntry(id, login, password, url, submitUrl, "", "", "", db);
- return ReturnValue::Success;
+ addEntry(dbid, login, password, url, submitUrl, "", "", "", db);
+ return true;
}
// Check if the entry password is a reference. If so, update the original entry instead
@@ -546,16 +504,17 @@ BrowserService::ReturnValue BrowserService::updateEntry(const QString& id,
if (!referenceUuid.isNull()) {
entry = db->rootGroup()->findEntryByUuid(referenceUuid);
if (!entry) {
- return ReturnValue::Error;
+ return false;
}
}
}
QString username = entry->username();
if (username.isEmpty()) {
- return ReturnValue::Error;
+ return false;
}
+ bool result = false;
if (username.compare(login, Qt::CaseSensitive) != 0
|| entry->password().compare(password, Qt::CaseSensitive) != 0) {
MessageBox::Button dialogResult = MessageBox::No;
@@ -577,9 +536,7 @@ BrowserService::ReturnValue BrowserService::updateEntry(const QString& id,
}
entry->setPassword(password);
entry->endUpdate();
- result = ReturnValue::Success;
- } else {
- result = ReturnValue::Canceled;
+ result = true;
}
hideWindow();
@@ -609,7 +566,8 @@ BrowserService::searchEntries(const QSharedPointer<Database>& db, const QString&
// Search for additional URL's starting with KP2A_URL
for (const auto& key : entry->attributes()->keys()) {
- if (key.startsWith(ADDITIONAL_URL) && handleURL(entry->attributes()->value(key), url, submitUrl)) {
+ if (key.startsWith(ADDITIONAL_URL) && handleURL(entry->attributes()->value(key), url, submitUrl)
+ && !entries.contains(entry)) {
entries.append(entry);
continue;
}
@@ -631,7 +589,7 @@ QList<Entry*> BrowserService::searchEntries(const QString& url, const QString& s
// Check if database is connected with KeePassXC-Browser
auto databaseConnected = [&](const QSharedPointer<Database>& db) {
for (const StringPair& keyPair : keyList) {
- QString key = db->metadata()->customData()->value(ASSOCIATE_KEY_PREFIX + keyPair.first);
+ QString key = db->metadata()->customData()->value(CustomData::BrowserKeyPrefix + keyPair.first);
if (!key.isEmpty() && keyPair.second == key) {
return true;
}
@@ -642,17 +600,14 @@ QList<Entry*> BrowserService::searchEntries(const QString& url, const QString& s
// Get the list of databases to search
QList<QSharedPointer<Database>> databases;
if (browserSettings()->searchInAllDatabases()) {
- const int count = m_dbTabWidget->count();
- for (int i = 0; i < count; ++i) {
- if (auto* dbWidget = qobject_cast<DatabaseWidget*>(m_dbTabWidget->widget(i))) {
- if (const auto& db = dbWidget->database()) {
- if (databaseConnected(db)) {
- databases << db;
- }
- }
+ for (auto dbWidget : getMainWindow()->getOpenDatabases()) {
+ auto db = dbWidget->database();
+ if (db && databaseConnected(dbWidget->database())) {
+ databases << db;
}
}
- } else if (const auto& db = getDatabase()) {
+ } else {
+ const auto& db = getDatabase();
if (databaseConnected(db)) {
databases << db;
}
@@ -670,9 +625,8 @@ QList<Entry*> BrowserService::searchEntries(const QString& url, const QString& s
return entries;
}
-void BrowserService::convertAttributesToCustomData(const QSharedPointer<Database>& currentDb)
+void BrowserService::convertAttributesToCustomData(QSharedPointer<Database> db)
{
- auto db = currentDb ? currentDb : getDatabase();
if (!db) {
return;
}
@@ -702,7 +656,7 @@ void BrowserService::convertAttributesToCustomData(const QSharedPointer<Database
if (entry->title() == KEEPASSHTTP_NAME || entry->title().contains(KEEPASSXCBROWSER_NAME, Qt::CaseInsensitive)) {
keyCounter += moveKeysToCustomData(entry, db);
- delete entry;
+ db->recycleEntry(entry);
}
progress.setValue(progress.value() + 1);
@@ -788,59 +742,69 @@ QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QStrin
return results;
}
-bool BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm,
- const QString& url,
- const QString& host,
- const QString& submitUrl,
- const QString& realm,
- const bool httpAuth)
+QList<Entry*> BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm,
+ const QString& url,
+ const QString& host,
+ const QString& submitHost,
+ const QString& realm,
+ const bool httpAuth)
{
if (pwEntriesToConfirm.isEmpty() || m_dialogActive) {
- return false;
+ return {};
}
m_dialogActive = true;
+ updateWindowState();
BrowserAccessControlDialog accessControlDialog;
- connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), &accessControlDialog, SLOT(reject()));
- accessControlDialog.setUrl(!submitUrl.isEmpty() ? submitUrl : url);
- accessControlDialog.setItems(pwEntriesToConfirm);
- accessControlDialog.setHTTPAuth(httpAuth);
- raiseWindow();
- accessControlDialog.show();
- accessControlDialog.activateWindow();
- accessControlDialog.raise();
+ connect(m_currentDatabaseWidget, SIGNAL(databaseLocked()), &accessControlDialog, SLOT(reject()));
- const QString submitHost = QUrl(submitUrl).host();
- int res = accessControlDialog.exec();
- if (accessControlDialog.remember()) {
- for (auto* entry : pwEntriesToConfirm) {
- BrowserEntryConfig config;
- config.load(entry);
- if (res == QDialog::Accepted) {
+ connect(&accessControlDialog, &BrowserAccessControlDialog::disableAccess, [&](QTableWidgetItem* item) {
+ auto entry = pwEntriesToConfirm[item->row()];
+ BrowserEntryConfig config;
+ config.load(entry);
+ config.deny(host);
+ if (!submitHost.isEmpty() && host != submitHost) {
+ config.deny(submitHost);
+ }
+ if (!realm.isEmpty()) {
+ config.setRealm(realm);
+ }
+ config.save(entry);
+ });
+
+ accessControlDialog.setItems(pwEntriesToConfirm, !submitHost.isEmpty() ? submitHost : url, httpAuth);
+
+ QList<Entry*> allowedEntries;
+ if (accessControlDialog.exec() == QDialog::Accepted) {
+ const auto selectedEntries = accessControlDialog.getSelectedEntries();
+ for (auto item : accessControlDialog.getSelectedEntries()) {
+ auto entry = pwEntriesToConfirm[item->row()];
+ if (accessControlDialog.remember()) {
+ BrowserEntryConfig config;
+ config.load(entry);
config.allow(host);
- if (!submitHost.isEmpty() && host != submitHost)
- config.allow(submitHost);
- } else if (res == QDialog::Rejected) {
- config.deny(host);
if (!submitHost.isEmpty() && host != submitHost) {
- config.deny(submitHost);
+ config.allow(submitHost);
}
+ if (!realm.isEmpty()) {
+ config.setRealm(realm);
+ }
+ config.save(entry);
}
- if (!realm.isEmpty()) {
- config.setRealm(realm);
- }
- config.save(entry);
+ allowedEntries.append(entry);
}
}
- m_dialogActive = false;
+#ifdef Q_OS_MAC
+ // Re-hide the application if it wasn't visible before
+ // only affects macOS because dialogs force the main window to show
hideWindow();
- if (res == QDialog::Accepted) {
- return true;
- }
+#endif
- return false;
+ m_dialogActive = false;
+
+ return allowedEntries;
}
QJsonObject BrowserService::prepareEntry(const Entry* entry)
@@ -850,6 +814,7 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry)
res["password"] = entry->resolveMultiplePlaceholders(entry->password());
res["name"] = entry->resolveMultiplePlaceholders(entry->title());
res["uuid"] = entry->resolveMultiplePlaceholders(entry->uuidToHex());
+ res["group"] = entry->resolveMultiplePlaceholders(entry->group()->name());
if (entry->hasTotp()) {
res["totp"] = entry->totp();
@@ -881,13 +846,14 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry)
BrowserService::Access
BrowserService::checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm)
{
+ if (entry->isExpired()) {
+ return browserSettings()->allowExpiredCredentials() ? Allowed : Denied;
+ }
+
BrowserEntryConfig config;
if (!config.load(entry)) {
return Unknown;
}
- if (entry->isExpired()) {
- return browserSettings()->allowExpiredCredentials() ? Allowed : Denied;
- }
if ((config.isAllowed(host)) && (submitHost.isEmpty() || config.isAllowed(submitHost))) {
return Allowed;
}
@@ -1096,10 +1062,8 @@ QString BrowserService::baseDomain(const QString& hostname) const
QSharedPointer<Database> BrowserService::getDatabase()
{
- if (DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget()) {
- if (const auto& db = dbWidget->database()) {
- return db;
- }
+ if (m_currentDatabaseWidget) {
+ return m_currentDatabaseWidget->database();
}
return {};
}
@@ -1107,22 +1071,15 @@ QSharedPointer<Database> BrowserService::getDatabase()
QSharedPointer<Database> BrowserService::selectedDatabase()
{
QList<DatabaseWidget*> databaseWidgets;
- for (int i = 0;; ++i) {
- auto* dbWidget = m_dbTabWidget->databaseWidgetFromIndex(i);
+ for (auto dbWidget : getMainWindow()->getOpenDatabases()) {
// Add only open databases
- if (dbWidget && dbWidget->database()->hasKey()
- && (dbWidget->currentMode() == DatabaseWidget::Mode::ViewMode
- || dbWidget->currentMode() == DatabaseWidget::Mode::EditMode)) {
- databaseWidgets.push_back(dbWidget);
- continue;
+ if (!dbWidget->isLocked()) {
+ databaseWidgets << dbWidget;
}
-
- // Break out if dbStruct.dbWidget is nullptr
- break;
}
BrowserEntrySaveDialog browserEntrySaveDialog;
- int openDatabaseCount = browserEntrySaveDialog.setItems(databaseWidgets, m_dbTabWidget->currentDatabaseWidget());
+ int openDatabaseCount = browserEntrySaveDialog.setItems(databaseWidgets, m_currentDatabaseWidget);
if (openDatabaseCount > 1) {
int res = browserEntrySaveDialog.exec();
if (res == QDialog::Accepted) {
@@ -1140,7 +1097,7 @@ QSharedPointer<Database> BrowserService::selectedDatabase()
return getDatabase();
}
-bool BrowserService::moveSettingsToCustomData(Entry* entry, const QString& name) const
+bool BrowserService::moveSettingsToCustomData(Entry* entry, const QString& name)
{
if (entry->attributes()->contains(name)) {
QString attr = entry->attributes()->value(name);
@@ -1155,17 +1112,18 @@ bool BrowserService::moveSettingsToCustomData(Entry* entry, const QString& name)
return false;
}
-int BrowserService::moveKeysToCustomData(Entry* entry, const QSharedPointer<Database>& db) const
+int BrowserService::moveKeysToCustomData(Entry* entry, QSharedPointer<Database> db)
{
int keyCounter = 0;
for (const auto& key : entry->attributes()->keys()) {
- if (key.contains(LEGACY_ASSOCIATE_KEY_PREFIX)) {
+ if (key.contains(CustomData::BrowserLegacyKeyPrefix)) {
QString publicKey = key;
- publicKey.remove(LEGACY_ASSOCIATE_KEY_PREFIX);
+ publicKey.remove(CustomData::BrowserLegacyKeyPrefix);
// Add key to database custom data
- if (db && !db->metadata()->customData()->contains(ASSOCIATE_KEY_PREFIX + publicKey)) {
- db->metadata()->customData()->set(ASSOCIATE_KEY_PREFIX + publicKey, entry->attributes()->value(key));
+ if (db && !db->metadata()->customData()->contains(CustomData::BrowserKeyPrefix + publicKey)) {
+ db->metadata()->customData()->set(CustomData::BrowserKeyPrefix + publicKey,
+ entry->attributes()->value(key));
++keyCounter;
}
}
@@ -1174,14 +1132,9 @@ int BrowserService::moveKeysToCustomData(Entry* entry, const QSharedPointer<Data
return keyCounter;
}
-bool BrowserService::checkLegacySettings()
+bool BrowserService::checkLegacySettings(QSharedPointer<Database> db)
{
- if (!browserSettings()->isEnabled() || browserSettings()->noMigrationPrompt()) {
- return false;
- }
-
- auto db = getDatabase();
- if (!db) {
+ if (!db || !browserSettings()->isEnabled() || browserSettings()->noMigrationPrompt()) {
return false;
}
@@ -1264,36 +1217,80 @@ void BrowserService::raiseWindow(const bool force)
#endif
}
+void BrowserService::updateWindowState()
+{
+ m_prevWindowState = WindowState::Normal;
+ if (getMainWindow()->isMinimized()) {
+ m_prevWindowState = WindowState::Minimized;
+ }
+#ifdef Q_OS_MACOS
+ if (macUtils()->isHidden()) {
+ m_prevWindowState = WindowState::Hidden;
+ }
+#else
+ if (getMainWindow()->isHidden()) {
+ m_prevWindowState = WindowState::Hidden;
+ }
+#endif
+}
+
void BrowserService::databaseLocked(DatabaseWidget* dbWidget)
{
if (dbWidget) {
- emit databaseLocked();
+ QJsonObject msg;
+ msg["action"] = QString("database-locked");
+ m_browserHost->sendClientMessage(msg);
}
}
void BrowserService::databaseUnlocked(DatabaseWidget* dbWidget)
{
if (dbWidget) {
+#ifdef Q_OS_MAC
if (m_bringToFrontRequested) {
- hideWindow();
m_bringToFrontRequested = false;
+ hideWindow();
}
- emit databaseUnlocked();
+#endif
+
+ QJsonObject msg;
+ msg["action"] = QString("database-unlocked");
+ m_browserHost->sendClientMessage(msg);
- if (checkLegacySettings()) {
- convertAttributesToCustomData();
+ auto db = dbWidget->database();
+ if (checkLegacySettings(db)) {
+ convertAttributesToCustomData(db);
}
}
}
-void BrowserService::activateDatabaseChanged(DatabaseWidget* dbWidget)
+void BrowserService::activeDatabaseChanged(DatabaseWidget* dbWidget)
{
- if (dbWidget) {
- auto currentMode = dbWidget->currentMode();
- if (currentMode == DatabaseWidget::Mode::ViewMode || currentMode == DatabaseWidget::Mode::EditMode) {
- emit databaseUnlocked();
+ // Only emit these signals when we are not searching in all databases
+ if (dbWidget && !browserSettings()->searchInAllDatabases()) {
+ if (dbWidget->isLocked()) {
+ databaseLocked(dbWidget);
} else {
- emit databaseLocked();
+ databaseUnlocked(dbWidget);
}
}
+
+ m_currentDatabaseWidget = dbWidget;
+}
+
+void BrowserService::processClientMessage(const QJsonObject& message)
+{
+ auto clientID = message["clientID"].toString();
+ if (clientID.isEmpty()) {
+ return;
+ }
+
+ // Create a new client action if we haven't seen this id yet
+ if (!m_browserClients.contains(clientID)) {
+ m_browserClients.insert(clientID, QSharedPointer<BrowserAction>::create());
+ }
+
+ auto& action = m_browserClients.value(clientID);
+ auto response = action->processClientMessage(message);
+ m_browserHost->sendClientMessage(response);
}