fix: deadlock and use-after-free in tests (#4981)
* fix: use-after-free in settings * refactor: put seventv api into a singleton * chore: add changelog entry * Add warning for when the 7TV load fails
This commit is contained in:
@@ -69,6 +69,7 @@
|
|||||||
- Dev: Removed `Outcome` from network requests. (#4959)
|
- Dev: Removed `Outcome` from network requests. (#4959)
|
||||||
- Dev: Added Tests for Windows and MacOS in CI. (#4970)
|
- Dev: Added Tests for Windows and MacOS in CI. (#4970)
|
||||||
- Dev: Refactored the Image Uploader feature. (#4971)
|
- Dev: Refactored the Image Uploader feature. (#4971)
|
||||||
|
- Dev: Fixed deadlock and use-after-free in tests. (#4981)
|
||||||
|
|
||||||
## 2.4.6
|
## 2.4.6
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,11 @@ public:
|
|||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SeventvAPI *getSeventvAPI() override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino::mock
|
} // namespace chatterino::mock
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "controllers/hotkeys/HotkeyController.hpp"
|
#include "controllers/hotkeys/HotkeyController.hpp"
|
||||||
#include "controllers/ignores/IgnoreController.hpp"
|
#include "controllers/ignores/IgnoreController.hpp"
|
||||||
#include "controllers/notifications/NotificationController.hpp"
|
#include "controllers/notifications/NotificationController.hpp"
|
||||||
|
#include "providers/seventv/SeventvAPI.hpp"
|
||||||
#include "singletons/ImageUploader.hpp"
|
#include "singletons/ImageUploader.hpp"
|
||||||
#ifdef CHATTERINO_HAVE_PLUGINS
|
#ifdef CHATTERINO_HAVE_PLUGINS
|
||||||
# include "controllers/plugins/PluginController.hpp"
|
# include "controllers/plugins/PluginController.hpp"
|
||||||
@@ -81,6 +82,7 @@ Application::Application(Settings &_settings, Paths &_paths)
|
|||||||
, windows(&this->emplace<WindowManager>())
|
, windows(&this->emplace<WindowManager>())
|
||||||
, toasts(&this->emplace<Toasts>())
|
, toasts(&this->emplace<Toasts>())
|
||||||
, imageUploader(&this->emplace<ImageUploader>())
|
, imageUploader(&this->emplace<ImageUploader>())
|
||||||
|
, seventvAPI(&this->emplace<SeventvAPI>())
|
||||||
|
|
||||||
, commands(&this->emplace<CommandController>())
|
, commands(&this->emplace<CommandController>())
|
||||||
, notifications(&this->emplace<NotificationController>())
|
, notifications(&this->emplace<NotificationController>())
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class ChatterinoBadges;
|
|||||||
class FfzBadges;
|
class FfzBadges;
|
||||||
class SeventvBadges;
|
class SeventvBadges;
|
||||||
class ImageUploader;
|
class ImageUploader;
|
||||||
|
class SeventvAPI;
|
||||||
|
|
||||||
class IApplication
|
class IApplication
|
||||||
{
|
{
|
||||||
@@ -68,6 +69,7 @@ public:
|
|||||||
virtual IUserDataController *getUserData() = 0;
|
virtual IUserDataController *getUserData() = 0;
|
||||||
virtual ITwitchLiveController *getTwitchLiveController() = 0;
|
virtual ITwitchLiveController *getTwitchLiveController() = 0;
|
||||||
virtual ImageUploader *getImageUploader() = 0;
|
virtual ImageUploader *getImageUploader() = 0;
|
||||||
|
virtual SeventvAPI *getSeventvAPI() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Application : public IApplication
|
class Application : public IApplication
|
||||||
@@ -97,6 +99,7 @@ public:
|
|||||||
WindowManager *const windows{};
|
WindowManager *const windows{};
|
||||||
Toasts *const toasts{};
|
Toasts *const toasts{};
|
||||||
ImageUploader *const imageUploader{};
|
ImageUploader *const imageUploader{};
|
||||||
|
SeventvAPI *const seventvAPI{};
|
||||||
|
|
||||||
CommandController *const commands{};
|
CommandController *const commands{};
|
||||||
NotificationController *const notifications{};
|
NotificationController *const notifications{};
|
||||||
@@ -174,6 +177,10 @@ public:
|
|||||||
{
|
{
|
||||||
return this->imageUploader;
|
return this->imageUploader;
|
||||||
}
|
}
|
||||||
|
SeventvAPI *getSeventvAPI() override
|
||||||
|
{
|
||||||
|
return this->seventvAPI;
|
||||||
|
}
|
||||||
|
|
||||||
pajlada::Signals::NoArgSignal streamerModeChanged;
|
pajlada::Signals::NoArgSignal streamerModeChanged;
|
||||||
|
|
||||||
|
|||||||
@@ -78,11 +78,5 @@ void SeventvAPI::updatePresence(const QString &twitchChannelID,
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
SeventvAPI &getSeventvAPI()
|
|
||||||
{
|
|
||||||
static SeventvAPI instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
// NOLINTEND(readability-convert-member-functions-to-static)
|
// NOLINTEND(readability-convert-member-functions-to-static)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/Singleton.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
class QString;
|
class QString;
|
||||||
@@ -9,25 +11,33 @@ namespace chatterino {
|
|||||||
|
|
||||||
class NetworkResult;
|
class NetworkResult;
|
||||||
|
|
||||||
class SeventvAPI
|
class SeventvAPI : public Singleton
|
||||||
{
|
{
|
||||||
using ErrorCallback = std::function<void(const NetworkResult &)>;
|
using ErrorCallback = std::function<void(const NetworkResult &)>;
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
using SuccessCallback = std::function<void(T...)>;
|
using SuccessCallback = std::function<void(T...)>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void getUserByTwitchID(const QString &twitchID,
|
SeventvAPI() = default;
|
||||||
SuccessCallback<const QJsonObject &> &&onSuccess,
|
~SeventvAPI() override = default;
|
||||||
ErrorCallback &&onError);
|
|
||||||
void getEmoteSet(const QString &emoteSet,
|
|
||||||
SuccessCallback<const QJsonObject &> &&onSuccess,
|
|
||||||
ErrorCallback &&onError);
|
|
||||||
|
|
||||||
void updatePresence(const QString &twitchChannelID,
|
SeventvAPI(const SeventvAPI &) = delete;
|
||||||
const QString &seventvUserID,
|
SeventvAPI(SeventvAPI &&) = delete;
|
||||||
SuccessCallback<> &&onSuccess, ErrorCallback &&onError);
|
SeventvAPI &operator=(const SeventvAPI &) = delete;
|
||||||
|
SeventvAPI &operator=(SeventvAPI &&) = delete;
|
||||||
|
|
||||||
|
virtual void getUserByTwitchID(
|
||||||
|
const QString &twitchID,
|
||||||
|
SuccessCallback<const QJsonObject &> &&onSuccess,
|
||||||
|
ErrorCallback &&onError);
|
||||||
|
virtual void getEmoteSet(const QString &emoteSet,
|
||||||
|
SuccessCallback<const QJsonObject &> &&onSuccess,
|
||||||
|
ErrorCallback &&onError);
|
||||||
|
|
||||||
|
virtual void updatePresence(const QString &twitchChannelID,
|
||||||
|
const QString &seventvUserID,
|
||||||
|
SuccessCallback<> &&onSuccess,
|
||||||
|
ErrorCallback &&onError);
|
||||||
};
|
};
|
||||||
|
|
||||||
SeventvAPI &getSeventvAPI();
|
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -2,15 +2,12 @@
|
|||||||
|
|
||||||
#include "messages/Emote.hpp"
|
#include "messages/Emote.hpp"
|
||||||
#include "messages/Image.hpp"
|
#include "messages/Image.hpp"
|
||||||
#include "providers/seventv/SeventvAPI.hpp"
|
|
||||||
#include "providers/seventv/SeventvEmotes.hpp"
|
#include "providers/seventv/SeventvEmotes.hpp"
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
std::optional<EmotePtr> SeventvBadges::getBadge(const UserId &id) const
|
std::optional<EmotePtr> SeventvBadges::getBadge(const UserId &id) const
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "providers/seventv/SeventvEmotes.hpp"
|
#include "providers/seventv/SeventvEmotes.hpp"
|
||||||
|
|
||||||
|
#include "Application.hpp"
|
||||||
#include "common/Literals.hpp"
|
#include "common/Literals.hpp"
|
||||||
#include "common/NetworkResult.hpp"
|
#include "common/NetworkResult.hpp"
|
||||||
#include "common/QLogging.hpp"
|
#include "common/QLogging.hpp"
|
||||||
@@ -214,7 +215,7 @@ void SeventvEmotes::loadGlobalEmotes()
|
|||||||
|
|
||||||
qCDebug(chatterinoSeventv) << "Loading 7TV Global Emotes";
|
qCDebug(chatterinoSeventv) << "Loading 7TV Global Emotes";
|
||||||
|
|
||||||
getSeventvAPI().getEmoteSet(
|
getIApp()->getSeventvAPI()->getEmoteSet(
|
||||||
u"global"_s,
|
u"global"_s,
|
||||||
[this](const auto &json) {
|
[this](const auto &json) {
|
||||||
QJsonArray parsedEmotes = json["emotes"].toArray();
|
QJsonArray parsedEmotes = json["emotes"].toArray();
|
||||||
@@ -243,7 +244,7 @@ void SeventvEmotes::loadChannelEmotes(
|
|||||||
qCDebug(chatterinoSeventv)
|
qCDebug(chatterinoSeventv)
|
||||||
<< "Reloading 7TV Channel Emotes" << channelId << manualRefresh;
|
<< "Reloading 7TV Channel Emotes" << channelId << manualRefresh;
|
||||||
|
|
||||||
getSeventvAPI().getUserByTwitchID(
|
getIApp()->getSeventvAPI()->getUserByTwitchID(
|
||||||
channelId,
|
channelId,
|
||||||
[callback = std::move(callback), channel, channelId,
|
[callback = std::move(callback), channel, channelId,
|
||||||
manualRefresh](const auto &json) {
|
manualRefresh](const auto &json) {
|
||||||
@@ -405,7 +406,7 @@ void SeventvEmotes::getEmoteSet(
|
|||||||
{
|
{
|
||||||
qCDebug(chatterinoSeventv) << "Loading 7TV Emote Set" << emoteSetId;
|
qCDebug(chatterinoSeventv) << "Loading 7TV Emote Set" << emoteSetId;
|
||||||
|
|
||||||
getSeventvAPI().getEmoteSet(
|
getIApp()->getSeventvAPI()->getEmoteSet(
|
||||||
emoteSetId,
|
emoteSetId,
|
||||||
[callback = std::move(successCallback), emoteSetId](const auto &json) {
|
[callback = std::move(successCallback), emoteSetId](const auto &json) {
|
||||||
auto parsedEmotes = json["emotes"].toArray();
|
auto parsedEmotes = json["emotes"].toArray();
|
||||||
|
|||||||
@@ -491,7 +491,15 @@ void TwitchAccount::loadSeventvUserID()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSeventvAPI().getUserByTwitchID(
|
auto *seventv = getIApp()->getSeventvAPI();
|
||||||
|
if (!seventv)
|
||||||
|
{
|
||||||
|
qCWarning(chatterinoSeventv)
|
||||||
|
<< "Not loading 7TV User ID because the 7TV API is not initialized";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
seventv->getUserByTwitchID(
|
||||||
this->getUserId(),
|
this->getUserId(),
|
||||||
[this](const auto &json) {
|
[this](const auto &json) {
|
||||||
const auto id = json["user"]["id"].toString();
|
const auto id = json["user"]["id"].toString();
|
||||||
|
|||||||
@@ -1646,7 +1646,7 @@ void TwitchChannel::updateSevenTVActivity()
|
|||||||
|
|
||||||
qCDebug(chatterinoSeventv) << "Sending activity in" << this->getName();
|
qCDebug(chatterinoSeventv) << "Sending activity in" << this->getName();
|
||||||
|
|
||||||
getSeventvAPI().updatePresence(
|
getIApp()->getSeventvAPI()->updatePresence(
|
||||||
this->roomId(), currentSeventvUserID,
|
this->roomId(), currentSeventvUserID,
|
||||||
[chan = weakOf<Channel>(this)]() {
|
[chan = weakOf<Channel>(this)]() {
|
||||||
const auto self =
|
const auto self =
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ bool Settings::toggleMutedChannel(const QString &channelName)
|
|||||||
Settings *Settings::instance_ = nullptr;
|
Settings *Settings::instance_ = nullptr;
|
||||||
|
|
||||||
Settings::Settings(const QString &settingsDirectory)
|
Settings::Settings(const QString &settingsDirectory)
|
||||||
|
: prevInstance_(Settings::instance_)
|
||||||
{
|
{
|
||||||
QString settingsPath = settingsDirectory + "/settings.json";
|
QString settingsPath = settingsDirectory + "/settings.json";
|
||||||
|
|
||||||
@@ -188,7 +189,10 @@ Settings::Settings(const QString &settingsDirectory)
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::~Settings() = default;
|
Settings::~Settings()
|
||||||
|
{
|
||||||
|
Settings::instance_ = this->prevInstance_;
|
||||||
|
}
|
||||||
|
|
||||||
void Settings::saveSnapshot()
|
void Settings::saveSnapshot()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ enum UsernameRightClickBehavior : int {
|
|||||||
class Settings
|
class Settings
|
||||||
{
|
{
|
||||||
static Settings *instance_;
|
static Settings *instance_;
|
||||||
|
Settings *prevInstance_ = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Settings(const QString &settingsDirectory);
|
Settings(const QString &settingsDirectory);
|
||||||
|
|||||||
Reference in New Issue
Block a user