BrowserTab.cpp raw
 1#include "BrowserTab.h"
 2#include <QApplication>
 3#include <QFile>
 4#include <QStyle>
 5#include <QWebChannel>
 6#include <QWebEnginePage>
 7#include <QWebEngineProfile>
 8#include <QWebEngineScript>
 9#include <QWebEngineScriptCollection>
10#include <QWebEngineSettings>
11#include "PasswordHelper.h"
12#include "ThemeConfig.h"
13
14BrowserTab::BrowserTab(QWidget *parent) : QSplitter(Qt::Vertical, parent) {
15	view = new BrowserView;
16	devtools = new QWebEngineView;
17	passwordHelper = new PasswordHelper(this);
18
19	auto *channel = new QWebChannel(this);
20	channel->registerObject("passwordHelper", passwordHelper);
21	view->page()->setWebChannel(channel);
22
23	view->page()->setDevToolsPage(devtools->page());
24	devtools->hide();
25
26	addWidget(view);
27	addWidget(devtools);
28
29	// Initial layout ratio
30	setStretchFactor(0, 3);
31	setStretchFactor(1, 1);
32	setOpaqueResize(false);
33
34	view->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
35
36	// Visual handle for resizing
37	handle(1)->setAttribute(Qt::WA_Hover);
38	setStyleSheet(QString("QSplitter::handle { background: %1; height: 4px; }").arg(ThemeConfig::SplitterHandleColorLight));
39
40	// Close devtools if requested by the page (e.g. clicking 'x')
41	connect(devtools->page(), &QWebEnginePage::windowCloseRequested, [this]() { setDevToolsVisible(false); });
42
43	setupScripts();
44}
45
46void BrowserTab::setupScripts() {
47	QWebEngineScript qwebchannel;
48	QFile file(":/js/qwebchannel.js");
49	if (file.open(QIODevice::ReadOnly)) {
50		qwebchannel.setSourceCode(file.readAll());
51		qwebchannel.setName("qwebchannel.js");
52		qwebchannel.setWorldId(QWebEngineScript::MainWorld);
53		qwebchannel.setInjectionPoint(QWebEngineScript::DocumentCreation);
54		qwebchannel.setRunsOnSubFrames(true);
55		view->page()->scripts().insert(qwebchannel);
56	} else {
57		qCritical() << "Failed to load bundled qwebchannel.js from resources!";
58	}
59
60	QWebEngineScript passwordScript;
61	QFile scriptFile(":/js/capture.js");
62	if (scriptFile.open(QIODevice::ReadOnly)) {
63		passwordScript.setSourceCode(scriptFile.readAll());
64		passwordScript.setName("passwordScript");
65		passwordScript.setWorldId(QWebEngineScript::MainWorld);
66		passwordScript.setInjectionPoint(QWebEngineScript::DocumentReady);
67		passwordScript.setRunsOnSubFrames(true);
68		view->page()->scripts().insert(passwordScript);
69	} else {
70		qCritical() << "Failed to load capture.js from resources!";
71	}
72}
73
74void BrowserTab::setDevToolsVisible(bool visible) {
75	devtools->setVisible(visible);
76	if (visible) {
77		int h = height();
78		setSizes({static_cast<int>(h * 0.7), static_cast<int>(h * 0.3)});
79	} else {
80		setSizes({height(), 0});
81	}
82}
83
84void BrowserTab::updateTabTheme(bool dark) {
85	view->settings()->setAttribute(QWebEngineSettings::ForceDarkMode, false);
86	devtools->settings()->setAttribute(QWebEngineSettings::ForceDarkMode, false);
87
88	view->page()->setBackgroundColor(dark ? QColor(45, 45, 45) : Qt::white);
89	devtools->page()->setBackgroundColor(dark ? QColor(45, 45, 45) : Qt::white);
90
91	// Keep the view palette default to allow it to inherit from the application
92	view->setPalette(QPalette());
93	devtools->setPalette(QPalette());
94
95	QString handleColor = dark ? ThemeConfig::SplitterHandleColorDark : ThemeConfig::SplitterHandleColorLight;
96	setStyleSheet(QString("QSplitter::handle { background: %1; height: 4px; }").arg(handleColor));
97}