File indexing completed on 2024-05-19 05:01:19

0001 /*
0002     This file is part of the KDE project.
0003 
0004     SPDX-FileCopyrightText: 2022 Stefano Crocco <stefano.crocco@alice.it>
0005 
0006     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0007 */
0008 
0009 #include "navigationrecorder.h"
0010 #include "webenginepage.h"
0011 
0012 NavigationRecorder::NavigationRecorder(QObject *parent) : QObject(parent)
0013 {
0014 }
0015 
0016 NavigationRecorder::~NavigationRecorder() noexcept
0017 {
0018 }
0019 
0020 void NavigationRecorder::registerPage(WebEnginePage* page)
0021 {
0022     connect(page, &QObject::destroyed, this, &NavigationRecorder::removePage);
0023     connect(page, &WebEnginePage::mainFrameNavigationRequested, this, &NavigationRecorder::recordNavigation);
0024     connect(page, &WebEnginePage::loadFinished, this, [this, page](bool){recordNavigationFinished(page, page->url());});
0025 }
0026 
0027 void NavigationRecorder::removePage(QObject*)
0028 {
0029     //NOTE: we cannot use QMultiHash::remove because this is connected to the QObject::destroyed signal,
0030     //which is emitted *after* the WebEnginePage destructor has been called, so it cannot be cast.
0031     //The workaround is to remove all nullptr entries, since the destroyed signal is emitted after
0032     //all instances of QPointer have been notified
0033     for (const QUrl &url : m_pendingNavigations.keys()) {
0034         m_pendingNavigations.remove(url, nullptr);
0035     }
0036     for (const QUrl &url : m_postNavigations.keys()) {
0037         m_postNavigations.remove(url, nullptr);
0038     }
0039 }
0040 
0041 void NavigationRecorder::recordNavigation(WebEnginePage* page, const QUrl& url)
0042 {
0043     m_pendingNavigations.insert(url, page);
0044 }
0045 
0046 void NavigationRecorder::recordNavigationFinished(WebEnginePage* page, const QUrl& url)
0047 {
0048     m_postNavigations.remove(url, page);
0049 }
0050 
0051 bool NavigationRecorder::isPostRequest(const QUrl& url, WebEnginePage* page) const
0052 {
0053     return m_postNavigations.contains(url, page);
0054 }
0055 
0056 void NavigationRecorder::recordRequestDetails(const QWebEngineUrlRequestInfo& info)
0057 {
0058     QUrl url(info.requestUrl());
0059     QList<QPointer<WebEnginePage>> pages = m_pendingNavigations.values(url);
0060     WebEnginePage *page = nullptr;
0061     if (!pages.isEmpty()) {
0062         //NOTE: QMultiHash::values returns a list where the first element is the one inserted last:
0063         //pages.last() is the page which first made the navigation request
0064         page = pages.last();
0065         m_pendingNavigations.remove(url, page);
0066     } else {
0067         return;
0068     }
0069     if (info.requestMethod() == QByteArrayLiteral("POST")) {
0070         m_postNavigations.insert(url, page);
0071     }
0072 }