File indexing completed on 2024-04-28 08:50:37

0001 /* This file is part of the KDE project
0002     SPDX-FileCopyrightText: 2006 David Faure <faure@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <QtGlobal>
0008 
0009 #include "konqapplication.h"
0010 #include "konqsettings.h"
0011 #include <konqueror-version.h>
0012 #include "konqmainwindow.h"
0013 #include "KonquerorAdaptor.h"
0014 #include "konqviewmanager.h"
0015 #include "konqurl.h"
0016 #include "konqsettingsxt.h"
0017 #include "konqsessionmanager.h"
0018 #include "konqclosedwindowsmanager.h"
0019 #include "konqdebug.h"
0020 #include "konqmainwindow.h"
0021 #include "konqmainwindowfactory.h"
0022 #include "konqmisc.h"
0023 #include <config-konqueror.h>
0024 #include "implementations/konqbrowser.h"
0025 
0026 #include "interfaces/browser.h"
0027 
0028 #include <QDBusConnection>
0029 #include <QDBusMessage>
0030 #include <QCommandLineParser>
0031 #include <QCommandLineOption>
0032 #include <QDir>
0033 #include <QProcess>
0034 #include <QDirIterator>
0035 #include <QTextStream>
0036 
0037 #if QT_VERSION_MAJOR < 6
0038 #include <QX11Info>
0039 #else
0040 #include <QtGui/private/qtx11extras_p.h>
0041 #endif
0042 
0043 #include <KCrash>
0044 #include <KLocalizedString>
0045 #include <KSharedConfig>
0046 #include <KDBusService>
0047 #include <KStartupInfo>
0048 #include <KWindowSystem>
0049 #include <kwindowsystem_version.h>
0050 #include <KX11Extras>
0051 #include <KMessageBox>
0052 
0053 #ifdef KActivities_FOUND
0054 #include "activitymanager.h"
0055 #if QT_VERSION_MAJOR < 6
0056 #include <KActivities/Consumer>
0057 #else //QT_VERSION_MAJOR
0058 #include <PlasmaActivities/Consumer>
0059 #endif //QT_VERSION_MAJOR
0060 #endif //KActivities_FOUND
0061 
0062 #include <iostream>
0063 #include <unistd.h>
0064 
0065 #ifdef KActivities_FOUND
0066 #endif
0067 
0068 using namespace KonqInterfaces;
0069 
0070 QString KonquerorApplication::currentActivity()
0071 {
0072 #ifdef KActivities_FOUND
0073     KonquerorApplication* app = qobject_cast<KonquerorApplication*>(QApplication::instance());
0074     if (!app || !app->m_activityConsumer || app->m_activityConsumer->serviceStatus() != KActivities::Consumer::Running) {
0075         return QString();
0076     }
0077     return app->m_activityConsumer->currentActivity();
0078 #else
0079     return QString();
0080 #endif
0081 }
0082 
0083 KonquerorApplication::KonquerorApplication(int &argc, char **argv)
0084     : QApplication(argc, argv), m_browser(nullptr)
0085 #ifdef KActivities_FOUND
0086     , m_activityConsumer(new KActivities::Consumer(this))
0087 #endif
0088 {
0089     // enable high dpi support
0090     setAttribute(Qt::AA_UseHighDpiPixmaps, true);
0091 
0092     new KonquerorAdaptor; // not really an adaptor
0093     const QString dbusInterface = QStringLiteral("org.kde.Konqueror.Main");
0094     QDBusConnection dbus = QDBusConnection::sessionBus();
0095     dbus.connect(QString(), KONQ_MAIN_PATH, dbusInterface, QStringLiteral("reparseConfiguration"), this, SLOT(slotReparseConfiguration()));
0096     dbus.connect(QString(), KONQ_MAIN_PATH, dbusInterface, QStringLiteral("addToCombo"), this,
0097                  SLOT(slotAddToCombo(QString,QDBusMessage)));
0098     dbus.connect(QString(), KONQ_MAIN_PATH, dbusInterface, QStringLiteral("removeFromCombo"), this,
0099                  SLOT(slotRemoveFromCombo(QString,QDBusMessage)));
0100     dbus.connect(QString(), KONQ_MAIN_PATH, dbusInterface, QStringLiteral("comboCleared"), this, SLOT(slotComboCleared(QDBusMessage)));
0101 
0102 #ifdef WEBENGINEPART_OWN_DICTIONARY_DIR
0103     //If the user alredy set QTWEBENGINE_DICTIONARIES_PATH, don't override it
0104     if (!qEnvironmentVariableIsSet("QTWEBENGINE_DICTIONARIES_PATH")) {
0105         qputenv("QTWEBENGINE_DICTIONARIES_PATH", WEBENGINEPART_OWN_DICTIONARY_DIR);
0106     }
0107 #endif
0108 
0109     m_runningAsRootBehavior = checkRootBehavior();
0110 
0111     QByteArray flags = qgetenv("QTWEBENGINE_CHROMIUM_FLAGS");
0112     flags.append(" --enable-features=WebRTCPipeWireCapturer");
0113     if (m_runningAsRootBehavior == RunInDangerousMode) {
0114         flags.append (" --no-sandbox");
0115     }
0116 
0117     qputenv("QTWEBENGINE_CHROMIUM_FLAGS", flags);
0118     KLocalizedString::setApplicationDomain("konqueror");
0119 
0120 #ifdef KActivities_FOUND
0121     m_activityConsumer = new KActivities::Consumer(this);
0122 #endif
0123 }
0124 
0125 KonquerorApplication::KonquerorAsRootBehavior KonquerorApplication::checkRootBehavior()
0126 {
0127     uid_t uid = geteuid();
0128     if (uid == 0) {
0129         QString msg = i18n("<p>You're running Konqueror as root. This requires enabling a highly insecure mode in the browser component.</p><p>What do you want to do?</p>");
0130         KGuiItem enableInsecureMode(QLatin1String("Enable the insecure mode")); //Continue
0131         KGuiItem exitKonq(QLatin1String("Exit Konqueror")); //Cancel
0132         KMessageBox::ButtonCode ans = KMessageBox::warningContinueCancel(nullptr, msg, QString(), enableInsecureMode, exitKonq);
0133         return ans == KMessageBox::Continue ? RunInDangerousMode : PreventRunningAsRoot;
0134     } else {
0135         return NotRoot;
0136     }
0137 }
0138 
0139 void KonquerorApplication::slotReparseConfiguration()
0140 {
0141     KSharedConfig::openConfig()->reparseConfiguration();
0142     KonqFMSettings::reparseConfiguration();
0143     m_browser->applyConfiguration();
0144 
0145     QList<KonqMainWindow *> *mainWindows = KonqMainWindow::mainWindowList();
0146     if (mainWindows) {
0147         for (KonqMainWindow *window: *mainWindows) {
0148             window->reparseConfiguration();
0149         }
0150     }
0151 
0152     emit configurationChanged();
0153 }
0154 
0155 void KonquerorApplication::slotAddToCombo(const QString &url, const QDBusMessage &msg)
0156 {
0157     KonqMainWindow::comboAction(KonqMainWindow::ComboAdd, url, msg.service());
0158 }
0159 
0160 void KonquerorApplication::slotRemoveFromCombo(const QString &url, const QDBusMessage &msg)
0161 {
0162     KonqMainWindow::comboAction(KonqMainWindow::ComboRemove, url, msg.service());
0163 }
0164 
0165 void KonquerorApplication::slotComboCleared(const QDBusMessage &msg)
0166 {
0167     KonqMainWindow::comboAction(KonqMainWindow::ComboClear, QString(), msg.service());
0168 }
0169 
0170 void KonquerorApplication::setupAboutData()
0171 {
0172     KAboutData m_aboutData("konqueror", i18n("Konqueror"), KONQUEROR_VERSION);
0173     m_aboutData.setShortDescription(i18n("Web browser, file manager and document viewer."));
0174     m_aboutData.addLicense(KAboutLicense::GPL_V2);
0175     m_aboutData.setCopyrightStatement(i18n("(C) 1999-2023, The Konqueror developers"));
0176     m_aboutData.setHomepage("https://apps.kde.org/konqueror");
0177 
0178     m_aboutData.addAuthor(i18n("Stefano Crocco"), i18n("Current maintainer"), "stefano.crocco@alice.it");
0179     m_aboutData.addAuthor(i18n("David Faure"), i18n("Developer (framework, parts, JavaScript, I/O library) and former maintainer"), "faure@kde.org");
0180     m_aboutData.addAuthor(i18n("Simon Hausmann"), i18n("Developer (framework, parts)"), "hausmann@kde.org");
0181     m_aboutData.addAuthor(i18n("Michael Reiher"), i18n("Developer (framework)"), "michael.reiher@gmx.de");
0182     m_aboutData.addAuthor(i18n("Matthias Welk"), i18n("Developer"), "welk@fokus.gmd.de");
0183     m_aboutData.addAuthor(i18n("Alexander Neundorf"), i18n("Developer (List views)"), "neundorf@kde.org");
0184     m_aboutData.addAuthor(i18n("Michael Brade"), i18n("Developer (List views, I/O library)"), "brade@kde.org");
0185     m_aboutData.addAuthor(i18n("Lars Knoll"), i18n("Developer (HTML rendering engine)"), "knoll@kde.org");
0186     m_aboutData.addAuthor(i18n("Dirk Mueller"), i18n("Developer (HTML rendering engine)"), "mueller@kde.org");
0187     m_aboutData.addAuthor(i18n("Peter Kelly"), i18n("Developer (HTML rendering engine)"), "pmk@post.com");
0188     m_aboutData.addAuthor(i18n("Waldo Bastian"), i18n("Developer (HTML rendering engine, I/O library)"), "bastian@kde.org");
0189     m_aboutData.addAuthor(i18n("Germain Garand"), i18n("Developer (HTML rendering engine)"), "germain@ebooksfrance.org");
0190     m_aboutData.addAuthor(i18n("Leo Savernik"), i18n("Developer (HTML rendering engine)"), "l.savernik@aon.at");
0191     m_aboutData.addAuthor(i18n("Stephan Kulow"), i18n("Developer (HTML rendering engine, I/O library, regression test framework)"), "coolo@kde.org");
0192     m_aboutData.addAuthor(i18n("Antti Koivisto"), i18n("Developer (HTML rendering engine)"), "koivisto@kde.org");
0193     m_aboutData.addAuthor(i18n("Zack Rusin"),  i18n("Developer (HTML rendering engine)"), "zack@kde.org");
0194     m_aboutData.addAuthor(i18n("Tobias Anton"), i18n("Developer (HTML rendering engine)"), "anton@stud.fbi.fh-darmstadt.de");
0195     m_aboutData.addAuthor(i18n("Lubos Lunak"), i18n("Developer (HTML rendering engine)"), "l.lunak@kde.org");
0196     m_aboutData.addAuthor(i18n("Maks Orlovich"), i18n("Developer (HTML rendering engine, JavaScript)"), "maksim@kde.org");
0197     m_aboutData.addAuthor(i18n("Allan Sandfeld Jensen"), i18n("Developer (HTML rendering engine)"), "kde@carewolf.com");
0198     m_aboutData.addAuthor(i18n("Apple Safari Developers"), i18n("Developer (HTML rendering engine, JavaScript)"));
0199     m_aboutData.addAuthor(i18n("Harri Porten"), i18n("Developer (JavaScript)"), "porten@kde.org");
0200     m_aboutData.addAuthor(i18n("Koos Vriezen"), i18n("Developer (Java applets and other embedded objects)"), "koos.vriezen@xs4all.nl");
0201     m_aboutData.addAuthor(i18n("Matt Koss"), i18n("Developer (I/O library)"), "koss@miesto.sk");
0202     m_aboutData.addAuthor(i18n("Alex Zepeda"), i18n("Developer (I/O library)"), "zipzippy@sonic.net");
0203     m_aboutData.addAuthor(i18n("Richard Moore"), i18n("Developer (Java applet support)"), "rich@kde.org");
0204     m_aboutData.addAuthor(i18n("Dima Rogozin"), i18n("Developer (Java applet support)"), "dima@mercury.co.il");
0205     m_aboutData.addAuthor(i18n("Wynn Wilkes"), i18n("Developer (Java 2 security manager support,\n and other major improvements to applet support)"), "wynnw@calderasystems.com");
0206     m_aboutData.addAuthor(i18n("Stefan Schimanski"), i18n("Developer (Netscape plugin support)"), "schimmi@kde.org");
0207     m_aboutData.addAuthor(i18n("George Staikos"), i18n("Developer (SSL, Netscape plugins)"), "staikos@kde.org");
0208     m_aboutData.addAuthor(i18n("Dawit Alemayehu"), i18n("Developer (I/O library, Authentication support)"), "adawit@kde.org");
0209     m_aboutData.addAuthor(i18n("Carsten Pfeiffer"), i18n("Developer (framework)"), "pfeiffer@kde.org");
0210     m_aboutData.addAuthor(i18n("Torsten Rahn"), i18n("Graphics/icons"), "torsten@kde.org");
0211     m_aboutData.addAuthor(i18n("Torben Weis"), i18n("KFM author"), "weis@kde.org");
0212     m_aboutData.addAuthor(i18n("Joseph Wenninger"), i18n("Developer (navigation panel framework)"), "jowenn@kde.org");
0213     m_aboutData.addAuthor(i18n("Stephan Binner"), i18n("Developer (misc stuff)"), "binner@kde.org");
0214     m_aboutData.addAuthor(i18n("Ivor Hewitt"), i18n("Developer (AdBlock filter)"), "ivor@ivor.org");
0215     m_aboutData.addAuthor(i18n("Eduardo Robles Elvira"), i18n("Developer (framework)"), "edulix@gmail.com");
0216     m_aboutData.addAuthor(i18n("Matthias Kalle Dalheimer"), QLatin1String(""), QStringLiteral("kalle@kde.org"));
0217     m_aboutData.addAuthor(i18n("Daniel Molkentin"), QLatin1String(""), QStringLiteral("molkentin@kde.org"));
0218     m_aboutData.addCredit(i18n("Leo Savernik"), i18n("JavaScript access controls\n"
0219                      "Per-domain policies extensions"),
0220                      QStringLiteral("l.savernik@aon.at"));
0221     KAboutData::setApplicationData(m_aboutData);
0222 }
0223 
0224 void KonquerorApplication::setupParser()
0225 {
0226     m_parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
0227     m_aboutData.setupCommandLine(&m_parser);
0228 
0229     m_parser.addOption(QCommandLineOption(QStringList{QStringLiteral("silent")}, i18n("Start without a default window, when called without URLs")));
0230     m_parser.addOption(QCommandLineOption(QStringList{QStringLiteral("preload")}, i18n("Preload for later use. This mode does not support URLs on the command line")));
0231     m_parser.addOption(QCommandLineOption(QStringList{QStringLiteral("profile")}, i18n("Profile to open (DEPRECATED, IGNORED)"), i18n("profile")));
0232     m_parser.addOption(QCommandLineOption(QStringList{QStringLiteral("sessions")}, i18n("List available sessions")));
0233     m_parser.addOption(QCommandLineOption(QStringList{QStringLiteral("open-session")}, i18n("Session to open"), i18n("session")));
0234     m_parser.addOption(QCommandLineOption(QStringList{QStringLiteral("mimetype")}, i18n("Mimetype to use for this URL (e.g. text/html or inode/directory)"), i18n("mimetype")));
0235     m_parser.addOption(QCommandLineOption(QStringList{QStringLiteral("part")}, i18n("Part to use (e.g. khtml or kwebkitpart)"), i18n("service")));
0236     m_parser.addOption(QCommandLineOption(QStringList{QStringLiteral("select")}, i18n("For URLs that point to files, opens the directory and selects the file, instead of opening the actual file")));
0237     m_parser.addOption(QCommandLineOption(QStringList{QStringLiteral("tempfile")}, i18n("The files/URLs opened by the application will be deleted after use")));
0238 #ifdef DEVELOPER_MODE
0239     m_parser.addOption(QCommandLineOption({QStringLiteral("force-new-process")}, i18n("Create a new Konqueror process, even if one already exists. Meant to be used only when developing Konqueror itself")));
0240 #endif
0241     m_parser.addOption(QCommandLineOption({QStringLiteral("test-restore")}, i18n("TEST")));
0242     m_parser.addPositionalArgument(QStringLiteral("[URL]"), i18n("Location to open"));
0243 }
0244 
0245 static void fixOldStartUrl() {
0246     QUrl startUrl(KonqSettings::startURL());
0247     if (startUrl.scheme() == "about") {
0248         startUrl.setScheme(KonqUrl::scheme());
0249         KonqSettings::setStartURL(startUrl.url());
0250         KonqSettings::self()->save();
0251     }
0252 }
0253 
0254 int KonquerorApplication::startFirstInstance()
0255 {
0256     fixOldStartUrl();
0257 
0258     m_browser = new KonqBrowser(this);
0259     connect(this, &KonquerorApplication::configurationChanged, m_browser, &KonqBrowser::configurationChanged);
0260 
0261     if (isSessionRestored()) {
0262         restoreSession();
0263     } else {
0264         performStart(QDir::currentPath(), true);
0265     }
0266 
0267     QString programName = QApplication::applicationFilePath();
0268 
0269     //Ensure a session manager is created
0270     KonqSessionManager::self();
0271 
0272     const int ret = exec();
0273 
0274     //Don't preload if Konqueror is run as root
0275     bool alwaysPreload = m_runningAsRootBehavior == NotRoot && KonqSettings::alwaysHavePreloaded();
0276 
0277     // Delete all KonqMainWindows, so that we don't have
0278     // any parts loaded when KLibLoader::cleanUp is called.
0279     // (and Qt doesn't delete WA_DeleteOnClose widgets on exit anyway :()
0280     while (KonqMainWindow::mainWindowList() != nullptr) {
0281         // the list will be deleted by last KonqMainWindow
0282         delete KonqMainWindow::mainWindowList()->first();
0283     }
0284 
0285     // Notify the session manager that the instance was closed without errors, and normally.
0286     KonqSessionManager::self()->disableAutosave();
0287     KonqSessionManager::self()->deleteOwnedSessions();
0288 
0289     KonqClosedWindowsManager::destroy();
0290 
0291     if (alwaysPreload) {
0292         QProcess::startDetached(programName, {"--preload"});
0293     }
0294 
0295     return ret;
0296 }
0297 
0298 int KonquerorApplication::start()
0299 {
0300     if (m_runningAsRootBehavior == PreventRunningAsRoot) {
0301         return 0;
0302     }
0303 
0304     setupAboutData();
0305     setupParser();
0306 
0307     KCrash::initialize();
0308 
0309     m_parser.process(*this);
0310     m_aboutData.processCommandLine(&m_parser);
0311 
0312 #ifdef DEVELOPER_MODE
0313     bool forceNewProcess = m_runningAsRootBehavior != NotRoot || m_parser.isSet(QStringLiteral("force-new-process"));
0314 #else
0315     bool forceNewProcess = m_runningAsRootBehavior != NotRoot;
0316 #endif
0317 
0318     //Explicitly disable reusing existing instances if running as root. The behavior is not clear
0319     //and could be dangerous if new windows are unknowingly launched as root.
0320     //I thought that creating the KDBusService instance inside the if block should do it; however, doing
0321     //so prevents the new window to be created because the new instance produces a critical failure with message:
0322     //Couldn't register name 'org.kde.konqueror' with DBUS - another process owns it already!
0323     //Moving the service creation outside the if block seems to solve the issue.
0324     //
0325     //This also disables reusing an existing instance when running in developer mode
0326     KDBusService dbusService(forceNewProcess ? KDBusService::Multiple | KDBusService::NoExitOnFailure : KDBusService::Unique);
0327     if (!forceNewProcess) {
0328         auto activateApp = [this](const QStringList &arguments, const QString &workingDirectory) {
0329             m_parser.parse(arguments);
0330             performStart(workingDirectory, false);
0331         };
0332         QObject::connect(&dbusService, &KDBusService::activateRequested, activateApp);
0333     }
0334 
0335     return startFirstInstance();
0336 }
0337 
0338 int KonquerorApplication::performStart(const QString& workingDirectory, bool firstInstance)
0339 {
0340     const QStringList args = m_parser.positionalArguments();
0341 
0342     if (m_parser.isSet("sessions")) {
0343         listSessions();
0344         return 0;
0345     } else if (m_parser.isSet("open-session")) {
0346         //If the given session can't be opened for any reason, inform the user
0347         QString sessionName = m_parser.value("open-session");
0348         int result = openSession(sessionName);
0349         if (result != 0) {
0350             KMessageBox::error(nullptr, i18nc("The session asked by the user doesn't exist or can't be opened",
0351                                               "Session %1 couldn't be opened", sessionName));
0352         }
0353         //If there was an error opening the session and this is the first instance, don't return immediately
0354         //as this would lead to the application being run but with no windows open. Instead, open an empty
0355         //window
0356         if (result != 0 && firstInstance) {
0357             return result;
0358         }
0359     }
0360 
0361     //We check for the --preload switch before attempting recovering session because we shouldn't
0362     //display windows when the user only asked to preload a window
0363     if (m_parser.isSet("preload")) {
0364         preloadWindow(args);
0365         return 0;
0366     }
0367 
0368     //Don't attempt to restore session when running as root
0369     if (!m_sessionRecoveryAttempted && m_runningAsRootBehavior == NotRoot) {
0370         // Ask the user to recover session if applicable
0371         KonqSessionManager::self()->askUserToRestoreAutosavedAbandonedSessions();
0372         m_sessionRecoveryAttempted = true;
0373     }
0374 
0375     WindowCreationResult result;
0376 
0377     bool sessionRestored = KonqSessionManager::self()->restoreSessionSavedAtExit();
0378     if (!args.isEmpty()) {
0379         //KonqSessionManager::restoreSessionSavedAtExit only returns true if there's at least one main window,
0380         //so there's no need to check whether the list is empty
0381         result = createWindowsForUrlArguments(args, workingDirectory, sessionRestored ? KonqMainWindow::mainWindows().at(0) : nullptr);
0382     } else if (sessionRestored){
0383         result = WindowCreationResult{KonqMainWindow::mainWindows().at(0), 0};
0384     } else {
0385         result = createEmptyWindow(firstInstance, true);
0386     }
0387 
0388     KonqMainWindow *mw = result.first;
0389     if (!firstInstance && mw) {
0390         mw ->setAttribute(Qt::WA_NativeWindow, true);
0391         if (KWindowSystem::isPlatformX11()) {
0392             KStartupInfo::setNewStartupId(mw->windowHandle(), QX11Info::nextStartupId());
0393             KX11Extras::forceActiveWindow(mw->winId());
0394         } else {
0395             KStartupInfo::setNewStartupId(mw->windowHandle(), qEnvironmentVariable("XDG_ACTIVATION_TOKEN").toUtf8());
0396         }
0397     }
0398 
0399     return result.second;
0400 }
0401 
0402 KonquerorApplication::WindowCreationResult KonquerorApplication::createWindowsForUrlArguments(const QStringList& args, const QString &workingDirectory, KonqMainWindow *mainwin)
0403 {
0404     QList<QUrl> urlList;
0405     urlList.reserve(args.length());
0406 
0407     auto urlFromArg = [workingDirectory](const QString &arg) {
0408         const QUrl url = QUrl::fromUserInput(arg, workingDirectory);
0409         // KonqMisc::konqFilteredURL doesn't cope with local files... A bit of hackery below
0410         if (url.isLocalFile() && QFile::exists(url.toLocalFile())) { // "konqueror index.html"
0411             return url;
0412         } else { // "konqueror slashdot.org"
0413             return KonqMisc::konqFilteredURL(nullptr, arg);
0414         }
0415     };
0416 
0417     for (const QString &arg : args) {
0418         urlList.append(urlFromArg(arg));
0419     };
0420 
0421     QList<QUrl> filesToSelect;
0422     if (m_parser.isSet("select")) {
0423         // Get all distinct directories from 'files' and open a tab
0424         // for each directory.
0425         QList<QUrl> dirs;
0426         for (const QUrl &url : urlList) {
0427             const QUrl dir(url.adjusted(QUrl::RemoveFilename));
0428             if (!dirs.contains(dir)) {
0429                 dirs.append(dir);
0430             }
0431         }
0432         filesToSelect = urlList;
0433         urlList = dirs;
0434     }
0435 
0436     QUrl firstUrl = urlList.takeFirst();
0437 
0438     KParts::OpenUrlArguments urlargs;
0439     if (m_parser.isSet("mimetype")) {
0440         urlargs.setMimeType(m_parser.value("mimetype"));
0441     }
0442 
0443     KonqOpenURLRequest req;
0444     req.args = urlargs;
0445     req.filesToSelect = filesToSelect;
0446     req.tempFile = m_parser.isSet("tempfile");
0447     req.serviceName = m_parser.value("part");
0448 
0449     if (!mainwin) {
0450         mainwin = KonqMainWindowFactory::createNewWindow(firstUrl, req);
0451         if (!mainwin) {
0452             return qMakePair(nullptr, 1);
0453         }
0454     } else {
0455         req.browserArgs.setNewTab(true);
0456         mainwin->openUrl(nullptr, firstUrl, req.args.mimeType(), req);
0457     }
0458 
0459     mainwin->show();
0460     if (!urlList.isEmpty()) {
0461         // Open the other urls as tabs in that window
0462         mainwin->openMultiURL(urlList);
0463     }
0464 
0465     //Ensure the last tab is activated. This happens automatically if a new main window was created
0466     //but not if an existing main window was passed as argument, which is the case if the last Konqueror
0467     //session was restored
0468     mainwin->activateTab(mainwin->tabsCount()-1);
0469     return qMakePair(mainwin, 0);
0470 }
0471 
0472 void KonquerorApplication::preloadWindow(const QStringList &args)
0473 {
0474     if (!args.isEmpty()) {
0475         QTextStream ts(stderr, QIODevice::WriteOnly);
0476         ts << i18n("You can't pass URLs when using the --preload switch. The URLs will be ignored\n");
0477     }
0478     KonqMainWindowFactory::createPreloadWindow();
0479 }
0480 
0481 KonquerorApplication::WindowCreationResult KonquerorApplication::createEmptyWindow(bool firstInstance, bool calledFromPerformStart )
0482 {
0483     //Always create a new window except when called with the --silent switch or a session has been recovered (see #388333)
0484     if (m_parser.isSet("silent")) {
0485         return qMakePair(nullptr, 0);
0486     }
0487 
0488 //WORKAROUND for activities
0489 //Consider the following situation:
0490 //- multiple windows, in different activities
0491 //- the user stops one or more activities. The corresponding windows are closed
0492 //- the user exits Konqueror
0493 //- the user restarts Konqueror
0494 //- the user restarts one of the stopped activities which had Konqueror windows on them
0495 //What should happen is that the previously open windows in the restarted activity are restored
0496 //What really happens is that, besides those window, a new, empty window is created. This is because KWin/KSMService attempts
0497 //to start Konqueror again, passing it the information needed to restore the windows. However, for some reason, no information
0498 //is given and Konqueror creates an emtpy window. The following check avoids creating the window.
0499 #ifdef KActivities_FOUND
0500     ActivityManager *am = KonqSessionManager::self()->activityManager();
0501     if (calledFromPerformStart && am && am->restoringStoppedActivity()) {
0502         am->restoringStoppedActivityDone();
0503         return qMakePair(nullptr, 0);
0504     }
0505 #endif
0506 
0507     if (firstInstance) { // If session recovery created some windows, no need for an empty window here.
0508         QList<KonqMainWindow *> *mainWindowList = KonqMainWindow::mainWindowList();
0509         if (mainWindowList && !mainWindowList->isEmpty()) {
0510             return qMakePair(mainWindowList->at(0), 0);
0511         }
0512     }
0513 
0514     KonqMainWindow *mainWin = KonqMainWindowFactory::createNewWindow();
0515     if (mainWin) {
0516         mainWin->show();
0517         return qMakePair(mainWin, 0);
0518     } else {
0519         return qMakePair(nullptr, 1);
0520     }
0521 }
0522 
0523 void KonquerorApplication::listSessions()
0524 {
0525     const QString dir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/') + "sessions/";
0526     QDirIterator it(dir, QDir::Readable | QDir::NoDotAndDotDot | QDir::Dirs);
0527     QTextStream ts(stdout, QIODevice::WriteOnly);
0528     while (it.hasNext()) {
0529         QFileInfo fileInfo(it.next());
0530         ts << fileInfo.baseName();
0531     }
0532 }
0533 
0534 int KonquerorApplication::openSession(const QString& session)
0535 {
0536     QString sessionPath = session;
0537     if (!session.startsWith('/')) {
0538         sessionPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/') + "sessions/" + session;
0539     }
0540 
0541     QDirIterator it(sessionPath, QDir::Readable | QDir::Files);
0542     if (!it.hasNext()) {
0543         qCWarning(KONQUEROR_LOG) << "session" << session << "not found or empty";
0544         return 1;
0545     }
0546 
0547     KonqSessionManager::self()->restoreSessions(sessionPath);
0548 
0549     QList<KonqMainWindow*> *mainWindows = KonqMainWindow::mainWindowList();
0550     return (mainWindows && !mainWindows->isEmpty()) ? 0 : 1;
0551 }
0552 
0553 void KonquerorApplication::restoreSession()
0554 {
0555     KonqSessionManager::self()->restoreSessionSavedAtLogout();
0556 }