diff options
Diffstat (limited to 'src/core/net')
24 files changed, 3731 insertions, 0 deletions
diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp new file mode 100644 index 000000000..abc386204 --- /dev/null +++ b/src/core/net/cookie_monster_delegate_qt.cpp @@ -0,0 +1,252 @@ +/**************************************************************************** +** +** 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 "cookie_monster_delegate_qt.h" + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "content/public/browser/browser_thread.h" +#include "net/cookies/cookie_util.h" + +#include "api/qwebenginecookiestore.h" +#include "api/qwebenginecookiestore_p.h" +#include "type_conversion.h" + +namespace QtWebEngineCore { + +static GURL sourceUrlForCookie(const QNetworkCookie &cookie) { + QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path()); + return net::cookie_util::CookieOriginToURL(urlFragment.toStdString(), /* is_https */ cookie.isSecure()); +} + +static void onSetCookieCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, bool success) { + + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&QWebEngineCookieStorePrivate::onSetCallbackResult, base::Unretained(client), callbackId, success)); +} + +static void onDeleteCookiesCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, uint numCookies) { + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&QWebEngineCookieStorePrivate::onDeleteCallbackResult, base::Unretained(client), callbackId, numCookies)); +} + +static void onGetAllCookiesCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, const net::CookieList& cookies) { + QByteArray rawCookies; + for (auto&& cookie: cookies) + rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n"); + + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&QWebEngineCookieStorePrivate::onGetAllCallbackResult, base::Unretained(client), callbackId, rawCookies)); +} + +CookieMonsterDelegateQt::CookieMonsterDelegateQt() + : m_client(0) + , m_cookieMonster(nullptr) +{ +} + +CookieMonsterDelegateQt::~CookieMonsterDelegateQt() +{ + +} + +void CookieMonsterDelegateQt::AddStore(net::CookieStore *store) +{ + std::unique_ptr<net::CookieStore::CookieChangedSubscription> sub = + store->AddCallbackForAllChanges( + base::Bind(&CookieMonsterDelegateQt::OnCookieChanged, + // this object's destruction will deregister the subscription. + base::Unretained(this))); + + m_subscriptions.push_back(std::move(sub)); +} + +bool CookieMonsterDelegateQt::hasCookieMonster() +{ + return m_cookieMonster; +} + +void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId) +{ + net::CookieMonster::GetCookieListCallback callback = base::Bind(&onGetAllCookiesCallback, m_client->d_func(), callbackId); + + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, std::move(callback))); +} + +void CookieMonsterDelegateQt::GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback) +{ + if (m_cookieMonster) + m_cookieMonster->GetAllCookiesAsync(std::move(callback)); +} + +void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin) +{ + Q_ASSERT(hasCookieMonster()); + Q_ASSERT(m_client); + + net::CookieStore::SetCookiesCallback callback; + if (callbackId != CallbackDirectory::NoCallbackId) + callback = base::Bind(&onSetCookieCallback, m_client->d_func(), callbackId); + + GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); + + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&CookieMonsterDelegateQt::SetCookieOnIOThread, this, + gurl, cookie.toRawForm().toStdString(), std::move(callback))); +} + +void CookieMonsterDelegateQt::SetCookieOnIOThread( + const GURL& url, const std::string& cookie_line, + net::CookieMonster::SetCookiesCallback callback) +{ + net::CookieOptions options; + options.set_include_httponly(); + + if (m_cookieMonster) + m_cookieMonster->SetCookieWithOptionsAsync(url, cookie_line, options, std::move(callback)); +} + +void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin) +{ + Q_ASSERT(hasCookieMonster()); + Q_ASSERT(m_client); + + GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); + + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this, + gurl, cookie.name().toStdString())); +} + +void CookieMonsterDelegateQt::DeleteCookieOnIOThread(const GURL& url, const std::string& cookie_name) +{ + if (m_cookieMonster) + m_cookieMonster->DeleteCookieAsync(url, cookie_name, base::Closure()); +} + +void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId) +{ + Q_ASSERT(hasCookieMonster()); + Q_ASSERT(m_client); + + net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId); + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, std::move(callback))); +} + +void CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback) +{ + if (m_cookieMonster) + m_cookieMonster->DeleteSessionCookiesAsync(std::move(callback)); +} + +void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) +{ + Q_ASSERT(hasCookieMonster()); + Q_ASSERT(m_client); + + net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId); + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, std::move(callback))); +} + +void CookieMonsterDelegateQt::DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback) +{ + if (m_cookieMonster) + m_cookieMonster->DeleteAllAsync(std::move(callback)); +} + +void CookieMonsterDelegateQt::setCookieMonster(net::CookieMonster* monster) +{ + if (monster == m_cookieMonster) + return; + + m_subscriptions.clear(); + if (monster) + AddStore(monster); + + m_cookieMonster = monster; + + if (!m_client) + return; + + if (monster) + m_client->d_func()->processPendingUserCookies(); + else + m_client->d_func()->rejectPendingUserCookies(); +} + +void CookieMonsterDelegateQt::setClient(QWebEngineCookieStore *client) +{ + m_client = client; + + if (!m_client) + return; + + m_client->d_func()->delegate = this; + + if (hasCookieMonster()) + m_client->d_func()->processPendingUserCookies(); +} + +bool CookieMonsterDelegateQt::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &/*cookieLine*/, const QUrl &url) +{ + if (!m_client) + return true; + + return m_client->d_func()->canAccessCookies(firstPartyUrl, url); +} + +bool CookieMonsterDelegateQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) +{ + if (!m_client) + return true; + + return m_client->d_func()->canAccessCookies(firstPartyUrl, url); +} + +void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie& cookie, net::CookieStore::ChangeCause cause) +{ + if (!m_client) + return; + m_client->d_func()->onCookieChanged(toQt(cookie), cause != net::CookieStore::ChangeCause::INSERTED); +} + +} diff --git a/src/core/net/cookie_monster_delegate_qt.h b/src/core/net/cookie_monster_delegate_qt.h new file mode 100644 index 000000000..8aceca9c9 --- /dev/null +++ b/src/core/net/cookie_monster_delegate_qt.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef COOKIE_MONSTER_DELEGATE_QT_H +#define COOKIE_MONSTER_DELEGATE_QT_H + +#include "qtwebenginecoreglobal.h" + +QT_WARNING_PUSH +// For some reason adding -Wno-unused-parameter to QMAKE_CXXFLAGS has no +// effect with clang, so use a pragma for these dirty chromium headers +QT_WARNING_DISABLE_CLANG("-Wunused-parameter") +#include "base/memory/ref_counted.h" +#include "net/cookies/cookie_monster.h" +QT_WARNING_POP + +#include <QNetworkCookie> +#include <QPointer> + +QT_FORWARD_DECLARE_CLASS(QWebEngineCookieStore) + +namespace QtWebEngineCore { + +// Extends net::CookieMonster::kDefaultCookieableSchemes with qrc, without enabling +// cookies for the file:// scheme, which is disabled by default in Chromium. +// Since qrc:// is similar to file:// and there are some unknowns about how +// to correctly handle file:// cookies, qrc:// should only be used for testing. +static const char* const kCookieableSchemes[] = + { "http", "https", "qrc", "ws", "wss" }; + +class QWEBENGINE_EXPORT CookieMonsterDelegateQt : public base::RefCountedThreadSafe<CookieMonsterDelegateQt> { + QPointer<QWebEngineCookieStore> m_client; + net::CookieMonster *m_cookieMonster; + std::vector<std::unique_ptr<net::CookieStore::CookieChangedSubscription>> m_subscriptions; +public: + CookieMonsterDelegateQt(); + ~CookieMonsterDelegateQt(); + + bool hasCookieMonster(); + + void setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin); + void deleteCookie(const QNetworkCookie &cookie, const QUrl &origin); + void getAllCookies(quint64 callbackId); + void deleteSessionCookies(quint64 callbackId); + void deleteAllCookies(quint64 callbackId); + + void setCookieMonster(net::CookieMonster* monster); + void setClient(QWebEngineCookieStore *client); + + bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url); + bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url); + + void AddStore(net::CookieStore *store); + void OnCookieChanged(const net::CanonicalCookie &cookie, net::CookieStore::ChangeCause cause); + +private: + void GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback); + void SetCookieOnIOThread(const GURL& url, const std::string& cookie_line, net::CookieMonster::SetCookiesCallback callback); + void DeleteCookieOnIOThread(const GURL& url, const std::string& cookie_name); + void DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback); + void DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback); +}; + +} + +#endif // COOKIE_MONSTER_DELEGATE_QT_H diff --git a/src/core/net/custom_protocol_handler.cpp b/src/core/net/custom_protocol_handler.cpp new file mode 100644 index 000000000..402df04ba --- /dev/null +++ b/src/core/net/custom_protocol_handler.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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 "custom_protocol_handler.h" +#include "url_request_custom_job.h" + +#include "net/base/net_errors.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_error_job.h" + +namespace QtWebEngineCore { + +CustomProtocolHandler::CustomProtocolHandler(QWeakPointer<const BrowserContextAdapter> adapter) + : m_adapter(adapter) +{ +} + +net::URLRequestJob *CustomProtocolHandler::MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const +{ + if (!networkDelegate) + return new net::URLRequestErrorJob(request, Q_NULLPTR, net::ERR_ACCESS_DENIED); + + return new URLRequestCustomJob(request, networkDelegate, request->url().scheme(), m_adapter); +} + +} // namespace diff --git a/src/core/net/custom_protocol_handler.h b/src/core/net/custom_protocol_handler.h new file mode 100644 index 000000000..5d3838834 --- /dev/null +++ b/src/core/net/custom_protocol_handler.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef CUSTOM_PROTOCOL_HANDLER_H_ +#define CUSTOM_PROTOCOL_HANDLER_H_ + +#include "qtwebenginecoreglobal.h" +#include "net/url_request/url_request_job_factory.h" + +#include <QtCore/QByteArray> +#include <QtCore/QObject> +#include <QtCore/QWeakPointer> + +QT_FORWARD_DECLARE_CLASS(QIODevice) + +namespace net { +class NetworkDelegate; +class URLRequestJob; +} // namespace + +namespace QtWebEngineCore { + +class BrowserContextAdapter; + +// Implements a ProtocolHandler for custom URL schemes. +// If |network_delegate_| is NULL then all file requests will fail with ERR_ACCESS_DENIED. +class QWEBENGINE_EXPORT CustomProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { + +public: + CustomProtocolHandler(QWeakPointer<const BrowserContextAdapter> adapter); + + net::URLRequestJob *MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const override; + +private: + DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); + QWeakPointer<const BrowserContextAdapter> m_adapter; +}; + +} // namespace + +#endif // CUSTOM_PROTOCOL_HANDLER_H_ diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp new file mode 100644 index 000000000..74db51d7d --- /dev/null +++ b/src/core/net/network_delegate_qt.cpp @@ -0,0 +1,390 @@ +/**************************************************************************** +** +** 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 "browser_context_adapter.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 "cookie_monster_delegate_qt.h" +#include "ui/base/page_transition_types.h" +#include "url_request_context_getter_qt.h" +#include "net/base/load_flags.h" +#include "net/url_request/url_request.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" + +namespace QtWebEngineCore { + +WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition) +{ + 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; + } +} + +namespace { + +QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType) +{ + if (resourceType >= 0 && resourceType < content::ResourceType(QWebEngineUrlRequestInfo::ResourceTypeLast)) + return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType); + return QWebEngineUrlRequestInfo::ResourceTypeUnknown; +} + +QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType) +{ + return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType); +} + +// Notifies WebContentsAdapterClient of a new URLRequest. +class URLRequestNotification { +public: + URLRequestNotification(net::URLRequest *request, + const QUrl &url, + bool isMainFrameRequest, + int navigationType, + int frameTreeNodeId, + const net::CompletionCallback &callback) + : m_request(request) + , m_url(url) + , m_isMainFrameRequest(isMainFrameRequest) + , m_navigationType(navigationType) + , m_frameTreeNodeId(frameTreeNodeId) + , m_callback(callback) + { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + m_request->SetUserData(UserData::key, std::make_unique<UserData>(this)); + + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::Bind(&URLRequestNotification::notify, base::Unretained(this))); + } + +private: + // 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; + }; + + void cancel() + { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + // May run concurrently with notify() but we only touch m_request here. + + m_request = nullptr; + } + + void 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 = content::WebContents::FromFrameTreeNodeId(m_frameTreeNodeId); + if (webContents) { + int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; + WebContentsAdapterClient *client = + WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); + client->navigationRequested(m_navigationType, + m_url, + navigationRequestAction, + m_isMainFrameRequest); + error = net::ERR_FAILED; + switch (static_cast<WebContentsAdapterClient::NavigationRequestAction>(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. + content::BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind(&URLRequestNotification::complete, base::Unretained(this), error)); + } + + void complete(int error) + { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (m_request) { + if (m_request->status().status() != net::URLRequestStatus::CANCELED) + m_callback.Run(error); + m_request->RemoveUserData(UserData::key); + } + + delete this; + } + + ~URLRequestNotification() {} + + net::URLRequest *m_request; + QUrl m_url; + bool m_isMainFrameRequest; + int m_navigationType; + int m_frameTreeNodeId; + net::CompletionCallback m_callback; +}; + +const char URLRequestNotification::UserData::key[] = "QtWebEngineCore::URLRequestNotification"; + +} // namespace + +NetworkDelegateQt::NetworkDelegateQt(URLRequestContextGetterQt *requestContext) + : m_requestContextGetter(requestContext) +{ +} + +int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::CompletionCallback &callback, GURL *newUrl) +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_requestContextGetter); + + const content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request); + + content::ResourceType resourceType = content::RESOURCE_TYPE_LAST_TYPE; + WebContentsAdapterClient::NavigationType navigationType = WebContentsAdapterClient::OtherNavigation; + + if (resourceInfo) { + resourceType = resourceInfo->GetResourceType(); + navigationType = pageTransitionToNavigationType(resourceInfo->GetPageTransition()); + } + + const QUrl qUrl = toQt(request->url()); + + QWebEngineUrlRequestInterceptor* interceptor = m_requestContextGetter->m_requestInterceptor; + if (interceptor) { + QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), + toQt(navigationType), + qUrl, + toQt(request->site_for_cookies()), + QByteArray::fromStdString(request->method())); + QWebEngineUrlRequestInfo requestInfo(infoPrivate); + interceptor->interceptRequest(requestInfo); + 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) + request->SetExtraRequestHeaderByName(header.key().toStdString(), header.value().toStdString(), /* overwrite */ true); + } + + if (result != net::OK) + return result; + } + } + + if (!resourceInfo) + return net::OK; + + int frameTreeNodeId = resourceInfo->GetFrameTreeNodeId(); + // Only intercept MAIN_FRAME and SUB_FRAME with an associated render frame. + if (!content::IsResourceTypeFrame(resourceType) || frameTreeNodeId == -1) + return net::OK; + + new URLRequestNotification( + request, + qUrl, + resourceInfo->IsMainFrame(), + navigationType, + frameTreeNodeId, + callback + ); + + // 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*) +{ + return canSetCookies(request.site_for_cookies(), request.url(), std::string()); +} + +bool NetworkDelegateQt::OnCanGetCookies(const net::URLRequest& request, const net::CookieList&) +{ + return canGetCookies(request.site_for_cookies(), request.url()); +} + +bool NetworkDelegateQt::OnCanEnablePrivacyMode(const GURL &url, const GURL &site_for_cookies) const +{ + 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_requestContextGetter); + return m_requestContextGetter->m_cookieDelegate->canSetCookie(toQt(first_party), QByteArray::fromStdString(cookie_line), toQt(url)); +} + +bool NetworkDelegateQt::canGetCookies(const GURL &first_party, const GURL &url) const +{ + Q_ASSERT(m_requestContextGetter); + return m_requestContextGetter->m_cookieDelegate->canGetCookies(toQt(first_party), toQt(url)); +} + +int NetworkDelegateQt::OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionCallback &callback, net::HttpRequestHeaders *headers) +{ + 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*, const net::CompletionCallback&, 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&, const 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::OnAreExperimentalCookieFeaturesEnabled() const +{ + return false; +} + +bool NetworkDelegateQt::OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const +{ + return false; +} + +bool NetworkDelegateQt::OnCanQueueReportingReport(const url::Origin& origin) const +{ + return false; +} + +bool NetworkDelegateQt::OnCanSendReportingReport(const url::Origin& origin) const +{ + return false; +} + +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 diff --git a/src/core/net/network_delegate_qt.h b/src/core/net/network_delegate_qt.h new file mode 100644 index 000000000..b5165d229 --- /dev/null +++ b/src/core/net/network_delegate_qt.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef NETWORK_DELEGATE_QT_H +#define NETWORK_DELEGATE_QT_H + +#include "net/base/network_delegate.h" +#include "net/base/net_errors.h" + +#include <QUrl> +#include <QSet> + +namespace content { +class WebContents; +} + +namespace QtWebEngineCore { + +class URLRequestContextGetterQt; + +class NetworkDelegateQt : public net::NetworkDelegate { + URLRequestContextGetterQt *m_requestContextGetter; +public: + NetworkDelegateQt(URLRequestContextGetterQt *requestContext); + + // net::NetworkDelegate implementation + int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* newUrl) override; + void OnURLRequestDestroyed(net::URLRequest* request) override; + bool OnCanSetCookie(const net::URLRequest& request, const net::CanonicalCookie& cookie, net::CookieOptions* options) override; + int OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionCallback &callback, net::HttpRequestHeaders *headers) override; + void OnBeforeSendHeaders(net::URLRequest* request, const net::ProxyInfo& proxy_info, + const net::ProxyRetryInfoMap& proxy_retry_info, net::HttpRequestHeaders* headers) override; + void OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers) override; + int OnHeadersReceived(net::URLRequest*, const net::CompletionCallback&, const net::HttpResponseHeaders*, scoped_refptr<net::HttpResponseHeaders>*, GURL*) override; + void OnBeforeRedirect(net::URLRequest*, const GURL&) override; + void OnResponseStarted(net::URLRequest*, int) override; + void OnNetworkBytesReceived(net::URLRequest*, int64_t) override; + void OnNetworkBytesSent(net::URLRequest *, int64_t) override; + void OnCompleted(net::URLRequest *request, bool started, int net_error) override; + void OnPACScriptError(int, const base::string16&) override; + net::NetworkDelegate::AuthRequiredResponse OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, const AuthCallback&, net::AuthCredentials*) override; + bool OnCanGetCookies(const net::URLRequest&, const net::CookieList&) override; + bool OnCanAccessFile(const net::URLRequest&, const base::FilePath&, const base::FilePath&) const override; + bool OnCanEnablePrivacyMode(const GURL&, const GURL&) const override; + bool OnAreExperimentalCookieFeaturesEnabled() const override; + bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const override; + + bool OnCanQueueReportingReport(const url::Origin& origin) const override; + bool OnCanSendReportingReport(const url::Origin& origin) const override; + bool OnCanSetReportingClient(const url::Origin& origin, const GURL& endpoint) const override; + bool OnCanUseReportingClient(const url::Origin& origin, const GURL& endpoint) const override; + + bool canSetCookies(const GURL &first_party, const GURL &url, const std::string &cookie_line) const; + bool canGetCookies(const GURL &first_party, const GURL &url) const; +}; + +} // namespace QtWebEngineCore + +#endif // NETWORK_DELEGATE_QT_H diff --git a/src/core/net/proxy_config_service_qt.cpp b/src/core/net/proxy_config_service_qt.cpp new file mode 100644 index 000000000..7fca18eb6 --- /dev/null +++ b/src/core/net/proxy_config_service_qt.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +//================ Based on ChromeProxyConfigService ======================= +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.Chromium file. + +#include "proxy_config_service_qt.h" + +#include "base/bind.h" +#include "content/public/browser/browser_thread.h" + +using content::BrowserThread; + +net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qtProxy) +{ + net::HostPortPair hostPortPair(qtProxy.hostName().toStdString(), qtProxy.port()); + switch (qtProxy.type()) { + case QNetworkProxy::Socks5Proxy: + return net::ProxyServer(net::ProxyServer::SCHEME_SOCKS5, hostPortPair); + case QNetworkProxy::HttpProxy: + case QNetworkProxy::HttpCachingProxy: + case QNetworkProxy::FtpCachingProxy: + return net::ProxyServer(net::ProxyServer::SCHEME_HTTP, hostPortPair); + case QNetworkProxy::NoProxy: + case QNetworkProxy::DefaultProxy: + return net::ProxyServer(net::ProxyServer::SCHEME_DIRECT, net::HostPortPair()); + default: + return net::ProxyServer(net::ProxyServer::SCHEME_INVALID, net::HostPortPair()); + } +} + +ProxyConfigServiceQt::ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService) + : m_baseService(baseService.release()), + m_usesSystemConfiguration(false), + m_registeredObserver(false) +{ +} + +ProxyConfigServiceQt::~ProxyConfigServiceQt() +{ + if (m_registeredObserver && m_baseService.get()) + m_baseService->RemoveObserver(this); +} + +void ProxyConfigServiceQt::AddObserver(net::ProxyConfigService::Observer *observer) +{ + m_observers.AddObserver(observer); +} + +void ProxyConfigServiceQt::RemoveObserver(net::ProxyConfigService::Observer *observer) +{ + m_observers.RemoveObserver(observer); +} + +net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxyConfig(net::ProxyConfig *config) +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) + m_usesSystemConfiguration = QNetworkProxyFactory::usesSystemConfiguration(); +#endif + if (m_usesSystemConfiguration) { + // Use Chromium's base service to retrieve system settings + net::ProxyConfig systemConfig; + ConfigAvailability systemAvailability = net::ProxyConfigService::CONFIG_UNSET; + if (m_baseService.get()) + systemAvailability = m_baseService->GetLatestProxyConfig(&systemConfig); + *config = systemConfig; + // make sure to get updates via OnProxyConfigChanged + RegisterObserver(); + return systemAvailability; + } + + // Use QNetworkProxy::applicationProxy settings + const QNetworkProxy &qtProxy = QNetworkProxy::applicationProxy(); + if (qtProxy == m_qtApplicationProxy && !m_qtProxyConfig.proxy_rules().empty()) { + // no changes + *config = m_qtProxyConfig; + return CONFIG_VALID; + } + + m_qtApplicationProxy = qtProxy; + m_qtProxyConfig = net::ProxyConfig(); + + net::ProxyConfig::ProxyRules qtRules; + net::ProxyServer server = fromQNetworkProxy(qtProxy); + switch (qtProxy.type()) { + case QNetworkProxy::HttpProxy: + case QNetworkProxy::Socks5Proxy: + qtRules.type = net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + qtRules.single_proxies.SetSingleProxyServer(server); + break; + case QNetworkProxy::HttpCachingProxy: + qtRules.type = net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + qtRules.proxies_for_http.SetSingleProxyServer(server); + break; + case QNetworkProxy::FtpCachingProxy: + qtRules.type = net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + qtRules.proxies_for_ftp.SetSingleProxyServer(server); + break; + default: + qtRules.type = net::ProxyConfig::ProxyRules::TYPE_NO_RULES; + } + + qtRules.bypass_rules.AddRuleToBypassLocal(); // don't use proxy for connections to localhost + m_qtProxyConfig.proxy_rules() = qtRules; + *config = m_qtProxyConfig; + return CONFIG_VALID; +} + +void ProxyConfigServiceQt::OnLazyPoll() +{ + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) + // We need to update if + // - setUseSystemConfiguration() was called in between + // - user changed application proxy + if (m_usesSystemConfiguration != QNetworkProxyFactory::usesSystemConfiguration() + || (!m_usesSystemConfiguration && m_qtApplicationProxy != QNetworkProxy::applicationProxy())) { + Update(); + } else if (m_usesSystemConfiguration) { + if (m_baseService.get()) + m_baseService->OnLazyPoll(); + } +#else + if (m_qtApplicationProxy != QNetworkProxy::applicationProxy()) + Update(); +#endif +} + +// Called when the base service changed +void ProxyConfigServiceQt::OnProxyConfigChanged(const net::ProxyConfig &config, ConfigAvailability availability) +{ + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + Q_UNUSED(config); + + if (!m_usesSystemConfiguration) + return; + + Update(); +} + +// Update our observers +void ProxyConfigServiceQt::Update() +{ + net::ProxyConfig actual_config; + ConfigAvailability availability = GetLatestProxyConfig(&actual_config); + if (availability == CONFIG_PENDING) + return; + for (net::ProxyConfigService::Observer &observer: m_observers) + observer.OnProxyConfigChanged(actual_config, availability); +} + +// Register ourselves as observer of the base service. +// This has to be done on the IO thread, and therefore cannot be done +// in the constructor. +void ProxyConfigServiceQt::RegisterObserver() +{ + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (!m_registeredObserver && m_baseService.get()) { + m_baseService->AddObserver(this); + m_registeredObserver = true; + } +} diff --git a/src/core/net/proxy_config_service_qt.h b/src/core/net/proxy_config_service_qt.h new file mode 100644 index 000000000..7be3289d0 --- /dev/null +++ b/src/core/net/proxy_config_service_qt.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef PROXY_CONFIG_SERVICE_QT_H +#define PROXY_CONFIG_SERVICE_QT_H + +#include "base/memory/ref_counted.h" +#include "base/observer_list.h" + +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_config_service.h" + +#include <QNetworkProxy> + +class ProxyConfigServiceQt + : public net::ProxyConfigService, + public net::ProxyConfigService::Observer { +public: + + static net::ProxyServer fromQNetworkProxy(const QNetworkProxy &); + + explicit ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService); + ~ProxyConfigServiceQt() override; + + // ProxyConfigService implementation: + void AddObserver(net::ProxyConfigService::Observer *observer) override; + void RemoveObserver(net::ProxyConfigService::Observer *observer) override; + ConfigAvailability GetLatestProxyConfig(net::ProxyConfig *config) override; + void OnLazyPoll() override; + +private: + // ProxyConfigService::Observer implementation: + void OnProxyConfigChanged(const net::ProxyConfig& config, + ConfigAvailability availability) override; + + // Retrieve new proxy settings and notify observers. + void Update(); + + // Makes sure that the observer registration with the base service is set up. + void RegisterObserver(); + + std::unique_ptr<net::ProxyConfigService> m_baseService; + base::ObserverList<net::ProxyConfigService::Observer, true> m_observers; + + // Keep the last state around. + bool m_usesSystemConfiguration; + QNetworkProxy m_qtApplicationProxy; + net::ProxyConfig m_qtProxyConfig; + + // Indicates whether the base service registration is done. + bool m_registeredObserver; + + DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceQt); +}; + +#endif // PROXY_CONFIG_SERVICE_QT_H diff --git a/src/core/net/qrc_protocol_handler_qt.cpp b/src/core/net/qrc_protocol_handler_qt.cpp new file mode 100644 index 000000000..eb716f182 --- /dev/null +++ b/src/core/net/qrc_protocol_handler_qt.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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 "qrc_protocol_handler_qt.h" +#include "url_request_qrc_job_qt.h" + +#include "net/base/net_errors.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_error_job.h" + +namespace QtWebEngineCore { + +const char kQrcSchemeQt[] = "qrc"; + +QrcProtocolHandlerQt::QrcProtocolHandlerQt() +{ +} + +net::URLRequestJob *QrcProtocolHandlerQt::MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const +{ + if (!networkDelegate) + return new net::URLRequestErrorJob(request, Q_NULLPTR, net::ERR_ACCESS_DENIED); + + return new URLRequestQrcJobQt(request, networkDelegate); +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/qrc_protocol_handler_qt.h b/src/core/net/qrc_protocol_handler_qt.h new file mode 100644 index 000000000..f2849c1ef --- /dev/null +++ b/src/core/net/qrc_protocol_handler_qt.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QRC_PROTOCOL_HANDLER_QT_H_ +#define QRC_PROTOCOL_HANDLER_QT_H_ + +#include "net/url_request/url_request_job_factory.h" + +namespace net { + +class NetworkDelegate; +class URLRequestJob; + +} // namespace + +namespace QtWebEngineCore { + +extern const char kQrcSchemeQt[]; + +// Implements a ProtocolHandler for qrc file jobs. If |network_delegate_| is NULL, +// then all file requests will fail with ERR_ACCESS_DENIED. +class QrcProtocolHandlerQt : public net::URLRequestJobFactory::ProtocolHandler { + +public: + QrcProtocolHandlerQt(); + net::URLRequestJob *MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const override; + +private: + DISALLOW_COPY_AND_ASSIGN(QrcProtocolHandlerQt); +}; + +} // namespace QtWebEngineCore + +#endif // QRC_PROTOCOL_HANDLER_QT_H_ diff --git a/src/core/net/ssl_host_state_delegate_qt.cpp b/src/core/net/ssl_host_state_delegate_qt.cpp new file mode 100644 index 000000000..d8f73abda --- /dev/null +++ b/src/core/net/ssl_host_state_delegate_qt.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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 "base/callback.h" + +#include "ssl_host_state_delegate_qt.h" + +#include "type_conversion.h" + +namespace QtWebEngineCore { + +// Mirrors implementation in aw_ssl_host_state_delegate.cc + +CertPolicy::CertPolicy() +{ +} + +CertPolicy::~CertPolicy() +{ +} + +// For an allowance, we consider a given |cert| to be a match to a saved +// allowed cert if the |error| is an exact match to or subset of the errors +// in the saved CertStatus. +bool CertPolicy::Check(const net::X509Certificate &cert, net::CertStatus error) const +{ + net::SHA256HashValue fingerprint = cert.CalculateChainFingerprint256(); + auto allowed_iter = m_allowed.find(fingerprint); + if ((allowed_iter != m_allowed.end()) && (allowed_iter->second & error) && ((allowed_iter->second & error) == error)) + return true; + return false; +} + +void CertPolicy::Allow(const net::X509Certificate& cert, net::CertStatus error) +{ + net::SHA256HashValue fingerprint = cert.CalculateChainFingerprint256(); + m_allowed[fingerprint] |= error; +} + +SSLHostStateDelegateQt::SSLHostStateDelegateQt() +{ +} + +SSLHostStateDelegateQt::~SSLHostStateDelegateQt() +{ +} + +void SSLHostStateDelegateQt::AllowCert(const std::string &host, const net::X509Certificate &cert, net::CertStatus error) +{ + m_certPolicyforHost[host].Allow(cert, error); +} + +// Clear all allow preferences. +void SSLHostStateDelegateQt::Clear(const base::Callback<bool(const std::string&)>& host_filter) +{ + if (host_filter.is_null()) { + m_certPolicyforHost.clear(); + return; + } + + for (auto it = m_certPolicyforHost.begin(); it != m_certPolicyforHost.end();) { + auto next_it = std::next(it); + + if (host_filter.Run(it->first)) + m_certPolicyforHost.erase(it); + + it = next_it; + } +} + +// Queries whether |cert| is allowed for |host| and |error|. Returns true in +// |expired_previous_decision| if a previous user decision expired immediately +// prior to this query, otherwise false. +content::SSLHostStateDelegate::CertJudgment SSLHostStateDelegateQt::QueryPolicy( + const std::string &host, const net::X509Certificate &cert, + net::CertStatus error,bool *expired_previous_decision) +{ + return m_certPolicyforHost[host].Check(cert, error) ? SSLHostStateDelegate::ALLOWED : SSLHostStateDelegate::DENIED; +} + +// Records that a host has run insecure content. +void SSLHostStateDelegateQt::HostRanInsecureContent(const std::string &host, int pid, InsecureContentType content_type) +{ +} + +// Returns whether the specified host ran insecure content. +bool SSLHostStateDelegateQt::DidHostRunInsecureContent(const std::string &host, int pid, InsecureContentType content_type) const +{ + return false; +} + +// Revokes all SSL certificate error allow exceptions made by the user for +// |host|. +void SSLHostStateDelegateQt::RevokeUserAllowExceptions(const std::string &host) +{ + m_certPolicyforHost.erase(host); +} + +// Returns whether the user has allowed a certificate error exception for +// |host|. This does not mean that *all* certificate errors are allowed, just +// that there exists an exception. To see if a particular certificate and +// error combination exception is allowed, use QueryPolicy(). +bool SSLHostStateDelegateQt::HasAllowException(const std::string &host) const +{ + auto policy_iterator = m_certPolicyforHost.find(host); + return policy_iterator != m_certPolicyforHost.end() && + policy_iterator->second.HasAllowException(); +} + + +} // namespace QtWebEngineCore diff --git a/src/core/net/ssl_host_state_delegate_qt.h b/src/core/net/ssl_host_state_delegate_qt.h new file mode 100644 index 000000000..3ebabb601 --- /dev/null +++ b/src/core/net/ssl_host_state_delegate_qt.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef SSL_HOST_STATE_DELEGATE_QT_H +#define SSL_HOST_STATE_DELEGATE_QT_H + +#include "content/public/browser/ssl_host_state_delegate.h" +#include "browser_context_adapter.h" + +namespace QtWebEngineCore { + +class CertPolicy { +public: + CertPolicy(); + ~CertPolicy(); + bool Check(const net::X509Certificate& cert, net::CertStatus error) const; + void Allow(const net::X509Certificate& cert, net::CertStatus error); + bool HasAllowException() const { return m_allowed.size() > 0; } + +private: + std::map<net::SHA256HashValue, net::CertStatus> m_allowed; +}; + +class SSLHostStateDelegateQt : public content::SSLHostStateDelegate { + +public: + SSLHostStateDelegateQt(); + ~SSLHostStateDelegateQt(); + + // content::SSLHostStateDelegate implementation: + void AllowCert(const std::string &, const net::X509Certificate &cert, net::CertStatus error) override; + void Clear(const base::Callback<bool(const std::string&)>& host_filter) override; + virtual CertJudgment QueryPolicy(const std::string &host, const net::X509Certificate &cert, + net::CertStatus error,bool *expired_previous_decision) override; + void HostRanInsecureContent(const std::string& host, int child_id, InsecureContentType content_type) override; + bool DidHostRunInsecureContent(const std::string& host, int child_id, InsecureContentType content_type) const override; + void RevokeUserAllowExceptions(const std::string &host) override; + bool HasAllowException(const std::string &host) const override; + +private: + std::map<std::string, CertPolicy> m_certPolicyforHost; +}; + +} // namespace QtWebEngineCore + +#endif // SSL_HOST_STATE_DELEGATE_QT_H diff --git a/src/core/net/url_request_context_getter_qt.cpp b/src/core/net/url_request_context_getter_qt.cpp new file mode 100644 index 000000000..3b041639e --- /dev/null +++ b/src/core/net/url_request_context_getter_qt.cpp @@ -0,0 +1,648 @@ +/**************************************************************************** +** +** 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 "url_request_context_getter_qt.h" + +#include "base/command_line.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_util.h" +#include "base/task_scheduler/post_task.h" +#include "base/threading/sequenced_worker_pool.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" +#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" +#include "content/network/proxy_service_mojo.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/browsing_data_remover.h" +#include "content/public/browser/cookie_store_factory.h" +#include "content/public/common/content_features.h" +#include "content/public/common/content_switches.h" +#include "net/base/cache_type.h" +#include "net/cert/cert_verifier.h" +#include "net/cert/ct_known_logs.h" +#include "net/cert/ct_log_verifier.h" +#include "net/cert/ct_policy_enforcer.h" +#include "net/cert/multi_log_ct_verifier.h" +#include "net/dns/host_resolver.h" +#include "net/dns/mapped_host_resolver.h" +#include "net/extras/sqlite/sqlite_channel_id_store.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_auth_preferences.h" +#include "net/http/http_auth_scheme.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_session.h" +#include "net/http/http_server_properties_impl.h" +#include "net/proxy/dhcp_proxy_script_fetcher_factory.h" +#include "net/proxy/proxy_script_fetcher_impl.h" +#include "net/proxy/proxy_service.h" +#include "net/ssl/channel_id_service.h" +#include "net/ssl/default_channel_id_store.h" +#include "net/ssl/ssl_config_service_defaults.h" +#include "net/url_request/static_http_user_agent_settings.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/data_protocol_handler.h" +#include "net/url_request/file_protocol_handler.h" +#include "net/url_request/ftp_protocol_handler.h" +#include "net/url_request/url_request_intercepting_job_factory.h" +#include "net/ftp/ftp_network_layer.h" +#include "services/proxy_resolver/public/interfaces/proxy_resolver.mojom.h" + +#include "api/qwebengineurlschemehandler.h" +#include "browser_context_adapter.h" +#include "browser_context_qt.h" +#include "custom_protocol_handler.h" +#include "cookie_monster_delegate_qt.h" +#include "content_client_qt.h" +#include "network_delegate_qt.h" +#include "proxy_config_service_qt.h" +#include "qrc_protocol_handler_qt.h" +#include "qwebenginecookiestore.h" +#include "qwebenginecookiestore_p.h" +#include "type_conversion.h" + +namespace QtWebEngineCore { + +using content::BrowserThread; + +URLRequestContextGetterQt::URLRequestContextGetterQt(QSharedPointer<BrowserContextAdapter> browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors) + : m_ignoreCertificateErrors(false) + , m_mutex(QMutex::Recursive) + , m_contextInitialized(false) + , m_updateAllStorage(false) + , m_updateCookieStore(false) + , m_updateHttpCache(false) + , m_updateJobFactory(true) + , m_updateUserAgent(false) + , m_browserContext(browserContext) + , m_baseJobFactory(0) + , m_cookieDelegate(new CookieMonsterDelegateQt()) + , m_requestInterceptors(std::move(request_interceptors)) +{ + std::swap(m_protocolHandlers, *protocolHandlers); + + // The ProtocolHandlerRegistry and it's JobInterceptorFactory need to be + // created on the UI thread: + ProtocolHandlerRegistry* protocolHandlerRegistry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(browserContext->browserContext()); + DCHECK(protocolHandlerRegistry); + m_protocolHandlerInterceptor = + protocolHandlerRegistry->CreateJobInterceptorFactory(); + + QMutexLocker lock(&m_mutex); + m_cookieDelegate->setClient(browserContext->cookieStore()); + setFullConfiguration(browserContext); + updateStorageSettings(); +} + +URLRequestContextGetterQt::~URLRequestContextGetterQt() +{ + m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted + delete m_proxyConfigService.fetchAndStoreAcquire(0); +} + + +void URLRequestContextGetterQt::setFullConfiguration(QSharedPointer<BrowserContextAdapter> browserContext) +{ + if (!browserContext) + return; + + m_requestInterceptor = browserContext->requestInterceptor(); + m_persistentCookiesPolicy = browserContext->persistentCookiesPolicy(); + m_cookiesPath = browserContext->cookiesPath(); + m_channelIdPath = browserContext->channelIdPath(); + m_httpAcceptLanguage = browserContext->httpAcceptLanguage(); + m_httpUserAgent = browserContext->httpUserAgent(); + m_httpCacheType = browserContext->httpCacheType(); + m_httpCachePath = browserContext->httpCachePath(); + m_httpCacheMaxSize = browserContext->httpCacheMaxSize(); + m_customUrlSchemes = browserContext->customUrlSchemes(); +} + +net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + if (!m_urlRequestContext) { + m_urlRequestContext.reset(new net::URLRequestContext()); + + m_networkDelegate.reset(new NetworkDelegateQt(this)); + m_urlRequestContext->set_network_delegate(m_networkDelegate.get()); + m_urlRequestContext->set_enable_brotli(base::FeatureList::IsEnabled(features::kBrotliEncoding)); + + QMutexLocker lock(&m_mutex); + generateAllStorage(); + generateJobFactory(); + m_contextInitialized = true; + } + + return m_urlRequestContext.get(); +} + +void URLRequestContextGetterQt::updateStorageSettings() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + QMutexLocker lock(&m_mutex); + setFullConfiguration(m_browserContext.toStrongRef()); + + if (!m_updateAllStorage) { + m_updateAllStorage = true; + // We must create the proxy config service on the UI loop on Linux because it + // must synchronously run on the glib message loop. This will be passed to + // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). + Q_ASSERT(m_proxyConfigService == 0); + m_proxyConfigService = + new ProxyConfigServiceQt( + net::ProxyService::CreateSystemProxyConfigService( + content::BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))); + m_proxyResolverFactory = ChromeMojoProxyResolverFactory::CreateWithStrongBinding(); + + if (m_contextInitialized) + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestContextGetterQt::generateAllStorage, this)); + } +} + +void URLRequestContextGetterQt::cancelAllUrlRequests() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + + const std::set<const net::URLRequest*> *url_requests = m_urlRequestContext->url_requests(); + std::set<const net::URLRequest*>::const_iterator it = url_requests->begin(); + std::set<const net::URLRequest*>::const_iterator end = url_requests->end(); + for ( ; it != end; ++it) { + net::URLRequest* request = const_cast<net::URLRequest*>(*it); + if (request) + request->Cancel(); + } + +} + +void URLRequestContextGetterQt::generateAllStorage() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + QMutexLocker lock(&m_mutex); + generateStorage(); + generateCookieStore(); + generateUserAgent(); + generateHttpCache(); + m_updateAllStorage = false; +} + +static const char* const kDefaultAuthSchemes[] = { net::kBasicAuthScheme, + net::kDigestAuthScheme, +#if defined(USE_KERBEROS) && !defined(OS_ANDROID) + net::kNegotiateAuthScheme, +#endif + net::kNtlmAuthScheme }; + +void URLRequestContextGetterQt::generateStorage() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + + // We must stop all requests before deleting their backends. + if (m_storage) { + m_cookieDelegate->setCookieMonster(0); + m_storage->set_cookie_store(0); + cancelAllUrlRequests(); + // we need to get rid of dangling pointer due to coming storage deletion + m_urlRequestContext->set_http_transaction_factory(0); + m_httpNetworkSession.reset(); + } + + + m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); + + net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0); + Q_ASSERT(proxyConfigService); + + m_storage->set_cert_verifier(net::CertVerifier::CreateDefault()); + std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier()); + ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); + m_storage->set_cert_transparency_verifier(std::move(ct_verifier)); + m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::CTPolicyEnforcer)); + + std::unique_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); + + // The System Proxy Resolver has issues on Windows with unconfigured network cards, + // which is why we want to use the v8 one + if (!m_dhcpProxyScriptFetcherFactory) + m_dhcpProxyScriptFetcherFactory.reset(new net::DhcpProxyScriptFetcherFactory); + + m_storage->set_proxy_service(content::CreateProxyServiceUsingMojoFactory( + std::move(m_proxyResolverFactory), + std::unique_ptr<net::ProxyConfigService>(proxyConfigService), + std::make_unique<net::ProxyScriptFetcherImpl>(m_urlRequestContext.get()), + m_dhcpProxyScriptFetcherFactory->Create(m_urlRequestContext.get()), + host_resolver.get(), + nullptr /* NetLog */, + m_networkDelegate.get())); + + m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); + m_storage->set_transport_security_state(std::unique_ptr<net::TransportSecurityState>(new net::TransportSecurityState())); + + if (!m_httpAuthPreferences) { + std::vector<std::string> auth_types(std::begin(kDefaultAuthSchemes), std::end(kDefaultAuthSchemes)); + m_httpAuthPreferences.reset(new net::HttpAuthPreferences(auth_types +#if defined(OS_POSIX) && !defined(OS_ANDROID) + , std::string() /* gssapi library name */ +#endif + )); + } + m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerRegistryFactory::Create(m_httpAuthPreferences.get(), host_resolver.get())); + m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl)); + + // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|. + m_storage->set_host_resolver(std::move(host_resolver)); +} + +void URLRequestContextGetterQt::updateCookieStore() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + m_persistentCookiesPolicy = m_browserContext.data()->persistentCookiesPolicy(); + m_cookiesPath = m_browserContext.data()->cookiesPath(); + m_channelIdPath = m_browserContext.data()->channelIdPath(); + + if (m_contextInitialized && !m_updateAllStorage && !m_updateCookieStore) { + m_updateCookieStore = true; + m_updateHttpCache = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestContextGetterQt::generateCookieStore, this)); + } +} + +void URLRequestContextGetterQt::generateCookieStore() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + + QMutexLocker lock(&m_mutex); + m_updateCookieStore = false; + + scoped_refptr<net::SQLiteChannelIDStore> channel_id_db; + if (!m_channelIdPath.isEmpty() && m_persistentCookiesPolicy != BrowserContextAdapter::NoPersistentCookies) { + channel_id_db = new net::SQLiteChannelIDStore( + toFilePath(m_channelIdPath), + base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BACKGROUND})); + } + + m_storage->set_channel_id_service( + base::WrapUnique(new net::ChannelIDService( + new net::DefaultChannelIDStore(channel_id_db.get())))); + + // Unset it first to get a chance to destroy and flush the old cookie store before opening a new on possibly the same file. + m_cookieDelegate->setCookieMonster(0); + m_storage->set_cookie_store(0); + + std::unique_ptr<net::CookieStore> cookieStore; + switch (m_persistentCookiesPolicy) { + case BrowserContextAdapter::NoPersistentCookies: + cookieStore = content::CreateCookieStore( + content::CookieStoreConfig( + base::FilePath(), + false, + false, + nullptr) + ); + break; + case BrowserContextAdapter::AllowPersistentCookies: + cookieStore = content::CreateCookieStore( + content::CookieStoreConfig( + toFilePath(m_cookiesPath), + false, + true, + nullptr) + ); + break; + case BrowserContextAdapter::ForcePersistentCookies: + cookieStore = content::CreateCookieStore( + content::CookieStoreConfig( + toFilePath(m_cookiesPath), + true, + true, + nullptr) + ); + break; + } + + net::CookieMonster * const cookieMonster = static_cast<net::CookieMonster*>(cookieStore.get()); + cookieStore->SetChannelIDServiceID(m_urlRequestContext->channel_id_service()->GetUniqueID()); + m_cookieDelegate->setCookieMonster(cookieMonster); + m_storage->set_cookie_store(std::move(cookieStore)); + + const std::vector<std::string> cookieableSchemes(kCookieableSchemes, kCookieableSchemes + arraysize(kCookieableSchemes)); + cookieMonster->SetCookieableSchemes(cookieableSchemes); + + if (!m_updateAllStorage && m_updateHttpCache) { + // HttpCache needs to be regenerated when we generate a new channel id service + generateHttpCache(); + } +} + +void URLRequestContextGetterQt::updateUserAgent() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + m_httpAcceptLanguage = m_browserContext.data()->httpAcceptLanguage(); + m_httpUserAgent = m_browserContext.data()->httpUserAgent(); + + if (m_contextInitialized && !m_updateAllStorage && !m_updateUserAgent) { + m_updateUserAgent = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestContextGetterQt::generateUserAgent, this)); + } +} + +void URLRequestContextGetterQt::generateUserAgent() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + + QMutexLocker lock(&m_mutex); + m_updateUserAgent = false; + + m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>( + new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), m_httpUserAgent.toStdString()))); +} + +void URLRequestContextGetterQt::updateHttpCache() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + m_httpCacheType = m_browserContext.data()->httpCacheType(); + m_httpCachePath = m_browserContext.data()->httpCachePath(); + m_httpCacheMaxSize = m_browserContext.data()->httpCacheMaxSize(); + + if (m_httpCacheType == BrowserContextAdapter::NoCache) { + content::BrowsingDataRemover *remover = content::BrowserContext::GetBrowsingDataRemover(m_browserContext.data()->browserContext()); + remover->Remove(base::Time(), base::Time::Max(), + content::BrowsingDataRemover::DATA_TYPE_CACHE, + content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB); + } + + if (m_contextInitialized && !m_updateAllStorage && !m_updateHttpCache) { + m_updateHttpCache = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestContextGetterQt::generateHttpCache, this)); + } +} + +void URLRequestContextGetterQt::updateJobFactory() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + m_customUrlSchemes = m_browserContext.data()->customUrlSchemes(); + + if (m_contextInitialized && !m_updateJobFactory) { + m_updateJobFactory = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestContextGetterQt::regenerateJobFactory, this)); + } +} + +void URLRequestContextGetterQt::updateRequestInterceptor() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + QMutexLocker lock(&m_mutex); + m_requestInterceptor = m_browserContext.data()->requestInterceptor(); + + // We in this case do not need to regenerate any Chromium classes. +} + +static bool doNetworkSessionContextMatch(const net::HttpNetworkSession::Context &first, const net::HttpNetworkSession::Context &second) +{ + if (first.transport_security_state != second.transport_security_state) + return false; + if (first.cert_verifier != second.cert_verifier) + return false; + if (first.channel_id_service != second.channel_id_service) + return false; + if (first.proxy_service != second.proxy_service) + return false; + if (first.ssl_config_service != second.ssl_config_service) + return false; + if (first.http_auth_handler_factory != second.http_auth_handler_factory) + return false; + if (first.http_server_properties != second.http_server_properties) + return false; + if (first.host_resolver != second.host_resolver) + return false; + if (first.cert_transparency_verifier != second.cert_transparency_verifier) + return false; + if (first.ct_policy_enforcer != second.ct_policy_enforcer) + return false; + + return true; +} + +static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, const net::HttpNetworkSession::Params &second) +{ + if (first.ignore_certificate_errors != second.ignore_certificate_errors) + return false; + + return true; +} + +net::HttpNetworkSession::Context URLRequestContextGetterQt::generateNetworkSessionContext() +{ + Q_ASSERT(m_urlRequestContext); + + net::HttpNetworkSession::Context network_session_context; + + network_session_context.transport_security_state = m_urlRequestContext->transport_security_state(); + network_session_context.cert_verifier = m_urlRequestContext->cert_verifier(); + network_session_context.channel_id_service = m_urlRequestContext->channel_id_service(); + network_session_context.proxy_service = m_urlRequestContext->proxy_service(); + network_session_context.ssl_config_service = m_urlRequestContext->ssl_config_service(); + network_session_context.http_auth_handler_factory = m_urlRequestContext->http_auth_handler_factory(); + network_session_context.http_server_properties = m_urlRequestContext->http_server_properties(); + network_session_context.host_resolver = m_urlRequestContext->host_resolver(); + network_session_context.cert_transparency_verifier = m_urlRequestContext->cert_transparency_verifier(); + network_session_context.ct_policy_enforcer = m_urlRequestContext->ct_policy_enforcer(); + + return network_session_context; +} + +net::HttpNetworkSession::Params URLRequestContextGetterQt::generateNetworkSessionParams() +{ + Q_ASSERT(m_urlRequestContext); + + net::HttpNetworkSession::Params network_session_params; + + network_session_params.ignore_certificate_errors = m_ignoreCertificateErrors; + + return network_session_params; +} + +void URLRequestContextGetterQt::generateHttpCache() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + + QMutexLocker lock(&m_mutex); + m_updateHttpCache = false; + + if (m_updateCookieStore) + generateCookieStore(); + + net::HttpCache::DefaultBackend* main_backend = 0; + switch (m_httpCacheType) { + case BrowserContextAdapter::MemoryHttpCache: + main_backend = + new net::HttpCache::DefaultBackend( + net::MEMORY_CACHE, + net::CACHE_BACKEND_DEFAULT, + base::FilePath(), + m_httpCacheMaxSize + ); + break; + case BrowserContextAdapter::DiskHttpCache: + main_backend = + new net::HttpCache::DefaultBackend( + net::DISK_CACHE, + net::CACHE_BACKEND_DEFAULT, + toFilePath(m_httpCachePath), + m_httpCacheMaxSize + ); + break; + case BrowserContextAdapter::NoCache: + // It's safe to not create BackendFactory. + break; + } + + net::HttpCache *cache = 0; + net::HttpNetworkSession::Context network_session_context = generateNetworkSessionContext(); + net::HttpNetworkSession::Params network_session_params = generateNetworkSessionParams(); + + if (!m_httpNetworkSession + || !doNetworkSessionParamsMatch(network_session_params, m_httpNetworkSession->params()) + || !doNetworkSessionContextMatch(network_session_context, m_httpNetworkSession->context())) { + cancelAllUrlRequests(); + m_httpNetworkSession.reset(new net::HttpNetworkSession(network_session_params, network_session_context)); + } + + cache = new net::HttpCache(m_httpNetworkSession.get(), std::unique_ptr<net::HttpCache::DefaultBackend>(main_backend), false); + + m_storage->set_http_transaction_factory(std::unique_ptr<net::HttpCache>(cache)); +} + +void URLRequestContextGetterQt::generateJobFactory() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(!m_jobFactory); + + QMutexLocker lock(&m_mutex); + m_updateJobFactory = false; + + std::unique_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl()); + for (auto &it : m_protocolHandlers) + jobFactory->SetProtocolHandler(it.first, base::WrapUnique(it.second.release())); + m_protocolHandlers.clear(); + + jobFactory->SetProtocolHandler(url::kDataScheme, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::DataProtocolHandler())); + jobFactory->SetProtocolHandler(url::kFileScheme, + std::make_unique<net::FileProtocolHandler>( + base::CreateTaskRunnerWithTraits({base::MayBlock(), + base::TaskPriority::BACKGROUND, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}))); + jobFactory->SetProtocolHandler(kQrcSchemeQt, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new QrcProtocolHandlerQt())); + jobFactory->SetProtocolHandler(url::kFtpScheme, + net::FtpProtocolHandler::Create(m_urlRequestContext->host_resolver())); + + m_installedCustomSchemes = m_customUrlSchemes; + Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) { + jobFactory->SetProtocolHandler(scheme.toStdString(), std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext))); + } + + m_baseJobFactory = jobFactory.get(); + + // Set up interceptors in the reverse order. + std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory); + + for (content::URLRequestInterceptorScopedVector::reverse_iterator i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) { + topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), std::move(*i))); + } + + m_requestInterceptors.clear(); + + if (m_protocolHandlerInterceptor) { + m_protocolHandlerInterceptor->Chain(std::move(topJobFactory)); + topJobFactory = std::move(m_protocolHandlerInterceptor); + } + + m_jobFactory = std::move(topJobFactory); + + m_urlRequestContext->set_job_factory(m_jobFactory.get()); +} + +void URLRequestContextGetterQt::regenerateJobFactory() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_jobFactory); + Q_ASSERT(m_baseJobFactory); + + QMutexLocker lock(&m_mutex); + m_updateJobFactory = false; + + if (m_customUrlSchemes == m_installedCustomSchemes) + return; + + Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) { + m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr); + } + + m_installedCustomSchemes = m_customUrlSchemes; + Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) { + m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext))); + } +} + +scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const +{ + return content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO); +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/url_request_context_getter_qt.h b/src/core/net/url_request_context_getter_qt.h new file mode 100644 index 000000000..809e4190d --- /dev/null +++ b/src/core/net/url_request_context_getter_qt.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef URL_REQUEST_CONTEXT_GETTER_QT_H +#define URL_REQUEST_CONTEXT_GETTER_QT_H + +#include "net/url_request/url_request_context_getter.h" + +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/common/url_constants.h" +#include "net/http/http_network_session.h" +#include "net/url_request/url_request_context_storage.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "net/proxy/dhcp_proxy_script_fetcher_factory.h" + +#include "cookie_monster_delegate_qt.h" +#include "network_delegate_qt.h" +#include "browser_context_adapter.h" + +#include <QtCore/qatomic.h> +#include <QtCore/qmutex.h> +#include <QtCore/qsharedpointer.h> + +namespace net { +class HttpAuthPreferences; +class MappedHostResolver; +class ProxyConfigService; +} + +namespace QtWebEngineCore { + +// FIXME: This class should be split into a URLRequestContextGetter and a ProfileIOData, similar to what chrome does. +class URLRequestContextGetterQt : public net::URLRequestContextGetter { +public: + URLRequestContextGetterQt(QSharedPointer<BrowserContextAdapter> browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors); + + net::URLRequestContext *GetURLRequestContext() override; + scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; + + // Called on the UI thread: + void updateStorageSettings(); + void updateUserAgent(); + void updateCookieStore(); + void updateHttpCache(); + void updateJobFactory(); + void updateRequestInterceptor(); + +private: + virtual ~URLRequestContextGetterQt(); + + // Called on the IO thread: + void generateAllStorage(); + void generateStorage(); + void generateCookieStore(); + void generateHttpCache(); + void generateUserAgent(); + void generateJobFactory(); + void regenerateJobFactory(); + void cancelAllUrlRequests(); + net::HttpNetworkSession::Params generateNetworkSessionParams(); + net::HttpNetworkSession::Context generateNetworkSessionContext(); + + void setFullConfiguration(QSharedPointer<BrowserContextAdapter> browserContext); + + bool m_ignoreCertificateErrors; + + QMutex m_mutex; + bool m_contextInitialized; + bool m_updateAllStorage; + bool m_updateCookieStore; + bool m_updateHttpCache; + bool m_updateJobFactory; + bool m_updateUserAgent; + + QWeakPointer<BrowserContextAdapter> m_browserContext; + content::ProtocolHandlerMap m_protocolHandlers; + + QAtomicPointer<net::ProxyConfigService> m_proxyConfigService; + std::unique_ptr<net::URLRequestContext> m_urlRequestContext; + std::unique_ptr<NetworkDelegateQt> m_networkDelegate; + std::unique_ptr<net::URLRequestContextStorage> m_storage; + std::unique_ptr<net::URLRequestJobFactory> m_jobFactory; + std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> m_protocolHandlerInterceptor; + net::URLRequestJobFactoryImpl *m_baseJobFactory; + std::unique_ptr<net::DhcpProxyScriptFetcherFactory> m_dhcpProxyScriptFetcherFactory; + scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate; + content::URLRequestInterceptorScopedVector m_requestInterceptors; + std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession; + std::unique_ptr<net::HttpAuthPreferences> m_httpAuthPreferences; + proxy_resolver::mojom::ProxyResolverFactoryPtr m_proxyResolverFactory; + + QList<QByteArray> m_installedCustomSchemes; + QWebEngineUrlRequestInterceptor* m_requestInterceptor; + + // Configuration values to setup URLRequestContext in IO thread, copied from browserContext + // FIXME: Should later be moved to a separate ProfileIOData class. + BrowserContextAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy; + QString m_cookiesPath; + QString m_channelIdPath; + QString m_httpAcceptLanguage; + QString m_httpUserAgent; + BrowserContextAdapter::HttpCacheType m_httpCacheType; + QString m_httpCachePath; + int m_httpCacheMaxSize; + QList<QByteArray> m_customUrlSchemes; + + friend class NetworkDelegateQt; +}; + +} // namespace QtWebEngineCore + +#endif // URL_REQUEST_CONTEXT_GETTER_QT_H diff --git a/src/core/net/url_request_custom_job.cpp b/src/core/net/url_request_custom_job.cpp new file mode 100644 index 000000000..cf96cd6d9 --- /dev/null +++ b/src/core/net/url_request_custom_job.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** 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 "url_request_custom_job.h" +#include "url_request_custom_job_proxy.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/io_buffer.h" + +#include <QIODevice> + +using namespace net; + +namespace QtWebEngineCore { + +URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, + NetworkDelegate *networkDelegate, + const std::string &scheme, + QWeakPointer<const BrowserContextAdapter> adapter) + : URLRequestJob(request, networkDelegate) + , m_proxy(new URLRequestCustomJobProxy(this, scheme, adapter)) + , m_device(nullptr) + , m_error(0) + , m_pendingReadSize(0) + , m_pendingReadPos(0) + , m_pendingReadBuffer(nullptr) +{ +} + +URLRequestCustomJob::~URLRequestCustomJob() +{ + m_proxy->m_job = nullptr; + if (m_device && m_device->isOpen()) + m_device->close(); + m_device = nullptr; + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::release, + m_proxy)); +} + +void URLRequestCustomJob::Start() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::initialize, + m_proxy, request()->url(), request()->method(), request()->initiator())); +} + +void URLRequestCustomJob::Kill() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (m_device && m_device->isOpen()) + m_device->close(); + if (m_pendingReadBuffer) { + m_pendingReadBuffer->Release(); + m_pendingReadBuffer = nullptr; + m_pendingReadSize = 0; + m_pendingReadPos = 0; + } + m_device = nullptr; + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::release, + m_proxy)); + URLRequestJob::Kill(); +} + +bool URLRequestCustomJob::GetMimeType(std::string *mimeType) const +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (m_mimeType.size() > 0) { + *mimeType = m_mimeType; + return true; + } + return false; +} + +bool URLRequestCustomJob::GetCharset(std::string* charset) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (m_charset.size() > 0) { + *charset = m_charset; + return true; + } + return false; +} + +bool URLRequestCustomJob::IsRedirectResponse(GURL* location, int* http_status_code) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (m_redirect.is_valid()) { + *location = m_redirect; + *http_status_code = 303; + return true; + } + return false; +} + +int URLRequestCustomJob::ReadRawData(IOBuffer *buf, int bufSize) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (m_error) + return m_error; + qint64 rv = m_device ? m_device->read(buf->data(), bufSize) : -1; + if (rv > 0) { + return static_cast<int>(rv); + } else if (rv == 0) { + // Returning zero is interpreted as EOF by Chromium, so only + // return zero if we are the end of the file. + if (m_device->atEnd()) + return 0; + // Otherwise return IO_PENDING and call ReadRawDataComplete when we have data + // for them. + buf->AddRef(); + m_pendingReadPos = 0; + m_pendingReadSize = bufSize; + m_pendingReadBuffer = buf; + return ERR_IO_PENDING; + } else { + // QIODevice::read might have called fail on us. + if (m_error) + return m_error; + if (m_device && m_device->atEnd()) + return 0; + return ERR_FAILED; + } +} + +void URLRequestCustomJob::notifyReadyRead() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_device) + return; + if (!m_pendingReadSize) + return; + Q_ASSERT(m_pendingReadBuffer); + if (!m_pendingReadBuffer) + return; + + qint64 rv = m_device->read(m_pendingReadBuffer->data() + m_pendingReadPos, m_pendingReadSize - m_pendingReadPos); + if (rv == 0) + return; + if (rv < 0) { + if (m_error) + rv = m_error; + else if (m_device->atEnd()) + rv = 0; + else + rv = ERR_FAILED; + } else { + m_pendingReadPos += rv; + if (m_pendingReadPos < m_pendingReadSize && !m_device->atEnd()) + return; + rv = m_pendingReadPos; + } + // killJob may be called from ReadRawDataComplete + net::IOBuffer *buf = m_pendingReadBuffer; + m_pendingReadBuffer = nullptr; + m_pendingReadSize = 0; + m_pendingReadPos = 0; + ReadRawDataComplete(rv); + buf->Release(); +} + +} // namespace diff --git a/src/core/net/url_request_custom_job.h b/src/core/net/url_request_custom_job.h new file mode 100644 index 000000000..021cf3204 --- /dev/null +++ b/src/core/net/url_request_custom_job.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef URL_REQUEST_CUSTOM_JOB_H_ +#define URL_REQUEST_CUSTOM_JOB_H_ + +#include "net/url_request/url_request_job.h" +#include "url/gurl.h" +#include <QtCore/QWeakPointer> + +QT_FORWARD_DECLARE_CLASS(QIODevice) + +namespace QtWebEngineCore { + +class BrowserContextAdapter; +class URLRequestCustomJobDelegate; +class URLRequestCustomJobProxy; + +// A request job that handles reading custom URL schemes +class URLRequestCustomJob : public net::URLRequestJob { +public: + URLRequestCustomJob(net::URLRequest *request, + net::NetworkDelegate *networkDelegate, + const std::string &scheme, + QWeakPointer<const BrowserContextAdapter> adapter); + void Start() override; + void Kill() override; + int ReadRawData(net::IOBuffer *buf, int buf_size) override; + bool GetMimeType(std::string *mimeType) const override; + bool GetCharset(std::string *charset) override; + bool IsRedirectResponse(GURL* location, int* http_status_code) override; + +protected: + virtual ~URLRequestCustomJob(); + +private: + void notifyReadyRead(); + scoped_refptr<URLRequestCustomJobProxy> m_proxy; + std::string m_mimeType; + std::string m_charset; + GURL m_redirect; + QIODevice *m_device; + int m_error; + int m_pendingReadSize; + int m_pendingReadPos; + net::IOBuffer *m_pendingReadBuffer; + + friend class URLRequestCustomJobProxy; + + DISALLOW_COPY_AND_ASSIGN(URLRequestCustomJob); +}; +} // namespace QtWebEngineCore + +#endif // URL_REQUEST_CUSTOM_JOB_H_ diff --git a/src/core/net/url_request_custom_job_delegate.cpp b/src/core/net/url_request_custom_job_delegate.cpp new file mode 100644 index 000000000..338bd7137 --- /dev/null +++ b/src/core/net/url_request_custom_job_delegate.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** 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 "url_request_custom_job_delegate.h" +#include "url_request_custom_job_proxy.h" + +#include "type_conversion.h" +#include "net/base/net_errors.h" +#include "content/public/browser/browser_thread.h" + +#include <QByteArray> + +namespace QtWebEngineCore { + +URLRequestCustomJobDelegate::URLRequestCustomJobDelegate(URLRequestCustomJobProxy *proxy, + const QUrl &url, + const QByteArray &method, + const QUrl &initiatorOrigin) + : m_proxy(proxy), + m_request(url), + m_method(method), + m_initiatorOrigin(initiatorOrigin) +{ +} + +URLRequestCustomJobDelegate::~URLRequestCustomJobDelegate() +{ +} + +QUrl URLRequestCustomJobDelegate::url() const +{ + return m_request; +} + +QByteArray URLRequestCustomJobDelegate::method() const +{ + return m_method; +} + +QUrl URLRequestCustomJobDelegate::initiator() const +{ + return m_initiatorOrigin; +} + +void URLRequestCustomJobDelegate::reply(const QByteArray &contentType, QIODevice *device) +{ + if (device) + QObject::connect(device, &QIODevice::readyRead, this, &URLRequestCustomJobDelegate::slotReadyRead); + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::reply, + m_proxy,contentType.toStdString(),device)); +} + +void URLRequestCustomJobDelegate::slotReadyRead() +{ + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::readyRead, m_proxy)); +} + +void URLRequestCustomJobDelegate::abort() +{ + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::abort, m_proxy)); +} + +void URLRequestCustomJobDelegate::redirect(const QUrl &url) +{ + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::redirect, + m_proxy, toGurl(url))); +} + +void URLRequestCustomJobDelegate::fail(Error error) +{ + int net_error = 0; + switch (error) { + case NoError: + break; + case UrlInvalid: + net_error = net::ERR_INVALID_URL; + break; + case UrlNotFound: + net_error = net::ERR_FILE_NOT_FOUND; + break; + case RequestAborted: + net_error = net::ERR_ABORTED; + break; + case RequestDenied: + net_error = net::ERR_ACCESS_DENIED; + break; + case RequestFailed: + net_error = net::ERR_FAILED; + break; + } + if (net_error) { + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&URLRequestCustomJobProxy::fail, + m_proxy, net_error)); + } +} + +} // namespace diff --git a/src/core/net/url_request_custom_job_delegate.h b/src/core/net/url_request_custom_job_delegate.h new file mode 100644 index 000000000..6bbd10909 --- /dev/null +++ b/src/core/net/url_request_custom_job_delegate.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef URL_REQUEST_CUSTOM_JOB_DELEGATE_H_ +#define URL_REQUEST_CUSTOM_JOB_DELEGATE_H_ + +#include "base/memory/ref_counted.h" +#include "qtwebenginecoreglobal.h" + +#include <QObject> +#include <QUrl> + +QT_FORWARD_DECLARE_CLASS(QIODevice) + +namespace QtWebEngineCore { + +class URLRequestCustomJobProxy; + +class QWEBENGINE_EXPORT URLRequestCustomJobDelegate : public QObject { + Q_OBJECT +public: + ~URLRequestCustomJobDelegate(); + + enum Error { + NoError = 0, + UrlNotFound, + UrlInvalid, + RequestAborted, + RequestDenied, + RequestFailed + }; + + QUrl url() const; + QByteArray method() const; + QUrl initiator() const; + + void reply(const QByteArray &contentType, QIODevice *device); + void redirect(const QUrl& url); + void abort(); + void fail(Error); + +private Q_SLOTS: + void slotReadyRead(); + +private: + URLRequestCustomJobDelegate(URLRequestCustomJobProxy *proxy, + const QUrl &url, + const QByteArray &method, + const QUrl &initiatorOrigin); + + friend class URLRequestCustomJobProxy; + scoped_refptr<URLRequestCustomJobProxy> m_proxy; + QUrl m_request; + QByteArray m_method; + QUrl m_initiatorOrigin; +}; + +} // namespace + +#endif // URL_REQUEST_CUSTOM_JOB_DELEGATE_H_ diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp new file mode 100644 index 000000000..6c9824bb9 --- /dev/null +++ b/src/core/net/url_request_custom_job_proxy.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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_custom_job_proxy.h" +#include "url_request_custom_job.h" +#include "url_request_custom_job_delegate.h" +#include "api/qwebengineurlrequestjob.h" +#include "browser_context_adapter.h" +#include "type_conversion.h" +#include "content/public/browser/browser_thread.h" + +using namespace net; + +namespace QtWebEngineCore { + +URLRequestCustomJobProxy::URLRequestCustomJobProxy(URLRequestCustomJob *job, + const std::string &scheme, + QWeakPointer<const BrowserContextAdapter> adapter) + : m_job(job) + , m_started(false) + , m_scheme(scheme) + , m_delegate(nullptr) + , m_adapter(adapter) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); +} + +URLRequestCustomJobProxy::~URLRequestCustomJobProxy() +{ +} + +void URLRequestCustomJobProxy::release() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (m_delegate) { + m_delegate->deleteLater(); + m_delegate = nullptr; + } +} + +// Fix me: this is never used +/* +void URLRequestCustomJobProxy::setReplyCharset(const std::string &charset) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + m_job->m_charset = charset; +} +*/ +void URLRequestCustomJobProxy::reply(std::string mimeType, QIODevice *device) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + m_job->m_mimeType = mimeType; + m_job->m_device = device; + if (m_job->m_device && !m_job->m_device->isReadable()) + m_job->m_device->open(QIODevice::ReadOnly); + + qint64 size = m_job->m_device ? m_job->m_device->size() : -1; + if (size > 0) + m_job->set_expected_content_size(size); + if (m_job->m_device && m_job->m_device->isReadable()) { + m_started = true; + m_job->NotifyHeadersComplete(); + } else { + fail(ERR_INVALID_URL); + } +} + +void URLRequestCustomJobProxy::redirect(GURL url) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + if (m_job->m_device || m_job->m_error) + return; + m_job->m_redirect = url; + m_started = true; + m_job->NotifyHeadersComplete(); +} + +void URLRequestCustomJobProxy::abort() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + if (m_job->m_device && m_job->m_device->isOpen()) + m_job->m_device->close(); + m_job->m_device = nullptr; + if (m_started) + m_job->NotifyCanceled(); + else + m_job->NotifyStartError(URLRequestStatus(URLRequestStatus::CANCELED, ERR_ABORTED)); +} + +void URLRequestCustomJobProxy::fail(int error) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!m_job) + return; + m_job->m_error = error; + if (m_job->m_device) + m_job->m_device->close(); + if (!m_started) + m_job->NotifyStartError(URLRequestStatus::FromError(error)); + // else we fail on the next read, or the read that might already be in progress +} + +void URLRequestCustomJobProxy::readyRead() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (m_job) + m_job->notifyReadyRead(); +} + +void URLRequestCustomJobProxy::initialize(GURL url, std::string method, base::Optional<url::Origin> initiator) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + Q_ASSERT(!m_delegate); + + QUrl initiatorOrigin; + if (initiator.has_value()) + initiatorOrigin = toQt(initiator.value().GetURL()); + + QWebEngineUrlSchemeHandler *schemeHandler = 0; + QSharedPointer<const BrowserContextAdapter> browserContext = m_adapter.toStrongRef(); + if (browserContext) + schemeHandler = browserContext->customUrlSchemeHandlers()[toQByteArray(m_scheme)]; + if (schemeHandler) { + m_delegate = new URLRequestCustomJobDelegate(this, toQt(url), + QByteArray::fromStdString(method), + initiatorOrigin); + QWebEngineUrlRequestJob *requestJob = new QWebEngineUrlRequestJob(m_delegate); + schemeHandler->requestStarted(requestJob); + } +} + +} // namespace diff --git a/src/core/net/url_request_custom_job_proxy.h b/src/core/net/url_request_custom_job_proxy.h new file mode 100644 index 000000000..603ad5840 --- /dev/null +++ b/src/core/net/url_request_custom_job_proxy.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +#ifndef URL_REQUEST_CUSTOM_JOB_PROXY_H_ +#define URL_REQUEST_CUSTOM_JOB_PROXY_H_ + +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "url/gurl.h" +#include "url/origin.h" +#include <QtCore/QWeakPointer> + +QT_FORWARD_DECLARE_CLASS(QIODevice) + +namespace QtWebEngineCore { + +class URLRequestCustomJob; +class URLRequestCustomJobDelegate; +class BrowserContextAdapter; + +// Used to comunicate between URLRequestCustomJob living on the IO thread +// and URLRequestCustomJobDelegate living on the UI thread. +class URLRequestCustomJobProxy + : public base::RefCountedThreadSafe<URLRequestCustomJobProxy> { + +public: + URLRequestCustomJobProxy(URLRequestCustomJob *job, + const std::string &scheme, + QWeakPointer<const BrowserContextAdapter> adapter); + ~URLRequestCustomJobProxy(); + + // Called from URLRequestCustomJobDelegate via post: + //void setReplyCharset(const std::string &); + void reply(std::string mimeType, QIODevice *device); + void redirect(GURL url); + void abort(); + void fail(int error); + void release(); + void initialize(GURL url, std::string method, base::Optional<url::Origin> initiatorOrigin); + void readyRead(); + + // IO thread owned: + URLRequestCustomJob *m_job; + bool m_started; + + // UI thread owned: + std::string m_scheme; + URLRequestCustomJobDelegate *m_delegate; + QWeakPointer<const BrowserContextAdapter> m_adapter; +}; + +} // namespace QtWebEngineCore + +#endif // URL_REQUEST_CUSTOM_JOB_PROXY_H_ diff --git a/src/core/net/url_request_qrc_job_qt.cpp b/src/core/net/url_request_qrc_job_qt.cpp new file mode 100644 index 000000000..a2712653d --- /dev/null +++ b/src/core/net/url_request_qrc_job_qt.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** 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 "url_request_qrc_job_qt.h" + +#include "type_conversion.h" + +#include "base/pending_task.h" +#include "base/threading/thread_task_runner_handle.h" +#include "net/base/net_errors.h" +#include "net/base/io_buffer.h" + +#include <QUrl> +#include <QFileInfo> +#include <QMimeDatabase> +#include <QMimeType> + +using namespace net; +namespace QtWebEngineCore { + +URLRequestQrcJobQt::URLRequestQrcJobQt(URLRequest *request, NetworkDelegate *networkDelegate) + : URLRequestJob(request, networkDelegate) + , m_remainingBytes(0) + , m_weakFactory(this) +{ +} + +URLRequestQrcJobQt::~URLRequestQrcJobQt() +{ + if (m_file.isOpen()) + m_file.close(); +} + +void URLRequestQrcJobQt::Start() +{ + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&URLRequestQrcJobQt::startGetHead, m_weakFactory.GetWeakPtr())); +} + +void URLRequestQrcJobQt::Kill() +{ + if (m_file.isOpen()) + m_file.close(); + m_weakFactory.InvalidateWeakPtrs(); + + URLRequestJob::Kill(); +} + +bool URLRequestQrcJobQt::GetMimeType(std::string *mimeType) const +{ + DCHECK(request_); + if (m_mimeType.size() > 0) { + *mimeType = m_mimeType; + return true; + } + return false; +} + +int URLRequestQrcJobQt::ReadRawData(IOBuffer *buf, int bufSize) +{ + DCHECK_GE(m_remainingBytes, 0); + // File has been read finished. + if (!m_remainingBytes || !bufSize) { + return 0; + } + if (m_remainingBytes < bufSize) + bufSize = static_cast<int>(m_remainingBytes); + qint64 rv = m_file.read(buf->data(), bufSize); + if (rv >= 0) { + m_remainingBytes -= rv; + DCHECK_GE(m_remainingBytes, 0); + return static_cast<int>(rv); + } + return static_cast<int>(rv); +} + +void URLRequestQrcJobQt::startGetHead() +{ + // Get qrc file path. + QString qrcFilePath = ':' + toQt(request_->url()).path(); + m_file.setFileName(qrcFilePath); + QFileInfo qrcFileInfo(m_file); + // Get qrc file mime type. + QMimeDatabase mimeDatabase; + QMimeType mimeType = mimeDatabase.mimeTypeForFile(qrcFileInfo); + m_mimeType = mimeType.name().toStdString(); + // Open file + if (m_file.open(QIODevice::ReadOnly)) { + m_remainingBytes = m_file.size(); + set_expected_content_size(m_remainingBytes); + // Notify that the headers are complete + NotifyHeadersComplete(); + } else { + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, ERR_INVALID_URL)); + } +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/url_request_qrc_job_qt.h b/src/core/net/url_request_qrc_job_qt.h new file mode 100644 index 000000000..11c130693 --- /dev/null +++ b/src/core/net/url_request_qrc_job_qt.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef URL_REQUEST_QRC_JOB_QT_H_ +#define URL_REQUEST_QRC_JOB_QT_H_ + +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_job.h" + +#include <QFile> + +namespace QtWebEngineCore { + +// A request job that handles reading qrc file URLs +class URLRequestQrcJobQt : public net::URLRequestJob { + +public: + URLRequestQrcJobQt(net::URLRequest *request, net::NetworkDelegate *networkDelegate); + void Start() override; + void Kill() override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override;; + bool GetMimeType(std::string *mimeType) const override; + +protected: + virtual ~URLRequestQrcJobQt(); + // Get file mime type and try open file on a background thread. + void startGetHead(); + +private: + qint64 m_remainingBytes; + QFile m_file; + std::string m_mimeType; + base::WeakPtrFactory<URLRequestQrcJobQt> m_weakFactory; + + DISALLOW_COPY_AND_ASSIGN(URLRequestQrcJobQt); +}; + +} // namespace QtWebEngineCore + +#endif // URL_REQUEST_QRC_JOB_QT_H_ diff --git a/src/core/net/webui_controller_factory_qt.cpp b/src/core/net/webui_controller_factory_qt.cpp new file mode 100644 index 000000000..3b13f03b8 --- /dev/null +++ b/src/core/net/webui_controller_factory_qt.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +// Based on chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc: +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webui_controller_factory_qt.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/devtools_ui.h" +#include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h" +#include "chrome/browser/ui/webui/task_scheduler_internals/task_scheduler_internals_ui.h" +#include "chrome/common/url_constants.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/common/content_client.h" +#include "content/public/common/url_utils.h" +#include "extensions/features/features.h" +#include "media/media_features.h" +#include "ppapi/features/features.h" +#include "printing/features/features.h" +#include "ui/web_dialogs/web_dialog_ui.h" +#include "url/gurl.h" + +#if defined(OS_LINUX) || defined(OS_ANDROID) +#include "chrome/browser/ui/webui/sandbox_internals_ui.h" +#endif + +// The Following WebUIs are disabled because they currently doesn't build +// or doesn't work, but would be interesting for us if they did: + +// #include "chrome/browser/ui/webui/inspect_ui.h" +// #include "chrome/browser/ui/webui/user_actions/user_actions_ui.h" + +// #if BUILDFLAG(ENABLE_WEBRTC) +// #include "chrome/browser/ui/webui/media/webrtc_logs_ui.h" +// #endif + +// #if BUILDFLAG(ENABLE_PRINT_PREVIEW) +// #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" +// #endif + +// #if defined(USE_NSS_CERTS) && defined(USE_AURA) +// #include "chrome/browser/ui/webui/certificate_viewer_ui.h" +// #endif + +// #if BUILDFLAG(ENABLE_EXTENSIONS) +// #include "chrome/browser/extensions/extension_web_ui.h" +// #include "chrome/browser/ui/webui/extensions/extensions_ui.h" +// #include "chrome/common/extensions/extension_constants.h" +// #include "extensions/browser/extension_registry.h" +// #include "extensions/browser/extension_system.h" +// #include "extensions/common/constants.h" +// #include "extensions/common/extension.h" +// #include "extensions/common/feature_switch.h" +// #include "extensions/common/manifest.h" +// #endif + +using content::WebUI; +using content::WebUIController; + +namespace { + +// A function for creating a new WebUI. The caller owns the return value, which +// may be NULL (for example, if the URL refers to an non-existent extension). +typedef WebUIController* (*WebUIFactoryFunction)(WebUI *web_ui, const GURL &url); + +// Template for defining WebUIFactoryFunction. +template<class T> +WebUIController *NewWebUI(WebUI *web_ui, const GURL &/*url*/) +{ + return new T(web_ui); +} + +// Returns a function that can be used to create the right type of WebUI for a +// tab, based on its URL. Returns NULL if the URL doesn't have WebUI associated +// with it. +WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, const GURL &url) +{ + // This will get called a lot to check all URLs, so do a quick check of other + // schemes to filter out most URLs. + if (!content::HasWebUIScheme(url)) + return NULL; + + // We must compare hosts only since some of the Web UIs append extra stuff + // after the host name. + if (url.host() == chrome::kChromeUIQuotaInternalsHost) + return &NewWebUI<QuotaInternalsUI>; + if (url.host_piece() == chrome::kChromeUITaskSchedulerInternalsHost) + return &NewWebUI<TaskSchedulerInternalsUI>; + + if (url.SchemeIs(content::kChromeDevToolsScheme)) { +// if (!DevToolsUIBindings::IsValidFrontendURL(url)) +// return nullptr; + return &NewWebUI<DevToolsUI>; + } + +// if (url.host_piece() == chrome::kChromeUIUserActionsHost) +// return &NewWebUI<UserActionsUI>; +// if (url.host_piece() == chrome::kChromeUIInspectHost) +// return &NewWebUI<InspectUI>; +// +//#if defined(USE_NSS_CERTS) && defined(USE_AURA) +// if (url.host_piece() == chrome::kChromeUICertificateViewerHost) +// return &NewWebUI<CertificateViewerUI>; +//#endif // USE_NSS_CERTS && USE_AURA +//#if BUILDFLAG(ENABLE_EXTENSIONS) +// if (url.host_piece() == chrome::kChromeUIExtensionsFrameHost) +// return &NewWebUI<extensions::ExtensionsUI>; +//#endif +//#if BUILDFLAG(ENABLE_PLUGINS) +// if (url.host_piece() == chrome::kChromeUIFlashHost) +// return &NewWebUI<FlashUI>; +//#endif +//#if BUILDFLAG(ENABLE_PRINT_PREVIEW) +// if (url.host_piece() == chrome::kChromeUIPrintHost && +// !profile->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled)) { +// return &NewWebUI<PrintPreviewUI>; +// } +//#endif +//#if BUILDFLAG(ENABLE_WEBRTC) +// if (url.host_piece() == chrome::kChromeUIWebRtcLogsHost) +// return &NewWebUI<WebRtcLogsUI>; +//#endif +#if defined(OS_LINUX) || defined(OS_ANDROID) + if (url.host_piece() == chrome::kChromeUISandboxHost) + return &NewWebUI<SandboxInternalsUI>; +#endif + return nullptr; +} + +} // namespace + +namespace QtWebEngineCore { + +WebUI::TypeID WebUIControllerFactoryQt::GetWebUIType(content::BrowserContext *browser_context, const GURL &url) const +{ + Profile *profile = Profile::FromBrowserContext(browser_context); + WebUIFactoryFunction function = GetWebUIFactoryFunction(nullptr, profile, url); + return function ? reinterpret_cast<WebUI::TypeID>(function) : WebUI::kNoWebUI; +} + +bool WebUIControllerFactoryQt::UseWebUIForURL(content::BrowserContext *browser_context, const GURL &url) const +{ + return GetWebUIType(browser_context, url) != WebUI::kNoWebUI; +} + +bool WebUIControllerFactoryQt::UseWebUIBindingsForURL(content::BrowserContext *browser_context, const GURL &url) const +{ + return UseWebUIForURL(browser_context, url); +} + +WebUIController *WebUIControllerFactoryQt::CreateWebUIControllerForURL(WebUI *web_ui, const GURL &url) const +{ + Profile *profile = Profile::FromWebUI(web_ui); + WebUIFactoryFunction function = GetWebUIFactoryFunction(web_ui, profile, url); + if (!function) + return nullptr; + + return (*function)(web_ui, url); +} + +// static +WebUIControllerFactoryQt *WebUIControllerFactoryQt::GetInstance() +{ + return base::Singleton<WebUIControllerFactoryQt>::get(); +} + +WebUIControllerFactoryQt::WebUIControllerFactoryQt() +{ +} + +WebUIControllerFactoryQt::~WebUIControllerFactoryQt() +{ +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/webui_controller_factory_qt.h b/src/core/net/webui_controller_factory_qt.h new file mode 100644 index 000000000..440dd5a13 --- /dev/null +++ b/src/core/net/webui_controller_factory_qt.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +#ifndef WEB_UI_CONTROLLER_FACTORY_QT_H_ +#define WEB_UI_CONTROLLER_FACTORY_QT_H_ + +#include "base/macros.h" +#include "base/memory/singleton.h" +#include "components/favicon_base/favicon_callback.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_controller_factory.h" +#include "ui/base/layout.h" + +class Profile; + +namespace base { +class RefCountedMemory; +} + +namespace QtWebEngineCore { + +class WebUIControllerFactoryQt : public content::WebUIControllerFactory { +public: + content::WebUI::TypeID GetWebUIType(content::BrowserContext *browserContext, const GURL &url) const override; + bool UseWebUIForURL(content::BrowserContext *browserContext, const GURL &url) const override; + bool UseWebUIBindingsForURL(content::BrowserContext *browserContext, const GURL &url) const override; + content::WebUIController *CreateWebUIControllerForURL(content::WebUI *webUi, const GURL &url) const override; + + static WebUIControllerFactoryQt *GetInstance(); + +protected: + WebUIControllerFactoryQt(); + ~WebUIControllerFactoryQt() override; + +private: + friend struct base::DefaultSingletonTraits<WebUIControllerFactoryQt>; + + DISALLOW_COPY_AND_ASSIGN(WebUIControllerFactoryQt); +}; + +} // namespace QtWebEngineCore + +#endif // WEB_UI_CONTROLLER_FACTORY_QT_H_ |