diff --git a/.gitmodules b/.gitmodules index d1a5352bd..ebb944b6b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,9 +17,6 @@ [submodule "lib/rapidjson"] path = lib/rapidjson url = https://github.com/Tencent/rapidjson -[submodule "lib/qtkeychain"] - path = lib/qtkeychain - url = https://github.com/frankosterfeld/qtkeychain [submodule "cmake/sanitizers-cmake"] path = cmake/sanitizers-cmake url = https://github.com/arsenm/sanitizers-cmake diff --git a/BUILDING_ON_LINUX.md b/BUILDING_ON_LINUX.md index 8a299223f..fb9a55ac5 100644 --- a/BUILDING_ON_LINUX.md +++ b/BUILDING_ON_LINUX.md @@ -17,7 +17,7 @@ The built binary should be exportable from the final image & able to run on your ### Debian 13 (trixie) or later ```sh -sudo apt install qt6-base-dev qt6-svg-dev qt6-image-formats-plugins libboost-dev libnotify-dev libssl-dev libsecret-1-dev pkg-config cmake g++ git hunspell +sudo apt install qt6-base-dev qt6-svg-dev qt6-image-formats-plugins libboost-dev libnotify-dev libssl-dev pkg-config cmake g++ git hunspell ``` ### Arch Linux @@ -39,7 +39,7 @@ sudo zypper install cmake pkgconf boost-devel libboost_json1_89_0-devel desktop- ### Gentoo Linux ```sh -doas emerge dev-libs/openssl dev-qt/qt5compat dev-qt/qtbase dev-qt/qtsvg dev-qt/qtimageformats x11-libs/libnotify dev-libs/qtkeychain dev-libs/boost dev-build/cmake app-text/hunspell +doas emerge dev-libs/openssl dev-qt/qt5compat dev-qt/qtbase dev-qt/qtsvg dev-qt/qtimageformats x11-libs/libnotify dev-libs/boost dev-build/cmake app-text/hunspell ``` ### Fedora 42 and above @@ -67,7 +67,7 @@ nix-shell -p openssl boost qt6.full pkg-config cmake libnotify hunspell ``` 1. Generate build files. To enable Lua plugins in your build add `-DCHATTERINO_PLUGINS=ON` to this command. ```sh - cmake -DBUILD_WITH_QTKEYCHAIN=OFF -DCHATTERINO_SPELLCHECK=On .. + cmake -DCHATTERINO_SPELLCHECK=On .. ``` 1. Build the project ```sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 34e2ab7ec..036113278 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,16 +20,12 @@ option(BUILD_TESTS "Build the tests for Chatterino" OFF) option(BUILD_BENCHMARKS "Build the benchmarks for Chatterino" OFF) option(USE_SYSTEM_PAJLADA_SETTINGS "Use system pajlada settings library" OFF) option(USE_SYSTEM_LIBCOMMUNI "Use system communi library" OFF) -option(USE_SYSTEM_QTKEYCHAIN "Use system QtKeychain library" OFF) -option(BUILD_WITH_QTKEYCHAIN "Build Chatterino with support for your system key chain" ON) option(USE_SYSTEM_MINIAUDIO "Build Chatterino with your system miniaudio" OFF) option(BUILD_WITH_CRASHPAD "Build chatterino with crashpad" OFF) option(USE_PRECOMPILED_HEADERS "Use precompiled headers (Temporarily not supported on macOS)" ON) option(BUILD_WITH_QT6 "Build with Qt6" On) option(BUILD_WITH_LIBNOTIFY "Build with libnotify" ON) option(CHATTERINO_GENERATE_COVERAGE "Generate coverage files" OFF) -# We don't use translations, and we don't want qtkeychain to build translations -option(BUILD_TRANSLATIONS "" OFF) option(BUILD_SHARED_LIBS "" OFF) option(CHATTERINO_LTO "Enable LTO for all targets" OFF) # CMake doesn't detect LTO for some compilers (e.g. clang-cl: https://gitlab.kitware.com/cmake/cmake/-/issues/21635), @@ -196,32 +192,6 @@ else() add_subdirectory("${LIBCOMMUNI_ROOT_LIB_FOLDER}" EXCLUDE_FROM_ALL) endif() -if (BUILD_WITH_QTKEYCHAIN) - # Link QtKeychain statically - if (USE_SYSTEM_QTKEYCHAIN) - find_package(Qt${MAJOR_QT_VERSION}Keychain REQUIRED) - else() - set(QTKEYCHAIN_ROOT_LIB_FOLDER "${CMAKE_SOURCE_DIR}/lib/qtkeychain") - if (NOT EXISTS "${QTKEYCHAIN_ROOT_LIB_FOLDER}/CMakeLists.txt") - message(FATAL_ERROR "Submodules probably not loaded, unable to find lib/qtkeychain/CMakeLists.txt") - endif() - - set(_prev_testing ${BUILD_TESTING}) - set(BUILD_TESTING Off) - add_subdirectory("${QTKEYCHAIN_ROOT_LIB_FOLDER}" EXCLUDE_FROM_ALL) - set(BUILD_TESTING ${_prev_testing}) - - if (NOT TARGET qt${MAJOR_QT_VERSION}keychain) - message(FATAL_ERROR "qt${MAJOR_QT_VERSION}keychain target was not created :@") - endif() - if (MSVC AND "${MAJOR_QT_VERSION}" STREQUAL "5") - target_compile_definitions(qt5keychain PRIVATE UNICODE) - target_compile_options(qt5keychain PRIVATE /utf-8) - set_target_properties(qt5keychain PROPERTIES CXX_STANDARD 17) - endif() - endif() -endif() - if (BUILD_TESTS) include(GoogleTest) # For MSVC: Prevent overriding the parent project's compiler/linker settings diff --git a/lib/qtkeychain b/lib/qtkeychain deleted file mode 160000 index 53a8e6a31..000000000 --- a/lib/qtkeychain +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 53a8e6a31f7d24bc58d91515cc7fcbb34af554db diff --git a/resources/licenses/qtkeychain.txt b/resources/licenses/qtkeychain.txt deleted file mode 100644 index cca2a5c9a..000000000 --- a/resources/licenses/qtkeychain.txt +++ /dev/null @@ -1,20 +0,0 @@ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7fb4639eb..a5f2eff2f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,8 +26,6 @@ set(SOURCE_FILES common/ChatterinoSetting.hpp common/ChatterSet.cpp common/ChatterSet.hpp - common/Credentials.cpp - common/Credentials.hpp common/Env.cpp common/Env.hpp common/LastMessageLineStyle.hpp @@ -888,6 +886,12 @@ list(APPEND SOURCE_FILES ${RES_AUTOGEN_FILES}) add_library(${LIBRARY_PROJECT} OBJECT ${SOURCE_FILES}) +if (APPLE) + target_link_libraries(${LIBRARY_PROJECT} PRIVATE + "$" + ) +endif () + if(CHATTERINO_PLUGINS) target_compile_definitions(${LIBRARY_PROJECT} PUBLIC @@ -916,7 +920,6 @@ if (CHATTERINO_GENERATE_COVERAGE) EXCLUDE "lib/lua/*" EXCLUDE "lib/magic_enum/*" EXCLUDE "lib/miniaudio/*" - EXCLUDE "lib/qtkeychain/*" EXCLUDE "lib/rapidjson/*" EXCLUDE "lib/semver/*" EXCLUDE "lib/serialize/*" @@ -977,18 +980,6 @@ if (CHATTERINO_ALLOW_PRIVATE_QT_API) CHATTERINO_WITH_PRIVATE_QT_API) endif() -if (BUILD_WITH_QTKEYCHAIN) - target_link_libraries(${LIBRARY_PROJECT} - PUBLIC - qt${MAJOR_QT_VERSION}keychain - ) -else() - target_compile_definitions(${LIBRARY_PROJECT} - PUBLIC - NO_QTKEYCHAIN - ) -endif() - # Set the output of TARGET to be # - CMAKE_BIN_DIR/lib for libraries # - CMAKE_BIN_DIR/bin for BINARIES @@ -1200,11 +1191,6 @@ set(_c2_qt_defs target_compile_definitions(${VERSION_PROJECT} PUBLIC ${_c2_qt_defs}) target_compile_definitions(${LIBRARY_PROJECT} PUBLIC ${_c2_qt_defs}) -if (USE_SYSTEM_QTKEYCHAIN) - target_compile_definitions(${LIBRARY_PROJECT} PUBLIC - CMAKE_BUILD - ) -endif () if (WIN32) target_compile_definitions(${LIBRARY_PROJECT} PUBLIC USEWINSDK diff --git a/src/common/Credentials.cpp b/src/common/Credentials.cpp deleted file mode 100644 index 39a9f12e8..000000000 --- a/src/common/Credentials.cpp +++ /dev/null @@ -1,274 +0,0 @@ -// SPDX-FileCopyrightText: 2019 Contributors to Chatterino -// -// SPDX-License-Identifier: MIT - -#include "common/Credentials.hpp" - -#include "Application.hpp" -#include "common/Modes.hpp" -#include "debug/AssertInGuiThread.hpp" -#include "singletons/Paths.hpp" -#include "singletons/Settings.hpp" -#include "util/CombinePath.hpp" -#include "util/Variant.hpp" - -#include -#include -#include -#include -#include - -#include - -#ifndef NO_QTKEYCHAIN -# ifdef CMAKE_BUILD -# include "qt6keychain/keychain.h" -# else -# include -# endif -#endif - -namespace { - -using namespace chatterino; - -QString formatName(const QString &provider, const QString &name) -{ - assert(!provider.contains(":")); - return u"chatterino:" % provider % u':' % name; -} - -bool useKeyring() -{ -#ifdef NO_QTKEYCHAIN - return false; -#endif - if (Modes::instance().isPortable) - { - return false; - } - -#ifdef Q_OS_LINUX - return getSettings()->useKeyring; -#else - return true; -#endif -} - -// Insecure storage: -QString insecurePath() -{ - return combinePath(getApp()->getPaths().settingsDirectory, - "credentials.json"); -} - -QJsonDocument loadInsecure() -{ - QFile file(insecurePath()); - if (!file.open(QIODevice::ReadOnly)) - { - return {}; - } - - return QJsonDocument::fromJson(file.readAll()); -} - -void storeInsecure(const QJsonDocument &doc) -{ - QSaveFile file(insecurePath()); - if (!file.open(QIODevice::WriteOnly)) - { - return; - } - file.write(doc.toJson()); - file.commit(); -} - -QJsonDocument &insecureInstance() -{ - static auto store = loadInsecure(); - return store; -} - -void queueInsecureSave() -{ - static bool isQueued = false; - - if (!isQueued) - { - isQueued = true; - QTimer::singleShot(200, QApplication::instance(), [] { - storeInsecure(insecureInstance()); - isQueued = false; - }); - } -} - -// QKeychain runs jobs asyncronously, so we have to assure that set/erase -// jobs gets executed in order. -struct SetJob { - QString name; - QString credential; -}; - -struct EraseJob { - QString name; -}; - -using Job = std::variant; - -std::queue &jobQueue() -{ - static std::queue jobs; - return jobs; -} - -void runNextJob() -{ -#ifndef NO_QTKEYCHAIN - auto &&queue = jobQueue(); - - if (!queue.empty()) - { - // we were gonna use std::visit here but macos is shit - - auto &&item = queue.front(); - - std::visit( - variant::Overloaded{ - [](const SetJob &set) { - auto *job = new QKeychain::WritePasswordJob("chatterino"); - job->setAutoDelete(true); - job->setKey(set.name); - job->setTextData(set.credential); - QObject::connect(job, &QKeychain::Job::finished, - QApplication::instance(), [](auto) { - runNextJob(); - }); - job->start(); - }, - [](const EraseJob &erase) { - auto *job = new QKeychain::DeletePasswordJob("chatterino"); - job->setAutoDelete(true); - job->setKey(erase.name); - QObject::connect(job, &QKeychain::Job::finished, - QApplication::instance(), [](auto) { - runNextJob(); - }); - job->start(); - }, - }, - item); - - queue.pop(); - } -#endif -} - -void queueJob(Job &&job) -{ - auto &&queue = jobQueue(); - - queue.push(std::move(job)); - if (queue.size() == 1) - { - runNextJob(); - } -} - -} // namespace - -namespace chatterino { - -Credentials &Credentials::instance() -{ - static Credentials creds; - return creds; -} - -// NOLINTNEXTLINE(readability-convert-member-functions-to-static) -void Credentials::get(const QString &provider, const QString &name_, - QObject *receiver, - std::function &&onLoaded) -{ - assertInGuiThread(); - - auto name = formatName(provider, name_); - - if (useKeyring()) - { -#ifndef NO_QTKEYCHAIN - // if NO_QTKEYCHAIN is set, then this code is never used either way - auto *job = new QKeychain::ReadPasswordJob("chatterino"); - job->setAutoDelete(true); - job->setKey(name); - QObject::connect( - job, &QKeychain::Job::finished, receiver, - [job, onLoaded = std::move(onLoaded)](auto) mutable { - onLoaded(job->textData()); - }, - Qt::DirectConnection); - job->start(); -#endif - } - else - { - const auto &instance = insecureInstance(); - - onLoaded(instance[name].toString()); - } -} - -// NOLINTNEXTLINE(readability-convert-member-functions-to-static) -void Credentials::set(const QString &provider, const QString &name_, - const QString &credential) -{ - assertInGuiThread(); - - /// On linux, we try to use a keychain but show a message to disable it when it fails. - /// XXX: add said message - - auto name = formatName(provider, name_); - - if (useKeyring()) - { - queueJob(SetJob{name, credential}); - } - else - { - auto &instance = insecureInstance(); - - auto obj = instance.object(); - obj[name] = credential; - instance.setObject(obj); - - queueInsecureSave(); - } -} - -// NOLINTNEXTLINE(readability-convert-member-functions-to-static) -void Credentials::erase(const QString &provider, const QString &name_) -{ - assertInGuiThread(); - - auto name = formatName(provider, name_); - - if (useKeyring()) - { - queueJob(EraseJob{name}); - } - else - { - auto &instance = insecureInstance(); - - if (auto it = instance.object().find(name); - it != instance.object().end()) - { - instance.object().erase(it); - } - - queueInsecureSave(); - } -} - -} // namespace chatterino diff --git a/src/common/Credentials.hpp b/src/common/Credentials.hpp deleted file mode 100644 index 7ce931ac3..000000000 --- a/src/common/Credentials.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: 2019 Contributors to Chatterino -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include - -#include - -namespace chatterino { - -class Credentials -{ -public: - static Credentials &instance(); - - void get(const QString &provider, const QString &name, QObject *receiver, - std::function &&onLoaded); - void set(const QString &provider, const QString &name, - const QString &credential); - void erase(const QString &provider, const QString &name); - -private: - Credentials() = default; -}; - -} // namespace chatterino diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index b9515fa7b..603e44eb3 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -726,9 +726,6 @@ public: /// Misc BoolSetting betaUpdates = {"/misc/beta", false}; -#ifdef Q_OS_LINUX - BoolSetting useKeyring = {"/misc/useKeyring", true}; -#endif IntSetting startUpNotification = {"/misc/startUpNotification", 0}; QStringSetting currentVersion = {"/misc/currentVersion", ""}; diff --git a/src/widgets/Window.cpp b/src/widgets/Window.cpp index 52be6773a..0d884a486 100644 --- a/src/widgets/Window.cpp +++ b/src/widgets/Window.cpp @@ -7,7 +7,6 @@ #include "Application.hpp" #include "common/Args.hpp" #include "common/Common.hpp" -#include "common/Credentials.hpp" #include "common/Modes.hpp" #include "common/QLogging.hpp" #include "common/Version.hpp" diff --git a/src/widgets/settingspages/AboutPage.cpp b/src/widgets/settingspages/AboutPage.cpp index 5016fd09c..dd7c69f03 100644 --- a/src/widgets/settingspages/AboutPage.cpp +++ b/src/widgets/settingspages/AboutPage.cpp @@ -121,11 +121,6 @@ AboutPage::AboutPage() addLicense(form.getElement(), "Pajlada/Serialize", "https://github.com/pajlada/serialize", ":/licenses/pajlada_serialize.txt"); -#ifndef NO_QTKEYCHAIN - addLicense(form.getElement(), "QtKeychain", - "https://github.com/frankosterfeld/qtkeychain", - ":/licenses/qtkeychain.txt"); -#endif addLicense(form.getElement(), "lrucache", "https://github.com/lamerman/cpp-lru-cache", ":/licenses/lrucache.txt"); diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp index 5e4e079d9..3707fd1a2 100644 --- a/src/widgets/settingspages/GeneralPage.cpp +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -1364,16 +1364,6 @@ void GeneralPage::initLayout(GeneralPageView &layout) ->setTooltip("When possible, restart Chatterino if the program crashes") ->addTo(layout); -#if defined(Q_OS_LINUX) && !defined(NO_QTKEYCHAIN) - if (!getApp()->getPaths().isPortable()) - { - SettingWidget::checkbox( - "Use libsecret/KWallet/Gnome keychain to secure passwords", - s.useKeyring) - ->addTo(layout); - } -#endif - SettingWidget::inverseCheckbox("Show moderation messages", s.hideModerationActions) ->setTooltip(