Falkon Develop
Cross-platform Qt-based web browser
mainapplication.cpp
Go to the documentation of this file.
1/* ============================================================
2* Falkon - Qt web browser
3* Copyright (C) 2010-2018 David Rosca <nowrep@gmail.com>
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation, either version 3 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17* ============================================================ */
18#include "mainapplication.h"
19#include "history.h"
20#include "qztools.h"
21#include "updater.h"
22#include "autofill.h"
23#include "settings.h"
24#include "autosaver.h"
25#include "datapaths.h"
26#include "tabwidget.h"
27#include "cookiejar.h"
28#include "bookmarks.h"
29#include "qzsettings.h"
30#include "proxystyle.h"
31#include "pluginproxy.h"
32#include "iconprovider.h"
33#include "browserwindow.h"
34#include "checkboxdialog.h"
35#include "networkmanager.h"
36#include "profilemanager.h"
37#include "browsinglibrary.h"
38#include "downloadmanager.h"
39#include "clearprivatedata.h"
40#include "useragentmanager.h"
41#include "commandlineoptions.h"
45#include "sitesettingsmanager.h"
46#include "scripts.h"
47#include "sessionmanager.h"
50#include "../config.h"
51
52#include <QWebEngineSettings>
53#include <QDesktopServices>
54#include <QFontDatabase>
55#include <QSqlDatabase>
56#include <QLibraryInfo>
57#include <QMessageBox>
58#include <QTranslator>
59#include <QThreadPool>
60#include <QSettings>
61#include <QProcess>
62#include <QTimer>
63#include <QDir>
64#include <QStandardPaths>
65#include <QWebEngineProfile>
66#include <QWebEngineScriptCollection>
67#include <QRegularExpression>
68#include <QtWebEngineWidgetsVersion>
69#include <QtWebEngineCoreVersion>
70
71#include <QWebEngineNotification>
72#include <QWebEngineUrlScheme>
73
74#ifdef Q_OS_WIN
75#include <QtWin>
76#include <QWinJumpList>
77#include <QWinJumpListCategory>
78#endif
79
80#include <iostream>
81
82#if defined(Q_OS_WIN) && !defined(Q_OS_OS2)
84#endif
85
86static bool s_testMode = false;
87
88MainApplication::MainApplication(int &argc, char** argv)
89 : QtSingleApplication(argc, argv)
90 , m_isPrivate(false)
91 , m_isPortable(false)
92 , m_isClosing(false)
93 , m_isStartingAfterCrash(false)
94 , m_history(nullptr)
95 , m_bookmarks(nullptr)
96 , m_autoFill(nullptr)
97 , m_cookieJar(nullptr)
98 , m_plugins(nullptr)
99 , m_browsingLibrary(nullptr)
100 , m_networkManager(nullptr)
101 , m_restoreManager(nullptr)
102 , m_sessionManager(nullptr)
103 , m_downloadManager(nullptr)
104 , m_userAgentManager(nullptr)
105 , m_searchEnginesManager(nullptr)
106 , m_closedWindowsManager(nullptr)
107 , m_protocolHandlerManager(nullptr)
108 , m_html5PermissionsManager(nullptr)
109 , m_siteSettingsManager(nullptr)
110 , m_desktopNotifications(nullptr)
111 , m_webProfile(nullptr)
112 , m_autoSaver(nullptr)
113#if defined(Q_OS_WIN) && !defined(Q_OS_OS2)
114 , m_registerQAppAssociation(0)
115#endif
116{
117 setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
118
119 setApplicationName(QStringLiteral("falkon"));
120 setOrganizationDomain(QStringLiteral("org.kde"));
121 setWindowIcon(QIcon::fromTheme(QSL("falkon"), QIcon(QSL(":icons/falkon.svg"))));
122 setDesktopFileName(QSL("org.kde.falkon"));
123
124#ifdef GIT_REVISION
125 setApplicationVersion(QSL("%1 (%2)").arg(QString::fromLatin1(Qz::VERSION), GIT_REVISION));
126#else
127 setApplicationVersion(QString::fromLatin1(Qz::VERSION));
128#endif
129
130 // Set fallback icon theme (eg. on Windows/Mac)
131 if (QIcon::fromTheme(QSL("view-refresh")).isNull()) {
132 QIcon::setThemeName(QSL("breeze-fallback"));
133 }
134
135 // QSQLITE database plugin is required
136 if (!QSqlDatabase::isDriverAvailable(QSL("QSQLITE"))) {
137 QMessageBox::critical(nullptr, QSL("Error"), QSL("Qt SQLite database plugin is not available. Please install it and restart the application."));
138 m_isClosing = true;
139 return;
140 }
141
142#ifdef Q_OS_WIN
143 // Set default app font (needed for N'ko)
144 int fontId = QFontDatabase::addApplicationFont(QSL("font.ttf"));
145 if (fontId != -1) {
146 const QStringList families = QFontDatabase::applicationFontFamilies(fontId);
147 if (!families.empty())
148 setFont(QFont(families.at(0)));
149 }
150#endif
151
152 QByteArray chromium_flags = qgetenv("QTWEBENGINE_CHROMIUM_FLAGS");
153 chromium_flags.append(" --enable-features=WebRTCPipeWireCapturer");
154 qputenv("QTWEBENGINE_CHROMIUM_FLAGS", chromium_flags);
155
156 QUrl startUrl;
157 QString startProfile;
158 QStringList messages;
159
160 bool noAddons = false;
161 bool newInstance = false;
162
163 if (argc > 1) {
165 const auto actions = cmd.getActions();
166 for (const CommandLineOptions::ActionPair &pair : actions) {
167 switch (pair.action) {
169 noAddons = true;
170 break;
172 startProfile = pair.text;
173 break;
175 m_isPortable = true;
176 break;
177 case Qz::CL_NewTab:
178 messages.append(QStringLiteral("ACTION:NewTab"));
179 m_postLaunchActions.append(OpenNewTab);
180 break;
181 case Qz::CL_NewWindow:
182 messages.append(QStringLiteral("ACTION:NewWindow"));
183 break;
185 messages.append(QStringLiteral("ACTION:ToggleFullScreen"));
186 m_postLaunchActions.append(ToggleFullScreen);
187 break;
189 messages.append(QStringLiteral("ACTION:ShowDownloadManager"));
190 m_postLaunchActions.append(OpenDownloadManager);
191 break;
193 m_isPrivate = true;
194 break;
196 newInstance = true;
197 break;
199 startUrl = QUrl::fromUserInput(pair.text);
200 messages.append(QSL("ACTION:OpenUrlInCurrentTab") + pair.text);
201 break;
203 startUrl = QUrl::fromUserInput(pair.text);
204 messages.append(QSL("ACTION:OpenUrlInNewWindow") + pair.text);
205 break;
206 case Qz::CL_OpenUrl:
207 startUrl = QUrl::fromUserInput(pair.text);
208 messages.append(QSL("URL:") + pair.text);
209 break;
211 m_isClosing = true;
212 return;
213 case Qz::CL_WMClass:
214 m_wmClass = pair.text.toUtf8();
215 break;
216 default:
217 break;
218 }
219 }
220 }
221
222 if (!isPortable()) {
223 QSettings falkonConf(QSL("%1/falkon.conf").arg(applicationDirPath()), QSettings::IniFormat);
224 m_isPortable = falkonConf.value(QSL("Config/Portable")).toBool();
225 }
226
227 if (isPortable()) {
228 std::cout << "Falkon: Running in Portable Mode." << std::endl;
230 }
231
232 // Don't start single application in private browsing
233 if (!isPrivate()) {
234 QString appId = QStringLiteral("org.kde.Falkon");
235
236 if (isPortable()) {
237 appId.append(QLatin1String(".Portable"));
238 }
239
240 if (isTestModeEnabled()) {
241 appId.append(QSL(".TestMode"));
242 }
243
244 if (newInstance) {
245 if (startProfile.isEmpty() || startProfile == QLatin1String("default")) {
246 std::cout << "New instance cannot be started with default profile!" << std::endl;
247 }
248 else {
249 // Generate unique appId so it is possible to start more separate instances
250 // of the same profile. It is dangerous to run more instances of the same profile,
251 // but if the user wants it, we should allow it.
252 appId.append(QLatin1Char('.') + startProfile + QString::number(QDateTime::currentMSecsSinceEpoch()));
253 }
254 }
255
256 setAppId(appId);
257 }
258
259 // If there is nothing to tell other instance, we need to at least wake it
260 if (messages.isEmpty()) {
261 messages.append(QStringLiteral(" "));
262 }
263
264 if (isRunning()) {
265 m_isClosing = true;
266 for (const QString &message : std::as_const(messages)) {
267 sendMessage(message);
268 }
269 return;
270 }
271
272#ifdef Q_OS_MACOS
273 setQuitOnLastWindowClosed(false);
274 // disable tabbing issue#2261
275 extern void disableWindowTabbing();
277#else
278 setQuitOnLastWindowClosed(true);
279#endif
280
281 QSettings::setDefaultFormat(QSettings::IniFormat);
282 QDesktopServices::setUrlHandler(QSL("http"), this, "addNewTab");
283 QDesktopServices::setUrlHandler(QSL("https"), this, "addNewTab");
284 QDesktopServices::setUrlHandler(QSL("ftp"), this, "addNewTab");
285
286 ProfileManager profileManager;
287 profileManager.initConfigDir();
288 profileManager.initCurrentProfile(startProfile);
289
290 Settings::createSettings(DataPaths::currentProfilePath() + QLatin1String("/settings.ini"));
291 if (Settings::globalSettings()->value("Web-Browser-Settings/hardwareAccel", false).toBool()) {
292 chromium_flags.append(" --enable-oop-rasterization --enable-gpu-rasterization --enable-native-gpu-memory-buffers --use-gl=desktop");
293 qputenv("QTWEBENGINE_CHROMIUM_FLAGS", chromium_flags);
294 }
295
297 registerAllowedSchemes();
298
299 if (isPrivate()) {
300 m_webProfile = new QWebEngineProfile();
301 }
302 else {
303 m_webProfile = new QWebEngineProfile(startProfile.isEmpty() ? QSL("Default") : startProfile);
304 }
305 connect(m_webProfile, &QWebEngineProfile::downloadRequested, this, &MainApplication::downloadRequested);
306
307 m_webProfile->setNotificationPresenter([&] (std::unique_ptr<QWebEngineNotification> notification) {
308 auto notifications = desktopNotifications();
309 notifications->showNotification(
310 QPixmap::fromImage(notification->icon()), notification->title(), notification->message()
311 );
312 });
313
314 m_networkManager = new NetworkManager(this);
315
316 setupUserScripts();
317
318 if (!isPrivate() && !isTestModeEnabled()) {
319 m_sessionManager = new SessionManager(this);
320 m_autoSaver = new AutoSaver(this);
321 connect(m_autoSaver, &AutoSaver::save, m_sessionManager, &SessionManager::autoSaveLastSession);
322
323 Settings settings;
324 settings.beginGroup(QSL("SessionRestore"));
325 const bool wasRunning = settings.value(QSL("isRunning"), false).toBool();
326 const bool wasRestoring = settings.value(QSL("isRestoring"), false).toBool();
327 settings.setValue(QSL("isRunning"), true);
328 settings.setValue(QSL("isRestoring"), wasRunning);
329 settings.endGroup();
330 settings.sync();
331
332 m_isStartingAfterCrash = wasRunning && wasRestoring;
333
334 if (wasRunning) {
335 QTimer::singleShot(60 * 1000, this, [this]() {
336 Settings().setValue(QSL("SessionRestore/isRestoring"), false);
337 });
338 }
339
340 // we have to ask about startup session before creating main window
341 if (!m_isStartingAfterCrash && afterLaunch() == SelectSession)
342 m_restoreManager = new RestoreManager(sessionManager()->askSessionFromUser());
343 }
344
345 loadSettings();
346
347 m_plugins = new PluginProxy(this);
348 m_autoFill = new AutoFill(this);
349 mApp->protocolHandlerManager();
350
351 if (!noAddons)
352 m_plugins->loadPlugins();
353
355 connect(window, SIGNAL(startingCompleted()), this, SLOT(restoreOverrideCursor()));
356
357 connect(this, &QApplication::focusChanged, this, &MainApplication::onFocusChanged);
358
359 if (!isPrivate() && !isTestModeEnabled()) {
360#ifndef DISABLE_CHECK_UPDATES
361 Settings settings;
362 bool checkUpdates = settings.value("Web-Browser-Settings/CheckUpdates", true).toBool();
363
364 if (checkUpdates) {
365 new Updater(window);
366 }
367#endif
368
370
371 if (m_isStartingAfterCrash || afterLaunch() == RestoreSession) {
372 m_restoreManager = new RestoreManager(sessionManager()->lastActiveSessionPath());
373 if (!m_restoreManager->isValid()) {
375 }
376 }
377
378 if (!m_isStartingAfterCrash && m_restoreManager) {
379 restoreSession(window, m_restoreManager->restoreData());
380 }
381 }
382
383 QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, DataPaths::currentProfilePath());
384
385 connect(this, SIGNAL(messageReceived(QString)), this, SLOT(messageReceived(QString)));
386 connect(this, &QCoreApplication::aboutToQuit, this, &MainApplication::saveSettings);
387
388 QTimer::singleShot(0, this, &MainApplication::postLaunch);
389}
390
392{
393 m_isClosing = true;
394
395 QDesktopServices::unsetUrlHandler(QSL("http"));
396 QDesktopServices::unsetUrlHandler(QSL("https"));
397 QDesktopServices::unsetUrlHandler(QSL("ftp"));
398
400
401 // Wait for all QtConcurrent jobs to finish
402 QThreadPool::globalInstance()->waitForDone();
403
404 // Delete all classes that are saving data in destructor
405 delete m_bookmarks;
406 m_bookmarks = nullptr;
407 delete m_cookieJar;
408 m_cookieJar = nullptr;
409
410 // On Qt 6, deleting the web profile is necessary in order to make sure cache, cookies, etc. are flushed to disk.
411 delete m_webProfile;
412 m_webProfile = nullptr;
413
415}
416
418{
419 return m_isClosing;
420}
421
423{
424 return m_isPrivate;
425}
426
428{
429#ifdef PORTABLE_BUILD
430 return true;
431#else
432 return m_isPortable;
433#endif
434}
435
437{
438 return m_isStartingAfterCrash;
439}
440
442{
443 return m_windows.count();
444}
445
446QList<BrowserWindow*> MainApplication::windows() const
447{
448 return m_windows;
449}
450
452{
453 if (m_lastActiveWindow) {
454 return m_lastActiveWindow.data();
455 }
456
457 return m_windows.isEmpty() ? nullptr : m_windows.at(0);
458}
459
461{
462 if (windowCount() == 0 && type != Qz::BW_MacFirstWindow) {
464 }
465
466 auto* window = new BrowserWindow(type, startUrl);
467 connect(window, &QObject::destroyed, this, &MainApplication::windowDestroyed);
468
469 m_windows.prepend(window);
470 return window;
471}
472
474{
475 return static_cast<AfterLaunch>(Settings().value(QSL("Web-URL-Settings/afterLaunch"), RestoreSession).toInt());
476}
477
479{
480 setOverrideCursor(Qt::BusyCursor);
481
482 if (!window)
484
485 if (window->tabCount() != 0) {
486 // This can only happen when recovering crashed session!
487 // Don't restore tabs in current window as user already opened some new tabs.
489 } else {
490 window->restoreWindow(restoreData.windows.takeAt(0));
491 }
492
493 const auto restoreWindows = restoreData.windows;
494 for (const BrowserWindow::SavedWindow &data : restoreWindows) {
496 window->restoreWindow(data);
497 }
498
499 m_closedWindowsManager->restoreState(restoreData.closedWindows);
500
502}
503
505{
506 if (m_isPrivate || !restoreData.isValid()) {
507 return false;
508 }
509
510 openSession(window, restoreData);
511
512 m_restoreManager->clearRestoreData();
514
515 return true;
516}
517
519{
520 if (m_restoreManager && m_restoreManager->isValid()) {
521 return;
522 }
523
524 delete m_restoreManager;
525 m_restoreManager = nullptr;
526}
527
529{
530 loadSettings();
531 Q_EMIT settingsReloaded();
532}
533
535{
536 return m_proxyStyle ? m_proxyStyle->name() : QString();
537}
538
540{
541 m_proxyStyle = style;
542 setStyle(style);
543}
544
545QByteArray MainApplication::wmClass() const
546{
547 return m_wmClass;
548}
549
551{
552 if (!m_history) {
553 m_history = new History(this);
554 }
555 return m_history;
556}
557
559{
560 if (!m_bookmarks) {
561 m_bookmarks = new Bookmarks(this);
562 }
563 return m_bookmarks;
564}
565
567{
568 return m_autoFill;
569}
570
572{
573 if (!m_cookieJar) {
574 m_cookieJar = new CookieJar(this);
575 }
576 return m_cookieJar;
577}
578
580{
581 return m_plugins;
582}
583
585{
586 if (!m_browsingLibrary) {
587 m_browsingLibrary = new BrowsingLibrary(getWindow());
588 }
589 return m_browsingLibrary;
590}
591
593{
594 return m_networkManager;
595}
596
598{
599 return m_restoreManager;
600}
601
603{
604 return m_sessionManager;
605}
606
608{
609 if (!m_downloadManager) {
610 m_downloadManager = new DownloadManager();
611 }
612 return m_downloadManager;
613}
614
616{
617 if (!m_userAgentManager) {
618 m_userAgentManager = new UserAgentManager(this);
619 }
620 return m_userAgentManager;
621}
622
624{
625 if (!m_searchEnginesManager) {
626 m_searchEnginesManager = new SearchEnginesManager(this);
627 }
628 return m_searchEnginesManager;
629}
630
632{
633 if (!m_closedWindowsManager) {
634 m_closedWindowsManager = new ClosedWindowsManager(this);
635 }
636 return m_closedWindowsManager;
637}
638
640{
641 if (!m_protocolHandlerManager) {
642 m_protocolHandlerManager = new ProtocolHandlerManager(this);
643 }
644 return m_protocolHandlerManager;
645}
646
648{
649 if (!m_html5PermissionsManager) {
650 m_html5PermissionsManager = new HTML5PermissionsManager(this);
651 }
652 return m_html5PermissionsManager;
653}
654
656{
657 if (!m_siteSettingsManager) {
658 m_siteSettingsManager = new SiteSettingsManager(this);
659 }
660 return m_siteSettingsManager;
661}
662
664{
665 if (!m_desktopNotifications) {
666 m_desktopNotifications = new DesktopNotificationsFactory(this);
667 }
668 return m_desktopNotifications;
669}
670
671QWebEngineProfile *MainApplication::webProfile() const
672{
673 return m_webProfile;
674}
675
676QWebEngineSettings *MainApplication::webSettings() const
677{
678 return m_webProfile->settings();
679}
680
681// static
683{
684 return static_cast<MainApplication*>(QCoreApplication::instance());
685}
686
687// static
689{
690 return s_testMode;
691}
692
693// static
695{
696 s_testMode = enabled;
697}
698
699void MainApplication::addNewTab(const QUrl &url)
700{
701 BrowserWindow* window = getWindow();
702
703 if (window) {
705 }
706}
707
709{
710 QUrl url = startUrl;
711 if (auto* act = qobject_cast<QAction*>(sender())) {
712 url = act->data().toUrl();
713 }
714
715 QStringList args;
716 args.append(QSL("--private-browsing"));
717 args.append(QSL("--profile=") + ProfileManager::currentProfile());
718
719 if (!url.isEmpty()) {
720 args << QString::fromUtf8(url.toEncoded());
721 }
722
723 if (!QProcess::startDetached(applicationFilePath(), args)) {
724 qWarning() << "MainApplication: Cannot start new browser process for private browsing!" << applicationFilePath() << args;
725 }
726}
727
729{
730 const QString userCssFile = Settings().value(QSL("Web-Browser-Settings/userStyleSheet"), QString()).toString();
731 setUserStyleSheet(userCssFile);
732}
733
735{
736 QApplication::restoreOverrideCursor();
737}
738
740{
741 if (m_autoSaver)
742 m_autoSaver->changeOccurred();
743}
744
746{
747 if (m_downloadManager && !m_downloadManager->canClose()) {
748 m_downloadManager->show();
749 return;
750 }
751
752 for (BrowserWindow *window : std::as_const(m_windows)) {
753 Q_EMIT window->aboutToClose();
754 }
755
756 if (m_sessionManager && m_windows.count() > 0) {
757 m_sessionManager->autoSaveLastSession();
758 }
759
760 m_isClosing = true;
761
762 for (BrowserWindow *window : std::as_const(m_windows)) {
763 window->close();
764 }
765
766 // Saving settings in saveSettings() slot called from quit() so
767 // everything gets saved also when quitting application in other
768 // way than clicking Quit action in File menu or closing last window
769 // eg. on Mac (#157)
770
771 if (!isPrivate()) {
773 }
774
775 quit();
776}
777
778void MainApplication::postLaunch()
779{
780 if (m_postLaunchActions.contains(OpenDownloadManager)) {
782 }
783
784 if (m_postLaunchActions.contains(OpenNewTab)) {
786 }
787
788 if (m_postLaunchActions.contains(ToggleFullScreen)) {
790 }
791
792 createJumpList();
793 initPulseSupport();
794
795 QTimer::singleShot(5000, this, &MainApplication::runDeferredPostLaunchActions);
796}
797
799{
800 RestoreData restoreData;
801 restoreData.windows.reserve(m_windows.count());
802 for (BrowserWindow *window : std::as_const(m_windows)) {
803 restoreData.windows.append(BrowserWindow::SavedWindow(window));
804 }
805
806 if (m_restoreManager && m_restoreManager->isValid()) {
807 QDataStream stream(&restoreData.crashedSession, QIODevice::WriteOnly);
808 stream << m_restoreManager->restoreData();
809 }
810
811 restoreData.closedWindows = m_closedWindowsManager->saveState();
812
813 QByteArray data;
814 QDataStream stream(&data, QIODevice::WriteOnly);
815
816 stream << Qz::sessionVersion;
817 stream << restoreData;
818
819 return data;
820}
821
822void MainApplication::saveSettings()
823{
824 if (isPrivate()) {
825 return;
826 }
827
828 m_isClosing = true;
829
830 Settings settings;
831 settings.beginGroup(QSL("SessionRestore"));
832 settings.setValue(QSL("isRunning"), false);
833 settings.setValue(QSL("isRestoring"), false);
834 settings.endGroup();
835
836 settings.beginGroup(QSL("Web-Browser-Settings"));
837 bool deleteCache = settings.value(QSL("deleteCacheOnClose"), false).toBool();
838 bool deleteHistory = settings.value(QSL("deleteHistoryOnClose"), false).toBool();
839 bool deleteHtml5Storage = settings.value(QSL("deleteHTML5StorageOnClose"), false).toBool();
840 settings.endGroup();
841
842 settings.beginGroup(QSL("Cookie-Settings"));
843 bool deleteCookies = settings.value(QSL("deleteCookiesOnClose"), false).toBool();
844 settings.endGroup();
845
846 if (deleteHistory) {
847 m_history->clearHistory();
848 }
849 if (deleteHtml5Storage) {
851 }
852 if (deleteCookies) {
853 m_cookieJar->deleteAllCookies(false);
854 }
855 if (deleteCache) {
856 QzTools::removeRecursively(mApp->webProfile()->cachePath());
857 }
858
859 m_searchEnginesManager->saveSettings();
860 m_plugins->shutdown();
861 m_networkManager->shutdown();
862
863 qzSettings->saveSettings();
864 QFile::remove(DataPaths::currentProfilePath() + QLatin1String("/WebpageIcons.db"));
865
867}
868
869void MainApplication::messageReceived(const QString &message)
870{
871 QWidget* actWin = getWindow();
872 QUrl actUrl;
873
874 if (message.startsWith(QLatin1String("URL:"))) {
875 const QUrl url = QUrl::fromUserInput(message.mid(4));
876 addNewTab(url);
877 actWin = getWindow();
878 }
879 else if (message.startsWith(QLatin1String("ACTION:"))) {
880 const QString text = message.mid(7);
881 if (text == QLatin1String("NewTab")) {
882 addNewTab();
883 }
884 else if (text == QLatin1String("NewWindow")) {
886 }
887 else if (text == QLatin1String("ShowDownloadManager")) {
889 actWin = downloadManager();
890 }
891 else if (text == QLatin1String("ToggleFullScreen") && actWin) {
892 auto* qz = static_cast<BrowserWindow*>(actWin);
893 qz->toggleFullScreen();
894 }
895 else if (text.startsWith(QLatin1String("OpenUrlInCurrentTab"))) {
896 actUrl = QUrl::fromUserInput(text.mid(19));
897 }
898 else if (text.startsWith(QLatin1String("OpenUrlInNewWindow"))) {
899 createWindow(Qz::BW_NewWindow, QUrl::fromUserInput(text.mid(18)));
900 return;
901 }
902 }
903 else {
904 // User attempted to start another instance, let's open a new window
906 }
907
908 if (!actWin) {
909 if (!isClosing()) {
910 // It can only occur if download manager window was still opened
912 }
913 return;
914 }
915
916 actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized);
917 actWin->raise();
918 actWin->activateWindow();
919 actWin->setFocus();
920
921 auto* win = qobject_cast<BrowserWindow*>(actWin);
922
923 if (win && !actUrl.isEmpty()) {
924 win->loadAddress(actUrl);
925 }
926}
927
928void MainApplication::windowDestroyed(QObject* window)
929{
930 // qobject_cast doesn't work because QObject::destroyed is emitted from destructor
931 Q_ASSERT(static_cast<BrowserWindow*>(window));
932 Q_ASSERT(m_windows.contains(static_cast<BrowserWindow*>(window)));
933
934 m_windows.removeOne(static_cast<BrowserWindow*>(window));
935}
936
937void MainApplication::onFocusChanged()
938{
939 auto* activeBrowserWindow = qobject_cast<BrowserWindow*>(activeWindow());
940
941 if (activeBrowserWindow) {
942 m_lastActiveWindow = activeBrowserWindow;
943
944 Q_EMIT activeWindowChanged(m_lastActiveWindow);
945 }
946}
947
948void MainApplication::runDeferredPostLaunchActions()
949{
950 checkDefaultWebBrowser();
951 checkOptimizeDatabase();
952}
953
954void MainApplication::downloadRequested(QWebEngineDownloadRequest *download)
955{
956 downloadManager()->download(download);
957}
958
959void MainApplication::loadSettings()
960{
961 Settings settings;
962 settings.beginGroup(QSL("Themes"));
963 QString activeTheme = settings.value(QSL("activeTheme"), DEFAULT_THEME_NAME).toString();
964 settings.endGroup();
965
966 loadTheme(activeTheme);
967
968 QWebEngineSettings* webSettings = m_webProfile->settings();
969
970 // Web browsing settings
971 settings.beginGroup(QSL("Web-Browser-Settings"));
972
973 webSettings->setAttribute(QWebEngineSettings::LocalStorageEnabled, settings.value(QSL("HTML5StorageEnabled"), true).toBool());
974 webSettings->setAttribute(QWebEngineSettings::PluginsEnabled, settings.value(QSL("allowPlugins"), true).toBool());
975 webSettings->setAttribute(QWebEngineSettings::JavascriptEnabled, settings.value(QSL("allowJavaScript"), true).toBool());
976 webSettings->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, settings.value(QSL("allowJavaScriptOpenWindow"), false).toBool());
977 webSettings->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, settings.value(QSL("allowJavaScriptAccessClipboard"), true).toBool());
978 webSettings->setAttribute(QWebEngineSettings::LinksIncludedInFocusChain, settings.value(QSL("IncludeLinkInFocusChain"), false).toBool());
979 webSettings->setAttribute(QWebEngineSettings::XSSAuditingEnabled, settings.value(QSL("XSSAuditing"), false).toBool());
980 webSettings->setAttribute(QWebEngineSettings::PrintElementBackgrounds, settings.value(QSL("PrintElementBackground"), true).toBool());
981 webSettings->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, settings.value(QSL("SpatialNavigation"), false).toBool());
982 webSettings->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled, settings.value(QSL("AnimateScrolling"), true).toBool());
983 webSettings->setAttribute(QWebEngineSettings::HyperlinkAuditingEnabled, false);
984 webSettings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
985 webSettings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
986 webSettings->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, false);
987
988 webSettings->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, settings.value(QSL("allowJavaScriptActivateWindow"), false).toBool());
989
990 webSettings->setAttribute(QWebEngineSettings::JavascriptCanPaste, settings.value(QSL("allowJavaScriptPaste"), true).toBool());
991 webSettings->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, settings.value(QSL("DisableVideoAutoPlay"), false).toBool());
992 webSettings->setAttribute(QWebEngineSettings::WebRTCPublicInterfacesOnly, settings.value(QSL("WebRTCPublicIpOnly"), true).toBool());
993 webSettings->setUnknownUrlSchemePolicy(QWebEngineSettings::AllowAllUnknownUrlSchemes);
994 webSettings->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, settings.value(QSL("DNSPrefetch"), true).toBool());
995 webSettings->setAttribute(QWebEngineSettings::PdfViewerEnabled, settings.value(QSL("intPDFViewer"), false).toBool());
996 webSettings->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, settings.value(QSL("screenCaptureEnabled"), false).toBool());
997
998#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 6, 0)
999 webSettings->setAttribute(QWebEngineSettings::ReadingFromCanvasEnabled, settings.value(QSL("readingFromCanvasEnabled"), true).toBool());
1000#endif
1001#if QTWEBENGINECORE_VERSION >= QT_VERSION_CHECK(6, 7, 0)
1002 webSettings->setAttribute(QWebEngineSettings::ForceDarkMode, settings.value(QSL("forceDarkMode"), false).toBool());
1003#endif
1004
1005 webSettings->setDefaultTextEncoding(settings.value(QSL("DefaultEncoding"), webSettings->defaultTextEncoding()).toString());
1006
1007 setWheelScrollLines(settings.value(QSL("wheelScrollLines"), wheelScrollLines()).toInt());
1008
1009 const QString userCss = settings.value(QSL("userStyleSheet"), QString()).toString();
1010 settings.endGroup();
1011
1012 setUserStyleSheet(userCss);
1013
1014 settings.beginGroup(QSL("Browser-Fonts"));
1015 webSettings->setFontFamily(QWebEngineSettings::StandardFont, settings.value(QSL("StandardFont"), webSettings->fontFamily(QWebEngineSettings::StandardFont)).toString());
1016 webSettings->setFontFamily(QWebEngineSettings::CursiveFont, settings.value(QSL("CursiveFont"), webSettings->fontFamily(QWebEngineSettings::CursiveFont)).toString());
1017 webSettings->setFontFamily(QWebEngineSettings::FantasyFont, settings.value(QSL("FantasyFont"), webSettings->fontFamily(QWebEngineSettings::FantasyFont)).toString());
1018 webSettings->setFontFamily(QWebEngineSettings::FixedFont, settings.value(QSL("FixedFont"), webSettings->fontFamily(QWebEngineSettings::FixedFont)).toString());
1019 webSettings->setFontFamily(QWebEngineSettings::SansSerifFont, settings.value(QSL("SansSerifFont"), webSettings->fontFamily(QWebEngineSettings::SansSerifFont)).toString());
1020 webSettings->setFontFamily(QWebEngineSettings::SerifFont, settings.value(QSL("SerifFont"), webSettings->fontFamily(QWebEngineSettings::SerifFont)).toString());
1021 webSettings->setFontSize(QWebEngineSettings::DefaultFontSize, settings.value(QSL("DefaultFontSize"), 15).toInt());
1022 webSettings->setFontSize(QWebEngineSettings::DefaultFixedFontSize, settings.value(QSL("FixedFontSize"), 14).toInt());
1023 webSettings->setFontSize(QWebEngineSettings::MinimumFontSize, settings.value(QSL("MinimumFontSize"), 3).toInt());
1024 webSettings->setFontSize(QWebEngineSettings::MinimumLogicalFontSize, settings.value(QSL("MinimumLogicalFontSize"), 5).toInt());
1025 settings.endGroup();
1026
1027 QWebEngineProfile* profile = m_webProfile;
1028 profile->setPersistentCookiesPolicy(QWebEngineProfile::AllowPersistentCookies);
1029 profile->setPersistentStoragePath(DataPaths::currentProfilePath());
1030
1031 QString defaultPath = DataPaths::path(DataPaths::Cache);
1032 if (!defaultPath.startsWith(DataPaths::currentProfilePath()))
1033 defaultPath.append(QLatin1Char('/') + ProfileManager::currentProfile());
1034 const QString &cachePath = settings.value(QSL("Web-Browser-Settings/CachePath"), defaultPath).toString();
1035 profile->setCachePath(cachePath);
1036
1037 const bool allowCache = settings.value(QSL("Web-Browser-Settings/AllowLocalCache"), true).toBool();
1038 profile->setHttpCacheType(allowCache ? QWebEngineProfile::DiskHttpCache : QWebEngineProfile::MemoryHttpCache);
1039
1040 const int cacheSize = settings.value(QSL("Web-Browser-Settings/LocalCacheSize"), 50).toInt() * 1000 * 1000;
1041 profile->setHttpCacheMaximumSize(cacheSize);
1042
1043 settings.beginGroup(QSL("SpellCheck"));
1044 profile->setSpellCheckEnabled(settings.value(QSL("Enabled"), false).toBool());
1045 profile->setSpellCheckLanguages(settings.value(QSL("Languages")).toStringList());
1046 settings.endGroup();
1047
1048 if (isPrivate()) {
1049 profile->setPersistentStoragePath(DataPaths::path(DataPaths::Temp) + QLatin1String("/private-storage"));
1050 history()->setSaving(false);
1051 }
1052
1053 if (m_downloadManager) {
1054 m_downloadManager->loadSettings();
1055 }
1056
1057 qzSettings->loadSettings();
1060}
1061
1062void MainApplication::loadTheme(const QString &name)
1063{
1064 QString activeThemePath = DataPaths::locate(DataPaths::Themes, name);
1065
1066 if (activeThemePath.isEmpty()) {
1067 qWarning() << "Cannot load theme " << name;
1068 activeThemePath = QSL("%1/%2").arg(DataPaths::path(DataPaths::Themes), DEFAULT_THEME_NAME);
1069 }
1070
1071 QString qss = QzTools::readAllFileContents(activeThemePath + QLatin1String("/main.css"));
1072
1073#if defined(Q_OS_MACOS)
1074 qss.append(QzTools::readAllFileContents(activeThemePath + QLatin1String("/mac.css")));
1075#elif defined(Q_OS_UNIX)
1076 qss.append(QzTools::readAllFileContents(activeThemePath + QLatin1String("/linux.css")));
1077#elif defined(Q_OS_WIN) || defined(Q_OS_OS2)
1078 qss.append(QzTools::readAllFileContents(activeThemePath + QLatin1String("/windows.css")));
1079#endif
1080
1081 if (isRightToLeft()) {
1082 qss.append(QzTools::readAllFileContents(activeThemePath + QLatin1String("/rtl.css")));
1083 }
1084
1085 if (isPrivate()) {
1086 qss.append(QzTools::readAllFileContents(activeThemePath + QLatin1String("/private.css")));
1087 }
1088
1089 qss.append(QzTools::readAllFileContents(DataPaths::currentProfilePath() + QL1S("/userChrome.css")));
1090
1091 QString relativePath = QDir::current().relativeFilePath(activeThemePath);
1092 qss.replace(QRegularExpression(QSL("url\\s*\\(\\s*([^\\*:\\);]+)\\s*\\)")), QSL("url(%1/\\1)").arg(relativePath));
1093 setStyleSheet(qss);
1094}
1095
1096void MainApplication::checkDefaultWebBrowser()
1097{
1098 if (isPortable()) {
1099 return;
1100 }
1101
1102#if defined(Q_OS_WIN) && !defined(Q_OS_OS2)
1103 Settings settings;
1104 bool checkNow = settings.value(QSL("Web-Browser-Settings/CheckDefaultBrowser"), DEFAULT_CHECK_DEFAULTBROWSER).toBool();
1105
1106 if (!checkNow) {
1107 return;
1108 }
1109
1110 bool checkAgain = true;
1111
1112 if (!associationManager()->isDefaultForAllCapabilities()) {
1113 CheckBoxDialog dialog(QMessageBox::Yes | QMessageBox::No, getWindow());
1114 dialog.setDefaultButton(QMessageBox::Yes);
1115 dialog.setText(tr("Falkon is not currently your default browser. Would you like to make it your default browser?"));
1116 dialog.setCheckBoxText(tr("Always perform this check when starting Falkon."));
1117 dialog.setDefaultCheckState(Qt::Checked);
1118 dialog.setWindowTitle(tr("Default Browser"));
1119 dialog.setIcon(QMessageBox::Warning);
1120
1121 if (dialog.exec() == QMessageBox::Yes) {
1122 if (!mApp->associationManager()->showNativeDefaultAppSettingsUi())
1123 mApp->associationManager()->registerAllAssociation();
1124 }
1125
1126 checkAgain = dialog.isChecked();
1127 }
1128
1129 settings.setValue(QSL("Web-Browser-Settings/CheckDefaultBrowser"), checkAgain);
1130#endif
1131}
1132
1133void MainApplication::checkOptimizeDatabase()
1134{
1135 Settings settings;
1136 settings.beginGroup(QSL("Browser"));
1137 const int numberOfRuns = settings.value(QSL("RunsWithoutOptimizeDb"), 0).toInt();
1138 settings.setValue(QSL("RunsWithoutOptimizeDb"), numberOfRuns + 1);
1139
1140 if (numberOfRuns > 20) {
1141 std::cout << "Optimizing database..." << std::endl;
1143 settings.setValue(QSL("RunsWithoutOptimizeDb"), 0);
1144 }
1145
1146 settings.endGroup();
1147}
1148
1149void MainApplication::registerAllowedSchemes()
1150{
1151 for (const QString &schemeName : std::as_const(qzSettings->allowedSchemes)) {
1152 if (qzSettings->blockedSchemes.contains(schemeName)) {
1153 continue;
1154 }
1155 QWebEngineUrlScheme scheme(schemeName.toUtf8());
1156 scheme.setFlags(QWebEngineUrlScheme::SecureScheme | QWebEngineUrlScheme::ContentSecurityPolicyIgnored);
1157 scheme.setSyntax(QWebEngineUrlScheme::Syntax::Path);
1158 QWebEngineUrlScheme::registerScheme(scheme);
1159 }
1160}
1161
1162void MainApplication::setupUserScripts()
1163{
1164 // WebChannel for SafeJsWorld
1165 QWebEngineScript script;
1166 script.setName(QSL("_falkon_webchannel"));
1167 script.setInjectionPoint(QWebEngineScript::DocumentCreation);
1168 script.setWorldId(WebPage::SafeJsWorld);
1169 script.setRunsOnSubFrames(true);
1170 script.setSourceCode(Scripts::setupWebChannel());
1171 m_webProfile->scripts()->insert(script);
1172
1173 // falkon:restore
1174 QWebEngineScript falkonRestore;
1175 falkonRestore.setWorldId(WebPage::SafeJsWorld);
1176 falkonRestore.setSourceCode(QzTools::readAllFileContents(QSL(":html/restore.user.js")));
1177 m_webProfile->scripts()->insert(falkonRestore);
1178
1179 // falkon:speeddial
1180 QWebEngineScript falkonSpeedDial;
1181 falkonSpeedDial.setWorldId(WebPage::SafeJsWorld);
1182 falkonSpeedDial.setSourceCode(Scripts::setupSpeedDial());
1183 m_webProfile->scripts()->insert(falkonSpeedDial);
1184
1185 // document.window object addons
1186 QWebEngineScript documentWindowAddons;
1187 documentWindowAddons.setName(QSL("_falkon_window_object"));
1188 documentWindowAddons.setInjectionPoint(QWebEngineScript::DocumentCreation);
1189 documentWindowAddons.setWorldId(WebPage::UnsafeJsWorld);
1190 documentWindowAddons.setRunsOnSubFrames(true);
1191 documentWindowAddons.setSourceCode(Scripts::setupWindowObject());
1192 m_webProfile->scripts()->insert(documentWindowAddons);
1193}
1194
1195void MainApplication::setUserStyleSheet(const QString &filePath)
1196{
1197 QString userCss;
1198
1199#if !defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
1200 // Don't grey out selection on losing focus (to prevent graying out found text)
1201 QString highlightColor;
1202 QString highlightedTextColor;
1203#ifdef Q_OS_MACOS
1204 highlightColor = QLatin1String("#b6d6fc");
1205 highlightedTextColor = QLatin1String("#000");
1206#else
1207 QPalette pal = style()->standardPalette();
1208 highlightColor = pal.color(QPalette::Highlight).name();
1209 highlightedTextColor = pal.color(QPalette::HighlightedText).name();
1210#endif
1211 userCss += QString("::selection {background: %1; color: %2;} ").arg(highlightColor, highlightedTextColor);
1212#endif
1213
1214 userCss += QzTools::readAllFileContents(filePath).remove(QLatin1Char('\n'));
1215
1216 const QString name = QStringLiteral("_falkon_userstylesheet");
1217 for (const QWebEngineScript &oldScript : m_webProfile->scripts()->find(name)) {
1218 m_webProfile->scripts()->remove(oldScript);
1219 }
1220
1221 if (userCss.isEmpty())
1222 return;
1223
1224 QWebEngineScript script;
1225 script.setName(name);
1226 script.setInjectionPoint(QWebEngineScript::DocumentReady);
1227 script.setWorldId(WebPage::SafeJsWorld);
1228 script.setRunsOnSubFrames(true);
1229 script.setSourceCode(Scripts::setCss(userCss));
1230 m_webProfile->scripts()->insert(script);
1231}
1232
1233void MainApplication::createJumpList()
1234{
1235#ifdef Q_OS_WIN
1236 QWinJumpList *jumpList = new QWinJumpList(this);
1237 jumpList->clear();
1238
1239 // Frequent
1240 QWinJumpListCategory *frequent = jumpList->frequent();
1241 frequent->setVisible(true);
1242 const QVector<HistoryEntry> mostList = m_history->mostVisited(7);
1243 for (const HistoryEntry &entry : mostList) {
1244 frequent->addLink(IconProvider::iconForUrl(entry.url), entry.title, applicationFilePath(), QStringList{(QString::fromUtf8entry.url.toEncoded())});
1245 }
1246
1247 // Tasks
1248 QWinJumpListCategory *tasks = jumpList->tasks();
1249 tasks->setVisible(true);
1250 tasks->addLink(IconProvider::newTabIcon(), tr("Open new tab"), applicationFilePath(), {QSL("--new-tab")});
1251 tasks->addLink(IconProvider::newWindowIcon(), tr("Open new window"), applicationFilePath(), {QSL("--new-window")});
1252 tasks->addLink(IconProvider::privateBrowsingIcon(), tr("Open new private window"), applicationFilePath(), {QSL("--private-browsing")});
1253#endif
1254}
1255
1256void MainApplication::initPulseSupport()
1257{
1258 qputenv("PULSE_PROP_OVERRIDE_application.name", "Falkon");
1259 qputenv("PULSE_PROP_OVERRIDE_application.icon_name", "falkon");
1260 qputenv("PULSE_PROP_OVERRIDE_media.icon_name", "falkon");
1261}
1262
1263#if defined(Q_OS_WIN) && !defined(Q_OS_OS2)
1264RegisterQAppAssociation* MainApplication::associationManager()
1265{
1266 if (!m_registerQAppAssociation) {
1267 QString desc = tr("Falkon is a new and very fast Qt web browser. Falkon is licensed under GPL version 3 or (at your option) any later version. It is based on QtWebEngine and Qt Framework.");
1268 QString fileIconPath = QApplication::applicationFilePath() + QSL(",1");
1269 QString appIconPath = QApplication::applicationFilePath() + QSL(",0");
1270 m_registerQAppAssociation = new RegisterQAppAssociation(QSL("Falkon"), QApplication::applicationFilePath(), appIconPath, desc, this);
1271 m_registerQAppAssociation->addCapability(QSL(".html"), QSL("FalkonHTML"), QSL("Falkon HTML Document"), fileIconPath, RegisterQAppAssociation::FileAssociation);
1272 m_registerQAppAssociation->addCapability(QSL(".htm"), QSL("FalkonHTML"), QSL("Falkon HTML Document"), fileIconPath, RegisterQAppAssociation::FileAssociation);
1273 m_registerQAppAssociation->addCapability(QSL("http"), QSL("FalkonURL"), QSL("Falkon URL"), appIconPath, RegisterQAppAssociation::UrlAssociation);
1274 m_registerQAppAssociation->addCapability(QSL("https"), QSL("FalkonURL"), QSL("Falkon URL"), appIconPath, RegisterQAppAssociation::UrlAssociation);
1275 m_registerQAppAssociation->addCapability(QSL("ftp"), QSL("FalkonURL"), QSL("Falkon URL"), appIconPath, RegisterQAppAssociation::UrlAssociation);
1276 }
1277 return m_registerQAppAssociation;
1278}
1279#endif
1280
1281#ifdef Q_OS_MACOS
1282#include <QFileOpenEvent>
1283
1284bool MainApplication::event(QEvent* e)
1285{
1286 switch (e->type()) {
1287 case QEvent::FileOpen: {
1288 QFileOpenEvent *ev = static_cast<QFileOpenEvent*>(e);
1289 if (!ev->url().isEmpty()) {
1290 addNewTab(ev->url());
1291 } else if (!ev->file().isEmpty()) {
1292 addNewTab(QUrl::fromLocalFile(ev->file()));
1293 } else {
1294 return false;
1295 }
1296 return true;
1297 }
1298
1299 case QEvent::ApplicationActivate:
1300 if (!activeWindow() && m_windows.isEmpty())
1302 break;
1303
1304 default:
1305 break;
1306 }
1307
1308 return QtSingleApplication::event(e);
1309}
1310#endif
void changeOccurred()
Definition: autosaver.cpp:39
void save()
TabWidget * tabWidget() const
int tabCount() const
void toggleFullScreen()
void restoreWindow(const SavedWindow &window)
static void clearLocalStorage()
QByteArray saveState() const
void restoreState(const QByteArray &state)
ActionPairList getActions()
static void setPortableVersion()
Definition: datapaths.cpp:46
static QString path(Path type)
Definition: datapaths.cpp:66
static QString currentProfilePath()
Definition: datapaths.cpp:95
static QString locate(Path type, const QString &file)
Definition: datapaths.cpp:82
void download(QWebEngineDownloadRequest *downloadItem)
void setSaving(bool state)
Definition: history.cpp:259
void clearHistory()
Definition: history.cpp:248
QVector< HistoryEntry > mostVisited(int count)
Definition: history.cpp:230
static QIcon iconForUrl(const QUrl &url, bool allowNull=false)
static QIcon privateBrowsingIcon()
static IconProvider * instance()
static QIcon newWindowIcon()
void clearOldIconsInDatabase()
static QIcon newTabIcon()
void saveIconsToDatabase()
CookieJar * cookieJar()
Bookmarks * bookmarks()
QString styleName() const
void startPrivateBrowsing(const QUrl &startUrl=QUrl())
AfterLaunch afterLaunch() const
static bool isTestModeEnabled()
AutoFill * autoFill()
void settingsReloaded()
ProtocolHandlerManager * protocolHandlerManager()
void activeWindowChanged(BrowserWindow *window)
void setProxyStyle(ProxyStyle *style)
int windowCount() const
RestoreManager * restoreManager()
void openSession(BrowserWindow *window, RestoreData &restoreData)
SessionManager * sessionManager()
MainApplication(int &argc, char **argv)
QByteArray wmClass() const
QWebEngineSettings * webSettings() const
ClosedWindowsManager * closedWindowsManager()
DownloadManager * downloadManager()
HTML5PermissionsManager * html5PermissionsManager()
PluginProxy * plugins()
bool isClosing() const
bool restoreSession(BrowserWindow *window, RestoreData restoreData)
UserAgentManager * userAgentManager()
DesktopNotificationsFactory * desktopNotifications()
QList< BrowserWindow * > windows() const
bool isPrivate() const
QByteArray saveState() const
SearchEnginesManager * searchEnginesManager()
NetworkManager * networkManager()
BrowserWindow * createWindow(Qz::BrowserWindowType type, const QUrl &startUrl=QUrl())
static MainApplication * instance()
SiteSettingsManager * siteSettingsManager()
void addNewTab(const QUrl &url=QUrl())
bool isStartingAfterCrash() const
static void setTestModeEnabled(bool enabled)
BrowserWindow * getWindow() const
BrowsingLibrary * browsingLibrary()
QWebEngineProfile * webProfile() const
bool isPortable() const
static void registerSchemes()
void shutdown()
Definition: plugins.cpp:165
void loadPlugins()
Definition: plugins.cpp:222
void initCurrentProfile(const QString &profileName)
static QString currentProfile()
QString name() const
Definition: proxystyle.cpp:80
The QtSingleApplication class provides an API to detect and communicate with running instances of an ...
bool sendMessage(const QString &message, int timeout=5000)
void setAppId(const QString &id)
static QString readAllFileContents(const QString &filename)
Definition: qztools.cpp:98
static bool removeRecursively(const QString &filePath)
Definition: qztools.cpp:139
RestoreData restoreData() const
bool isValid() const
static QString setCss(const QString &css)
Definition: scripts.cpp:200
static QString setupWindowObject()
Definition: scripts.cpp:175
static QString setupWebChannel()
Definition: scripts.cpp:26
static QString setupSpeedDial()
Definition: scripts.cpp:192
void backupSavedSessions()
QString askSessionFromUser()
void autoSaveLastSession()
void beginGroup(const QString &prefix)
Definition: settings.cpp:79
static QSettings * globalSettings()
Definition: settings.cpp:94
void endGroup()
Definition: settings.cpp:84
QVariant value(const QString &key, const QVariant &defaultValue=QVariant())
Definition: settings.cpp:74
void setValue(const QString &key, const QVariant &defaultValue=QVariant())
Definition: settings.cpp:69
void sync()
Definition: settings.cpp:89
static void createSettings(const QString &fileName)
Definition: settings.cpp:35
static void syncSettings()
Definition: settings.cpp:41
int addView(const LoadRequest &req, const Qz::NewTabPositionFlags &openFlags, bool selectLine=false, bool pinned=false)
Definition: tabwidget.cpp:314
@ UnsafeJsWorld
Definition: webpage.h:44
@ SafeJsWorld
Definition: webpage.h:45
void disableWindowTabbing()
#define mApp
int value(const QColor &c)
Definition: colors.cpp:238
const int sessionVersion
Definition: qzcommon.cpp:23
@ CL_OpenUrl
Definition: qzcommon.h:73
@ CL_WMClass
Definition: qzcommon.h:86
@ CL_ToggleFullScreen
Definition: qzcommon.h:81
@ CL_OpenUrlInNewWindow
Definition: qzcommon.h:75
@ CL_StartNewInstance
Definition: qzcommon.h:83
@ CL_OpenUrlInCurrentTab
Definition: qzcommon.h:74
@ CL_NewWindow
Definition: qzcommon.h:79
@ CL_NewTab
Definition: qzcommon.h:78
@ CL_ShowDownloadManager
Definition: qzcommon.h:80
@ CL_StartWithProfile
Definition: qzcommon.h:76
@ CL_StartPrivateBrowsing
Definition: qzcommon.h:82
@ CL_ExitAction
Definition: qzcommon.h:85
@ CL_StartPortable
Definition: qzcommon.h:84
@ CL_StartWithoutAddons
Definition: qzcommon.h:77
FALKON_EXPORT const char * VERSION
Definition: qzcommon.cpp:26
BrowserWindowType
Definition: qzcommon.h:64
@ BW_NewWindow
Definition: qzcommon.h:67
@ BW_OtherRestoredWindow
Definition: qzcommon.h:66
@ BW_FirstAppWindow
Definition: qzcommon.h:65
@ BW_MacFirstWindow
Definition: qzcommon.h:68
@ NT_SelectedTabAtTheEnd
Definition: qzcommon.h:104
@ NT_SelectedNewEmptyTab
Definition: qzcommon.h:103
#define QL1S(x)
Definition: qzcommon.h:44
#define DEFAULT_THEME_NAME
Definition: qzcommon.h:123
#define DEFAULT_CHECK_DEFAULTBROWSER
Definition: qzcommon.h:132
#define QSL(x)
Definition: qzcommon.h:40
#define qzSettings
Definition: qzsettings.h:69
Definition: history.h:39
QVector< BrowserWindow::SavedWindow > windows
QByteArray crashedSession
bool isValid() const
QByteArray closedWindows