Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Thunderbird #9706

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/browser/BrowserSettingsWidget.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2023 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
Expand Down Expand Up @@ -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. <br />Download it for %1 and %2 and %3. %4")
tr("KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2 and %3 and %4. %5")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
tr("KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2 and %3 and %4. %5")
tr("KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1, %2, %3, %4, %5")

Or maybe split this to one line per link?

.arg("<a href=\"https://addons.mozilla.org/firefox/addon/keepassxc-browser/\">Firefox</a>",
"<a href=\"https://addons.thunderbird.net/thunderbird/addon/keepassxc-mail/\">Thunderbird</a>",
"<a href=\"https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk\">"
"Google Chrome / Chromium / Vivaldi / Brave</a>",
"<a href=\"https://microsoftedge.microsoft.com/addons/detail/pdffhmdngciaglkoonimfcmckehcpafo\">Microsoft Edge</a>",
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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());
Expand Down
10 changes: 10 additions & 0 deletions src/browser/BrowserSettingsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QCheckBox" name="thunderBirdSupport">
<property name="text">
<string>Thunderbird</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="chromeSupport">
<property name="text">
Expand Down
3 changes: 2 additions & 1 deletion src/browser/BrowserShared.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2023 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
Expand Down Expand Up @@ -33,6 +33,7 @@ namespace BrowserShared
TOR_BROWSER,
BRAVE,
EDGE,
THUNDERBIRD,
CUSTOM,
MAX_SUPPORTED
};
Expand Down
50 changes: 37 additions & 13 deletions src/browser/NativeMessageInstaller.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2023 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
Expand Down Expand Up @@ -37,14 +36,17 @@ 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/");
#if defined(Q_OS_MACOS)
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");
Expand All @@ -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");
Expand All @@ -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

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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
*
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
}
5 changes: 3 additions & 2 deletions src/browser/NativeMessageInstaller.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2023 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
Expand Down Expand Up @@ -40,8 +39,10 @@ class NativeMessageInstaller
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);
};
Expand Down