| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtWebEngine module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "network_delegate_qt.h" |
| |
| #include "base/task/post_task.h" |
| #include "content/browser/web_contents/web_contents_impl.h" |
| #include "content/public/browser/browser_task_traits.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/resource_request_info.h" |
| #include "net/base/load_flags.h" |
| #include "net/url_request/url_request.h" |
| #include "ui/base/page_transition_types.h" |
| |
| #include "profile_adapter.h" |
| #include "cookie_monster_delegate_qt.h" |
| #include "profile_io_data_qt.h" |
| #include "qwebengineurlrequestinfo.h" |
| #include "qwebengineurlrequestinfo_p.h" |
| #include "qwebengineurlrequestinterceptor.h" |
| #include "type_conversion.h" |
| #include "web_contents_adapter_client.h" |
| #include "web_contents_view_qt.h" |
| #include "url_request_notification.h" |
| |
| namespace QtWebEngineCore { |
| |
| WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition) |
| { |
| if (ui::PageTransitionIsRedirect(transition)) |
| return WebContentsAdapterClient::RedirectNavigation; |
| |
| int32_t qualifier = ui::PageTransitionGetQualifier(transition); |
| |
| if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK) |
| return WebContentsAdapterClient::BackForwardNavigation; |
| |
| ui::PageTransition strippedTransition = ui::PageTransitionStripQualifier(transition); |
| |
| switch (strippedTransition) { |
| case ui::PAGE_TRANSITION_LINK: |
| return WebContentsAdapterClient::LinkNavigation; |
| case ui::PAGE_TRANSITION_TYPED: |
| return WebContentsAdapterClient::TypedNavigation; |
| case ui::PAGE_TRANSITION_FORM_SUBMIT: |
| return WebContentsAdapterClient::FormSubmittedNavigation; |
| case ui::PAGE_TRANSITION_RELOAD: |
| return WebContentsAdapterClient::ReloadNavigation; |
| default: |
| return WebContentsAdapterClient::OtherNavigation; |
| } |
| } |
| |
| static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType) |
| { |
| if (resourceType >= content::ResourceType::kMainFrame && resourceType <= content::ResourceType::kMaxValue) |
| return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType); |
| return QWebEngineUrlRequestInfo::ResourceTypeUnknown; |
| } |
| |
| static QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType) |
| { |
| return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType); |
| } |
| |
| NetworkDelegateQt::NetworkDelegateQt(ProfileIODataQt *data) |
| : m_profileIOData(data) |
| { |
| } |
| |
| int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::CompletionOnceCallback callback, GURL *newUrl) |
| { |
| Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| Q_ASSERT(m_profileIOData); |
| content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request); |
| |
| content::ResourceType resourceType = content::ResourceType::kMaxValue; |
| WebContentsAdapterClient::NavigationType navigationType = WebContentsAdapterClient::OtherNavigation; |
| |
| if (resourceInfo) { |
| resourceType = resourceInfo->GetResourceType(); |
| navigationType = pageTransitionToNavigationType(resourceInfo->GetPageTransition()); |
| } |
| |
| const QUrl qUrl = toQt(request->url()); |
| |
| QUrl firstPartyUrl = QUrl(); |
| if (resourceType == content::ResourceType::kSubFrame) |
| firstPartyUrl = toQt(request->first_party_url()); |
| else |
| firstPartyUrl = toQt(request->site_for_cookies()); |
| |
| const QUrl initiator = request->initiator().has_value() ? toQt(request->initiator()->GetURL()) : QUrl(); |
| |
| QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), |
| toQt(navigationType), |
| qUrl, |
| firstPartyUrl, |
| initiator, |
| QByteArray::fromStdString(request->method())); |
| QWebEngineUrlRequestInfo requestInfo(infoPrivate); |
| |
| // Deprecated =begin |
| // quick peek if deprecated |
| |
| if (m_profileIOData->isInterceptorDeprecated()) { |
| QWebEngineUrlRequestInterceptor *profileInterceptor = m_profileIOData->acquireInterceptor(); |
| if (profileInterceptor && m_profileIOData->isInterceptorDeprecated()) { |
| profileInterceptor->interceptRequest(requestInfo); |
| m_profileIOData->releaseInterceptor(); |
| if (requestInfo.changed()) { |
| int result = infoPrivate->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; |
| |
| if (qUrl != infoPrivate->url) |
| *newUrl = toGurl(infoPrivate->url); |
| |
| if (!infoPrivate->extraHeaders.isEmpty()) { |
| auto end = infoPrivate->extraHeaders.constEnd(); |
| for (auto header = infoPrivate->extraHeaders.constBegin(); header != end; ++header) { |
| std::string h = header.key().toStdString(); |
| if (base::LowerCaseEqualsASCII(h, "referer")) { |
| request->SetReferrer(header.value().toStdString()); |
| } else { |
| request->SetExtraRequestHeaderByName(h, header.value().toStdString(), /* overwrite */ true); |
| } |
| } |
| } |
| |
| if (result != net::OK) |
| return result; |
| |
| requestInfo.resetChanged(); |
| } |
| } else { |
| m_profileIOData->releaseInterceptor(); |
| } |
| } |
| // Deprecated =cut |
| |
| if (!resourceInfo) |
| return net::OK; |
| |
| // try to bail out |
| if (!m_profileIOData->hasPageInterceptors() && (!m_profileIOData->requestInterceptor() || m_profileIOData->isInterceptorDeprecated()) && |
| !content::IsResourceTypeFrame(resourceType)) |
| return net::OK; |
| |
| auto webContentsGetter = resourceInfo->GetWebContentsGetterForRequest(); |
| new URLRequestNotification( |
| request, |
| resourceInfo->IsMainFrame(), |
| newUrl, |
| std::move(requestInfo), |
| webContentsGetter, |
| std::move(callback), |
| m_profileIOData->profileAdapter() |
| ); |
| |
| // We'll run the callback after we notified the UI thread. |
| return net::ERR_IO_PENDING; |
| } |
| |
| void NetworkDelegateQt::OnURLRequestDestroyed(net::URLRequest *) {} |
| |
| void NetworkDelegateQt::OnCompleted(net::URLRequest * /*request*/, bool /*started*/, int /*net_error*/) {} |
| |
| bool NetworkDelegateQt::OnCanSetCookie(const net::URLRequest &request, const net::CanonicalCookie & /*cookie*/, |
| net::CookieOptions *, bool allowedFromCaller) |
| { |
| if (!allowedFromCaller) |
| return false; |
| return canSetCookies(request.site_for_cookies(), request.url(), std::string()); |
| } |
| |
| bool NetworkDelegateQt::OnCanGetCookies(const net::URLRequest &request, const net::CookieList &, bool allowedFromCaller) |
| { |
| if (!allowedFromCaller) |
| return false; |
| return canGetCookies(request.site_for_cookies(), request.url()); |
| } |
| |
| bool NetworkDelegateQt::OnForcePrivacyMode(const GURL &url, const GURL &site_for_cookies) const |
| { |
| return false; |
| // FIXME: This is what the NetworkContext implementation does (changes tst_QWebEngineCookieStore tests since 72) |
| // return !canGetCookies(site_for_cookies, url); |
| } |
| |
| bool NetworkDelegateQt::canSetCookies(const GURL &first_party, const GURL &url, const std::string &cookie_line) const |
| { |
| Q_ASSERT(m_profileIOData); |
| return m_profileIOData->canSetCookie(toQt(first_party), QByteArray::fromStdString(cookie_line), toQt(url)); |
| } |
| |
| bool NetworkDelegateQt::canGetCookies(const GURL &first_party, const GURL &url) const |
| { |
| Q_ASSERT(m_profileIOData); |
| return m_profileIOData->canGetCookies(toQt(first_party), toQt(url)); |
| } |
| |
| int NetworkDelegateQt::OnBeforeStartTransaction(net::URLRequest *, net::CompletionOnceCallback, net::HttpRequestHeaders *) |
| { |
| return net::OK; |
| } |
| |
| void NetworkDelegateQt::OnBeforeSendHeaders(net::URLRequest *request, const net::ProxyInfo &proxy_info, |
| const net::ProxyRetryInfoMap &proxy_retry_info, |
| net::HttpRequestHeaders *headers) |
| {} |
| |
| void NetworkDelegateQt::OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers) {} |
| |
| int NetworkDelegateQt::OnHeadersReceived(net::URLRequest *, net::CompletionOnceCallback, const net::HttpResponseHeaders *, |
| scoped_refptr<net::HttpResponseHeaders> *, GURL *) |
| { |
| return net::OK; |
| } |
| |
| void NetworkDelegateQt::OnBeforeRedirect(net::URLRequest *, const GURL &) {} |
| |
| void NetworkDelegateQt::OnResponseStarted(net::URLRequest *, int) {} |
| |
| void NetworkDelegateQt::OnNetworkBytesReceived(net::URLRequest *, int64_t) {} |
| |
| void NetworkDelegateQt::OnNetworkBytesSent(net::URLRequest *, int64_t) {} |
| |
| void NetworkDelegateQt::OnPACScriptError(int, const base::string16 &) {} |
| |
| net::NetworkDelegate::AuthRequiredResponse NetworkDelegateQt::OnAuthRequired(net::URLRequest *, |
| const net::AuthChallengeInfo &, |
| AuthCallback, net::AuthCredentials *) |
| { |
| return AUTH_REQUIRED_RESPONSE_NO_ACTION; |
| } |
| |
| bool NetworkDelegateQt::OnCanAccessFile(const net::URLRequest &, const base::FilePath &, const base::FilePath &) const |
| { |
| return true; |
| } |
| |
| bool NetworkDelegateQt::OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest &, const GURL &, |
| const GURL &) const |
| { |
| return false; |
| } |
| |
| bool NetworkDelegateQt::OnCanQueueReportingReport(const url::Origin &origin) const |
| { |
| return false; |
| } |
| |
| void NetworkDelegateQt::OnCanSendReportingReports(std::set<url::Origin> origins, |
| base::OnceCallback<void(std::set<url::Origin>)> result_callback) const |
| { |
| std::move(result_callback).Run(std::set<url::Origin>()); |
| } |
| |
| bool NetworkDelegateQt::OnCanSetReportingClient(const url::Origin &origin, const GURL &endpoint) const |
| { |
| return false; |
| } |
| |
| bool NetworkDelegateQt::OnCanUseReportingClient(const url::Origin &origin, const GURL &endpoint) const |
| { |
| return false; |
| } |
| |
| } // namespace QtWebEngineCore |