From a8b48040243c95316a9dad92360f086cf6e537af Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Wed, 30 Jan 2019 10:58:06 +0100 Subject: Move url_request_notification to own unit Change-Id: I37a0a7194e339136d73e9c8f7faebb8c97ee2c97 Reviewed-by: Allan Sandfeld Jensen --- src/core/net/url_request_notification.cpp | 175 ++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 src/core/net/url_request_notification.cpp (limited to 'src/core/net/url_request_notification.cpp') diff --git a/src/core/net/url_request_notification.cpp b/src/core/net/url_request_notification.cpp new file mode 100644 index 000000000..325474bc4 --- /dev/null +++ b/src/core/net/url_request_notification.cpp @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 "url_request_notification.h" + +#include "base/supports_user_data.h" +#include "base/task/post_task.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/browser_thread.h" +#include "net/url_request/url_request.h" +#include "web_contents_adapter_client.h" +#include "web_contents_view_qt.h" +#include "qwebengineurlrequestinfo_p.h" +#include "type_conversion.h" + +namespace QtWebEngineCore { + +// Calls cancel() when the URLRequest is destroyed. +class UserData : public base::SupportsUserData::Data { +public: + UserData(URLRequestNotification *ptr) : m_ptr(ptr) {} + ~UserData() { m_ptr->cancel(); } + static const char key[]; +private: + URLRequestNotification *m_ptr; +}; + +const char UserData::key[] = "QtWebEngineCore::URLRequestNotification"; + +static content::ResourceType fromQt(QWebEngineUrlRequestInfo::ResourceType resourceType) +{ + return static_cast(resourceType); +} + +URLRequestNotification::URLRequestNotification(net::URLRequest *request, + bool isMainFrameRequest, + GURL *newUrl, + QWebEngineUrlRequestInfo &&requestInfo, + content::ResourceRequestInfo::WebContentsGetter webContentsGetter, + net::CompletionOnceCallback callback) + : m_request(request) + , m_isMainFrameRequest(isMainFrameRequest) + , m_newUrl(newUrl) + , m_originalUrl(requestInfo.requestUrl()) + , m_requestInfo(std::move(requestInfo)) + , m_webContentsGetter(webContentsGetter) + , m_callback(std::move(callback)) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + m_request->SetUserData(UserData::key, std::make_unique(this)); + + base::PostTaskWithTraits( + FROM_HERE, + {content::BrowserThread::UI}, + base::BindOnce(&URLRequestNotification::notify, base::Unretained(this))); +} + + +void URLRequestNotification::notify() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + // May run concurrently with cancel() so no peeking at m_request here. + + int error = net::OK; + content::WebContents *webContents = m_webContentsGetter.Run(); + + if (webContents) { + WebContentsAdapterClient *client = + WebContentsViewQt::from(static_cast(webContents)->GetView())->client(); + + client->interceptRequest(m_requestInfo); + if (m_requestInfo.changed()) { + error = m_requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; + // We handle the rest of the changes later when we are back in I/O thread + } + + // Only do navigationRequested on MAIN_FRAME and SUB_FRAME resources + if (error == net::OK && content::IsResourceTypeFrame(fromQt(m_requestInfo.resourceType()))) { + int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; + client->navigationRequested(m_requestInfo.navigationType(), + m_requestInfo.requestUrl(), + navigationRequestAction, + m_isMainFrameRequest); + error = net::ERR_FAILED; + switch (static_cast(navigationRequestAction)) { + case WebContentsAdapterClient::AcceptRequest: + error = net::OK; + break; + case WebContentsAdapterClient::IgnoreRequest: + error = net::ERR_ABORTED; + break; + } + DCHECK(error != net::ERR_FAILED); + } + } + + // Run the callback on the IO thread. + base::PostTaskWithTraits( + FROM_HERE, + {content::BrowserThread::IO}, + base::BindOnce(&URLRequestNotification::complete, base::Unretained(this), error)); +} + +void URLRequestNotification::cancel() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + // May run concurrently with notify() but we only touch m_request here. + + m_request = nullptr; +} + +void URLRequestNotification::complete(int error) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (m_request) { + if (m_requestInfo.changed()) { + if (m_originalUrl != m_requestInfo.d_ptr->url) + *m_newUrl = toGurl(m_requestInfo.d_ptr->url); + + if (!m_requestInfo.d_ptr->extraHeaders.isEmpty()) { + auto end = m_requestInfo.d_ptr->extraHeaders.constEnd(); + for (auto header = m_requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header) + m_request->SetExtraRequestHeaderByName(header.key().toStdString(), header.value().toStdString(), /* overwrite */ true); + } + } + + if (m_request->status().status() != net::URLRequestStatus::CANCELED) + std::move(m_callback).Run(error); + m_request->RemoveUserData(UserData::key); + } + + delete this; +} + +} -- cgit v1.2.3