/******************************************************************************* ** ** smolbote: yet another qute browser ** Copyright (C) 2017 Xian Nox ** ** 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 3 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 . ** ******************************************************************************/ #include "browser.h" #include "mainwindow.h" #include #include Browser::Browser(int &argc, char *argv[]) : QApplication(argc, argv) { setApplicationName("smolbote"); // This lets the web view automatically scale on high-dpi displays. setAttribute(Qt::AA_EnableHighDpiScaling); m_settings = nullptr; m_localServer = nullptr; m_networkAccessManager = nullptr; m_urlRequestInterceptor = nullptr; m_bookmarksManager = nullptr; m_downloadManager = nullptr; m_blocklistManager = nullptr; } Browser::~Browser() { qDeleteAll(m_windows); m_windows.clear(); if(m_networkAccessManager) { delete m_networkAccessManager; } if(m_bookmarksManager) { delete m_bookmarksManager; } if(m_downloadManager) { delete m_downloadManager; } } QString Browser::applicationLongVersion() const { #ifdef GIT_DESCRIBE return QString(GIT_DESCRIBE); #else return applicationVersion(); #endif } bool Browser::prepare(QStringList urls) { if(m_settings->value("browser.singleInstance", true).toBool()) { QString serverName = m_settings->value("browser.localSocket", "smolbote-singlelock").toString(); // Check for other running instance QLocalSocket socket; socket.connectToServer(serverName); if(socket.waitForConnected(500)) { QTextStream stream(&socket); stream << urls.join('|'); stream.flush(); socket.waitForBytesWritten(); return false; } // There is no other instance m_localServer = new QLocalServer(this); connect(m_localServer, SIGNAL(newConnection()), this, SLOT(handleNewConnection())); if (!m_localServer->listen(serverName) && m_localServer->serverError() == QAbstractSocket::AddressInUseError) { // Could not create local server because the socket is already in use QLocalServer::removeServer(serverName); if (!m_localServer->listen(serverName)) { // Couldn't free the socket qWarning("Could not create local socket %s.", qPrintable(serverName)); } } else { qDebug("Created local socket."); } } if(m_settings->isEmpty()) { // There are no keys in the settings QMessageBox::information(0, tr("Configuration is empty"), tr("The configuration file %1 is empty. Using default values").arg(m_settings->filePath())); } m_networkAccessManager = new QNetworkAccessManager(); m_bookmarksManager = new BookmarksWidget; m_downloadManager = new DownloadsWidget; m_blocklistManager = new BlockerManager; QtWebEngine::initialize(); return true; } Browser *Browser::instance() { return static_cast(QCoreApplication::instance()); } Settings *Browser::settings() { return m_settings; } QNetworkAccessManager *Browser::network() { return m_networkAccessManager; } BookmarksWidget *Browser::bookmarks() { return m_bookmarksManager; } DownloadsWidget *Browser::downloads() { return m_downloadManager; } BlockerManager *Browser::blocklists() { return m_blocklistManager; } void Browser::setConfigPath(const QString &path) { // set custom config path if any if(!path.isEmpty()) { m_settings = new Settings(path); return; } // check if config file exists for this user QString cpath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/poi.conf"; if(QFile::exists(cpath)) { m_settings = new Settings(cpath); } // check system-specific locations #ifdef Q_OS_LINUX else if(QFile::exists("/usr/share/smolbote/poi.conf")) { m_settings = new Settings("/usr/share/smolbote/poi.conf"); } else if(QFile::exists("/usr/local/share/smolbote/poi.conf")) { m_settings = new Settings("/usr/local/share/smolbote/poi.conf"); } #endif else { m_settings = new Settings(); } } void Browser::addWindow(MainWindow *window) { if(m_windows.contains(window)) { return; } m_windows.append(window); connect(window, &QObject::destroyed, [this, window]() { this->removeWindow(window); }); window->show(); } MainWindow *Browser::mainWindow() { if(m_windows.isEmpty()) { addWindow(new MainWindow()); } return m_windows.first(); } void Browser::removeWindow(MainWindow *window) { m_windows.removeOne(window); } WebEngineProfile* Browser::profile(const QString name) { if(!m_profiles.contains(name)) { // name can be empty --> off-the-record profile if(name.isEmpty()) { m_profiles.insert(name, new WebEngineProfile(this)); } else { m_profiles.insert(name, new WebEngineProfile(name, this)); } if(!m_urlRequestInterceptor) { m_urlRequestInterceptor = new UrlRequestInterceptor(this); m_urlRequestInterceptor->setSubscription(m_blocklistManager); } m_profiles[name]->setRequestInterceptor(m_urlRequestInterceptor); connect(m_profiles[name], SIGNAL(downloadRequested(QWebEngineDownloadItem*)), downloads(), SLOT(addDownload(QWebEngineDownloadItem*))); } return m_profiles[name]; } void Browser::handleNewConnection() { QLocalSocket *socket = m_localServer->nextPendingConnection(); if(!socket) { // null socket -> return return; } socket->waitForReadyRead(); const QStringList urls = QString(socket->readAll()).split('|'); delete socket; QStringList::const_iterator i; for(i = urls.constBegin(); i != urls.constEnd(); ++i) { mainWindow()->addNewTab(QUrl::fromUserInput(*i)); } }