File indexing completed on 2024-05-19 05:01:20
0001 /* 0002 This file is part of the KDE project. 0003 0004 SPDX-FileCopyrightText: 2008 Dirk Mueller <mueller@kde.org> 0005 SPDX-FileCopyrightText: 2008 Urs Wolfer <uwolfer @ kde.org> 0006 SPDX-FileCopyrightText: 2009 Dawit Alemayehu <adawit@kde.org> 0007 0008 SPDX-License-Identifier: LGPL-2.1-or-later 0009 */ 0010 0011 #ifndef WEBENGINEPAGE_H 0012 #define WEBENGINEPAGE_H 0013 0014 #include "websslinfo.h" 0015 #include "kwebenginepartlib_export.h" 0016 #include "qtwebengine6compat.h" 0017 #include "browserextension.h" 0018 #include "webenginepartdownloadmanager.h" 0019 0020 #include <QWebEnginePage> 0021 0022 #include <QUrl> 0023 #include <QMultiHash> 0024 #include <QPointer> 0025 #include <QScopedPointer> 0026 #include <QWebEngineFullScreenRequest> 0027 0028 class QAuthenticator; 0029 class WebSslInfo; 0030 class WebEnginePart; 0031 class KPasswdServerClient; 0032 class WebEngineWallet; 0033 class WebEngineDownloadJob; 0034 0035 class WebEnginePage : public QWebEnginePage 0036 { 0037 Q_OBJECT 0038 public: 0039 explicit WebEnginePage(WebEnginePart *wpart, QWidget *parent = nullptr); 0040 ~WebEnginePage() override; 0041 0042 /** 0043 * Returns the SSL information for the current page. 0044 * 0045 * @see WebSslInfo. 0046 */ 0047 const WebSslInfo& sslInfo() const; 0048 0049 /** 0050 * Sets the page's SSL information to @p other. 0051 * 0052 * @see WebSslInfo 0053 */ 0054 void setSslInfo (const WebSslInfo &other); 0055 0056 void requestDownload(QWebEngineDownloadRequest *item, bool newWindow, WebEnginePartDownloadManager::DownloadObjective objective); 0057 0058 void setStatusBarText(const QString &text); 0059 0060 /** 0061 * @brief Sets the webengine part to be used by this object. 0062 * @param part the part 0063 */ 0064 void setPart(WebEnginePart *part); 0065 0066 #ifndef REMOTE_DND_NOT_HANDLED_BY_WEBENGINE 0067 /** 0068 * @brief Informs the page that a drop operation has been started 0069 * 0070 * Calling this method changes the behavior of createWindow() 0071 * @note Since `QWebEngineView` doesn't provide a way to tell when a drop operation actually end, 0072 * there's no function to inform that the drop operation has ended. The page considers the 0073 * drop operation to have ended when one the following happens: 0074 * - createWindow() is called 0075 * - the `loadStarted` signal is emitted 0076 * - 100ms have elapsed since the last call to this method (this time interval has been chosen arbitrary: it should 0077 * be enough for the drop operation to have actually ended but short enough to make it unlikely that 0078 * the user has started another action) 0079 * @see m_dropOperationTimer 0080 * @see createWindow() 0081 * @see WebEngineView::dropEvent 0082 */ 0083 void setDropOperationStarted(); 0084 #endif 0085 0086 #if QT_VERSION_MAJOR == 6 0087 QWidget* view() const; 0088 #endif 0089 0090 Q_SIGNALS: 0091 /** 0092 * This signal is emitted whenever a user cancels/aborts a load resource 0093 * request. 0094 */ 0095 void loadAborted(const QUrl &url); 0096 0097 void mainFrameNavigationRequested(WebEnginePage *page, const QUrl); 0098 0099 protected: 0100 /** 0101 * Returns the webengine part in use by this object. 0102 * @internal 0103 */ 0104 WebEnginePart* part() const; 0105 0106 /** 0107 * @brief Override of `QWebEnginePage::createWindow` 0108 * 0109 * Reimplemented for internal reasons, the API is not affected. 0110 * 0111 * By default, a new NewWindowPage will be returned; however, calling setDropOperationStarted changes 0112 * this behavior: in this case, no pages will be created and the function returns `this`. The default 0113 * behavior is restored when the drop operation ends (see setDropOperationStarted()). 0114 * @param type the window type to create. This is ignored if setDropOperationStarted has been called with `true` 0115 * @return a new NewWindowPage or `this` if within a drop operation 0116 * @see setDropOperationStarted 0117 */ 0118 QWebEnginePage* createWindow(WebWindowType type) override; 0119 protected: 0120 0121 /** 0122 * Reimplemented for internal reasons, the API is not affected. 0123 * @internal 0124 */ 0125 bool acceptNavigationRequest(const QUrl& request, NavigationType type, bool isMainFrame) override; 0126 0127 #if QT_VERSION_MAJOR < 6 0128 /** 0129 * @brief Override of `QWebEnginePage::certificateError` 0130 * 0131 * If the error is overridable, it first checks whether the user has already choosen to permanently ignore the error, in which case it returns `true`. 0132 * If the user hasn't made such a choice, the error is deferred and a WebEnginePartCertificateErrorDlg is shown. The result is handled by handleCertificateError. 0133 * 0134 * @internal 0135 * A problem arises if the certificate error happens while loading a page opened from a part which is not a WebEnginePart (this also includes the case when the 0136 * URL is entered in the location bar when the part is active). In this case, the URL is first loaded by KIO, then by WebEnginePart. If there's a certificate error, 0137 * it will be reported twice: by KIO and by the WebEnginePart. The old trick of using `m_urlLoadedByPart` doesn't work anymore, because if the current part is 0138 * a WebEnginePart, WebEnginePart::openUrl will be called, but everything will be handled by WebEnginePart. 0139 * 0140 * @param _ce the certificate error 0141 * @return @b false if the error is not overridable and @true in all other cases. Note that if @b _ce is deferred, according to the documentation for `QWebEngineCertificateError 0142 * the return value is ignored. 0143 */ 0144 bool certificateError(const QWebEngineCertificateError &_ce) override; 0145 #else 0146 signals: 0147 protected Q_SLOTS: 0148 void handleCertificateError(const QWebEngineCertificateError &ce); 0149 #endif 0150 0151 protected Q_SLOTS: 0152 void slotLoadFinished(bool ok); 0153 virtual void slotGeometryChangeRequested(const QRect& rect); 0154 void slotFeaturePermissionRequested(const QUrl& url, QWebEnginePage::Feature feature); 0155 void slotAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth); 0156 void changeFullScreenMode(QWebEngineFullScreenRequest req); 0157 void changeLifecycleState(QWebEnginePage::LifecycleState recommendedState); 0158 0159 /** 0160 * @brief Updates the stylesheet applied to the page 0161 * 0162 * Since `QtWebEngine` doesn't directly support custom stylesheets, this is done using javascript 0163 * @param script the script to run to update the stylesheet 0164 * @see WebEnginePartControls::updateUserStyleSheet 0165 * @see WebEnginePartControls::updateStyleSheet 0166 */ 0167 void updateUserStyleSheet(const QString &script); 0168 0169 private: 0170 bool checkFormData(const QUrl& url) const; 0171 bool handleMailToUrl (const QUrl& , NavigationType type) const; 0172 void setPageJScriptPolicy(const QUrl& url); 0173 bool askBrowserToOpenUrl(const QUrl &url, const QString &mimetype=QString(), const KParts::OpenUrlArguments &args = KParts::OpenUrlArguments(), const BrowserArguments &bargs = BrowserArguments()); 0174 bool downloadWithExternalDonwloadManager(const QUrl &url); 0175 0176 /** 0177 * @brief Whether WebEnginePart should open an URL by itself or delegate the main application 0178 * 0179 * This tries to take into account the user preferences and it's needed, for example, to ensure that 0180 * the link "Home Folder" in the introduction page is displayed in the part the user choose for directories 0181 * rather than in WebEnginePart. 0182 * 0183 * This function is meant to be used by acceptNavigationRequest(), which unfortunately means it doesn't know 0184 * the URL mimetype. Because of this, only preferences related to the URL's scheme can be applied. In particular: 0185 * - if the URL has the `file` scheme, its mimetype is detected using QMimeTypeDatabase and the appropriate 0186 * preferences are enforced 0187 * - if the URL has the `trash` or `remote` schemes, it is handled by the application 0188 * @param url the URL to open 0189 * @return `true` if WebEnginePart should open the URL and `false` if it should let the application open it 0190 */ 0191 bool shouldOpenUrl(const QUrl &url) const; 0192 0193 /** 0194 * @brief Saves the given remote URL to disk and asks the browser to display it 0195 * 0196 * This is used in response to the "Save URL as" entry in the context menu 0197 * 0198 * The URL is saved using the \link KonqInterfaces::DownloaderInterface DownloaderInterface\endlink. 0199 * The browser is asked to display the downloaded URL in a new tab and only if it 0200 * can be embedded. This is to minimize disturbance for the user (which has already 0201 * had to choose the download destination). 0202 * 0203 * @param req the object describing the download request 0204 * @param args the `KParts::OpenUrlArguments` to pass when asking the browser to display the downloaded URL 0205 * @param bArgs the `BrowserArguments` arguments to pass when asking the browser to display the downloaded URL 0206 * @todo Instead of asking the browser to display the downloaded URL, show a message widget at the bottom with 0207 * a button allowing the user to display the file and which disappears automatically after a time. It's similar 0208 * to the way Chrome allows to quickly open a file after downloading it, but it is only done when the user 0209 * explicitly asks to save the URL. 0210 */ 0211 void saveUrlToDiskAndDisplay(QWebEngineDownloadRequest *req, const KParts::OpenUrlArguments &args, const BrowserArguments &bArgs); 0212 0213 /** 0214 * @brief Saves the page currently displayed and opens the local copy 0215 * 0216 * This is used in response to the "Save as" menu entry 0217 * @param req the object describing the download request 0218 */ 0219 void saveAs(QWebEngineDownloadRequest *req); 0220 0221 private: 0222 enum WebEnginePageSecurity { PageUnencrypted, PageEncrypted, PageMixed }; 0223 0224 int m_kioErrorCode; 0225 bool m_ignoreError; 0226 0227 WebSslInfo m_sslInfo; 0228 QPointer<WebEnginePart> m_part; 0229 0230 QScopedPointer<KPasswdServerClient> m_passwdServerClient; 0231 0232 #ifndef REMOTE_DND_NOT_HANDLED_BY_WEBENGINE 0233 /** 0234 * @brief Timer used to decide whether a drop operation is happening 0235 * 0236 * A drop operation is happening if this timer is active 0237 * @see setDropOperationStarted for more details 0238 */ 0239 QTimer *m_dropOperationTimer; 0240 #endif 0241 0242 QMultiHash<QUrl, QWebEngineDownloadRequest*> m_downloadItems; 0243 }; 0244 0245 0246 /** 0247 * This is a fake implementation of WebEnginePage to workaround the ugly API used 0248 * to request for the creation of a new window from javascript in QtWebEngine. PORTING_TODO 0249 * 0250 * The KPart API for creating new windows requires all the information about the 0251 * new window up front. Unfortunately QWebEnginePage::createWindow function does not 0252 * provide any of these necessary information except for the window type. All 0253 * the other necessary information is emitted as signals instead! Hence, the 0254 * need for this class to collect all of the necessary information, such as 0255 * window name, size and position, before calling KPart's createNewWindow 0256 * function. 0257 */ 0258 class NewWindowPage : public WebEnginePage 0259 { 0260 Q_OBJECT 0261 public: 0262 NewWindowPage(WebWindowType windowType, WebEnginePart* part, 0263 QWidget* parent = nullptr); 0264 ~NewWindowPage() override; 0265 0266 protected: 0267 bool acceptNavigationRequest(const QUrl& request, NavigationType type, bool isMainFrame) override; 0268 0269 private Q_SLOTS: 0270 void slotGeometryChangeRequested(const QRect& rect) override; 0271 void slotMenuBarVisibilityChangeRequested(bool visible); 0272 void slotStatusBarVisibilityChangeRequested(bool visible); 0273 void slotToolBarVisibilityChangeRequested(bool visible); 0274 void slotLoadFinished(bool); 0275 0276 private: 0277 /** 0278 * @brief Decide whether the page is allowed to open a new window requested by javascript or not 0279 * @param url the URL to load in the new window 0280 * @return `true` if the page is allowed to open the new window and `false` if it isn't 0281 */ 0282 bool decideHandlingOfJavascripWindow(const QUrl url) const; 0283 0284 private: 0285 WindowArgs m_windowArgs; 0286 WebWindowType m_type; 0287 bool m_createNewWindow; 0288 }; 0289 0290 #endif // WEBENGINEPAGE_H 0291