mirror of
https://github.com/obsproject/obs-studio.git
synced 2025-12-23 22:48:02 -05:00
At a glance, the GenId function looks like it can only return a 16-character hexadecimal string with all characters being [0-9A-F]. However, it seems that it can rarely return a 16-character string that has one or two space characters at the beginning due to the value of id, from which the final string is derived, being too low (lower than 1152921504606846976 or 0x1000000000000000) and the printf format specifier having a width of 16. This results in a string of less than 16 characters that is padded with blank spaces. The end result is a cookie directory that has leading spaces in its name, which can cause various issues, such as breaking syncing on OneDrive. If we set the format specifier to pad with zeroes instead of spaces, the resulting hexadecimal value is always 16 characters long without spaces.
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), "%016llX", (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
|
|
}
|