From acce17434876082ba46c631109b48e641185ca17 Mon Sep 17 00:00:00 2001 From: Andras Becsi Date: Fri, 17 Oct 2014 16:01:40 +0200 Subject: Implement acceptNavigationRequest for the widgets API. This is the equivalent API for navigationRequested in QtQuick. This patch also enables and updates tests that depended on this API, and removes the ones that we will not support. Change-Id: I28970c11225420a9680fbd767880130492664179 Reviewed-by: Michael Bruning --- examples/webenginewidgets/browser/webview.cpp | 34 +---- examples/webenginewidgets/browser/webview.h | 4 +- src/webenginewidgets/api/qwebenginepage.cpp | 15 ++ src/webenginewidgets/api/qwebenginepage.h | 11 ++ src/webenginewidgets/api/qwebenginepage_p.h | 2 +- .../doc/src/qwebenginepage_lgpl.qdoc | 24 +++ .../widgets/qwebenginepage/tst_qwebenginepage.cpp | 166 ++++++--------------- 7 files changed, 106 insertions(+), 150 deletions(-) diff --git a/examples/webenginewidgets/browser/webview.cpp b/examples/webenginewidgets/browser/webview.cpp index 5094cfa66..07027fe3a 100644 --- a/examples/webenginewidgets/browser/webview.cpp +++ b/examples/webenginewidgets/browser/webview.cpp @@ -97,37 +97,15 @@ BrowserMainWindow *WebPage::mainWindow() return BrowserApplication::instance()->mainWindow(); } -#if defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) -bool WebPage::acceptNavigationRequest(QWebEngineFrame *frame, const QNetworkRequest &request, NavigationType type) +bool WebPage::acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) { - // ctrl open in new tab - // ctrl-shift open in new tab and select - // ctrl-alt open in new window - if (type == QWebEnginePage::NavigationTypeLinkClicked - && (m_keyboardModifiers & Qt::ControlModifier - || m_pressedButtons == Qt::MidButton)) { - bool newWindow = (m_keyboardModifiers & Qt::AltModifier); - WebView *webView; - if (newWindow) { - BrowserApplication::instance()->newMainWindow(); - BrowserMainWindow *newMainWindow = BrowserApplication::instance()->mainWindow(); - webView = newMainWindow->currentTab(); - newMainWindow->raise(); - newMainWindow->activateWindow(); - webView->setFocus(); - } else { - bool selectNewTab = (m_keyboardModifiers & Qt::ShiftModifier); - webView = mainWindow()->tabWidget()->newTab(selectNewTab); - } - webView->load(request); - m_keyboardModifiers = Qt::NoModifier; - m_pressedButtons = Qt::NoButton; - return false; + Q_UNUSED(type); + if (isMainFrame) { + m_loadingUrl = url; + emit loadingUrl(m_loadingUrl); } - m_loadingUrl = request.url(); - emit loadingUrl(m_loadingUrl); + return true; } -#endif bool WebPage::certificateError(const QWebEngineCertificateError &error) { diff --git a/examples/webenginewidgets/browser/webview.h b/examples/webenginewidgets/browser/webview.h index 2cedeb79b..5ed674f6a 100644 --- a/examples/webenginewidgets/browser/webview.h +++ b/examples/webenginewidgets/browser/webview.h @@ -65,9 +65,7 @@ public: BrowserMainWindow *mainWindow(); protected: -#if defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) - bool acceptNavigationRequest(QWebEngineFrame *frame, const QNetworkRequest &request, NavigationType type); -#endif + bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame); QWebEnginePage *createWindow(QWebEnginePage::WebWindowType type); #if !defined(QT_NO_UITOOLS) QObject *createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 8c3c2bb45..51cb84514 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -624,6 +624,13 @@ bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData return true; } +void QWebEnginePagePrivate::navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) +{ + Q_Q(QWebEnginePage); + bool accepted = q->acceptNavigationRequest(url, static_cast(navigationType), isMainFrame); + navigationRequestAction = accepted ? WebContentsAdapterClient::AcceptRequest : WebContentsAdapterClient::IgnoreRequest; +} + void QWebEnginePagePrivate::javascriptDialog(QSharedPointer controller) { Q_Q(QWebEnginePage); @@ -945,6 +952,14 @@ bool QWebEnginePage::certificateError(const QWebEngineCertificateError &) return false; } +bool QWebEnginePage::acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) +{ + Q_UNUSED(url); + Q_UNUSED(type); + Q_UNUSED(isMainFrame); + return true; +} + QT_END_NAMESPACE #include "moc_qwebenginepage.cpp" diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index cda6e620f..ecd8a5712 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -135,6 +135,16 @@ public: PermissionDeniedByUser }; + // must match WebContentsAdapterClient::NavigationType + enum NavigationType { + NavigationTypeLinkClicked, + NavigationTypeTyped, + NavigationTypeFormSubmitted, + NavigationTypeBackForward, + NavigationTypeReload, + NavigationTypeOther + }; + enum Feature { Notifications, Geolocation, @@ -244,6 +254,7 @@ protected: virtual bool javaScriptPrompt(const QUrl &securityOrigin, const QString& msg, const QString& defaultValue, QString* result); virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID); virtual bool certificateError(const QWebEngineCertificateError &certificateError); + virtual bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame); private: Q_DECLARE_PRIVATE(QWebEnginePage); diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index ccbfb2bc1..eeae6de65 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -122,7 +122,7 @@ public: virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &initialGeometry) Q_DECL_OVERRIDE; virtual void close() Q_DECL_OVERRIDE; virtual bool contextMenuRequested(const WebEngineContextMenuData &data) Q_DECL_OVERRIDE; - virtual void navigationRequested(int, const QUrl &, int &, bool) Q_DECL_OVERRIDE { } + virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) Q_DECL_OVERRIDE; virtual void requestFullScreen(bool) Q_DECL_OVERRIDE { } virtual bool isFullScreen() const Q_DECL_OVERRIDE { return false; } virtual void javascriptDialog(QSharedPointer) Q_DECL_OVERRIDE; diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index 983b80d7e..e254e6753 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -146,6 +146,21 @@ \sa featurePermissionRequested(), featurePermissionRequestCanceled(), setFeaturePermission(), Feature */ +/*! + \enum QWebEnginePage::NavigationType + + This enum describes the type of a navigation request. + + \value NavigationTypeLinkClicked The navigation request resulted from a clicked link. + \value NavigationTypeTyped The navigation request resulted from an explicitly loaded url. + \value NavigationTypeFormSubmitted The navigation request resulted from a form submission. + \value NavigationTypeBackForward The navigation request resulted from a back/forward action. + \value NavigationTypeReload The navigation request resulted from a reload action. + \value NavigationTypeOther The navigation request was triggered by other means not covered by the above. + + \sa acceptNavigationRequest() +*/ + /*! \enum QWebEnginePage::Feature @@ -210,6 +225,15 @@ The default implementation prints nothing. */ +/*! + \fn bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) + This function is called whenever there is a request to navigate to a specified \a url by means of the specified navigation type \atype. + The \a isMainFrame argument marks if the request corresponds to the main frame, or a sub frame. + If the request is accepted Chromium will continue to load the page, else the request will be ignored. + The default implementation accepts the navigation request. +*/ + + /*! \fn void QWebEnginePage::javaScriptAlert(const QUrl &securityOrigin, const QString& msg) This function is called whenever a JavaScript program running in a frame affiliated with \a securityOrigin calls the alert() function with diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index b6d3f14c5..f0a89d9aa 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -107,11 +107,11 @@ private Q_SLOTS: void contextMenuCopy(); void contextMenuPopulatedOnce(); void acceptNavigationRequest(); + void acceptNavigationRequestNavigationType(); void geolocationRequestJS(); void loadFinished(); void actionStates(); void popupFormSubmission(); - void acceptNavigationRequestWithNewWindow(); void userStyleSheet(); void userStyleSheetFromLocalFileUrl(); void userStyleSheetFromQrcUrl(); @@ -133,8 +133,6 @@ private Q_SLOTS: void textEditing(); void backActionUpdate(); void frameAt(); - void requestCache(); - void loadCachedPage(); void protectBindingsRuntimeObjectsFromCollector(); void localURLSchemes(); void testOptionalJSObjects(); @@ -238,7 +236,6 @@ void tst_QWebEnginePage::cleanupTestCase() cleanupFiles(); // Be nice } -#if defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) class NavigationRequestOverride : public QWebEnginePage { public: @@ -246,21 +243,18 @@ public: bool m_acceptNavigationRequest; protected: - virtual bool acceptNavigationRequest(QWebEngineFrame* frame, const QNetworkRequest &request, QWebEnginePage::NavigationType type) { - Q_UNUSED(frame); - Q_UNUSED(request); + virtual bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) + { + Q_UNUSED(url); Q_UNUSED(type); + Q_UNUSED(isMainFrame); return m_acceptNavigationRequest; } }; -#endif void tst_QWebEnginePage::acceptNavigationRequest() { -#if !defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) - QSKIP("QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST"); -#else QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool))); NavigationRequestOverride* newPage = new NavigationRequestOverride(m_view, false); @@ -276,11 +270,10 @@ void tst_QWebEnginePage::acceptNavigationRequest() evaluateJavaScriptSync(m_view->page(), "tstform.submit();"); QTRY_COMPARE(loadSpy.count(), 2); - QCOMPARE(m_view->page()->toPlainText(), QString("foo?")); + QCOMPARE(toPlainTextSync(m_view->page()), QString("foo?")); // Restore default page m_view->setPage(0); -#endif } #if defined(QWEBENGINEPAGE_SETFEATUREPERMISSION) @@ -437,23 +430,22 @@ public: connect(this, SIGNAL(geometryChangeRequested(QRect)), this, SLOT(slotGeometryChangeRequested(QRect))); } -#if defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) struct Navigation { - QWebEngineFrame *frame; - QNetworkRequest request; NavigationType type; + QUrl url; + bool isMainFrame; }; QList navigations; - virtual bool acceptNavigationRequest(QWebEngineFrame* frame, const QNetworkRequest &request, NavigationType type) { + virtual bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) + { Navigation n; - n.frame = frame; - n.request = request; + n.url = url; n.type = type; + n.isMainFrame = isMainFrame; navigations.append(n); return true; } -#endif QList createdWindows; virtual QWebEnginePage* createWindow(WebWindowType) { @@ -469,6 +461,42 @@ private Q_SLOTS: } }; +void tst_QWebEnginePage::acceptNavigationRequestNavigationType() +{ + + TestPage page; + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + + page.load(QUrl("qrc:///resources/script.html")); + QTRY_COMPARE(loadSpy.count(), 1); + QTRY_COMPARE(page.navigations.count(), 1); + + page.load(QUrl("qrc:///resources/content.html")); + QTRY_COMPARE(loadSpy.count(), 2); + QTRY_COMPARE(page.navigations.count(), 2); + + page.triggerAction(QWebEnginePage::Stop); + QVERIFY(page.history()->canGoBack()); + page.triggerAction(QWebEnginePage::Back); + + QTRY_COMPARE(loadSpy.count(), 3); + QTRY_COMPARE(page.navigations.count(), 3); + + page.triggerAction(QWebEnginePage::Reload); + QTRY_COMPARE(loadSpy.count(), 4); + QTRY_COMPARE(page.navigations.count(), 4); + + QList expectedList; + expectedList << QWebEnginePage::NavigationTypeTyped + << QWebEnginePage::NavigationTypeTyped + << QWebEnginePage::NavigationTypeBackForward + << QWebEnginePage::NavigationTypeReload; + QVERIFY(expectedList.count() == page.navigations.count()); + for (int i = 0; i < expectedList.count(); ++i) { + QCOMPARE(page.navigations[i].type, expectedList[i]); + } +} + void tst_QWebEnginePage::popupFormSubmission() { TestPage page; @@ -489,38 +517,6 @@ void tst_QWebEnginePage::popupFormSubmission() QVERIFY(url.contains("?foo=bar")); } -void tst_QWebEnginePage::acceptNavigationRequestWithNewWindow() -{ -#if !defined(QWEBENGINESETTINGS) - QSKIP("QWEBENGINESETTINGS"); -#else - TestPage* page = new TestPage(m_view); - page->settings()->setAttribute(QWebEngineSettings::LinksIncludedInFocusChain, true); - m_page = page; - m_view->setPage(m_page); - - m_view->setUrl(QString("data:text/html,Click me")); - QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool)))); - - QFocusEvent fe(QEvent::FocusIn); - m_page->event(&fe); - - QVERIFY(m_page->focusNextPrevChild(/*next*/ true)); - - QKeyEvent keyEnter(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); - m_page->event(&keyEnter); - - QCOMPARE(page->navigations.count(), 2); - - TestPage::Navigation n = page->navigations.at(1); - QVERIFY(!n.frame); - QCOMPARE(n.request.url().toString(), QString("data:text/html,Reached")); - QVERIFY(n.type == QWebEnginePage::NavigationTypeLinkClicked); - - QCOMPARE(page->createdWindows.count(), 1); -#endif -} - class TestNetworkManager : public QNetworkAccessManager { public: @@ -1604,72 +1600,6 @@ void tst_QWebEnginePage::textEditing() #endif } -void tst_QWebEnginePage::requestCache() -{ -#if !defined(ACCEPTNAVIGATIONREQUEST) - QSKIP("ACCEPTNAVIGATIONREQUEST"); -#else - TestPage page; - QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); - - page.setUrl(QString("data:text/html,Click me")); - QTRY_COMPARE(loadSpy.count(), 1); - QTRY_COMPARE(page.navigations.count(), 1); - - page.setUrl(QString("data:text/html,Click me2")); - QTRY_COMPARE(loadSpy.count(), 2); - QTRY_COMPARE(page.navigations.count(), 2); - - page.triggerAction(QWebEnginePage::Stop); - QVERIFY(page.history()->canGoBack()); - page.triggerAction(QWebEnginePage::Back); - - QTRY_COMPARE(loadSpy.count(), 3); - QTRY_COMPARE(page.navigations.count(), 3); - QCOMPARE(page.navigations.at(0).request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(), - (int)QNetworkRequest::PreferNetwork); - QCOMPARE(page.navigations.at(1).request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(), - (int)QNetworkRequest::PreferNetwork); - QCOMPARE(page.navigations.at(2).request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(), - (int)QNetworkRequest::PreferCache); -#endif -} - -void tst_QWebEnginePage::loadCachedPage() -{ -#if !defined(QWEBENGINESETTINGS) - QSKIP("QWEBENGINESETTINGS"); -#else - TestPage page; - QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); - page.settings()->setMaximumPagesInCache(3); - - page.load(QUrl("data:text/html,This is first page")); - - QTRY_COMPARE(loadSpy.count(), 1); - QTRY_COMPARE(page.navigations.count(), 1); - - QUrl firstPageUrl = page.url(); - page.load(QUrl("data:text/html,This is second page")); - - QTRY_COMPARE(loadSpy.count(), 2); - QTRY_COMPARE(page.navigations.count(), 2); - - page.triggerAction(QWebEnginePage::Stop); - QVERIFY(page.history()->canGoBack()); - - QSignalSpy urlSpy(&page, SIGNAL(urlChanged(QUrl))); - QVERIFY(urlSpy.isValid()); - - page.triggerAction(QWebEnginePage::Back); - ::waitForSignal(&page, SIGNAL(urlChanged(QUrl))); - QCOMPARE(urlSpy.size(), 1); - - QList arguments1 = urlSpy.takeFirst(); - QCOMPARE(arguments1.at(0).toUrl(), firstPageUrl); -#endif -} - void tst_QWebEnginePage::backActionUpdate() { QWebEngineView view; -- cgit v1.2.3