diff --git a/src/browser/BrowserSettingsWidget.cpp b/src/browser/BrowserSettingsWidget.cpp index c8d98fa54..970afc1a2 100644 --- a/src/browser/BrowserSettingsWidget.cpp +++ b/src/browser/BrowserSettingsWidget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 KeePassXC Team + * Copyright (C) 2023 KeePassXC Team * * 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 @@ -42,8 +42,9 @@ BrowserSettingsWidget::BrowserSettingsWidget(QWidget* parent) m_ui->extensionLabel->setOpenExternalLinks(true); m_ui->extensionLabel->setText( - tr("KeePassXC-Browser is needed for the browser integration to work.
Download it for %1 and %2 and %3. %4") + tr("KeePassXC-Browser is needed for the browser integration to work.
Download it for %1 and %2 and %3 and %4. %5") .arg("Firefox", + "Thunderbird", "" "Google Chrome / Chromium / Vivaldi / Brave", "Microsoft Edge", @@ -133,6 +134,7 @@ void BrowserSettingsWidget::loadSettings() m_ui->chromiumSupport->setChecked(settings->browserSupport(BrowserShared::CHROMIUM)); m_ui->firefoxSupport->setChecked(settings->browserSupport(BrowserShared::FIREFOX)); m_ui->edgeSupport->setChecked(settings->browserSupport(BrowserShared::EDGE)); + m_ui->thunderBirdSupport->setChecked(settings->browserSupport(BrowserShared::THUNDERBIRD)); #ifndef Q_OS_WIN m_ui->braveSupport->setChecked(settings->browserSupport(BrowserShared::BRAVE)); m_ui->vivaldiSupport->setChecked(settings->browserSupport(BrowserShared::VIVALDI)); @@ -261,6 +263,7 @@ void BrowserSettingsWidget::saveSettings() settings->setBrowserSupport(BrowserShared::CHROMIUM, m_ui->chromiumSupport->isChecked()); settings->setBrowserSupport(BrowserShared::FIREFOX, m_ui->firefoxSupport->isChecked()); settings->setBrowserSupport(BrowserShared::EDGE, m_ui->edgeSupport->isChecked()); + settings->setBrowserSupport(BrowserShared::THUNDERBIRD, m_ui->thunderBirdSupport->isChecked()); #ifndef Q_OS_WIN settings->setBrowserSupport(BrowserShared::BRAVE, m_ui->braveSupport->isChecked()); settings->setBrowserSupport(BrowserShared::VIVALDI, m_ui->vivaldiSupport->isChecked()); diff --git a/src/browser/BrowserSettingsWidget.ui b/src/browser/BrowserSettingsWidget.ui index 2c9d085c2..cc9971505 100644 --- a/src/browser/BrowserSettingsWidget.ui +++ b/src/browser/BrowserSettingsWidget.ui @@ -134,6 +134,16 @@ + + + + Thunderbird + + + false + + + diff --git a/src/browser/BrowserShared.h b/src/browser/BrowserShared.h index e9542a74c..d7bbe5d97 100644 --- a/src/browser/BrowserShared.h +++ b/src/browser/BrowserShared.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 KeePassXC Team + * Copyright (C) 2023 KeePassXC Team * * 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 @@ -33,6 +33,7 @@ namespace BrowserShared TOR_BROWSER, BRAVE, EDGE, + THUNDERBIRD, CUSTOM, MAX_SUPPORTED }; diff --git a/src/browser/NativeMessageInstaller.cpp b/src/browser/NativeMessageInstaller.cpp index 7409989ab..155df5d9a 100644 --- a/src/browser/NativeMessageInstaller.cpp +++ b/src/browser/NativeMessageInstaller.cpp @@ -1,6 +1,5 @@ /* - * Copyright (C) 2017 Sami Vänttinen - * Copyright (C) 2021 KeePassXC Team + * Copyright (C) 2023 KeePassXC Team * * 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 @@ -37,7 +36,9 @@ using namespace BrowserShared; namespace { const QString HOST_NAME = QStringLiteral("org.keepassxc.keepassxc_browser"); - const QStringList ALLOWED_EXTENSIONS = QStringList() << QStringLiteral("keepassxc-browser@keepassxc.org"); + const QString FIREFOX_EXTENSION = QStringLiteral("keepassxc-browser@keepassxc.org"); + const QString THUNDERBIRD_HOST_NAME = QStringLiteral("org.keepassxc.keepassxc_mail"); + const QString THUNDERBIRD_EXTENSION = QStringLiteral("keepassxc-mail@kkapsner.de"); const QStringList ALLOWED_ORIGINS = QStringList() << QStringLiteral("chrome-extension://pdffhmdngciaglkoonimfcmckehcpafo/") << QStringLiteral("chrome-extension://oboonakemofpalcgghocfoadofidjkkk/"); @@ -45,6 +46,7 @@ namespace const QString TARGET_DIR_CHROME = QStringLiteral("/Library/Application Support/Google/Chrome/NativeMessagingHosts"); const QString TARGET_DIR_CHROMIUM = QStringLiteral("/Library/Application Support/Chromium/NativeMessagingHosts"); const QString TARGET_DIR_FIREFOX = QStringLiteral("/Library/Application Support/Mozilla/NativeMessagingHosts"); + const QString TARGET_DIR_THUNDERBIRD = QStringLiteral("/Library/Mozilla/NativeMessagingHosts"); const QString TARGET_DIR_VIVALDI = QStringLiteral("/Library/Application Support/Vivaldi/NativeMessagingHosts"); const QString TARGET_DIR_TOR_BROWSER = QStringLiteral("/Library/Application Support/TorBrowser-Data/Browser/Mozilla/NativeMessagingHosts"); @@ -63,6 +65,8 @@ namespace const QString TARGET_DIR_BRAVE = TARGET_DIR_CHROME; const QString TARGET_DIR_EDGE = QStringLiteral( "HKEY_CURRENT_USER\\Software\\Microsoft\\Edge\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser"); + const QString TARGET_DIR_THUNDERBIRD = + QStringLiteral("HKEY_CURRENT_USER\\Software\\Mozilla\\NativeMessagingHosts\\org.keepassxc.keepassxc_mail"); #else const QString TARGET_DIR_CHROME = QStringLiteral("/google-chrome/NativeMessagingHosts"); const QString TARGET_DIR_CHROMIUM = QStringLiteral("/chromium/NativeMessagingHosts"); @@ -72,6 +76,7 @@ namespace "/torbrowser/tbb/x86_64/tor-browser_en-US/Browser/TorBrowser/Data/Browser/.mozilla/native-messaging-hosts"); const QString TARGET_DIR_BRAVE = QStringLiteral("/BraveSoftware/Brave-Browser/NativeMessagingHosts"); const QString TARGET_DIR_EDGE = QStringLiteral("/microsoft-edge/NativeMessagingHosts"); + const QString TARGET_DIR_THUNDERBIRD = QStringLiteral("/.mozilla/native-messaging-hosts"); #endif } // namespace @@ -160,6 +165,8 @@ QString NativeMessageInstaller::getTargetPath(SupportedBrowsers browser) const return TARGET_DIR_BRAVE; case SupportedBrowsers::EDGE: return TARGET_DIR_EDGE; + case SupportedBrowsers::THUNDERBIRD: + return TARGET_DIR_THUNDERBIRD; case SupportedBrowsers::CUSTOM: return browserSettings()->customBrowserLocation(); default: @@ -191,6 +198,8 @@ QString NativeMessageInstaller::getBrowserName(SupportedBrowsers browser) const return QStringLiteral("brave"); case SupportedBrowsers::EDGE: return QStringLiteral("edge"); + case SupportedBrowsers::THUNDERBIRD: + return QStringLiteral("thunderbird"); case SupportedBrowsers::CUSTOM: return QStringLiteral("custom"); default: @@ -214,7 +223,7 @@ QString NativeMessageInstaller::getNativeMessagePath(SupportedBrowsers browser) } else { basePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); } - return QStringLiteral("%1/%2_%3.json").arg(basePath, HOST_NAME, getBrowserName(browser)); + return QStringLiteral("%1/%2_%3.json").arg(basePath, getHostName(browser), getBrowserName(browser)); #elif defined(KEEPASSXC_DIST_FLATPAK) // Flatpak sandboxes do not have access to the XDG_DATA_HOME and XDG_CONFIG_HOME variables // defined in the host, so we must hardcode them here. @@ -237,10 +246,10 @@ QString NativeMessageInstaller::getNativeMessagePath(SupportedBrowsers browser) basePath = QDir::homePath(); #endif if (browser == SupportedBrowsers::CUSTOM) { - return QString("%1/%2.json").arg(getTargetPath(browser), HOST_NAME); + return QString("%1/%2.json").arg(getTargetPath(browser), getHostName(browser)); } - return QStringLiteral("%1%2/%3.json").arg(basePath, getTargetPath(browser), HOST_NAME); + return QStringLiteral("%1%2/%3.json").arg(basePath, getTargetPath(browser), getHostName(browser)); } #ifdef KEEPASSXC_DIST_FLATPAK @@ -305,6 +314,17 @@ QString NativeMessageInstaller::getInstalledProxyPath() const return QDir::toNativeSeparators(path); } +/** + * Returns name of the extension. Thunderbird differs from the default. + * + * @param browser Selected browser + * @return QString Name of the extension + */ +QString NativeMessageInstaller::getHostName(BrowserShared::SupportedBrowsers browser) const +{ + return browser == SupportedBrowsers::THUNDERBIRD ? THUNDERBIRD_HOST_NAME : HOST_NAME; +} + /** * Constructs the JSON script file used with native messaging * @@ -315,18 +335,14 @@ QString NativeMessageInstaller::getInstalledProxyPath() const QJsonObject NativeMessageInstaller::constructFile(SupportedBrowsers browser) { QJsonObject script; - script["name"] = HOST_NAME; + script["name"] = getHostName(browser); script["description"] = QStringLiteral("KeePassXC integration with native messaging support"); script["path"] = getProxyPath(); script["type"] = QStringLiteral("stdio"); QJsonArray arr; - if (browser == SupportedBrowsers::FIREFOX || browser == SupportedBrowsers::TOR_BROWSER - || (browser == SupportedBrowsers::CUSTOM - && browserSettings()->customBrowserType() == SupportedBrowsers::FIREFOX)) { - for (const QString& extension : ALLOWED_EXTENSIONS) { - arr.append(extension); - } + if (isFirefoxBrowser(browser)) { + arr.append(browser == SupportedBrowsers::THUNDERBIRD ? THUNDERBIRD_EXTENSION : FIREFOX_EXTENSION); script["allowed_extensions"] = arr; } else { for (const QString& origin : ALLOWED_ORIGINS) { @@ -373,3 +389,11 @@ bool NativeMessageInstaller::createNativeMessageFile(SupportedBrowsers browser) } return true; } + +bool NativeMessageInstaller::isFirefoxBrowser(BrowserShared::SupportedBrowsers browser) const +{ + return browser == SupportedBrowsers::FIREFOX || browser == SupportedBrowsers::TOR_BROWSER + || browser == SupportedBrowsers::THUNDERBIRD + || (browser == SupportedBrowsers::CUSTOM + && browserSettings()->customBrowserType() == SupportedBrowsers::FIREFOX); +} diff --git a/src/browser/NativeMessageInstaller.h b/src/browser/NativeMessageInstaller.h index f54d68885..03ead4308 100644 --- a/src/browser/NativeMessageInstaller.h +++ b/src/browser/NativeMessageInstaller.h @@ -1,6 +1,5 @@ /* - * Copyright (C) 2017 Sami Vänttinen - * Copyright (C) 2017 KeePassXC Team + * Copyright (C) 2023 KeePassXC Team * * 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 @@ -40,8 +39,10 @@ private: QString getTargetPath(BrowserShared::SupportedBrowsers browser) const; QString getBrowserName(BrowserShared::SupportedBrowsers browser) const; QString getNativeMessagePath(BrowserShared::SupportedBrowsers browser) const; + QString getHostName(BrowserShared::SupportedBrowsers browser) const; QJsonObject constructFile(BrowserShared::SupportedBrowsers browser); bool createNativeMessageFile(BrowserShared::SupportedBrowsers browser); + bool isFirefoxBrowser(BrowserShared::SupportedBrowsers browser) const; Q_DISABLE_COPY(NativeMessageInstaller); };