/* * This file is part of smolbote. It's copyrighted by the contributors recorded * in the version control history of the file, available from its original * location: https://neueland.iserlohn-fortress.net/smolbote.hg * * SPDX-License-Identifier: GPL-3.0 */ #include "browser.h" #include "configuration/configuration.h" #include "mainwindow/mainwindow.h" #include "webengine/urlinterceptor.h" #include "webengine/webengineprofile.h" #include #include #include #include Browser::Browser(int &argc, char *argv[]) : SingleApplication(argc, argv) { QApplication::setApplicationName("smolbote"); QApplication::setWindowIcon(QIcon(":/icon.svg")); connect(this, &Browser::messageAvailable, this, &Browser::createSession); } Browser::~Browser() { if(m_bookmarksManager) { QtConcurrent::run(QThreadPool::globalInstance(), m_bookmarksManager.get(), &BookmarksWidget::save); } qDebug("Waiting for threads to wind down..."); qDebug("Thread pool is done: %s", QThreadPool::globalInstance()->waitForDone() ? "okay" : "failed"); delete m_urlRequestInterceptor; delete m_cookieInterceptor; } void Browser::setConfiguration(std::shared_ptr &config) { m_config = config; QDir pluginsDir(QString::fromStdString(m_config->value("plugins.path").value())); if(pluginsDir.exists()) { const QStringList entries = pluginsDir.entryList(QDir::Files | QDir::Readable); for(const QString &name : entries) { QPluginLoader loader(pluginsDir.absoluteFilePath(name)); qDebug("Loading plugin %s: %s", qUtf8Printable(name), loader.load() ? "ok" : "failed"); if(!loader.isLoaded()) { qDebug("Error: %s", qUtf8Printable(loader.errorString())); } else { Plugin d; d.meta = loader.metaData()["MetaData"].toObject(); d.pointer = loader.instance(); d.pointer->setParent(this); m_plugins.append(d); } } } m_bookmarksManager = std::make_shared(QString::fromStdString(m_config->value("bookmarks.path").value())); m_downloadManager = std::make_shared(QString::fromStdString(m_config->value("downloads.path").value())); m_urlRequestInterceptor = new UrlRequestInterceptor(QString::fromStdString(m_config->value("filter.path").value())); m_cookieInterceptor = new CookieFilter( m_config->value("filter.cookies.block.all").value(), m_config->value("filter.cookies.block.thirdParty").value()); // set default profile m_defaultProfile = profile(QString::fromStdString(m_config->value("browser.profile").value())); } MainWindow *Browser::createWindow() { // the window will delete itself when it closes, so we don't need to delete it MainWindow *window = new MainWindow(m_config); window->setBookmarksWidget(m_bookmarksManager); window->setDownloadsWidget(m_downloadManager); window->setProfile(m_defaultProfile); window->addPlugins(m_plugins); m_windows.append(window); // has to be window.get(), but can't be *window connect(window, &MainWindow::destroyed, this, [this, window]() { m_windows.removeOne(window); }); window->show(); return window; } MainWindow *Browser::createSession(const QString &profileName, bool newWindow, const QStringList &urls) { MainWindow *window = nullptr; // if we need to open in a new window, or there are no windows, make one if(newWindow || m_windows.isEmpty()) { window = createWindow(); window->setProfile(profile(profileName)); } else { // reverse-iterate through windows to check for window with the same profile for(auto it = m_windows.rbegin(); it != m_windows.rend(); ++it) { if((*it)->profile()->storageName() == profileName) { window = *it; break; } } // if none is found, create one if(window == nullptr) { window = createWindow(); window->setProfile(profile(profileName)); } } Q_CHECK_PTR(window); if(urls.isEmpty()) { // no URLs were given window->newTab(QUrl::fromUserInput(m_config->value("profile.homepage").value().c_str())); } else { for(const QString &url : urls) { window->newTab(QUrl::fromUserInput(url)); } } return window; } std::shared_ptr Browser::profile(const QString &storageName) { if(m_profiles.contains(storageName)) { return m_profiles[storageName]; } // profile with name storageName has not been loaded Q_ASSERT(m_config); const QString &path = QString::fromStdString(m_config->value("profile.path").value()); std::shared_ptr _profile; if(storageName.isEmpty()) { // create off-the-record profile _profile = std::make_shared(nullptr); _profile->loadProfile(m_config->section("profile"), path + "/otr.ini"); } else { // regular profile _profile = std::make_shared(storageName, nullptr); _profile->loadProfile(m_config->section("profile"), path + "/" + storageName + "/profile.ini"); _profile->setPersistentStoragePath(path + "/storage"); _profile->setCachePath(path + "/cache"); } _profile->setRequestInterceptor(m_urlRequestInterceptor); _profile->cookieStore()->setCookieFilter([this](QWebEngineCookieStore::FilterRequest &request) { request.accepted = !m_cookieInterceptor->shouldBlock(request); }); connect(_profile.get(), &WebEngineProfile::downloadRequested, m_downloadManager.get(), &DownloadsWidget::addDownload); m_profiles.insert(storageName, _profile); return _profile; }