mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-03-27 10:52:16 -04:00
286 lines
7.3 KiB
C++
286 lines
7.3 KiB
C++
/******************************************************************************
|
|
Copyright (C) 2023 by Lain Bailey <lain@obsproject.com>
|
|
|
|
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
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
******************************************************************************/
|
|
|
|
#include "OBSBasic.hpp"
|
|
|
|
#ifdef BROWSER_AVAILABLE
|
|
#include <dialogs/OBSExtraBrowsers.hpp>
|
|
#include <docks/BrowserDock.hpp>
|
|
|
|
#include <json11.hpp>
|
|
#include <qt-wrappers.hpp>
|
|
|
|
#include <QDir>
|
|
|
|
using namespace json11;
|
|
#endif
|
|
|
|
#include <random>
|
|
|
|
struct QCef;
|
|
struct QCefCookieManager;
|
|
|
|
QCef *cef = nullptr;
|
|
QCefCookieManager *panel_cookies = nullptr;
|
|
bool cef_js_avail = false;
|
|
|
|
#ifdef BROWSER_AVAILABLE
|
|
void OBSBasic::ClearExtraBrowserDocks()
|
|
{
|
|
extraBrowserDockTargets.clear();
|
|
extraBrowserDockNames.clear();
|
|
extraBrowserDocks.clear();
|
|
}
|
|
|
|
void OBSBasic::LoadExtraBrowserDocks()
|
|
{
|
|
const char *jsonStr = config_get_string(App()->GetUserConfig(), "BasicWindow", "ExtraBrowserDocks");
|
|
|
|
std::string err;
|
|
Json json = Json::parse(jsonStr, err);
|
|
if (!err.empty())
|
|
return;
|
|
|
|
Json::array array = json.array_items();
|
|
if (!array.empty())
|
|
extraBrowserMenuDocksSeparator = ui->menuDocks->addSeparator();
|
|
|
|
for (Json &item : array) {
|
|
std::string title = item["title"].string_value();
|
|
std::string url = item["url"].string_value();
|
|
std::string uuid = item["uuid"].string_value();
|
|
|
|
AddExtraBrowserDock(title.c_str(), url.c_str(), uuid.c_str(), false);
|
|
}
|
|
}
|
|
|
|
void OBSBasic::SaveExtraBrowserDocks()
|
|
{
|
|
Json::array array;
|
|
for (int i = 0; i < extraBrowserDocks.size(); i++) {
|
|
QDockWidget *dock = extraBrowserDocks[i].get();
|
|
QString title = extraBrowserDockNames[i];
|
|
QString url = extraBrowserDockTargets[i];
|
|
QString uuid = dock->property("uuid").toString();
|
|
Json::object obj{
|
|
{"title", QT_TO_UTF8(title)},
|
|
{"url", QT_TO_UTF8(url)},
|
|
{"uuid", QT_TO_UTF8(uuid)},
|
|
};
|
|
array.push_back(obj);
|
|
}
|
|
|
|
std::string output = Json(array).dump();
|
|
config_set_string(App()->GetUserConfig(), "BasicWindow", "ExtraBrowserDocks", output.c_str());
|
|
}
|
|
|
|
void OBSBasic::ManageExtraBrowserDocks()
|
|
{
|
|
if (!extraBrowsers.isNull()) {
|
|
extraBrowsers->show();
|
|
extraBrowsers->raise();
|
|
return;
|
|
}
|
|
|
|
extraBrowsers = new OBSExtraBrowsers(this);
|
|
extraBrowsers->show();
|
|
}
|
|
|
|
void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url, const QString &uuid, bool firstCreate)
|
|
{
|
|
static int panel_version = -1;
|
|
if (panel_version == -1) {
|
|
panel_version = obs_browser_qcef_version();
|
|
}
|
|
|
|
BrowserDock *dock = new BrowserDock(title);
|
|
QString bId(uuid.isEmpty() ? QUuid::createUuid().toString() : uuid);
|
|
bId.replace(QRegularExpression("[{}-]"), "");
|
|
dock->setProperty("uuid", bId);
|
|
dock->setObjectName(title + OBJ_NAME_SUFFIX);
|
|
dock->resize(460, 600);
|
|
dock->setMinimumSize(80, 80);
|
|
dock->setWindowTitle(title);
|
|
dock->setAllowedAreas(Qt::AllDockWidgetAreas);
|
|
|
|
QCefWidget *browser = cef->create_widget(dock, QT_TO_UTF8(url), nullptr);
|
|
if (browser && panel_version >= 1)
|
|
browser->allowAllPopups(true);
|
|
|
|
dock->SetWidget(browser);
|
|
|
|
/* Add support for Twitch Dashboard panels */
|
|
if (url.contains("twitch.tv/popout") && url.contains("dashboard/live")) {
|
|
QRegularExpression re("twitch.tv\\/popout\\/([^/]+)\\/");
|
|
QRegularExpressionMatch match = re.match(url);
|
|
QString username = match.captured(1);
|
|
if (username.length() > 0) {
|
|
std::string script;
|
|
script = "Object.defineProperty(document, 'referrer', { get: () => '";
|
|
script += "https://twitch.tv/";
|
|
script += QT_TO_UTF8(username);
|
|
script += "/dashboard/live";
|
|
script += "'});";
|
|
browser->setStartupScript(script);
|
|
}
|
|
}
|
|
|
|
AddDockWidget(dock, Qt::RightDockWidgetArea, true);
|
|
extraBrowserDocks.push_back(std::shared_ptr<QDockWidget>(dock));
|
|
extraBrowserDockNames.push_back(title);
|
|
extraBrowserDockTargets.push_back(url);
|
|
|
|
if (firstCreate) {
|
|
dock->setFloating(true);
|
|
|
|
QPoint curPos = pos();
|
|
QSize wSizeD2 = size() / 2;
|
|
QSize dSizeD2 = dock->size() / 2;
|
|
|
|
curPos.setX(curPos.x() + wSizeD2.width() - dSizeD2.width());
|
|
curPos.setY(curPos.y() + wSizeD2.height() - dSizeD2.height());
|
|
|
|
dock->move(curPos);
|
|
dock->setVisible(true);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static std::string GenId()
|
|
{
|
|
std::random_device rd;
|
|
std::mt19937_64 e2(rd());
|
|
std::uniform_int_distribution<uint64_t> dist(0, 0xFFFFFFFFFFFFFFFF);
|
|
|
|
uint64_t id = dist(e2);
|
|
|
|
char id_str[20];
|
|
snprintf(id_str, sizeof(id_str), "%16llX", (unsigned long long)id);
|
|
return std::string(id_str);
|
|
}
|
|
|
|
void CheckExistingCookieId()
|
|
{
|
|
OBSBasic *main = OBSBasic::Get();
|
|
if (config_has_user_value(main->Config(), "Panels", "CookieId"))
|
|
return;
|
|
|
|
config_set_string(main->Config(), "Panels", "CookieId", GenId().c_str());
|
|
}
|
|
|
|
#ifdef BROWSER_AVAILABLE
|
|
static void InitPanelCookieManager()
|
|
{
|
|
if (!cef)
|
|
return;
|
|
if (panel_cookies)
|
|
return;
|
|
|
|
CheckExistingCookieId();
|
|
|
|
OBSBasic *main = OBSBasic::Get();
|
|
const char *cookie_id = config_get_string(main->Config(), "Panels", "CookieId");
|
|
|
|
std::string sub_path;
|
|
sub_path += "obs_profile_cookies/";
|
|
sub_path += cookie_id;
|
|
|
|
panel_cookies = cef->create_cookie_manager(sub_path);
|
|
}
|
|
#endif
|
|
|
|
void DestroyPanelCookieManager()
|
|
{
|
|
#ifdef BROWSER_AVAILABLE
|
|
if (panel_cookies) {
|
|
panel_cookies->FlushStore();
|
|
delete panel_cookies;
|
|
panel_cookies = nullptr;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DeleteCookies()
|
|
{
|
|
#ifdef BROWSER_AVAILABLE
|
|
if (panel_cookies) {
|
|
panel_cookies->DeleteCookies("", "");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DuplicateCurrentCookieProfile(ConfigFile &config)
|
|
{
|
|
#ifdef BROWSER_AVAILABLE
|
|
if (cef) {
|
|
OBSBasic *main = OBSBasic::Get();
|
|
std::string cookie_id = config_get_string(main->Config(), "Panels", "CookieId");
|
|
|
|
std::string src_path;
|
|
src_path += "obs_profile_cookies/";
|
|
src_path += cookie_id;
|
|
|
|
std::string new_id = GenId();
|
|
|
|
std::string dst_path;
|
|
dst_path += "obs_profile_cookies/";
|
|
dst_path += new_id;
|
|
|
|
BPtr<char> src_path_full = cef->get_cookie_path(src_path);
|
|
BPtr<char> dst_path_full = cef->get_cookie_path(dst_path);
|
|
|
|
QDir srcDir(src_path_full.Get());
|
|
QDir dstDir(dst_path_full.Get());
|
|
|
|
if (srcDir.exists()) {
|
|
if (!dstDir.exists())
|
|
dstDir.mkdir(dst_path_full.Get());
|
|
|
|
QStringList files = srcDir.entryList(QDir::Files);
|
|
for (const QString &file : files) {
|
|
QString src = QString(src_path_full);
|
|
QString dst = QString(dst_path_full);
|
|
src += QDir::separator() + file;
|
|
dst += QDir::separator() + file;
|
|
QFile::copy(src, dst);
|
|
}
|
|
}
|
|
|
|
config_set_string(config, "Panels", "CookieId", cookie_id.c_str());
|
|
config_set_string(main->Config(), "Panels", "CookieId", new_id.c_str());
|
|
}
|
|
#else
|
|
UNUSED_PARAMETER(config);
|
|
#endif
|
|
}
|
|
|
|
void OBSBasic::InitBrowserPanelSafeBlock()
|
|
{
|
|
#ifdef BROWSER_AVAILABLE
|
|
if (!cef)
|
|
return;
|
|
if (cef->init_browser()) {
|
|
InitPanelCookieManager();
|
|
return;
|
|
}
|
|
|
|
ExecThreadedWithoutBlocking([] { cef->wait_for_browser_init(); }, QTStr("BrowserPanelInit.Title"),
|
|
QTStr("BrowserPanelInit.Text"));
|
|
InitPanelCookieManager();
|
|
#endif
|
|
}
|