diff options
Diffstat (limited to 'src/core/net')
35 files changed, 972 insertions, 2409 deletions
diff --git a/src/core/net/client_cert_override.cpp b/src/core/net/client_cert_override.cpp index afb7ab5af..d768092e8 100644 --- a/src/core/net/client_cert_override.cpp +++ b/src/core/net/client_cert_override.cpp @@ -65,7 +65,7 @@ #include "net/ssl/client_cert_store_win.h" #endif -#if defined(OS_MACOSX) +#if defined(OS_MAC) #include "net/ssl/client_cert_store_mac.h" #endif @@ -83,7 +83,7 @@ public: std::move(private_key_callback).Run(m_key); } -#if defined(OS_MACOSX) +#if defined(OS_MAC) SecIdentityRef sec_identity_ref() const override { return nullptr; @@ -142,7 +142,7 @@ void ClientCertOverrideStore::GetClientCerts(const net::SSLCertRequestInfo &cert { #if QT_CONFIG(ssl) // Access the user-provided data from the UI thread, but return on whatever thread this is. - if (base::PostTaskWithTraitsAndReplyWithResult( + if (base::PostTaskAndReplyWithResult( FROM_HERE, { content::BrowserThread::UI }, base::BindOnce(&ClientCertOverrideStore::GetClientCertsOnUIThread, base::Unretained(this), std::cref(cert_request_info)), @@ -167,7 +167,7 @@ std::unique_ptr<net::ClientCertStore> ClientCertOverrideStore::createNativeStore return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(net::ClientCertStoreNSS::PasswordDelegateFactory())); #elif defined(OS_WIN) return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin()); -#elif defined(OS_MACOSX) +#elif defined(OS_MAC) return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac()); #else return nullptr; diff --git a/src/core/net/client_cert_store_data.cpp b/src/core/net/client_cert_store_data.cpp index 314e64145..a96e247b2 100644 --- a/src/core/net/client_cert_store_data.cpp +++ b/src/core/net/client_cert_store_data.cpp @@ -104,8 +104,8 @@ public: std::vector<uint16_t> GetAlgorithmPreferences() override { - return { SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA512 - , SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA256 }; + return net::SSLPrivateKey::DefaultAlgorithmPreferences(EVP_PKEY_id(m_key), + /* supports pss */ true); } std::string GetProviderName() override { return "qtwebengine"; diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp index e0fa60be7..6d72a622b 100644 --- a/src/core/net/cookie_monster_delegate_qt.cpp +++ b/src/core/net/cookie_monster_delegate_qt.cpp @@ -61,10 +61,9 @@ public: ~CookieChangeListener() override = default; // network::mojom::CookieChangeListener: - void OnCookieChange(const net::CanonicalCookie &canonical_cookie, - network::mojom::CookieChangeCause cause) override + void OnCookieChange(const net::CookieChangeInfo &change) override { - m_delegate->OnCookieChanged(canonical_cookie, net::CookieChangeCause(cause)); + m_delegate->OnCookieChanged(change); } private: @@ -73,6 +72,25 @@ private: DISALLOW_COPY_AND_ASSIGN(CookieChangeListener); }; +class CookieAccessFilter : public network::mojom::CookieRemoteAccessFilter +{ +public: + CookieAccessFilter(CookieMonsterDelegateQt *delegate) : m_delegate(delegate) { } + ~CookieAccessFilter() override = default; + + void AllowedAccess(const GURL &url, const net::SiteForCookies &site_for_cookies, AllowedAccessCallback callback) override + { + bool allow = m_delegate->canGetCookies(toQt(site_for_cookies.first_party_url()), toQt(url)); + std::move(callback).Run(allow); + } + +private: + CookieMonsterDelegateQt *m_delegate; + + DISALLOW_COPY_AND_ASSIGN(CookieAccessFilter); +}; + + static GURL sourceUrlForCookie(const QNetworkCookie &cookie) { QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path()); @@ -80,50 +98,37 @@ static GURL sourceUrlForCookie(const QNetworkCookie &cookie) } CookieMonsterDelegateQt::CookieMonsterDelegateQt() - : m_client(0) - , m_cookieMonster(nullptr) + : m_client(nullptr) , m_listener(new CookieChangeListener(this)) - , m_binding(m_listener.get()) + , m_filter(new CookieAccessFilter(this)) + , m_receiver(m_listener.get()) + , m_filterReceiver(m_filter.get()) + , m_hasFilter(false) { } CookieMonsterDelegateQt::~CookieMonsterDelegateQt() { - } void CookieMonsterDelegateQt::AddStore(net::CookieStore *store) { std::unique_ptr<net::CookieChangeSubscription> sub = store->GetChangeDispatcher().AddCallbackForAllChanges( - base::Bind(&CookieMonsterDelegateQt::OnCookieChanged, - // this object's destruction will deregister the subscription. - base::Unretained(this))); + base::BindRepeating(&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 || m_mojoCookieManager.is_bound(); + return m_mojoCookieManager.is_bound(); } void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId) { - if (m_mojoCookieManager.is_bound()) { - m_mojoCookieManager->GetAllCookies(base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId)); - } else { - net::CookieMonster::GetCookieListCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, std::move(callback))); - } -} - -void CookieMonsterDelegateQt::GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_cookieMonster) - m_cookieMonster->GetAllCookiesAsync(std::move(callback)); + m_mojoCookieManager->GetAllCookies(base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId)); } void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin) @@ -136,31 +141,18 @@ void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); std::string cookie_line = cookie.toRawForm().toStdString(); - if (m_mojoCookieManager.is_bound()) { - if (callbackId != CallbackDirectory::NoCallbackId) - callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId); - net::CookieOptions options; - options.set_include_httponly(); - auto cookie = net::CanonicalCookie::Create(gurl, cookie_line, base::Time::Now(), options); - m_mojoCookieManager->SetCanonicalCookie(*cookie.get(), gurl.scheme(), options, std::move(callback)); - } else { - if (callbackId != CallbackDirectory::NoCallbackId) - callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::SetCookieOnIOThread, this, - gurl, std::move(cookie_line), std::move(callback))); + if (callbackId != CallbackDirectory::NoCallbackId) + callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId); + net::CookieInclusionStatus inclusion; + auto canonCookie = net::CanonicalCookie::Create(gurl, cookie_line, base::Time::Now(), base::nullopt, &inclusion); + if (!inclusion.IsInclude()) { + LOG(WARNING) << "QWebEngineCookieStore::setCookie() - Tried to set invalid cookie"; + return; } -} - -void CookieMonsterDelegateQt::SetCookieOnIOThread(const GURL &url, const std::string &cookie_line, - net::CookieMonster::SetCookiesCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); net::CookieOptions options; options.set_include_httponly(); - - if (m_cookieMonster) - m_cookieMonster->SetCookieWithOptionsAsync(url, cookie_line, options, std::move(callback)); + options.set_same_site_cookie_context(net::CookieOptions::SameSiteCookieContext::MakeInclusiveForSet()); + m_mojoCookieManager->SetCanonicalCookie(*canonCookie.get(), gurl, options, std::move(callback)); } void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin) @@ -170,69 +162,22 @@ void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const Q GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); std::string cookie_name = cookie.name().toStdString(); - if (m_mojoCookieManager.is_bound()) { - auto filter = network::mojom::CookieDeletionFilter::New(); - filter->url = gurl; - filter->cookie_name = cookie_name; - m_mojoCookieManager->DeleteCookies(std::move(filter), network::mojom::CookieManager::DeleteCookiesCallback()); - } else { - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this, - gurl, cookie_name)); - } -} - -void CookieMonsterDelegateQt::DeleteCookieOnIOThread(const GURL &url, const std::string &cookie_name) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_cookieMonster) { - net::CookieMonster::GetCookieListCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::GetCookiesToDeleteCallback, this, cookie_name); - m_cookieMonster->GetAllCookiesForURLAsync(url, std::move(callback)); - } + auto filter = network::mojom::CookieDeletionFilter::New(); + filter->url = gurl; + filter->cookie_name = cookie_name; + m_mojoCookieManager->DeleteCookies(std::move(filter), network::mojom::CookieManager::DeleteCookiesCallback()); } -void CookieMonsterDelegateQt::GetCookiesToDeleteCallback(const std::string &cookie_name, const net::CookieList &cookies, - const net::CookieStatusList &statusList) -{ - Q_UNUSED(statusList); - if (!m_cookieMonster) - return; - - net::CookieList cookiesToDelete; - for (auto cookie : cookies) { - if (cookie.Name() == cookie_name) - cookiesToDelete.push_back(cookie); - } - for (auto cookie : cookiesToDelete) - m_cookieMonster->DeleteCanonicalCookieAsync(cookie, base::DoNothing()); -} - - void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId) { Q_ASSERT(hasCookieMonster()); Q_ASSERT(m_client); - if (m_mojoCookieManager.is_bound()) { - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); - auto filter = network::mojom::CookieDeletionFilter::New(); - filter->session_control = network::mojom::CookieDeletionSessionControl::SESSION_COOKIES; - m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); - } else { - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, std::move(callback))); - } -} - -void CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_cookieMonster) - m_cookieMonster->DeleteSessionCookiesAsync(std::move(callback)); + network::mojom::CookieManager::DeleteCookiesCallback callback = + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); + auto filter = network::mojom::CookieDeletionFilter::New(); + filter->session_control = network::mojom::CookieDeletionSessionControl::SESSION_COOKIES; + m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); } void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) @@ -240,63 +185,48 @@ void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) Q_ASSERT(hasCookieMonster()); Q_ASSERT(m_client); - if (m_mojoCookieManager.is_bound()) { - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); - auto filter = network::mojom::CookieDeletionFilter::New(); - m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); - } else { - net::CookieMonster::DeleteCallback callback = - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, std::move(callback))); - } -} - -void CookieMonsterDelegateQt::DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (m_cookieMonster) - m_cookieMonster->DeleteAllAsync(std::move(callback)); + network::mojom::CookieManager::DeleteCookiesCallback callback = + base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId); + auto filter = network::mojom::CookieDeletionFilter::New(); + m_mojoCookieManager->DeleteCookies(std::move(filter), std::move(callback)); } -void CookieMonsterDelegateQt::setCookieMonster(net::CookieMonster *monster) +void CookieMonsterDelegateQt::setMojoCookieManager(network::mojom::CookieManagerPtrInfo cookie_manager_info) { - if (monster == m_cookieMonster) - return; + if (m_mojoCookieManager.is_bound()) + unsetMojoCookieManager(); - m_subscriptions.clear(); - if (monster) - AddStore(monster); + Q_ASSERT(!m_mojoCookieManager.is_bound()); + Q_ASSERT(!m_receiver.is_bound()); - m_cookieMonster = monster; + m_mojoCookieManager.Bind(std::move(cookie_manager_info)); - if (!m_client) - return; + m_mojoCookieManager->AddGlobalChangeListener(m_receiver.BindNewPipeAndPassRemote()); + if (m_hasFilter) + m_mojoCookieManager->SetRemoteFilter(m_filterReceiver.BindNewPipeAndPassRemote()); - if (monster) + if (m_client) m_client->d_func()->processPendingUserCookies(); - else - m_client->d_func()->rejectPendingUserCookies(); } -void CookieMonsterDelegateQt::setMojoCookieManager(network::mojom::CookieManagerPtrInfo cookie_manager_info) +void CookieMonsterDelegateQt::setHasFilter(bool hasFilter) { -// DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - m_mojoCookieManager.Bind(std::move(cookie_manager_info)); - - network::mojom::CookieChangeListenerPtr listener_ptr; - m_binding.Bind(mojo::MakeRequest(&listener_ptr)); - - m_mojoCookieManager->AddGlobalChangeListener(std::move(listener_ptr)); - - if (m_client) - m_client->d_func()->processPendingUserCookies(); + m_hasFilter = hasFilter; + if (!m_mojoCookieManager.is_bound()) + return; + if (m_hasFilter) { + if (!m_filterReceiver.is_bound()) + m_mojoCookieManager->SetRemoteFilter(m_filterReceiver.BindNewPipeAndPassRemote()); + } else { + if (m_filterReceiver.is_bound()) + m_filterReceiver.reset(); + } } void CookieMonsterDelegateQt::unsetMojoCookieManager() { - m_binding.Close(); + m_receiver.reset(); + m_filterReceiver.reset(); m_mojoCookieManager.reset(); } @@ -329,62 +259,24 @@ bool CookieMonsterDelegateQt::canGetCookies(const QUrl &firstPartyUrl, const QUr return m_client->d_func()->canAccessCookies(firstPartyUrl, url); } -void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie &cookie, net::CookieChangeCause cause) +void CookieMonsterDelegateQt::OnCookieChanged(const net::CookieChangeInfo &change) { if (!m_client) return; - m_client->d_func()->onCookieChanged(toQt(cookie), cause != net::CookieChangeCause::INSERTED); -} - -void CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread(qint64 callbackId, const net::CookieList &cookies, const net::CookieStatusList &statusList) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - QByteArray rawCookies; - for (auto &&cookie : cookies) - rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n"); - - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesResultOnUIThread, this, callbackId, rawCookies)); + m_client->d_func()->onCookieChanged(toQt(change.cookie), change.cause != net::CookieChangeCause::INSERTED); } -void CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread(qint64 callbackId, const std::vector<net::CanonicalCookie> &cookies) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - QByteArray rawCookies; - for (auto &&cookie : cookies) - rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n"); - - GetAllCookiesResultOnUIThread(callbackId, rawCookies); -} - -void CookieMonsterDelegateQt::SetCookieCallbackOnIOThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId, status)); -} - -void CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId, numCookies)); -} - -void CookieMonsterDelegateQt::GetAllCookiesResultOnUIThread(qint64 callbackId, const QByteArray &cookies) +void CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread(qint64 callbackId, const net::CookieList &cookies) { + QByteArray rawCookies = QByteArray::fromStdString(net::CanonicalCookie::BuildCookieLine(cookies)); if (m_client) - m_client->d_func()->onGetAllCallbackResult(callbackId, cookies); + m_client->d_func()->onGetAllCallbackResult(callbackId, rawCookies); } -void CookieMonsterDelegateQt::SetCookieCallbackOnUIThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status) +void CookieMonsterDelegateQt::SetCookieCallbackOnUIThread(qint64 callbackId, net::CookieAccessResult status) { if (m_client) - m_client->d_func()->onSetCallbackResult(callbackId, - status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE); + m_client->d_func()->onSetCallbackResult(callbackId, status.status.IsInclude()); } void CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread(qint64 callbackId, uint numCookies) @@ -392,4 +284,5 @@ void CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread(qint64 callbackId, if (m_client) m_client->d_func()->onDeleteCallbackResult(callbackId, numCookies); } -} + +} // namespace QtWebEngineCore diff --git a/src/core/net/cookie_monster_delegate_qt.h b/src/core/net/cookie_monster_delegate_qt.h index 02c84e061..fe1ed5be6 100644 --- a/src/core/net/cookie_monster_delegate_qt.h +++ b/src/core/net/cookie_monster_delegate_qt.h @@ -64,8 +64,9 @@ QT_WARNING_DISABLE_CLANG("-Wunused-parameter") #undef signals #endif #include "base/memory/ref_counted.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "net/cookies/cookie_monster.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "net/cookies/cookie_change_dispatcher.h" +#include "net/cookies/cookie_store.h" #include "services/network/public/mojom/cookie_manager.mojom-forward.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #ifdef StAsH_signals @@ -81,23 +82,19 @@ 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 CookieMonsterDelegateQtPrivate; class Q_WEBENGINECORE_PRIVATE_EXPORT CookieMonsterDelegateQt : public base::RefCountedThreadSafe<CookieMonsterDelegateQt> { QPointer<QWebEngineCookieStore> m_client; - net::CookieMonster *m_cookieMonster; std::vector<std::unique_ptr<net::CookieChangeSubscription>> m_subscriptions; network::mojom::CookieManagerPtr m_mojoCookieManager; std::unique_ptr<network::mojom::CookieChangeListener> m_listener; - mojo::Binding<network::mojom::CookieChangeListener> m_binding; + std::unique_ptr<network::mojom::CookieRemoteAccessFilter> m_filter; + mojo::Receiver<network::mojom::CookieChangeListener> m_receiver; + mojo::Receiver<network::mojom::CookieRemoteAccessFilter> m_filterReceiver; + bool m_hasFilter; public: CookieMonsterDelegateQt(); ~CookieMonsterDelegateQt(); @@ -110,35 +107,20 @@ public: void deleteSessionCookies(quint64 callbackId); void deleteAllCookies(quint64 callbackId); - void setCookieMonster(net::CookieMonster *monster); void setClient(QWebEngineCookieStore *client); void setMojoCookieManager(network::mojom::CookieManagerPtrInfo cookie_manager_info); void unsetMojoCookieManager(); + void setHasFilter(bool b); bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const; bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const; void AddStore(net::CookieStore *store); - void OnCookieChanged(const net::CanonicalCookie &cookie, net::CookieChangeCause cause); + void OnCookieChanged(const net::CookieChangeInfo &change); 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); - - void GetCookiesToDeleteCallback(const std::string &cookie_name, const net::CookieList &cookies, - const net::CookieStatusList &statusList); - void GetAllCookiesCallbackOnIOThread(qint64 callbackId, const net::CookieList &cookies, - const net::CookieStatusList &statusList); - void SetCookieCallbackOnIOThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status); - void DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies); - - void GetAllCookiesCallbackOnUIThread(qint64 callbackId, const std::vector<net::CanonicalCookie> &cookies); - void GetAllCookiesResultOnUIThread(qint64 callbackId, const QByteArray &cookies); - void SetCookieCallbackOnUIThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status); + void GetAllCookiesCallbackOnUIThread(qint64 callbackId, const net::CookieList &cookies); + void SetCookieCallbackOnUIThread(qint64 callbackId, net::CookieAccessResult status); void DeleteCookiesCallbackOnUIThread(qint64 callbackId, uint numCookies); }; diff --git a/src/core/net/custom_protocol_handler.cpp b/src/core/net/custom_protocol_handler.cpp deleted file mode 100644 index 7e8ee47ab..000000000 --- a/src/core/net/custom_protocol_handler.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** 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(QPointer<ProfileAdapter> profileAdapter) - : m_profileAdapter(profileAdapter) -{ -} - -net::URLRequestJob *CustomProtocolHandler::MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const -{ - if (!networkDelegate) - return new net::URLRequestErrorJob(request, nullptr, net::ERR_ACCESS_DENIED); - - return new URLRequestCustomJob(request, networkDelegate, request->url().scheme(), m_profileAdapter); -} - -} // namespace diff --git a/src/core/net/custom_protocol_handler.h b/src/core/net/custom_protocol_handler.h deleted file mode 100644 index 625afc1d5..000000000 --- a/src/core/net/custom_protocol_handler.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef CUSTOM_PROTOCOL_HANDLER_H_ -#define CUSTOM_PROTOCOL_HANDLER_H_ - -#include "qtwebenginecoreglobal_p.h" -#include "net/url_request/url_request_job_factory.h" - -#include <QtCore/QByteArray> -#include <QtCore/QObject> -#include <QtCore/QPointer> - -QT_FORWARD_DECLARE_CLASS(QIODevice) - -namespace net { -class NetworkDelegate; -class URLRequestJob; -} // namespace - -namespace QtWebEngineCore { - -class ProfileAdapter; - -// Implements a ProtocolHandler for custom URL schemes. -// If |network_delegate_| is NULL then all file requests will fail with ERR_ACCESS_DENIED. -class Q_WEBENGINECORE_PRIVATE_EXPORT CustomProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler -{ - -public: - CustomProtocolHandler(QPointer<ProfileAdapter> profileAdapter); - - net::URLRequestJob *MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const override; - -private: - DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); - QPointer<ProfileAdapter> m_profileAdapter; -}; - -} // namespace - -#endif // CUSTOM_PROTOCOL_HANDLER_H_ diff --git a/src/core/net/custom_url_loader_factory.cpp b/src/core/net/custom_url_loader_factory.cpp index a9e7e1c34..c7426a5b9 100644 --- a/src/core/net/custom_url_loader_factory.cpp +++ b/src/core/net/custom_url_loader_factory.cpp @@ -43,14 +43,18 @@ #include "base/task/post_task.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/system/data_pipe.h" -#include "mojo/public/cpp/system/data_pipe_producer.h" +#include "mojo/public/cpp/system/simple_watcher.h" #include "net/base/net_errors.h" #include "net/http/http_status_code.h" #include "net/http/http_util.h" +#include "services/network/public/cpp/cors/cors.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" +#include "services/network/public/mojom/url_response_head.mojom.h" #include "api/qwebengineurlscheme.h" #include "net/url_request_custom_job_proxy.h" @@ -87,27 +91,29 @@ public: // network::mojom::URLLoader: void FollowRedirect(const std::vector<std::string> &removed_headers, const net::HttpRequestHeaders &modified_headers, + const net::HttpRequestHeaders &modified_cors_exempt_headers, // FIXME: do something with this? const base::Optional<GURL> &new_url) override { // We can be asked for follow our own redirect scoped_refptr<URLRequestCustomJobProxy> proxy = new URLRequestCustomJobProxy(this, m_proxy->m_scheme, m_proxy->m_profileAdapter); m_proxy->m_client = nullptr; // m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); - base::PostTaskWithTraits(FROM_HERE, { content::BrowserThread::UI }, - base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); + base::PostTask(FROM_HERE, { content::BrowserThread::UI }, + base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); m_proxy = std::move(proxy); if (new_url) m_request.url = *new_url; else m_request.url = m_redirect; - // ### remove and modify headers? m_redirect = GURL(); + for (const std::string &header: removed_headers) + m_request.headers.RemoveHeader(header); + m_request.headers.MergeFrom(modified_headers); Start(); } void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override { } void PauseReadingBodyFromNet() override { } void ResumeReadingBodyFromNet() override { } - void ProceedWithResponse() override { } private: CustomURLLoader(const network::ResourceRequest &request, @@ -121,8 +127,10 @@ private: , m_client(std::move(client_info)) , m_request(request) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); m_binding.set_connection_error_handler( - base::BindOnce(&CustomURLLoader::OnConnectionError, base::Unretained(this))); + base::BindOnce(&CustomURLLoader::OnConnectionError, m_weakPtrFactory.GetWeakPtr())); + m_firstBytePosition = 0; m_device = nullptr; m_error = 0; QWebEngineUrlScheme scheme = QWebEngineUrlScheme::schemeByName(QByteArray::fromStdString(request.url.scheme())); @@ -133,7 +141,20 @@ private: void Start() { - m_head.request_start = base::TimeTicks::Now(); + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + + if (network::cors::IsCorsEnabledRequestMode(m_request.mode)) { + // CORS mode requires a valid request_initiator. + if (!m_request.request_initiator) + return CompleteWithFailure(net::ERR_INVALID_ARGUMENT); + + // Custom schemes are not covered by CorsURLLoader, so we need to reject CORS requests manually. + if (!m_corsEnabled && !m_request.request_initiator->IsSameOriginWith(url::Origin::Create(m_request.url))) + return CompleteWithFailure(network::CorsErrorStatus(network::mojom::CorsError::kCorsDisabledScheme)); + } + + m_head = network::mojom::URLResponseHead::New(); + m_head->request_start = base::TimeTicks::Now(); if (!m_pipe.consumer_handle.is_valid()) return CompleteWithFailure(net::ERR_FAILED); @@ -145,20 +166,33 @@ private: if (!m_request.referrer.is_empty()) headers.emplace("Referer", m_request.referrer.spec()); + std::string rangeHeader; + if (ParseRange(m_request.headers)) + m_firstBytePosition = m_byteRange.first_byte_position(); + // m_taskRunner->PostTask(FROM_HERE, - base::PostTaskWithTraits(FROM_HERE, { content::BrowserThread::UI }, - base::BindOnce(&URLRequestCustomJobProxy::initialize, m_proxy, - m_request.url, m_request.method, m_request.request_initiator, std::move(headers))); + base::PostTask(FROM_HERE, { content::BrowserThread::UI }, + base::BindOnce(&URLRequestCustomJobProxy::initialize, m_proxy, + m_request.url, m_request.method, m_request.request_initiator, std::move(headers))); + } + + void CompleteWithFailure(network::CorsErrorStatus cors_error) + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_client->OnComplete(network::URLLoaderCompletionStatus(cors_error)); + ClearProxyAndClient(false); } void CompleteWithFailure(net::Error net_error) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); m_client->OnComplete(network::URLLoaderCompletionStatus(net_error)); ClearProxyAndClient(false); } void OnConnectionError() { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); m_binding.Close(); if (m_client.is_bound()) ClearProxyAndClient(false); @@ -168,9 +202,10 @@ private: void OnTransferComplete(MojoResult result) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); if (result == MOJO_RESULT_OK) { network::URLLoaderCompletionStatus status(net::OK); - status.encoded_data_length = m_totalBytesRead + m_head.headers->raw_headers().length(); + status.encoded_data_length = m_totalBytesRead + m_headerBytesRead; status.encoded_body_length = m_totalBytesRead; status.decoded_body_length = m_totalBytesRead; m_client->OnComplete(status); @@ -182,14 +217,15 @@ private: void ClearProxyAndClient(bool wait_for_loader_error = false) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); m_proxy->m_client = nullptr; m_client.reset(); if (m_device && m_device->isOpen()) m_device->close(); m_device = nullptr; // m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); - base::PostTaskWithTraits(FROM_HERE, { content::BrowserThread::UI }, - base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); + base::PostTask(FROM_HERE, { content::BrowserThread::UI }, + base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); if (!wait_for_loader_error || !m_binding.is_bound()) delete this; } @@ -197,26 +233,44 @@ private: // URLRequestCustomJobProxy::Client: void notifyExpectedContentSize(qint64 size) override { - m_head.content_length = size; + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_totalSize = size; + if (m_byteRange.IsValid()) { + if (!m_byteRange.ComputeBounds(size)) { + CompleteWithFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); + } else { + m_maxBytesToRead = m_byteRange.last_byte_position() - m_byteRange.first_byte_position() + 1; + m_head->content_length = m_maxBytesToRead; + } + } else { + m_head->content_length = size; + } } void notifyHeadersComplete() override { - m_taskRunner->PostTask(FROM_HERE, - base::BindOnce(&CustomURLLoader::reportHeadersComplete, base::Unretained(this))); - } - void reportHeadersComplete() - { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); DCHECK(!m_error); - m_head.response_start = base::TimeTicks::Now(); + m_head->response_start = base::TimeTicks::Now(); std::string headers; if (!m_redirect.is_empty()) { headers += "HTTP/1.1 303 See Other\n"; headers += base::StringPrintf("Location: %s\n", m_redirect.spec().c_str()); } else { - headers += "HTTP/1.1 200 OK\n"; + if (m_byteRange.IsValid() && m_totalSize > 0) { + headers += "HTTP/1.1 206 Partial Content\n"; + headers += net::HttpResponseHeaders::kContentRange; + headers += base::StringPrintf(": bytes %lld-%lld/%lld", + qlonglong{m_byteRange.first_byte_position()}, + qlonglong{m_byteRange.last_byte_position()}, + qlonglong{m_totalSize}); + headers += "\n"; + } else { + headers += "HTTP/1.1 200 OK\n"; + } if (m_mimeType.size() > 0) { - headers += base::StringPrintf("Content-Type: %s", m_mimeType.c_str()); + headers += net::HttpRequestHeaders::kContentType; + headers += base::StringPrintf(": %s", m_mimeType.c_str()); if (m_charset.size() > 0) headers += base::StringPrintf("; charset=%s", m_charset.c_str()); headers += "\n"; @@ -229,43 +283,56 @@ private: headers += "Access-Control-Allow-Credentials: true\n"; } } - m_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); - m_head.encoded_data_length = m_head.headers->raw_headers().length(); + m_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); + m_head->encoded_data_length = m_head->headers->raw_headers().length(); if (!m_redirect.is_empty()) { - m_head.content_length = m_head.encoded_body_length = -1; - net::URLRequest::FirstPartyURLPolicy first_party_url_policy = - m_request.update_first_party_url_on_redirect ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT - : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; + m_head->content_length = m_head->encoded_body_length = -1; + net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy = + m_request.update_first_party_url_on_redirect ? net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT + : net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL; net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo( m_request.method, m_request.url, - m_request.site_for_cookies, m_request.top_frame_origin, + m_request.site_for_cookies, first_party_url_policy, m_request.referrer_policy, m_request.referrer.spec(), net::HTTP_SEE_OTHER, m_redirect, base::nullopt, false /*insecure_scheme_was_upgraded*/); - m_client->OnReceiveRedirect(redirectInfo, m_head); + m_client->OnReceiveRedirect(redirectInfo, std::move(m_head)); + m_head = nullptr; // ### should m_request be updated with RedirectInfo? (see FollowRedirect) return; } DCHECK(m_device); - m_head.mime_type = m_mimeType; - m_head.charset = m_charset; - m_client->OnReceiveResponse(m_head); + m_head->mime_type = m_mimeType; + m_head->charset = m_charset; + m_headerBytesRead = m_head->headers->raw_headers().length(); + m_client->OnReceiveResponse(std::move(m_head)); m_client->OnStartLoadingResponseBody(std::move(m_pipe.consumer_handle)); + m_head = nullptr; - readAvailableData(); + m_watcher = std::make_unique<mojo::SimpleWatcher>( + FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL, m_taskRunner); + m_watcher->Watch(m_pipe.producer_handle.get(), MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_WATCH_CONDITION_SATISFIED, + base::BindRepeating(&CustomURLLoader::notifyReadyWrite, + m_weakPtrFactory.GetWeakPtr())); + + readAvailableData(); // May delete this } void notifyCanceled() override { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); OnTransferComplete(MOJO_RESULT_CANCELLED); } void notifyAborted() override { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); notifyStartFailure(net::ERR_ABORTED); } void notifyStartFailure(int error) override { - m_head.response_start = base::TimeTicks::Now(); + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + m_head->response_start = base::TimeTicks::Now(); std::string headers; switch (error) { case net::ERR_INVALID_URL: @@ -287,83 +354,128 @@ private: headers = "HTTP/1.1 500 Internal Error\n"; break; } - m_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); - m_head.encoded_data_length = m_head.headers->raw_headers().length(); - m_head.content_length = m_head.encoded_body_length = -1; - m_client->OnReceiveResponse(m_head); + m_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers)); + m_head->encoded_data_length = m_head->headers->raw_headers().length(); + m_head->content_length = m_head->encoded_body_length = -1; + m_client->OnReceiveResponse(std::move(m_head)); CompleteWithFailure(net::Error(error)); } void notifyReadyRead() override { - m_taskRunner->PostTask(FROM_HERE, - base::BindOnce(&CustomURLLoader::readAvailableData, base::Unretained(this))); + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + readAvailableData(); } - void readAvailableData() + void notifyReadyWrite(MojoResult result, const mojo::HandleSignalsState &state) { - if (m_error) { - CompleteWithFailure(net::Error(m_error)); - return; - } - if (!m_device) { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + if (result != MOJO_RESULT_OK) { CompleteWithFailure(net::ERR_FAILED); return; } - char buffer[2048]; - do { - int read_size = m_device->read(buffer, 2048); - if (m_error) { - CompleteWithFailure(net::Error(m_error)); - return; + readAvailableData(); + } + bool readAvailableData() + { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); + for (;;) { + if (m_error || !m_device) + break; + + void *buffer = nullptr; + uint32_t bufferSize = 0; + MojoResult beginResult = m_pipe.producer_handle->BeginWriteData( + &buffer, &bufferSize, MOJO_BEGIN_WRITE_DATA_FLAG_NONE); + if (beginResult == MOJO_RESULT_SHOULD_WAIT) { + m_watcher->ArmOrNotify(); + return false; // Wait for pipe watcher } - if (read_size > 0) { - uint32_t read_bytes = read_size; - m_pipe.producer_handle->WriteData(buffer, &read_bytes, MOJO_WRITE_DATA_FLAG_NONE); - m_totalBytesRead += read_bytes; - } else if (read_size < 0 && !m_device->atEnd()) { - CompleteWithFailure(net::ERR_FAILED); - return; + if (beginResult != MOJO_RESULT_OK) + break; + if (m_maxBytesToRead > 0 && m_maxBytesToRead <= int64_t{std::numeric_limits<uint32_t>::max()}) + bufferSize = std::min(bufferSize, uint32_t(m_maxBytesToRead)); + + int readResult = m_device->read(static_cast<char *>(buffer), bufferSize); + uint32_t bytesRead = std::max(readResult, 0); + m_pipe.producer_handle->EndWriteData(bytesRead); + m_totalBytesRead += bytesRead; + m_client->OnTransferSizeUpdated(m_totalBytesRead); + + if (m_device->atEnd() || (m_maxBytesToRead > 0 && m_totalBytesRead >= m_maxBytesToRead)) { + OnTransferComplete(MOJO_RESULT_OK); + return true; // Done with reading + } + + if (readResult == 0) + return false; // Wait for readyRead + if (readResult < 0) + break; + } + + CompleteWithFailure(m_error ? net::Error(m_error) : net::ERR_FAILED); + return true; // Done with reading + } + bool ParseRange(const net::HttpRequestHeaders &headers) + { + std::string range_header; + if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { + std::vector<net::HttpByteRange> ranges; + if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { + // Chromium doesn't support multirange requests. + if (ranges.size() == 1) { + m_byteRange = ranges[0]; + return true; + } } - } while (m_device->bytesAvailable()); - m_client->OnTransferSizeUpdated(m_totalBytesRead); - if (m_device->atEnd()) - OnTransferComplete(MOJO_RESULT_OK); + } + return false; } - base::TaskRunner *taskRunner() override + base::SequencedTaskRunner *taskRunner() override { + DCHECK(m_taskRunner->RunsTasksInCurrentSequence()); return m_taskRunner.get(); } - scoped_refptr<base::TaskRunner> m_taskRunner; + scoped_refptr<base::SequencedTaskRunner> m_taskRunner; scoped_refptr<URLRequestCustomJobProxy> m_proxy; mojo::Binding<network::mojom::URLLoader> m_binding; network::mojom::URLLoaderClientPtr m_client; mojo::DataPipe m_pipe; + std::unique_ptr<mojo::SimpleWatcher> m_watcher; + net::HttpByteRange m_byteRange; + int64_t m_totalSize = 0; + int64_t m_maxBytesToRead = -1; network::ResourceRequest m_request; - network::ResourceResponseHead m_head; + network::mojom::URLResponseHeadPtr m_head; + qint64 m_headerBytesRead = 0; qint64 m_totalBytesRead = 0; bool m_corsEnabled; + base::WeakPtrFactory<CustomURLLoader> m_weakPtrFactory{this}; + DISALLOW_COPY_AND_ASSIGN(CustomURLLoader); }; class CustomURLLoaderFactory : public network::mojom::URLLoaderFactory { public: - CustomURLLoaderFactory(ProfileAdapter *profileAdapter) + CustomURLLoaderFactory(ProfileAdapter *profileAdapter, mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) : m_taskRunner(base::CreateSequencedTaskRunner({ content::BrowserThread::IO })) , m_profileAdapter(profileAdapter) { + m_receivers.set_disconnect_handler(base::BindRepeating( + &CustomURLLoaderFactory::OnDisconnect, base::Unretained(this))); + m_receivers.Add(this, std::move(receiver)); } ~CustomURLLoaderFactory() override = default; // network::mojom::URLLoaderFactory: - void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, + void CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> loader, int32_t routing_id, int32_t request_id, uint32_t options, const network::ResourceRequest &request, - network::mojom::URLLoaderClientPtr client, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -374,27 +486,40 @@ public: m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&CustomURLLoader::CreateAndStart, request, - std::move(loader), client.PassInterface(), + std::move(loader), std::move(client), m_profileAdapter)); } - void Clone(network::mojom::URLLoaderFactoryRequest request) override + void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) override + { + m_receivers.Add(this, std::move(receiver)); + } + + void OnDisconnect() + { + if (m_receivers.empty()) + delete this; + } + + static mojo::PendingRemote<network::mojom::URLLoaderFactory> Create(ProfileAdapter *profileAdapter) { - m_bindings.AddBinding(this, std::move(request)); + mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote; + new CustomURLLoaderFactory(profileAdapter, pending_remote.InitWithNewPipeAndPassReceiver()); + return pending_remote; } const scoped_refptr<base::SequencedTaskRunner> m_taskRunner; - mojo::BindingSet<network::mojom::URLLoaderFactory> m_bindings; + mojo::ReceiverSet<network::mojom::URLLoaderFactory> m_receivers; QPointer<ProfileAdapter> m_profileAdapter; DISALLOW_COPY_AND_ASSIGN(CustomURLLoaderFactory); }; } // namespace -std::unique_ptr<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter) +mojo::PendingRemote<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter) { - return std::make_unique<CustomURLLoaderFactory>(profileAdapter); + return CustomURLLoaderFactory::Create(profileAdapter); } } // namespace QtWebEngineCore diff --git a/src/core/net/custom_url_loader_factory.h b/src/core/net/custom_url_loader_factory.h index 58adf4b79..a9eecbd1c 100644 --- a/src/core/net/custom_url_loader_factory.h +++ b/src/core/net/custom_url_loader_factory.h @@ -51,7 +51,7 @@ #ifndef CUSTOM_URL_LOADER_FACTORY_H_ #define CUSTOM_URL_LOADER_FACTORY_H_ -#include <memory> +#include "mojo/public/cpp/bindings/pending_remote.h" namespace network { namespace mojom { @@ -62,7 +62,7 @@ class URLLoaderFactory; namespace QtWebEngineCore { class ProfileAdapter; -std::unique_ptr<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter); +mojo::PendingRemote<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter); } // namespace QtWebEngineCore diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp deleted file mode 100644 index 684558abb..000000000 --- a/src/core/net/network_delegate_qt.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "network_delegate_qt.h" - -#include "base/task/post_task.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/resource_request_info.h" -#include "net/base/load_flags.h" -#include "net/url_request/url_request.h" -#include "ui/base/page_transition_types.h" - -#include "profile_adapter.h" -#include "cookie_monster_delegate_qt.h" -#include "profile_io_data_qt.h" -#include "qwebengineurlrequestinfo.h" -#include "qwebengineurlrequestinfo_p.h" -#include "qwebengineurlrequestinterceptor.h" -#include "type_conversion.h" -#include "web_contents_adapter_client.h" -#include "web_contents_view_qt.h" -#include "url_request_notification.h" - -namespace QtWebEngineCore { - -WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition) -{ - if (ui::PageTransitionIsRedirect(transition)) - return WebContentsAdapterClient::RedirectNavigation; - - int32_t qualifier = ui::PageTransitionGetQualifier(transition); - - if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK) - return WebContentsAdapterClient::BackForwardNavigation; - - ui::PageTransition strippedTransition = ui::PageTransitionStripQualifier(transition); - - switch (strippedTransition) { - case ui::PAGE_TRANSITION_LINK: - return WebContentsAdapterClient::LinkNavigation; - case ui::PAGE_TRANSITION_TYPED: - return WebContentsAdapterClient::TypedNavigation; - case ui::PAGE_TRANSITION_FORM_SUBMIT: - return WebContentsAdapterClient::FormSubmittedNavigation; - case ui::PAGE_TRANSITION_RELOAD: - return WebContentsAdapterClient::ReloadNavigation; - default: - return WebContentsAdapterClient::OtherNavigation; - } -} - -static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType) -{ - if (resourceType >= content::ResourceType::kMainFrame && resourceType <= content::ResourceType::kMaxValue) - return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType); - return QWebEngineUrlRequestInfo::ResourceTypeUnknown; -} - -static QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType) -{ - return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType); -} - -NetworkDelegateQt::NetworkDelegateQt(ProfileIODataQt *data) - : m_profileIOData(data) -{ -} - -int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::CompletionOnceCallback callback, GURL *newUrl) -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_ASSERT(m_profileIOData); - content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request); - - content::ResourceType resourceType = content::ResourceType::kMaxValue; - WebContentsAdapterClient::NavigationType navigationType = WebContentsAdapterClient::OtherNavigation; - - if (resourceInfo) { - resourceType = resourceInfo->GetResourceType(); - navigationType = pageTransitionToNavigationType(resourceInfo->GetPageTransition()); - } - - const QUrl qUrl = toQt(request->url()); - - QUrl firstPartyUrl = QUrl(); - if (resourceType == content::ResourceType::kSubFrame) - firstPartyUrl = toQt(request->first_party_url()); - else - firstPartyUrl = toQt(request->site_for_cookies()); - - const QUrl initiator = request->initiator().has_value() ? toQt(request->initiator()->GetURL()) : QUrl(); - - QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), - toQt(navigationType), - qUrl, - firstPartyUrl, - initiator, - QByteArray::fromStdString(request->method())); - QWebEngineUrlRequestInfo requestInfo(infoPrivate); - - // Deprecated =begin - // quick peek if deprecated - - if (m_profileIOData->isInterceptorDeprecated()) { - QWebEngineUrlRequestInterceptor *profileInterceptor = m_profileIOData->acquireInterceptor(); - if (profileInterceptor && m_profileIOData->isInterceptorDeprecated()) { - profileInterceptor->interceptRequest(requestInfo); - m_profileIOData->releaseInterceptor(); - if (requestInfo.changed()) { - int result = infoPrivate->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; - - if (qUrl != infoPrivate->url) - *newUrl = toGurl(infoPrivate->url); - - if (!infoPrivate->extraHeaders.isEmpty()) { - auto end = infoPrivate->extraHeaders.constEnd(); - for (auto header = infoPrivate->extraHeaders.constBegin(); header != end; ++header) { - std::string h = header.key().toStdString(); - if (base::LowerCaseEqualsASCII(h, "referer")) { - request->SetReferrer(header.value().toStdString()); - } else { - request->SetExtraRequestHeaderByName(h, header.value().toStdString(), /* overwrite */ true); - } - } - } - - if (result != net::OK) - return result; - - requestInfo.resetChanged(); - } - } else { - m_profileIOData->releaseInterceptor(); - } - } - // Deprecated =cut - - if (!resourceInfo) - return net::OK; - - // try to bail out - if (!m_profileIOData->hasPageInterceptors() && (!m_profileIOData->requestInterceptor() || m_profileIOData->isInterceptorDeprecated())) - return net::OK; - - auto webContentsGetter = resourceInfo->GetWebContentsGetterForRequest(); - new URLRequestNotification( - request, - resourceInfo->IsMainFrame(), - newUrl, - std::move(requestInfo), - webContentsGetter, - std::move(callback), - m_profileIOData->profileAdapter() - ); - - // We'll run the callback after we notified the UI thread. - return net::ERR_IO_PENDING; -} - -void NetworkDelegateQt::OnURLRequestDestroyed(net::URLRequest *) {} - -void NetworkDelegateQt::OnCompleted(net::URLRequest * /*request*/, bool /*started*/, int /*net_error*/) {} - -bool NetworkDelegateQt::OnCanSetCookie(const net::URLRequest &request, const net::CanonicalCookie & /*cookie*/, - net::CookieOptions *, bool allowedFromCaller) -{ - if (!allowedFromCaller) - return false; - return canSetCookies(request.site_for_cookies(), request.url(), std::string()); -} - -bool NetworkDelegateQt::OnCanGetCookies(const net::URLRequest &request, const net::CookieList &, bool allowedFromCaller) -{ - if (!allowedFromCaller) - return false; - return canGetCookies(request.site_for_cookies(), request.url()); -} - -bool NetworkDelegateQt::OnForcePrivacyMode(const GURL &url, const GURL &site_for_cookies) const -{ - return false; - // FIXME: This is what the NetworkContext implementation does (changes tst_QWebEngineCookieStore tests since 72) - // return !canGetCookies(site_for_cookies, url); -} - -bool NetworkDelegateQt::canSetCookies(const GURL &first_party, const GURL &url, const std::string &cookie_line) const -{ - Q_ASSERT(m_profileIOData); - return m_profileIOData->canSetCookie(toQt(first_party), QByteArray::fromStdString(cookie_line), toQt(url)); -} - -bool NetworkDelegateQt::canGetCookies(const GURL &first_party, const GURL &url) const -{ - Q_ASSERT(m_profileIOData); - return m_profileIOData->canGetCookies(toQt(first_party), toQt(url)); -} - -int NetworkDelegateQt::OnBeforeStartTransaction(net::URLRequest *, net::CompletionOnceCallback, net::HttpRequestHeaders *) -{ - return net::OK; -} - -void NetworkDelegateQt::OnBeforeSendHeaders(net::URLRequest *request, const net::ProxyInfo &proxy_info, - const net::ProxyRetryInfoMap &proxy_retry_info, - net::HttpRequestHeaders *headers) -{} - -void NetworkDelegateQt::OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers) {} - -int NetworkDelegateQt::OnHeadersReceived(net::URLRequest *, net::CompletionOnceCallback, const net::HttpResponseHeaders *, - scoped_refptr<net::HttpResponseHeaders> *, GURL *) -{ - return net::OK; -} - -void NetworkDelegateQt::OnBeforeRedirect(net::URLRequest *, const GURL &) {} - -void NetworkDelegateQt::OnResponseStarted(net::URLRequest *, int) {} - -void NetworkDelegateQt::OnNetworkBytesReceived(net::URLRequest *, int64_t) {} - -void NetworkDelegateQt::OnNetworkBytesSent(net::URLRequest *, int64_t) {} - -void NetworkDelegateQt::OnPACScriptError(int, const base::string16 &) {} - -net::NetworkDelegate::AuthRequiredResponse NetworkDelegateQt::OnAuthRequired(net::URLRequest *, - const net::AuthChallengeInfo &, - AuthCallback, net::AuthCredentials *) -{ - return AUTH_REQUIRED_RESPONSE_NO_ACTION; -} - -bool NetworkDelegateQt::OnCanAccessFile(const net::URLRequest &, const base::FilePath &, const base::FilePath &) const -{ - return true; -} - -bool NetworkDelegateQt::OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest &, const GURL &, - const GURL &) const -{ - return false; -} - -bool NetworkDelegateQt::OnCanQueueReportingReport(const url::Origin &origin) const -{ - return false; -} - -void NetworkDelegateQt::OnCanSendReportingReports(std::set<url::Origin> origins, - base::OnceCallback<void(std::set<url::Origin>)> result_callback) const -{ - std::move(result_callback).Run(std::set<url::Origin>()); -} - -bool NetworkDelegateQt::OnCanSetReportingClient(const url::Origin &origin, const GURL &endpoint) const -{ - return false; -} - -bool NetworkDelegateQt::OnCanUseReportingClient(const url::Origin &origin, const GURL &endpoint) const -{ - return false; -} - -} // namespace QtWebEngineCore diff --git a/src/core/net/network_delegate_qt.h b/src/core/net/network_delegate_qt.h deleted file mode 100644 index f294c6c7c..000000000 --- a/src/core/net/network_delegate_qt.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** 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 ProfileIODataQt; - -class NetworkDelegateQt : public net::NetworkDelegate -{ - ProfileIODataQt *m_profileIOData; - -public: - NetworkDelegateQt(ProfileIODataQt *data); - - // net::NetworkDelegate implementation - int OnBeforeURLRequest(net::URLRequest *request, net::CompletionOnceCallback callback, GURL *new_url) override; - void OnURLRequestDestroyed(net::URLRequest *request) override; - bool OnCanSetCookie(const net::URLRequest &request, const net::CanonicalCookie &cookie, net::CookieOptions *options, - bool) override; - int OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionOnceCallback 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 *, net::CompletionOnceCallback, 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 &, - AuthCallback, net::AuthCredentials *) override; - bool OnCanGetCookies(const net::URLRequest &, const net::CookieList &, bool) override; - bool OnCanAccessFile(const net::URLRequest &, const base::FilePath &, const base::FilePath &) const override; - bool OnForcePrivacyMode(const GURL &, const GURL &) const override; - bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest &, const GURL &, - const GURL &) const override; - - bool OnCanQueueReportingReport(const url::Origin &origin) const override; - void OnCanSendReportingReports(std::set<url::Origin> origins, - base::OnceCallback<void(std::set<url::Origin>)> result_callback) 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/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp new file mode 100644 index 000000000..d868e4f54 --- /dev/null +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "plugin_response_interceptor_url_loader_throttle.h" + +#include "base/bind.h" +#include "base/guid.h" +#include "base/task/post_task.h" +#include "chrome/browser/extensions/api/streams_private/streams_private_api.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/download_request_utils.h" +#include "content/public/browser/download_utils.h" +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.h" +#include "extensions/common/constants.h" +#include "extensions/common/extension.h" +#include "extensions/common/manifest_handlers/mime_types_handler.h" +#include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h" + +#include "extensions/extension_system_qt.h" +#include "web_contents_delegate_qt.h" + +#include <string> + +namespace QtWebEngineCore { + +PluginResponseInterceptorURLLoaderThrottle::PluginResponseInterceptorURLLoaderThrottle( + content::BrowserContext *browser_context, int resource_type, int frame_tree_node_id) + : m_browser_context(browser_context), m_resource_type(resource_type), m_frame_tree_node_id(frame_tree_node_id) +{} + +void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL &response_url, + network::mojom::URLResponseHead *response_head, + bool *defer) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (content::download_utils::MustDownload(response_url, response_head->headers.get(), response_head->mime_type)) + return; + + content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(m_frame_tree_node_id); + if (!web_contents) + return; + + std::string extension_id; + if (response_head->mime_type == "application/pdf") + extension_id = extension_misc::kPdfExtensionId; + if (extension_id.empty()) + return; + + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate()); + if (!contentsDelegate) + return; + + WebEngineSettings *settings = contentsDelegate->webEngineSettings(); + if (!settings->testAttribute(WebEngineSettings::PdfViewerEnabled) + || !settings->testAttribute(WebEngineSettings::PluginsEnabled)) { + // PluginServiceFilterQt will inform the URLLoader about the disabled state of plugins + // and we can expect the download to be triggered automatically. It's unnecessary to + // go further and start the guest view embedding process. + return; + } + + // Chrome's PDF Extension does not work properly in the face of a restrictive + // Content-Security-Policy, and does not currently respect the policy anyway. + // Ignore CSP served on a PDF response. https://crbug.com/271452 + if (extension_id == extension_misc::kPdfExtensionId && response_head->headers) + response_head->headers->RemoveHeader("Content-Security-Policy"); + + MimeTypesHandler::ReportUsedHandler(extension_id); + + std::string view_id = base::GenerateGUID(); + // The string passed down to the original client with the response body. + std::string payload = view_id; + + mojo::PendingRemote<network::mojom::URLLoader> dummy_new_loader; + ignore_result(dummy_new_loader.InitWithNewPipeAndPassReceiver()); + mojo::Remote<network::mojom::URLLoaderClient> new_client; + mojo::PendingReceiver<network::mojom::URLLoaderClient> new_client_receiver = + new_client.BindNewPipeAndPassReceiver(); + + + uint32_t data_pipe_size = 64U; + // Provide the MimeHandlerView code a chance to override the payload. This is + // the case where the resource is handled by frame-based MimeHandlerView. + *defer = extensions::MimeHandlerViewAttachHelper::OverrideBodyForInterceptedResponse( + m_frame_tree_node_id, response_url, response_head->mime_type, view_id, + &payload, &data_pipe_size, + base::BindOnce( + &PluginResponseInterceptorURLLoaderThrottle::ResumeLoad, + weak_factory_.GetWeakPtr())); + + mojo::DataPipe data_pipe(data_pipe_size); + uint32_t len = static_cast<uint32_t>(payload.size()); + CHECK_EQ(MOJO_RESULT_OK, + data_pipe.producer_handle->WriteData( + payload.c_str(), &len, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); + + + new_client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle)); + + network::URLLoaderCompletionStatus status(net::OK); + status.decoded_body_length = len; + new_client->OnComplete(status); + + mojo::PendingRemote<network::mojom::URLLoader> original_loader; + mojo::PendingReceiver<network::mojom::URLLoaderClient> original_client; + delegate_->InterceptResponse(std::move(dummy_new_loader), + std::move(new_client_receiver), &original_loader, + &original_client); + + // Make a deep copy of URLResponseHead before passing it cross-thread. + auto deep_copied_response = response_head->Clone(); + if (response_head->headers) { + deep_copied_response->headers = + base::MakeRefCounted<net::HttpResponseHeaders>( + response_head->headers->raw_headers()); + } + + auto transferrable_loader = blink::mojom::TransferrableURLLoader::New(); + transferrable_loader->url = GURL( + extensions::Extension::GetBaseURLFromExtensionId(extension_id).spec() + + base::GenerateGUID()); + transferrable_loader->url_loader = std::move(original_loader); + transferrable_loader->url_loader_client = std::move(original_client); + transferrable_loader->head = std::move(deep_copied_response); + transferrable_loader->head->intercepted_by_plugin = true; + + bool embedded = m_resource_type != + static_cast<int>(blink::mojom::ResourceType::kMainFrame); + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce( + &extensions::StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent, + extension_id, view_id, embedded, m_frame_tree_node_id, + -1 /* render_process_id */, -1 /* render_frame_id */, + std::move(transferrable_loader), response_url)); +} + +void PluginResponseInterceptorURLLoaderThrottle::ResumeLoad() { + delegate_->Resume(); +} + +} // namespace QtWebEngineCore diff --git a/src/core/net/url_request_notification.h b/src/core/net/plugin_response_interceptor_url_loader_throttle.h index 673e07bf0..205ab25e6 100644 --- a/src/core/net/url_request_notification.h +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.h @@ -37,50 +37,44 @@ ** ****************************************************************************/ -#ifndef URL_REQUEST_NOTIFIACTION_H -#define URL_REQUEST_NOTIFIACTION_H +#ifndef PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ +#define PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ -#include "content/public/browser/resource_request_info.h" -#include "net/base/completion_once_callback.h" -#include "qwebengineurlrequestinfo.h" -#include <QPointer> +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "third_party/blink/public/common/loader/url_loader_throttle.h" -class GURL; - -namespace net { -class URLRequest; +namespace content { +class BrowserContext; } namespace QtWebEngineCore { -class ProfileAdapter; -class ProfileIoDataQt; - -// Notifies WebContentsAdapterClient of a new URLRequest. -class URLRequestNotification +class PluginResponseInterceptorURLLoaderThrottle : public blink::URLLoaderThrottle { public: - URLRequestNotification(net::URLRequest *request, - bool isMainFrameRequest, - GURL *newUrl, - QWebEngineUrlRequestInfo &&requestInfo, - content::ResourceRequestInfo::WebContentsGetter webContentsGetter, - net::CompletionOnceCallback callback, - QPointer<ProfileAdapter> adapter); - ~URLRequestNotification() = default; - void cancel(); - void notify(); - void complete(int error); + PluginResponseInterceptorURLLoaderThrottle(content::BrowserContext *browser_context, + int resource_type, int frame_tree_node_id); + ~PluginResponseInterceptorURLLoaderThrottle() override = default; private: - net::URLRequest *m_request; //used only by io thread - bool m_isMainFrameRequest; - GURL *m_newUrl; - const QUrl m_originalUrl; - QWebEngineUrlRequestInfo m_requestInfo; - content::ResourceRequestInfo::WebContentsGetter m_webContentsGetter; - net::CompletionOnceCallback m_callback; - QPointer<ProfileAdapter> m_profileAdapter; + // content::URLLoaderThrottle overrides; + void WillProcessResponse(const GURL &response_url, network::mojom::URLResponseHead *response_head, bool *defer) override; + + // Resumes loading for an intercepted response. This would give the extension + // layer chance to initialize its browser side state. + void ResumeLoad(); + + content::BrowserContext *m_browser_context = nullptr; + const int m_resource_type; + const int m_frame_tree_node_id; + + base::WeakPtrFactory<PluginResponseInterceptorURLLoaderThrottle> + weak_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(PluginResponseInterceptorURLLoaderThrottle); }; -} -#endif + +} // namespace QtWebEngineCore + +#endif // PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ diff --git a/src/core/net/proxy_config_monitor.cpp b/src/core/net/proxy_config_monitor.cpp index 818b6cb7f..a0aaf0c05 100644 --- a/src/core/net/proxy_config_monitor.cpp +++ b/src/core/net/proxy_config_monitor.cpp @@ -67,7 +67,7 @@ ProxyConfigMonitor::ProxyConfigMonitor(PrefService *prefs) proxy_config_service_.reset( new ProxyConfigServiceQt( - prefs, base::CreateSingleThreadTaskRunnerWithTraits({ BrowserThread::UI }))); + prefs, base::CreateSingleThreadTaskRunner({ BrowserThread::UI }))); proxy_config_service_->AddObserver(this); } @@ -82,12 +82,13 @@ ProxyConfigMonitor::~ProxyConfigMonitor() void ProxyConfigMonitor::AddToNetworkContextParams( network::mojom::NetworkContextParams *network_context_params) { - network::mojom::ProxyConfigClientPtr proxy_config_client; - network_context_params->proxy_config_client_request = mojo::MakeRequest(&proxy_config_client); - proxy_config_client_set_.AddPtr(std::move(proxy_config_client)); + mojo::PendingRemote<network::mojom::ProxyConfigClient> proxy_config_client; + network_context_params->proxy_config_client_receiver = + proxy_config_client.InitWithNewPipeAndPassReceiver(); + proxy_config_client_set_.Add(std::move(proxy_config_client)); - poller_binding_set_.AddBinding( - this, mojo::MakeRequest(&network_context_params->proxy_config_poller_client)); + poller_receiver_set_.Add(this, + network_context_params->proxy_config_poller_client.InitWithNewPipeAndPassReceiver()); net::ProxyConfigWithAnnotation proxy_config; net::ProxyConfigService::ConfigAvailability availability = @@ -102,21 +103,19 @@ void ProxyConfigMonitor::OnProxyConfigChanged( { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || !BrowserThread::IsThreadInitialized(BrowserThread::UI)); - proxy_config_client_set_.ForAllPtrs( - [config, availability](network::mojom::ProxyConfigClient *proxy_config_client) { - switch (availability) { - case net::ProxyConfigService::CONFIG_VALID: - proxy_config_client->OnProxyConfigUpdated(config); - break; - case net::ProxyConfigService::CONFIG_UNSET: - proxy_config_client->OnProxyConfigUpdated( - net::ProxyConfigWithAnnotation::CreateDirect()); - break; - case net::ProxyConfigService::CONFIG_PENDING: - NOTREACHED(); - break; - } - }); + for (const auto &proxy_config_client : proxy_config_client_set_) { + switch (availability) { + case net::ProxyConfigService::CONFIG_VALID: + proxy_config_client->OnProxyConfigUpdated(config); + break; + case net::ProxyConfigService::CONFIG_UNSET: + proxy_config_client->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation::CreateDirect()); + break; + case net::ProxyConfigService::CONFIG_PENDING: + NOTREACHED(); + break; + } + } } void ProxyConfigMonitor::OnLazyProxyConfigPoll() diff --git a/src/core/net/proxy_config_monitor.h b/src/core/net/proxy_config_monitor.h index 23f073a84..fda6a6fb9 100644 --- a/src/core/net/proxy_config_monitor.h +++ b/src/core/net/proxy_config_monitor.h @@ -51,8 +51,8 @@ #include "base/macros.h" #include "build/buildflag.h" #include "extensions/buildflags/buildflags.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_ptr_set.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "mojo/public/cpp/bindings/remote_set.h" #include "net/proxy_resolution/proxy_config_service.h" #include "services/network/public/mojom/network_context.mojom-forward.h" #include "services/network/public/mojom/network_service.mojom-forward.h" @@ -94,9 +94,8 @@ private: std::unique_ptr<ProxyConfigServiceQt> proxy_config_service_; - mojo::BindingSet<network::mojom::ProxyConfigPollerClient> poller_binding_set_; - - mojo::InterfacePtrSet<network::mojom::ProxyConfigClient> proxy_config_client_set_; + mojo::ReceiverSet<network::mojom::ProxyConfigPollerClient> poller_receiver_set_; + mojo::RemoteSet<network::mojom::ProxyConfigClient> proxy_config_client_set_; DISALLOW_COPY_AND_ASSIGN(ProxyConfigMonitor); }; diff --git a/src/core/net/proxy_config_service_qt.cpp b/src/core/net/proxy_config_service_qt.cpp index 59884961d..bc934c960 100644 --- a/src/core/net/proxy_config_service_qt.cpp +++ b/src/core/net/proxy_config_service_qt.cpp @@ -48,7 +48,7 @@ #include "base/bind.h" #include "components/proxy_config/pref_proxy_config_tracker_impl.h" #include "content/public/browser/browser_thread.h" -#include "net/proxy_resolution/proxy_resolution_service.h" +#include "net/proxy_resolution/configured_proxy_resolution_service.h" using content::BrowserThread; @@ -72,7 +72,7 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt ProxyConfigServiceQt::ProxyConfigServiceQt(PrefService *prefService, const scoped_refptr<base::SingleThreadTaskRunner> &taskRunner) - : m_baseService(net::ProxyResolutionService::CreateSystemProxyConfigService(taskRunner)) + : m_baseService(net::ConfiguredProxyResolutionService::CreateSystemProxyConfigService(taskRunner)) , m_usesSystemConfiguration(false) , m_registeredObserver(false) , m_prefState(prefService diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.cpp b/src/core/net/proxying_restricted_cookie_manager_qt.cpp index b6abeb567..f86c0e997 100644 --- a/src/core/net/proxying_restricted_cookie_manager_qt.cpp +++ b/src/core/net/proxying_restricted_cookie_manager_qt.cpp @@ -54,76 +54,52 @@ #include "base/task/post_task.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/strong_binding.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" namespace QtWebEngineCore { -class ProxyingRestrictedCookieManagerListenerQt : public network::mojom::CookieChangeListener { -public: - ProxyingRestrictedCookieManagerListenerQt(const GURL &url, - const GURL &site_for_cookies, - base::WeakPtr<ProxyingRestrictedCookieManagerQt> restricted_cookie_manager, - network::mojom::CookieChangeListenerPtr client_listener) - : url_(url) - , site_for_cookies_(site_for_cookies) - , restricted_cookie_manager_(restricted_cookie_manager) - , client_listener_(std::move(client_listener)) - {} - - void OnCookieChange(const net::CanonicalCookie &cookie, network::mojom::CookieChangeCause cause) override - { - if (restricted_cookie_manager_ && restricted_cookie_manager_->allowCookies(url_, site_for_cookies_)) - client_listener_->OnCookieChange(cookie, cause); - } - -private: - const GURL url_; - const GURL site_for_cookies_; - base::WeakPtr<ProxyingRestrictedCookieManagerQt> restricted_cookie_manager_; - network::mojom::CookieChangeListenerPtr client_listener_; -}; - // static void ProxyingRestrictedCookieManagerQt::CreateAndBind(ProfileIODataQt *profileIoData, - network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int process_id, int frame_id, - network::mojom::RestrictedCookieManagerRequest request) + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProxyingRestrictedCookieManagerQt::CreateAndBindOnIoThread, - profileIoData, - std::move(underlying_rcm), - is_service_worker, process_id, frame_id, - std::move(request))); + base::PostTask(FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&ProxyingRestrictedCookieManagerQt::CreateAndBindOnIoThread, + profileIoData, + std::move(underlying_rcm), + is_service_worker, process_id, frame_id, + std::move(receiver))); } // static void ProxyingRestrictedCookieManagerQt::CreateAndBindOnIoThread(ProfileIODataQt *profileIoData, - network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int process_id, int frame_id, - network::mojom::RestrictedCookieManagerRequest request) + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); auto wrapper = base::WrapUnique(new ProxyingRestrictedCookieManagerQt( profileIoData->getWeakPtrOnIOThread(), - network::mojom::RestrictedCookieManagerPtr(std::move(underlying_rcm)), + std::move(underlying_rcm), is_service_worker, process_id, frame_id)); - mojo::MakeStrongBinding(std::move(wrapper), std::move(request)); + mojo::MakeSelfOwnedReceiver(std::move(wrapper), std::move(receiver)); } -ProxyingRestrictedCookieManagerQt::ProxyingRestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerPtr underlyingRestrictedCookieManager, - bool is_service_worker, - int32_t process_id, - int32_t frame_id) +ProxyingRestrictedCookieManagerQt::ProxyingRestrictedCookieManagerQt( + base::WeakPtr<ProfileIODataQt> profileIoData, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlyingRestrictedCookieManager, + bool is_service_worker, + int32_t process_id, + int32_t frame_id) : m_profileIoData(std::move(profileIoData)) , underlying_restricted_cookie_manager_(std::move(underlyingRestrictedCookieManager)) , is_service_worker_(is_service_worker) @@ -140,92 +116,88 @@ ProxyingRestrictedCookieManagerQt::~ProxyingRestrictedCookieManagerQt() } void ProxyingRestrictedCookieManagerQt::GetAllForUrl(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, network::mojom::CookieManagerGetOptionsPtr options, GetAllForUrlCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, std::move(options), std::move(callback)); + underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, top_frame_origin, std::move(options), std::move(callback)); } else { - std::move(callback).Run(std::vector<net::CanonicalCookie>()); + std::move(callback).Run(std::vector<net::CookieWithAccessResult>()); } } void ProxyingRestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalCookie &cookie, const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, SetCanonicalCookieCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->SetCanonicalCookie(cookie, url, site_for_cookies, std::move(callback)); + underlying_restricted_cookie_manager_->SetCanonicalCookie(cookie, url, site_for_cookies, top_frame_origin, std::move(callback)); } else { std::move(callback).Run(false); } } void ProxyingRestrictedCookieManagerQt::AddChangeListener(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieChangeListenerPtr listener, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, + mojo::PendingRemote<network::mojom::CookieChangeListener> listener, AddChangeListenerCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - network::mojom::CookieChangeListenerPtr proxy_listener_ptr; - auto proxy_listener = - std::make_unique<ProxyingRestrictedCookieManagerListenerQt>( - url, site_for_cookies, weak_factory_.GetWeakPtr(), - std::move(listener)); - - mojo::MakeStrongBinding(std::move(proxy_listener), - mojo::MakeRequest(&proxy_listener_ptr)); - - underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, std::move(proxy_listener_ptr), std::move(callback)); + underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, top_frame_origin, std::move(listener), std::move(callback)); } void ProxyingRestrictedCookieManagerQt::SetCookieFromString(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, const std::string &cookie, SetCookieFromStringCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, cookie, std::move(callback)); + underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, top_frame_origin, cookie, std::move(callback)); } else { std::move(callback).Run(); } } void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, GetCookiesStringCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->GetCookiesString(url, site_for_cookies, std::move(callback)); + underlying_restricted_cookie_manager_->GetCookiesString(url, site_for_cookies, top_frame_origin, std::move(callback)); } else { std::move(callback).Run(""); } } void ProxyingRestrictedCookieManagerQt::CookiesEnabledFor(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin & /*top_frame_origin*/, CookiesEnabledForCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); std::move(callback).Run(allowCookies(url, site_for_cookies)); } -bool ProxyingRestrictedCookieManagerQt::allowCookies(const GURL &url, const GURL &site_for_cookies) const +bool ProxyingRestrictedCookieManagerQt::allowCookies(const GURL &url, const net::SiteForCookies &site_for_cookies) const { if (!m_profileIoData) return false; - return m_profileIoData->canGetCookies(toQt(site_for_cookies), toQt(url)); + return m_profileIoData->canGetCookies(toQt(site_for_cookies.first_party_url()), toQt(url)); } } // namespace QtWebEngineCore diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.h b/src/core/net/proxying_restricted_cookie_manager_qt.h index 7a9f0e3ab..3d4765b3b 100644 --- a/src/core/net/proxying_restricted_cookie_manager_qt.h +++ b/src/core/net/proxying_restricted_cookie_manager_qt.h @@ -42,6 +42,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "mojo/public/cpp/bindings/remote.h" #include "services/network/public/mojom/restricted_cookie_manager.mojom.h" #include "url/gurl.h" @@ -54,59 +55,64 @@ class ProxyingRestrictedCookieManagerQt : public network::mojom::RestrictedCooki public: // Expects to be called on the UI thread. static void CreateAndBind(ProfileIODataQt *profileIoData, - network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int process_id, int frame_id, - network::mojom::RestrictedCookieManagerRequest request); + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver); ~ProxyingRestrictedCookieManagerQt() override; // network::mojom::RestrictedCookieManager interface: void GetAllForUrl(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, network::mojom::CookieManagerGetOptionsPtr options, GetAllForUrlCallback callback) override; void SetCanonicalCookie(const net::CanonicalCookie& cookie, const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, SetCanonicalCookieCallback callback) override; void AddChangeListener(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieChangeListenerPtr listener, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, + mojo::PendingRemote<network::mojom::CookieChangeListener> listener, AddChangeListenerCallback callback) override; void SetCookieFromString(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, const std::string &cookie, SetCookieFromStringCallback callback) override; void GetCookiesString(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, GetCookiesStringCallback callback) override; - void CookiesEnabledFor(const GURL &url, - const GURL &site_for_cookies, + const net::SiteForCookies &site_for_cookies, + const url::Origin &top_frame_origin, CookiesEnabledForCallback callback) override; // Internal: - bool allowCookies(const GURL &url, const GURL &site_for_cookies) const; + bool allowCookies(const GURL &url, const net::SiteForCookies &site_for_cookies) const; private: ProxyingRestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerPtr underlyingRestrictedCookieManager, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int32_t process_id, int32_t frame_id); static void CreateAndBindOnIoThread(ProfileIODataQt *profileIoData, - network::mojom::RestrictedCookieManagerPtrInfo underlying_rcm, + mojo::PendingRemote<network::mojom::RestrictedCookieManager> underlying_rcm, bool is_service_worker, int process_id, int frame_id, - network::mojom::RestrictedCookieManagerRequest request); + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver); base::WeakPtr<ProfileIODataQt> m_profileIoData; - network::mojom::RestrictedCookieManagerPtr underlying_restricted_cookie_manager_; + mojo::Remote<network::mojom::RestrictedCookieManager> underlying_restricted_cookie_manager_; bool is_service_worker_; int process_id_; int frame_id_; diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp index 173e19eeb..a016cbc72 100644 --- a/src/core/net/proxying_url_loader_factory_qt.cpp +++ b/src/core/net/proxying_url_loader_factory_qt.cpp @@ -42,30 +42,23 @@ #include <utility> #include "base/bind.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" #include "base/task/post_task.h" -#include "components/safe_browsing/common/safebrowsing_constants.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/global_request_id.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/resource_request_info.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/content_constants.h" -#include "content/public/common/url_utils.h" -#include "net/base/load_flags.h" +#include "content/public/common/content_switches.h" #include "net/http/http_status_code.h" -#include "net/http/http_util.h" +#include "services/network/public/cpp/cors/cors.h" +#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" +#include "url/url_util.h" #include "api/qwebengineurlrequestinfo_p.h" -#include "net/url_request_custom_job_proxy.h" -#include "net/url_request_notification.h" -#include "profile_io_data_qt.h" #include "type_conversion.h" +#include "web_contents_adapter.h" #include "web_contents_adapter_client.h" #include "web_contents_view_qt.h" + #include <QVariant> // originally based on aw_proxying_url_loader_factory.cc: @@ -73,13 +66,47 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +namespace { + network::mojom::URLResponseHeadPtr createResponse(const network::ResourceRequest &request) { + const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity); + network::mojom::URLResponseHeadPtr response = network::mojom::URLResponseHead::New(); + response->response_type = network::cors::CalculateResponseType( + request.mode, disable_web_security || ( + request.request_initiator && request.request_initiator->IsSameOriginWith(url::Origin::Create(request.url)))); + + return response; + } +} + namespace QtWebEngineCore { +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMainFrame, blink::mojom::ResourceType::kMainFrame) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSubFrame, blink::mojom::ResourceType::kSubFrame) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeStylesheet, blink::mojom::ResourceType::kStylesheet) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeScript, blink::mojom::ResourceType::kScript) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeImage, blink::mojom::ResourceType::kImage) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeFontResource, blink::mojom::ResourceType::kFontResource) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSubResource, blink::mojom::ResourceType::kSubResource) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeObject, blink::mojom::ResourceType::kObject) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMedia, blink::mojom::ResourceType::kMedia) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeWorker, blink::mojom::ResourceType::kWorker) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSharedWorker, blink::mojom::ResourceType::kSharedWorker) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePrefetch, blink::mojom::ResourceType::kPrefetch) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeFavicon, blink::mojom::ResourceType::kFavicon) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeXhr, blink::mojom::ResourceType::kXhr) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePing, blink::mojom::ResourceType::kPing) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker, blink::mojom::ResourceType::kServiceWorker) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeCspReport, blink::mojom::ResourceType::kCspReport) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePluginResource, blink::mojom::ResourceType::kPluginResource) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadMainFrame, blink::mojom::ResourceType::kNavigationPreloadMainFrame) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeNavigationPreloadSubFrame, blink::mojom::ResourceType::kNavigationPreloadSubFrame) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeLast, blink::mojom::ResourceType::kMaxValue) + extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition); -static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType) +static QWebEngineUrlRequestInfo::ResourceType toQt(blink::mojom::ResourceType resourceType) { - if (resourceType >= content::ResourceType::kMainFrame && resourceType <= content::ResourceType::kMaxValue) + if (resourceType >= blink::mojom::ResourceType::kMinValue && resourceType <= blink::mojom::ResourceType::kMaxValue) return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType); return QWebEngineUrlRequestInfo::ResourceTypeUnknown; } @@ -95,20 +122,20 @@ class InterceptedRequest : public network::mojom::URLLoader , public network::mojom::URLLoaderClient { public: - InterceptedRequest(int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, + InterceptedRequest(ProfileAdapter *profile_adapter, + int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, const network::ResourceRequest &request, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, - ProfileIODataQt *profileData, - network::mojom::URLLoaderRequest loader_request, network::mojom::URLLoaderClientPtr client, - network::mojom::URLLoaderFactoryPtr target_factory); + mojo::PendingReceiver<network::mojom::URLLoader> loader, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, + mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory); ~InterceptedRequest() override; void Restart(); - void InterceptOnUIThread(); // network::mojom::URLLoaderClient - void OnReceiveResponse(const network::ResourceResponseHead &head) override; - void OnReceiveRedirect(const net::RedirectInfo &redirect_info, const network::ResourceResponseHead &head) override; + void OnReceiveResponse(network::mojom::URLResponseHeadPtr head) override; + void OnReceiveRedirect(const net::RedirectInfo &redirect_info, network::mojom::URLResponseHeadPtr head) override; void OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback callback) override; void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override; void OnTransferSizeUpdated(int32_t transfer_size_diff) override; @@ -117,15 +144,17 @@ public: // network::mojom::URLLoader void FollowRedirect(const std::vector<std::string> &removed_headers, - const net::HttpRequestHeaders &modified_headers, const base::Optional<GURL> &new_url) override; - void ProceedWithResponse() override; + const net::HttpRequestHeaders &modified_headers, + const net::HttpRequestHeaders &modified_cors_exempt_headers, + const base::Optional<GURL> &new_url) override; void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override; void PauseReadingBodyFromNet() override; void ResumeReadingBodyFromNet() override; + void InterceptOnUIThread(QWebEngineUrlRequestInterceptor *profileInterceptor); + void InterceptOnIOThread(base::WaitableEvent *event, QWebEngineUrlRequestInterceptor *profileInterceptor); void ContinueAfterIntercept(); -private: // This is called when the original URLLoaderClient has a connection error. void OnURLLoaderClientError(); @@ -139,158 +168,227 @@ private: void SendErrorAndCompleteImmediately(int error_code); + content::WebContents* webContents(); + QWebEngineUrlRequestInterceptor* getProfileInterceptor(); + QWebEngineUrlRequestInterceptor* getPageInterceptor(); + + QPointer<ProfileAdapter> profile_adapter_; const int process_id_; const uint64_t request_id_; const int32_t routing_id_; const uint32_t options_; - bool input_stream_previously_failed_ = false; - bool request_was_redirected_ = false; + bool allowed_cors_ = true; + + bool loader_error_seen_ = false; // If the |target_loader_| called OnComplete with an error this stores it. // That way the destructor can send it to OnReceivedError if safe browsing // error didn't occur. int error_status_ = net::OK; - GURL m_originalUrl; - network::ResourceRequest request_; - network::ResourceResponseHead current_response_; + network::mojom::URLResponseHeadPtr current_response_; const net::MutableNetworkTrafficAnnotationTag traffic_annotation_; - ProfileIODataQt *m_profileData; - mojo::Binding<network::mojom::URLLoader> proxied_loader_binding_; - network::mojom::URLLoaderClientPtr target_client_; + static inline void cleanup(QWebEngineUrlRequestInfo *info) { delete info; } + QScopedPointer<QWebEngineUrlRequestInfo, InterceptedRequest> request_info_; - mojo::Binding<network::mojom::URLLoaderClient> proxied_client_binding_; - network::mojom::URLLoaderPtr target_loader_; - network::mojom::URLLoaderFactoryPtr target_factory_; + mojo::Receiver<network::mojom::URLLoader> proxied_loader_receiver_; + mojo::Remote<network::mojom::URLLoaderClient> target_client_; + mojo::Receiver<network::mojom::URLLoaderClient> proxied_client_receiver_{this}; + mojo::Remote<network::mojom::URLLoader> target_loader_; + mojo::Remote<network::mojom::URLLoaderFactory> target_factory_; - base::WeakPtrFactory<InterceptedRequest> m_weakFactory; - base::WeakPtr<InterceptedRequest> m_weakPtr; + base::WeakPtrFactory<InterceptedRequest> weak_factory_; DISALLOW_COPY_AND_ASSIGN(InterceptedRequest); }; -InterceptedRequest::InterceptedRequest(int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, +InterceptedRequest::InterceptedRequest(ProfileAdapter *profile_adapter, + int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, const network::ResourceRequest &request, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, - ProfileIODataQt *profileData, - network::mojom::URLLoaderRequest loader_request, - network::mojom::URLLoaderClientPtr client, - network::mojom::URLLoaderFactoryPtr target_factory) - : process_id_(process_id) + mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, + mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory) + : profile_adapter_(profile_adapter) + , process_id_(process_id) , request_id_(request_id) , routing_id_(routing_id) , options_(options) , request_(request) , traffic_annotation_(traffic_annotation) - , m_profileData(profileData) - , proxied_loader_binding_(this, std::move(loader_request)) + , proxied_loader_receiver_(this, std::move(loader_receiver)) , target_client_(std::move(client)) - , proxied_client_binding_(this) , target_factory_(std::move(target_factory)) - , m_weakFactory(this) - , m_weakPtr(m_weakFactory.GetWeakPtr()) + , weak_factory_(this) { + const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity); + current_response_ = createResponse(request_); // If there is a client error, clean up the request. - target_client_.set_connection_error_handler( - base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, m_weakFactory.GetWeakPtr())); - proxied_loader_binding_.set_connection_error_with_reason_handler( - base::BindOnce(&InterceptedRequest::OnURLLoaderError, m_weakFactory.GetWeakPtr())); + target_client_.set_disconnect_handler( + base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, base::Unretained(this))); + proxied_loader_receiver_.set_disconnect_with_reason_handler( + base::BindOnce(&InterceptedRequest::OnURLLoaderError, base::Unretained(this))); + if (!disable_web_security && request_.request_initiator) { + const std::vector<std::string> &localSchemes = url::GetLocalSchemes(); + std::string fromScheme = request_.request_initiator->GetTupleOrPrecursorTupleIfOpaque().scheme(); + if (base::Contains(localSchemes, fromScheme)) { + content::WebContents *wc = webContents(); + std::string toScheme = request_.url.scheme(); + // local schemes must have universal access, or be accessing something local and have local access. + if (fromScheme != toScheme) { + // note allow_file_access_from_file_urls maps to LocalContentCanAccessFileUrls in our API + // and allow_universal_access_from_file_urls to LocalContentCanAccessRemoteUrls, so we are + // using them as proxies for our API here. + if (toScheme == "file") + allowed_cors_ = wc && wc->GetOrCreateWebPreferences().allow_file_access_from_file_urls; + else if (!base::Contains(localSchemes, toScheme)) + allowed_cors_ = wc && wc->GetOrCreateWebPreferences().allow_universal_access_from_file_urls; + else + allowed_cors_ = true; // We should think about this for future patches + } + } + } } InterceptedRequest::~InterceptedRequest() { - m_weakFactory.InvalidateWeakPtrs(); + weak_factory_.InvalidateWeakPtrs(); } -void InterceptedRequest::Restart() +content::WebContents* InterceptedRequest::webContents() +{ + if (process_id_) { + content::RenderFrameHost *frameHost = content::RenderFrameHost::FromID(process_id_, request_.render_frame_id); + return content::WebContents::FromRenderFrameHost(frameHost); + } + + return content::WebContents::FromFrameTreeNodeId(request_.render_frame_id); +} + +QWebEngineUrlRequestInterceptor* InterceptedRequest::getProfileInterceptor() { - // FIXME: Support deprecated interceptors here + return profile_adapter_ ? profile_adapter_->requestInterceptor() : nullptr; +} - // FIXME: unretained post? - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&InterceptedRequest::InterceptOnUIThread, base::Unretained(this))); +QWebEngineUrlRequestInterceptor* InterceptedRequest::getPageInterceptor() +{ + if (auto wc = webContents()) { + auto view = static_cast<content::WebContentsImpl *>(wc)->GetView(); + if (WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client()) + return client->webContentsAdapter()->requestInterceptor(); + } + return nullptr; } -void InterceptedRequest::InterceptOnUIThread() +void InterceptedRequest::Restart() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - content::ResourceType resourceType = content::ResourceType(request_.resource_type); - WebContentsAdapterClient::NavigationType navigationType = - pageTransitionToNavigationType(ui::PageTransition(request_.transition_type)); + // This is a CORS check on the from URL, the normal check on the to URL is applied later + if (!allowed_cors_ && current_response_->response_type == network::mojom::FetchResponseType::kCors) { + target_client_->OnComplete(network::URLLoaderCompletionStatus( + network::CorsErrorStatus(network::mojom::CorsError::kCorsDisabledScheme))); + delete this; + return; + } - m_originalUrl = request_.url; - const QUrl qUrl = toQt(request_.url); + // MEMO since all codepatch leading to Restart scheduled and executed as asynchronous tasks in main thread, + // interceptors may change in meantime and also during intercept call, so they should be resolved anew. + // Set here only profile's interceptor since it runs first without going to user code. + auto profileInterceptor = getProfileInterceptor(); + if (!profileInterceptor && !getPageInterceptor()) { + ContinueAfterIntercept(); + return; + } + auto resourceType = toQt(blink::mojom::ResourceType(request_.resource_type)); + auto navigationType = toQt(pageTransitionToNavigationType(ui::PageTransition(request_.transition_type))); + const QUrl originalUrl = toQt(request_.url); const QUrl initiator = request_.request_initiator.has_value() ? toQt(request_.request_initiator->GetURL()) : QUrl(); + auto wc = webContents(); + GURL top_document_url = wc ? wc->GetVisibleURL() : GURL(); QUrl firstPartyUrl; - if (resourceType == content::ResourceType::kSubFrame) - firstPartyUrl = toQt(request_.first_party_url); + if (!top_document_url.is_empty()) + firstPartyUrl = toQt(top_document_url); else - firstPartyUrl = toQt(request_.site_for_cookies); + firstPartyUrl = toQt(request_.site_for_cookies.first_party_url()); // m_topDocumentUrl can be empty for the main-frame. + + auto info = new QWebEngineUrlRequestInfoPrivate(resourceType, navigationType, originalUrl, firstPartyUrl, + initiator, QByteArray::fromStdString(request_.method)); + Q_ASSERT(!request_info_); + request_info_.reset(new QWebEngineUrlRequestInfo(info)); + + // TODO: remove for Qt6 + bool isDeprecatedProfileInterceptor = profileInterceptor == nullptr; + if (profileInterceptor && profileInterceptor->property("deprecated").toBool()) { + isDeprecatedProfileInterceptor = true; + // sync call supports depracated call of an interceptor on io thread + base::WaitableEvent event; + base::PostTask(FROM_HERE, { content::BrowserThread::IO }, + base::BindOnce(&InterceptedRequest::InterceptOnIOThread, + base::Unretained(this), &event, profileInterceptor)); + event.Wait(); + if (request_info_->changed()) { + ContinueAfterIntercept(); + return; + } + } + InterceptOnUIThread(isDeprecatedProfileInterceptor ? nullptr : profileInterceptor); + ContinueAfterIntercept(); +} - QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), - toQt(navigationType), - qUrl, - firstPartyUrl, - initiator, - QByteArray::fromStdString(request_.method)); - QWebEngineUrlRequestInfo requestInfo(infoPrivate); +void InterceptedRequest::InterceptOnIOThread(base::WaitableEvent *event, QWebEngineUrlRequestInterceptor *interceptor) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + interceptor->interceptRequest(*request_info_); + event->Signal(); +} - content::WebContents *webContents = nullptr; - if (process_id_) { - content::RenderFrameHost *frameHost = content::RenderFrameHost::FromID(process_id_, request_.render_frame_id); - webContents = content::WebContents::FromRenderFrameHost(frameHost); - } else - webContents = content::WebContents::FromFrameTreeNodeId(request_.render_frame_id); - - if (webContents) { - int result = net::OK; - if (m_profileData) { - QWebEngineUrlRequestInterceptor *interceptor = m_profileData->requestInterceptor(); - if (interceptor && !interceptor->property("deprecated").toBool()) - interceptor->interceptRequest(requestInfo); - } +void InterceptedRequest::InterceptOnUIThread(QWebEngineUrlRequestInterceptor *profileInterceptor) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (profileInterceptor) + profileInterceptor->interceptRequest(*request_info_); - WebContentsAdapterClient *client = - WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); + if (!request_info_->changed()) { + if (auto interceptor = getPageInterceptor()) + interceptor->interceptRequest(*request_info_); + } +} - if (!requestInfo.changed()) { - client->interceptRequest(requestInfo); - } +void InterceptedRequest::ContinueAfterIntercept() +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (requestInfo.changed()) { - result = requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; - // We handle the rest of the changes later when we are back in I/O thread - } + if (request_info_) { + // cleanup in scope because of delete this and it's not needed else where after + decltype(request_info_) scoped_request_info(request_info_.take()); + QWebEngineUrlRequestInfoPrivate &info = *scoped_request_info->d_ptr; + + if (info.changed) { + if (info.shouldBlockRequest) + return SendErrorAndCompleteImmediately(net::ERR_BLOCKED_BY_CLIENT); + + for (auto header = info.extraHeaders.constBegin(); header != info.extraHeaders.constEnd(); ++header) { + std::string h = header.key().toStdString(); + if (base::LowerCaseEqualsASCII(h, "referer")) { + request_.referrer = GURL(header.value().toStdString()); + } else { + request_.headers.SetHeader(h, header.value().toStdString()); + } + } - if (result != net::OK) { - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&InterceptedRequest::SendErrorAndCompleteImmediately, m_weakPtr, result)); - return; - } - if (requestInfo.changed()) { - if (requestInfo.requestUrl() != qUrl) { - net::URLRequest::FirstPartyURLPolicy first_party_url_policy = - request_.update_first_party_url_on_redirect ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT - : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; - net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo(request_.method, request_.url, - request_.site_for_cookies, request_.top_frame_origin, - first_party_url_policy, request_.referrer_policy, - request_.referrer.spec(), net::HTTP_TEMPORARY_REDIRECT, - toGurl(requestInfo.requestUrl()), base::nullopt, - false /*insecure_scheme_was_upgraded*/); - - // FIXME: Should probably create a new header. - current_response_.encoded_data_length = 0; - // FIXME: unretained post. - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&network::mojom::URLLoaderClientProxy::OnReceiveRedirect, base::Unretained(&(*target_client_)), redirectInfo, current_response_)); + if (info.shouldRedirectRequest) { + net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy = + request_.update_first_party_url_on_redirect ? net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT + : net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL; + net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo( + request_.method, request_.url, request_.site_for_cookies, + first_party_url_policy, request_.referrer_policy, request_.referrer.spec(), + net::HTTP_TEMPORARY_REDIRECT, toGurl(info.url), base::nullopt, + false /*insecure_scheme_was_upgraded*/); request_.method = redirectInfo.new_method; request_.url = redirectInfo.new_url; request_.site_for_cookies = redirectInfo.new_site_for_cookies; @@ -298,53 +396,39 @@ void InterceptedRequest::InterceptOnUIThread() request_.referrer_policy = redirectInfo.new_referrer_policy; if (request_.method == net::HttpRequestHeaders::kGetMethod) request_.request_body = nullptr; + // In case of multiple sequential rediredts, current_response_ has previously been moved to target_client_ + // so we create a new one using the redirect url. + if (!current_response_) + current_response_ = createResponse(request_); + current_response_->encoded_data_length = 0; + target_client_->OnReceiveRedirect(redirectInfo, std::move(current_response_)); return; } - - if (!requestInfo.d_ptr->extraHeaders.isEmpty()) { - auto end = requestInfo.d_ptr->extraHeaders.constEnd(); - for (auto header = requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header) { - std::string h = header.key().toStdString(); - if (base::LowerCaseEqualsASCII(h, "referer")) { - request_.referrer = GURL(header.value().toStdString()); - } else { - request_.headers.SetHeader(h, header.value().toStdString()); - } - } - } } } - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&InterceptedRequest::ContinueAfterIntercept, m_weakPtr)); -} -void InterceptedRequest::ContinueAfterIntercept() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (!target_loader_ && target_factory_) { - network::mojom::URLLoaderClientPtr proxied_client; - proxied_client_binding_.Bind(mojo::MakeRequest(&proxied_client)); - target_factory_->CreateLoaderAndStart(mojo::MakeRequest(&target_loader_), routing_id_, request_id_, options_, - request_, std::move(proxied_client), traffic_annotation_); + loader_error_seen_ = false; + target_factory_->CreateLoaderAndStart(target_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_, + options_, request_, proxied_client_receiver_.BindNewPipeAndPassRemote(), + traffic_annotation_); } } // URLLoaderClient methods. -void InterceptedRequest::OnReceiveResponse(const network::ResourceResponseHead &head) +void InterceptedRequest::OnReceiveResponse(network::mojom::URLResponseHeadPtr head) { - current_response_ = head; + current_response_ = head.Clone(); - target_client_->OnReceiveResponse(head); + target_client_->OnReceiveResponse(std::move(head)); } -void InterceptedRequest::OnReceiveRedirect(const net::RedirectInfo &redirect_info, const network::ResourceResponseHead &head) +void InterceptedRequest::OnReceiveRedirect(const net::RedirectInfo &redirect_info, network::mojom::URLResponseHeadPtr head) { // TODO(timvolodine): handle redirect override. - request_was_redirected_ = true; - current_response_ = head; - target_client_->OnReceiveRedirect(redirect_info, head); + current_response_ = head.Clone(); + target_client_->OnReceiveRedirect(redirect_info, std::move(head)); request_.url = redirect_info.new_url; request_.method = redirect_info.new_method; request_.site_for_cookies = redirect_info.new_site_for_cookies; @@ -384,10 +468,11 @@ void InterceptedRequest::OnComplete(const network::URLLoaderCompletionStatus &st void InterceptedRequest::FollowRedirect(const std::vector<std::string> &removed_headers, const net::HttpRequestHeaders &modified_headers, + const net::HttpRequestHeaders &modified_cors_exempt_headers, const base::Optional<GURL> &new_url) { if (target_loader_) - target_loader_->FollowRedirect(removed_headers, modified_headers, new_url); + target_loader_->FollowRedirect(removed_headers, modified_headers, modified_cors_exempt_headers, new_url); // If |OnURLLoaderClientError| was called then we're just waiting for the // connection error handler of |proxied_loader_binding_|. Don't restart the @@ -398,12 +483,6 @@ void InterceptedRequest::FollowRedirect(const std::vector<std::string> &removed_ Restart(); } -void InterceptedRequest::ProceedWithResponse() -{ - if (target_loader_) - target_loader_->ProceedWithResponse(); -} - void InterceptedRequest::SetPriority(net::RequestPriority priority, int32_t intra_priority_value) { if (target_loader_) @@ -435,11 +514,13 @@ void InterceptedRequest::OnURLLoaderError(uint32_t custom_reason, const std::str // If CallOnComplete was already called, then this object is ready to be deleted. if (!target_client_) delete this; + else + loader_error_seen_ = true; } void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus &status, bool wait_for_loader_error) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Save an error status so that we call onReceiveError at destruction if there // was no safe browsing error. if (status.error_code != net::OK) @@ -448,22 +529,22 @@ void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus if (target_client_) target_client_->OnComplete(status); - if (proxied_loader_binding_ && wait_for_loader_error) { - // Don't delete |this| yet, in case the |proxied_loader_binding_|'s + if (proxied_loader_receiver_.is_bound() && wait_for_loader_error && !loader_error_seen_) { + // Since the original client is gone no need to continue loading the + // request. + proxied_client_receiver_.reset(); + target_loader_.reset(); + + // Don't delete |this| yet, in case the |proxied_loader_receiver_|'s // error_handler is called with a reason to indicate an error which we want // to send to the client bridge. Also reset |target_client_| so we don't // get its error_handler called and then delete |this|. target_client_.reset(); - // Since the original client is gone no need to continue loading the - // request. - proxied_client_binding_.Close(); - target_loader_.reset(); - // In case there are pending checks as to whether this request should be // intercepted, we don't want that causing |target_client_| to be used // later. - m_weakFactory.InvalidateWeakPtrs(); + weak_factory_.InvalidateWeakPtrs(); } else { delete this; } @@ -471,26 +552,25 @@ void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus void InterceptedRequest::SendErrorAndCompleteImmediately(int error_code) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); auto status = network::URLLoaderCompletionStatus(error_code); target_client_->OnComplete(status); delete this; } -ProxyingURLLoaderFactoryQt::ProxyingURLLoaderFactoryQt(int process_id, - content::ResourceContext *resourceContext, - network::mojom::URLLoaderFactoryRequest loader_request, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info) - : m_processId(process_id), m_resourceContext(resourceContext), m_weakFactory(this) +ProxyingURLLoaderFactoryQt::ProxyingURLLoaderFactoryQt(ProfileAdapter *adapter, int process_id, + mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver, + mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_info) + : m_profileAdapter(adapter), m_processId(process_id), m_weakFactory(this) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (target_factory_info) { m_targetFactory.Bind(std::move(target_factory_info)); - m_targetFactory.set_connection_error_handler( + m_targetFactory.set_disconnect_handler( base::BindOnce(&ProxyingURLLoaderFactoryQt::OnTargetFactoryError, m_weakFactory.GetWeakPtr())); } - m_proxyBindings.AddBinding(this, std::move(loader_request)); - m_proxyBindings.set_connection_error_handler( + m_proxyReceivers.Add(this, std::move(loader_receiver)); + m_proxyReceivers.set_disconnect_handler( base::BindRepeating(&ProxyingURLLoaderFactoryQt::OnProxyBindingError, m_weakFactory.GetWeakPtr())); } @@ -499,46 +579,20 @@ ProxyingURLLoaderFactoryQt::~ProxyingURLLoaderFactoryQt() m_weakFactory.InvalidateWeakPtrs(); } -// static -void ProxyingURLLoaderFactoryQt::CreateProxy(int process_id, - content::ResourceContext *resourceContext, - network::mojom::URLLoaderFactoryRequest loader_request, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - // Will manage its own lifetime - new ProxyingURLLoaderFactoryQt(process_id, resourceContext, std::move(loader_request), std::move(target_factory_info)); -} - -void ProxyingURLLoaderFactoryQt::CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, int32_t routing_id, - int32_t request_id, uint32_t options, - const network::ResourceRequest &request, - network::mojom::URLLoaderClientPtr client, +void ProxyingURLLoaderFactoryQt::CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> loader, int32_t routing_id, + int32_t request_id, uint32_t options, const network::ResourceRequest &request, + mojo::PendingRemote<network::mojom::URLLoaderClient> url_loader_client, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - ProfileIODataQt *profileIOData = ProfileIODataQt::FromResourceContext(m_resourceContext); - - QWebEngineUrlRequestInterceptor *profileInterceptor = profileIOData ? profileIOData->requestInterceptor() : nullptr; - if (!profileIOData || !(profileInterceptor || profileIOData->hasPageInterceptors())) { - m_targetFactory->CreateLoaderAndStart( - std::move(loader), routing_id, request_id, options, request, - std::move(client), traffic_annotation); - return; - } - - network::mojom::URLLoaderFactoryPtr target_factory_clone; + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_clone; if (m_targetFactory) - m_targetFactory->Clone(mojo::MakeRequest(&target_factory_clone)); - + m_targetFactory->Clone(target_factory_clone.InitWithNewPipeAndPassReceiver()); // Will manage its own lifetime - InterceptedRequest *req = new InterceptedRequest(m_processId, request_id, routing_id, options, request, - traffic_annotation, profileIOData, - std::move(loader), std::move(client), - std::move(target_factory_clone)); + InterceptedRequest *req = new InterceptedRequest(m_profileAdapter, m_processId, request_id, routing_id, options, + request, traffic_annotation, std::move(loader), + std::move(url_loader_client), std::move(target_factory_clone)); req->Restart(); } @@ -549,14 +603,14 @@ void ProxyingURLLoaderFactoryQt::OnTargetFactoryError() void ProxyingURLLoaderFactoryQt::OnProxyBindingError() { - if (m_proxyBindings.empty()) + if (m_proxyReceivers.empty()) delete this; } -void ProxyingURLLoaderFactoryQt::Clone(network::mojom::URLLoaderFactoryRequest loader_request) +void ProxyingURLLoaderFactoryQt::Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - m_proxyBindings.AddBinding(this, std::move(loader_request)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + m_proxyReceivers.Add(this, std::move(receiver)); } } // namespace QtWebEngineCore diff --git a/src/core/net/proxying_url_loader_factory_qt.h b/src/core/net/proxying_url_loader_factory_qt.h index a2f175885..5345e3220 100644 --- a/src/core/net/proxying_url_loader_factory_qt.h +++ b/src/core/net/proxying_url_loader_factory_qt.h @@ -42,61 +42,48 @@ #include "base/callback.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/ref_counted_delete_on_sequence.h" #include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/receiver_set.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/resource_request.h" -#include "services/network/public/cpp/resource_response.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" -#include "url/gurl.h" +#include <QPointer> // based on aw_proxying_url_loader_factory.h: // Copyright 2018 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. -namespace content { -class ResourceContext; -} - namespace QtWebEngineCore { +class ProfileAdapter; + class ProxyingURLLoaderFactoryQt : public network::mojom::URLLoaderFactory { public: - ProxyingURLLoaderFactoryQt(int process_id, content::ResourceContext *resourceContext, - network::mojom::URLLoaderFactoryRequest loader_request, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info); + ProxyingURLLoaderFactoryQt(ProfileAdapter *adapter, int processId, + mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver, + mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_target_factory_remote); ~ProxyingURLLoaderFactoryQt() override; - // static - static void CreateProxy(int process_id, content::ResourceContext *resourceContext, - network::mojom::URLLoaderFactoryRequest loader, - network::mojom::URLLoaderFactoryPtrInfo target_factory_info); - - void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, int32_t routing_id, int32_t request_id, + void CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> loader, + int32_t routing_id, int32_t request_id, uint32_t options, const network::ResourceRequest &request, - network::mojom::URLLoaderClientPtr client, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override; - void Clone(network::mojom::URLLoaderFactoryRequest loader_request) override; + void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) override; private: void OnTargetFactoryError(); void OnProxyBindingError(); - const int m_processId; - mojo::BindingSet<network::mojom::URLLoaderFactory> m_proxyBindings; - network::mojom::URLLoaderFactoryPtr m_targetFactory; - - content::ResourceContext *m_resourceContext; - + QPointer<ProfileAdapter> m_profileAdapter; + int m_processId; + mojo::ReceiverSet<network::mojom::URLLoaderFactory> m_proxyReceivers; + mojo::Remote<network::mojom::URLLoaderFactory> m_targetFactory; base::WeakPtrFactory<ProxyingURLLoaderFactoryQt> m_weakFactory; DISALLOW_COPY_AND_ASSIGN(ProxyingURLLoaderFactoryQt); diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp index 73bf24f1d..0a9943431 100644 --- a/src/core/net/qrc_url_scheme_handler.cpp +++ b/src/core/net/qrc_url_scheme_handler.cpp @@ -67,7 +67,10 @@ void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job) QFileInfo fileInfo(*file); QMimeDatabase mimeDatabase; QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo); - job->reply(mimeType.name().toUtf8(), file.take()); + if (mimeType.name() == QStringLiteral("application/x-extension-html")) + job->reply("text/html", file.take()); + else + job->reply(mimeType.name().toUtf8(), file.take()); } } // namespace QtWebEngineCore diff --git a/src/core/net/restricted_cookie_manager_qt.cpp b/src/core/net/restricted_cookie_manager_qt.cpp deleted file mode 100644 index 7f1ca163e..000000000 --- a/src/core/net/restricted_cookie_manager_qt.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// originally based on android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.cc: -// Copyright 2019 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 "restricted_cookie_manager_qt.h" - -#include "api/qwebenginecookiestore.h" -#include "api/qwebenginecookiestore_p.h" -#include "profile_adapter.h" -#include "profile_qt.h" -#include "type_conversion.h" - -#include "base/memory/ptr_util.h" -#include "base/task/post_task.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/strong_binding.h" - -namespace QtWebEngineCore { - -class RestrictedCookieManagerListenerQt : public network::mojom::CookieChangeListener -{ -public: - RestrictedCookieManagerListenerQt(const GURL &url, - const GURL &site_for_cookies, - base::WeakPtr<RestrictedCookieManagerQt> restricted_cookie_manager, - network::mojom::CookieChangeListenerPtr client_listener) - : url_(url) - , site_for_cookies_(site_for_cookies) - , restricted_cookie_manager_(restricted_cookie_manager) - , client_listener_(std::move(client_listener)) - {} - - void OnCookieChange(const net::CanonicalCookie &cookie, network::mojom::CookieChangeCause cause) override - { - if (restricted_cookie_manager_ && restricted_cookie_manager_->allowCookies(url_, site_for_cookies_)) - client_listener_->OnCookieChange(cookie, cause); - } - -private: - const GURL url_; - const GURL site_for_cookies_; - base::WeakPtr<RestrictedCookieManagerQt> restricted_cookie_manager_; - network::mojom::CookieChangeListenerPtr client_listener_; -}; - -RestrictedCookieManagerQt::RestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerRole role, - net::CookieStore *cookie_store, - network::CookieSettings *cookie_settings, - const url::Origin &origin, - bool is_service_worker, - int32_t process_id, - int32_t frame_id) - : network::RestrictedCookieManager(role, cookie_store, cookie_settings, origin, - nullptr, is_service_worker, process_id, frame_id) - , m_profileIoData(profileIoData) - , weak_factory_(this) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -} - -RestrictedCookieManagerQt::~RestrictedCookieManagerQt() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -} - -void RestrictedCookieManagerQt::GetAllForUrl(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieManagerGetOptionsPtr options, - GetAllForUrlCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (allowCookies(url, site_for_cookies)) { - network::RestrictedCookieManager::GetAllForUrl(url, site_for_cookies, std::move(options), std::move(callback)); - } else { - std::move(callback).Run(std::vector<net::CanonicalCookie>()); - } -} - -void RestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalCookie &cookie, - const GURL &url, - const GURL &site_for_cookies, - SetCanonicalCookieCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (allowCookies(url, site_for_cookies)) { - network::RestrictedCookieManager::SetCanonicalCookie(cookie, url, site_for_cookies, std::move(callback)); - } else { - std::move(callback).Run(false); - } -} - -void RestrictedCookieManagerQt::AddChangeListener(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieChangeListenerPtr listener, - AddChangeListenerCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - network::mojom::CookieChangeListenerPtr proxy_listener_ptr; - auto proxy_listener = - std::make_unique<RestrictedCookieManagerListenerQt>( - url, site_for_cookies, weak_factory_.GetWeakPtr(), - std::move(listener)); - - mojo::MakeStrongBinding(std::move(proxy_listener), - mojo::MakeRequest(&proxy_listener_ptr)); - - network::RestrictedCookieManager::AddChangeListener( - url, site_for_cookies, std::move(proxy_listener_ptr), - std::move(callback)); -} - -void RestrictedCookieManagerQt::GetCookiesString(const GURL &url, - const GURL &site_for_cookies, - GetCookiesStringCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (allowCookies(url, site_for_cookies)) { - network::RestrictedCookieManager::GetCookiesString(url, site_for_cookies, std::move(callback)); - } else { - std::move(callback).Run(""); - } -} - -void RestrictedCookieManagerQt::CookiesEnabledFor(const GURL &url, - const GURL &site_for_cookies, - CookiesEnabledForCallback callback) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - std::move(callback).Run(allowCookies(url, site_for_cookies)); -} - -bool RestrictedCookieManagerQt::allowCookies(const GURL &url, const GURL &site_for_cookies) const -{ - if (!m_profileIoData) - return false; - return m_profileIoData->canGetCookies(toQt(site_for_cookies), toQt(url)); -} - -} // namespace QtWebEngineCore diff --git a/src/core/net/restricted_cookie_manager_qt.h b/src/core/net/restricted_cookie_manager_qt.h deleted file mode 100644 index c135a1795..000000000 --- a/src/core/net/restricted_cookie_manager_qt.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef RESTRICTED_COOKIE_MANAGER_QT_H -#define RESTRICTED_COOKIE_MANAGER_QT_H - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "services/network/restricted_cookie_manager.h" -#include "url/gurl.h" - -namespace QtWebEngineCore { - -class ProfileIODataQt; - -class RestrictedCookieManagerQt : public network::RestrictedCookieManager -{ -public: - RestrictedCookieManagerQt(base::WeakPtr<ProfileIODataQt> profileIoData, - network::mojom::RestrictedCookieManagerRole role, - net::CookieStore *cookie_store, - network::CookieSettings *cookie_settings, - const url::Origin &origin, - bool is_service_worker, - int32_t process_id, - int32_t frame_id); - ~RestrictedCookieManagerQt() override; - - // network::RestrictedCookieManager: - void GetAllForUrl(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieManagerGetOptionsPtr options, - GetAllForUrlCallback callback) override; - void SetCanonicalCookie(const net::CanonicalCookie& cookie, - const GURL &url, - const GURL &site_for_cookies, - SetCanonicalCookieCallback callback) override; - void AddChangeListener(const GURL &url, - const GURL &site_for_cookies, - network::mojom::CookieChangeListenerPtr listener, - AddChangeListenerCallback callback) override; - - void GetCookiesString(const GURL &url, - const GURL &site_for_cookies, - GetCookiesStringCallback callback) override; - - void CookiesEnabledFor(const GURL &url, - const GURL &site_for_cookies, - CookiesEnabledForCallback callback) override; - - // Internal: - bool allowCookies(const GURL &url, const GURL &site_for_cookies) const; - -private: - base::WeakPtr<ProfileIODataQt> m_profileIoData; - - base::WeakPtrFactory<RestrictedCookieManagerQt> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(RestrictedCookieManagerQt); -}; - -} // namespace QtWebEngineCore - -#endif // RESTRICTED_COOKIE_MANAGER_QT_H diff --git a/src/core/net/ssl_host_state_delegate_qt.cpp b/src/core/net/ssl_host_state_delegate_qt.cpp index 0885475be..3390c092a 100644 --- a/src/core/net/ssl_host_state_delegate_qt.cpp +++ b/src/core/net/ssl_host_state_delegate_qt.cpp @@ -77,13 +77,13 @@ SSLHostStateDelegateQt::SSLHostStateDelegateQt() {} SSLHostStateDelegateQt::~SSLHostStateDelegateQt() {} -void SSLHostStateDelegateQt::AllowCert(const std::string &host, const net::X509Certificate &cert, int error) +void SSLHostStateDelegateQt::AllowCert(const std::string &host, const net::X509Certificate &cert, int error, content::WebContents *) { m_certPolicyforHost[host].Allow(cert, error); } // Clear all allow preferences. -void SSLHostStateDelegateQt::Clear(const base::Callback<bool(const std::string &)> &host_filter) +void SSLHostStateDelegateQt::Clear(base::RepeatingCallback<bool(const std::string&)> host_filter) { if (host_filter.is_null()) { m_certPolicyforHost.clear(); @@ -105,8 +105,7 @@ void SSLHostStateDelegateQt::Clear(const base::Callback<bool(const std::string & // prior to this query, otherwise false. content::SSLHostStateDelegate::CertJudgment SSLHostStateDelegateQt::QueryPolicy(const std::string &host, const net::X509Certificate &cert, - int error, - bool * /*expired_previous_decision*/) + int error, content::WebContents *) { return m_certPolicyforHost[host].Check(cert, error) ? SSLHostStateDelegate::ALLOWED : SSLHostStateDelegate::DENIED; } @@ -133,7 +132,7 @@ void SSLHostStateDelegateQt::RevokeUserAllowExceptions(const std::string &host) // |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) +bool SSLHostStateDelegateQt::HasAllowException(const std::string &host, content::WebContents *) { auto policy_iterator = m_certPolicyforHost.find(host); return policy_iterator != m_certPolicyforHost.end() && diff --git a/src/core/net/ssl_host_state_delegate_qt.h b/src/core/net/ssl_host_state_delegate_qt.h index e361aa0be..6b407353a 100644 --- a/src/core/net/ssl_host_state_delegate_qt.h +++ b/src/core/net/ssl_host_state_delegate_qt.h @@ -66,14 +66,13 @@ public: ~SSLHostStateDelegateQt(); // content::SSLHostStateDelegate implementation: - void AllowCert(const std::string &, const net::X509Certificate &cert, int error) override; - void Clear(const base::Callback<bool(const std::string &)> &host_filter) override; - CertJudgment QueryPolicy(const std::string &host, const net::X509Certificate &cert, int error, - bool *expired_previous_decision) override; + void AllowCert(const std::string &, const net::X509Certificate &cert, int error, content::WebContents *web_contents) override; + void Clear(base::RepeatingCallback<bool(const std::string&)> host_filter) override; + CertJudgment QueryPolicy(const std::string &host, const net::X509Certificate &cert, int error, content::WebContents *web_contents) 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) override; void RevokeUserAllowExceptions(const std::string &host) override; - bool HasAllowException(const std::string &host) override; + bool HasAllowException(const std::string &host, content::WebContents *web_contents) override; private: std::map<std::string, CertPolicy> m_certPolicyforHost; diff --git a/src/core/net/system_network_context_manager.cpp b/src/core/net/system_network_context_manager.cpp index cf84b840b..1fba115c6 100644 --- a/src/core/net/system_network_context_manager.cpp +++ b/src/core/net/system_network_context_manager.cpp @@ -44,42 +44,23 @@ #include "net/system_network_context_manager.h" -#include <set> -#include <unordered_map> -#include <utility> - #include "base/bind.h" #include "base/command_line.h" -#include "base/feature_list.h" -#include "base/logging.h" -#include "base/sequence_checker.h" -#include "base/strings/string_split.h" -#include "base/task/post_task.h" -#include "base/values.h" -#include "build/build_config.h" #include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" #include "chrome/common/chrome_switches.h" #include "components/certificate_transparency/ct_known_logs.h" -#include "components/network_session_configurator/common/network_features.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/cors_exempt_headers.h" +#include "components/network_session_configurator/common/network_switches.h" #include "content/public/browser/network_service_instance.h" -#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/common/service_names.mojom.h" -#include "content/public/common/user_agent.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" -#include "net/dns/public/util.h" #include "net/net_buildflags.h" -#include "net/third_party/uri_template/uri_template.h" #include "services/network/network_service.h" -#include "services/network/public/cpp/cross_thread_shared_url_loader_factory_info.h" +#include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/host_resolver.mojom.h" +#include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" -#include "url/gurl.h" namespace { @@ -100,8 +81,8 @@ network::mojom::HttpAuthDynamicParamsPtr CreateHttpAuthDynamicParams() network::mojom::HttpAuthDynamicParamsPtr auth_dynamic_params = network::mojom::HttpAuthDynamicParams::New(); auto *command_line = base::CommandLine::ForCurrentProcess(); - auth_dynamic_params->server_whitelist = command_line->GetSwitchValueASCII(switches::kAuthServerWhitelist); -// auth_dynamic_params->delegate_whitelist = command_line->GetSwitchValueASCII(switches::kAuthNegotiateDelegateWhitelist); + auth_dynamic_params->server_allowlist = command_line->GetSwitchValueASCII(switches::kAuthServerAllowlist); +// auth_dynamic_params->delegate_allowlist = command_line->GetSwitchValueASCII(switches::kAuthNegotiateDelegateWhitelist); // auth_dynamic_params->enable_negotiate_port = command_line->HasSwitch(switches::kEnableAuthNegotiatePort); return auth_dynamic_params; @@ -121,30 +102,34 @@ public: // mojom::URLLoaderFactory implementation: - void CreateLoaderAndStart(network::mojom::URLLoaderRequest request, int32_t routing_id, int32_t request_id, - uint32_t options, const network::ResourceRequest &url_request, - network::mojom::URLLoaderClientPtr client, + void CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> receiver, + int32_t routing_id, + int32_t request_id, + uint32_t options, + const network::ResourceRequest &url_request, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!manager_) return; - manager_->GetURLLoaderFactory()->CreateLoaderAndStart(std::move(request), routing_id, request_id, options, - url_request, std::move(client), traffic_annotation); + manager_->GetURLLoaderFactory()->CreateLoaderAndStart( + std::move(receiver), routing_id, request_id, options, url_request, + std::move(client), traffic_annotation); } - void Clone(network::mojom::URLLoaderFactoryRequest request) override + void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) override { if (!manager_) return; - manager_->GetURLLoaderFactory()->Clone(std::move(request)); + manager_->GetURLLoaderFactory()->Clone(std::move(receiver)); } // SharedURLLoaderFactory implementation: - std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override + std::unique_ptr<network::PendingSharedURLLoaderFactory> Clone() override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return std::make_unique<network::CrossThreadSharedURLLoaderFactoryInfo>(this); + return std::make_unique<network::CrossThreadPendingSharedURLLoaderFactory>(this); } void Shutdown() { manager_ = nullptr; } @@ -161,13 +146,8 @@ private: network::mojom::NetworkContext *SystemNetworkContextManager::GetContext() { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { - // SetUp should already have been called. - DCHECK(io_thread_network_context_); - return io_thread_network_context_.get(); - } - - if (!network_service_network_context_ || network_service_network_context_.encountered_error()) { + if (!network_service_network_context_ || + !network_service_network_context_.is_connected()) { // This should call into OnNetworkServiceCreated(), which will re-create // the network service, if needed. There's a chance that it won't be // invoked, if the NetworkContext has encountered an error but the @@ -183,14 +163,14 @@ network::mojom::NetworkContext *SystemNetworkContextManager::GetContext() network::mojom::URLLoaderFactory *SystemNetworkContextManager::GetURLLoaderFactory() { // Create the URLLoaderFactory as needed. - if (url_loader_factory_ && !url_loader_factory_.encountered_error()) { + if (url_loader_factory_ && url_loader_factory_.is_connected()) { return url_loader_factory_.get(); } network::mojom::URLLoaderFactoryParamsPtr params = network::mojom::URLLoaderFactoryParams::New(); params->process_id = network::mojom::kBrowserProcessId; params->is_corb_enabled = false; - GetContext()->CreateURLLoaderFactory(mojo::MakeRequest(&url_loader_factory_), std::move(params)); + GetContext()->CreateURLLoaderFactory(url_loader_factory_.BindNewPipeAndPassReceiver(), std::move(params)); return url_loader_factory_.get(); } @@ -199,23 +179,6 @@ scoped_refptr<network::SharedURLLoaderFactory> SystemNetworkContextManager::GetS return shared_url_loader_factory_; } -void SystemNetworkContextManager::SetUp( - network::mojom::NetworkContextRequest *network_context_request, - network::mojom::NetworkContextParamsPtr *network_context_params, bool *stub_resolver_enabled, - base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>> *dns_over_https_servers, - network::mojom::HttpAuthStaticParamsPtr *http_auth_static_params, - network::mojom::HttpAuthDynamicParamsPtr *http_auth_dynamic_params, bool *is_quic_allowed) -{ - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { - *network_context_request = mojo::MakeRequest(&io_thread_network_context_); - *network_context_params = CreateNetworkContextParams(); - } - *is_quic_allowed = false; - *http_auth_static_params = CreateHttpAuthStaticParams(); - *http_auth_dynamic_params = CreateHttpAuthDynamicParams(); - // GetStubResolverConfig(local_state_, stub_resolver_enabled, dns_over_https_servers); -} - // static SystemNetworkContextManager *SystemNetworkContextManager::CreateInstance() { @@ -249,17 +212,19 @@ SystemNetworkContextManager::~SystemNetworkContextManager() void SystemNetworkContextManager::OnNetworkServiceCreated(network::mojom::NetworkService *network_service) { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - return; + bool is_quic_force_enabled = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableQuic); // Disable QUIC globally - network_service->DisableQuic(); + if (!is_quic_force_enabled) + network_service->DisableQuic(); network_service->SetUpHttpAuth(CreateHttpAuthStaticParams()); network_service->ConfigureHttpAuthPrefs(CreateHttpAuthDynamicParams()); - // The system NetworkContext must be created first, since it sets - // |primary_network_context| to true. - network_service->CreateNetworkContext(MakeRequest(&network_service_network_context_), CreateNetworkContextParams()); + // The system NetworkContext is created first + network_service_network_context_.reset(); + network_service->CreateNetworkContext( + network_service_network_context_.BindNewPipeAndPassReceiver(), + CreateNetworkContextParams()); // Configure the stub resolver. This must be done after the system // NetworkContext is created, but before anything has the chance to use it. @@ -276,41 +241,21 @@ void SystemNetworkContextManager::AddSSLConfigToNetworkContextParams(network::mo network_context_params->initial_ssl_config->symantec_enforcement_disabled = true; } -network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateDefaultNetworkContextParams() +void SystemNetworkContextManager::ConfigureDefaultNetworkContextParams(network::mojom::NetworkContextParams *network_context_params) { - network::mojom::NetworkContextParamsPtr network_context_params = network::mojom::NetworkContextParams::New(); - content::UpdateCorsExemptHeader(network_context_params.get()); - network_context_params->enable_brotli = true; - // network_context_params->user_agent = GetUserAgent(); - // Disable referrers by default. Any consumer that enables referrers should // respect prefs::kEnableReferrers from the appropriate pref store. network_context_params->enable_referrers = false; - // const base::CommandLine& command_line = - // *base::CommandLine::ForCurrentProcess(); - - // // TODO(eroman): Figure out why this doesn't work in single-process mode, - // // or if it does work, now. - // // Should be possible now that a private isolate is used. - // // http://crbug.com/474654 - // if (!command_line.HasSwitch(switches::kWinHttpProxyResolver)) { - // if (command_line.HasSwitch(switches::kSingleProcess)) { - // LOG(ERROR) << "Cannot use V8 Proxy resolver in single process mode."; - // } else { network_context_params->proxy_resolver_factory = ChromeMojoProxyResolverFactory::CreateWithSelfOwnedReceiver(); - // } - // } - - // network_context_params->pac_quick_check_enabled = local_state_->GetBoolean(prefs::kQuickCheckEnabled); // Use the SystemNetworkContextManager to populate and update SSL // configuration. The SystemNetworkContextManager is owned by the // BrowserProcess itself, so will only be destroyed on shutdown, at which // point, all NetworkContexts will be destroyed as well. - AddSSLConfigToNetworkContextParams(network_context_params.get()); + AddSSLConfigToNetworkContextParams(network_context_params); // CT is only enabled on Desktop platforms for now. network_context_params->enforce_chrome_ct_policy = true; @@ -321,16 +266,13 @@ network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateDefau log_info->name = ct_log.log_name; network_context_params->ct_logs.push_back(std::move(log_info)); } - - network_context_params->http_09_on_non_default_ports_enabled = false; - - return network_context_params; } network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateNetworkContextParams() { // TODO(mmenke): Set up parameters here (in memory cookie store, etc). - network::mojom::NetworkContextParamsPtr network_context_params = CreateDefaultNetworkContextParams(); + network::mojom::NetworkContextParamsPtr network_context_params = network::mojom::NetworkContextParams::New(); + ConfigureDefaultNetworkContextParams(network_context_params.get()); network_context_params->context_name = std::string("system"); @@ -343,8 +285,6 @@ network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateNetwo network_context_params->enable_ftp_url_support = true; #endif - network_context_params->primary_network_context = true; - proxy_config_monitor_.AddToNetworkContextParams(network_context_params.get()); return network_context_params; diff --git a/src/core/net/system_network_context_manager.h b/src/core/net/system_network_context_manager.h index 288af5195..48cd99173 100644 --- a/src/core/net/system_network_context_manager.h +++ b/src/core/net/system_network_context_manager.h @@ -46,16 +46,10 @@ #define SYSTEM_NETWORK_CONTEXT_MANAGER_H_ #include <memory> -#include <string> -#include <vector> #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/optional.h" -#include "services/network/public/mojom/host_resolver.mojom-forward.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_service.mojom-forward.h" -#include "services/network/public/mojom/ssl_config.mojom-forward.h" #include "services/network/public/mojom/url_loader_factory.mojom-forward.h" #include "net/proxy_config_monitor.h" @@ -67,10 +61,6 @@ class URLLoaderFactory; class SharedURLLoaderFactory; } // namespace network -namespace net_log { -class NetExportFileWriter; -} - // Responsible for creating and managing access to the system NetworkContext. // Lives on the UI thread. The NetworkContext this owns is intended for requests // not associated with a profile. It stores no data on disk, and has no HTTP @@ -105,27 +95,6 @@ public: // Destroys the global SystemNetworkContextManager instance. static void DeleteInstance(); - // If the network service is disabled, |network_context_request| will be for - // the NetworkContext used by the SystemNetworkContextManager and - // |network_context_params| as needed to set up a system NetworkContext. - // Otherwise, this method can still be used to help set up the IOThread's - // in-process URLRequestContext. - // - // Must be called before the system NetworkContext is first used. - // - // |stub_resolver_enabled|, |dns_over_https_servers|, - // |http_auth_static_params|, |http_auth_dynamic_params|, and - // |is_quic_allowed| are used to pass initial NetworkService state to the - // caller, so the NetworkService can be configured appropriately. Using - // NetworkService's Mojo interface to set those options would lead to races - // with other UI->IO thread network-related tasks, since Mojo doesn't preserve - // execution order relative to PostTasks. - void SetUp(network::mojom::NetworkContextRequest *network_context_request, - network::mojom::NetworkContextParamsPtr *network_context_params, bool *stub_resolver_enabled, - base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>> *dns_over_https_servers, - network::mojom::HttpAuthStaticParamsPtr *http_auth_static_params, - network::mojom::HttpAuthDynamicParamsPtr *http_auth_dynamic_params, bool *is_quic_allowed); - // Returns the System NetworkContext. May only be called after SetUp(). Does // any initialization of the NetworkService that may be needed when first // called. @@ -151,8 +120,8 @@ public: // SSL configuration updates. void AddSSLConfigToNetworkContextParams(network::mojom::NetworkContextParams *network_context_params); - // Returns default set of parameters for configuring the network service. - network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams(); + // Configures the default set of parameters for the network context. + void ConfigureDefaultNetworkContextParams(network::mojom::NetworkContextParams *); private: class URLLoaderFactoryForSystem; @@ -167,17 +136,12 @@ private: // NetworkContext using the network service, if the network service is // enabled. nullptr, otherwise. - network::mojom::NetworkContextPtr network_service_network_context_; - - // This is a NetworkContext that wraps the IOThread's SystemURLRequestContext. - // Always initialized in SetUp, but it's only returned by Context() when the - // network service is disabled. - network::mojom::NetworkContextPtr io_thread_network_context_; + mojo::Remote<network::mojom::NetworkContext> network_service_network_context_; // URLLoaderFactory backed by the NetworkContext returned by GetContext(), so // consumers don't all need to create their own factory. scoped_refptr<URLLoaderFactoryForSystem> shared_url_loader_factory_; - network::mojom::URLLoaderFactoryPtr url_loader_factory_; + mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory_; ProxyConfigMonitor proxy_config_monitor_; diff --git a/src/core/net/url_request_context_getter_qt.cpp b/src/core/net/url_request_context_getter_qt.cpp deleted file mode 100644 index 6081a5e9f..000000000 --- a/src/core/net/url_request_context_getter_qt.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** 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 "profile_io_data_qt.h" - -#include "base/task/post_task.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" - -namespace QtWebEngineCore { - -URLRequestContextGetterQt::URLRequestContextGetterQt(ProfileIODataQt *data) - : m_profileIOData(data) -{ -} - -URLRequestContextGetterQt::~URLRequestContextGetterQt() -{ -} - -net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() -{ - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - return m_profileIOData->urlRequestContext(); -} - -scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const -{ - return base::CreateSingleThreadTaskRunnerWithTraits({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 deleted file mode 100644 index a6ef6eae0..000000000 --- a/src/core/net/url_request_context_getter_qt.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** 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" - -namespace QtWebEngineCore { - -class ProfileIODataQt; - -class URLRequestContextGetterQt : public net::URLRequestContextGetter -{ -public: - URLRequestContextGetterQt(ProfileIODataQt *data); - net::URLRequestContext *GetURLRequestContext() override; - scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; - -private: - virtual ~URLRequestContextGetterQt(); - ProfileIODataQt *m_profileIOData; -}; - -} // 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 deleted file mode 100644 index fe287d0b7..000000000 --- a/src/core/net/url_request_custom_job.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/**************************************************************************** -** -** 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 "api/qwebengineurlscheme.h" - -#include "base/strings/stringprintf.h" -#include "base/task/post_task.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "net/base/io_buffer.h" -#include "net/http/http_util.h" - -#include <QIODevice> - -using namespace net; - -namespace QtWebEngineCore { - -URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, - NetworkDelegate *networkDelegate, - const std::string &scheme, - QPointer<ProfileAdapter> profileAdapter) - : URLRequestJob(request, networkDelegate) - , m_taskRunner(base::CreateSingleThreadTaskRunner({ content::BrowserThread::IO })) - , m_proxy(new URLRequestCustomJobProxy(this, scheme, profileAdapter)) - , m_pendingReadSize(0) - , m_pendingReadPos(0) - , m_pendingReadBuffer(nullptr) - , m_corsEnabled(QWebEngineUrlScheme::schemeByName(QByteArray::fromStdString(scheme)) - .flags().testFlag(QWebEngineUrlScheme::CorsEnabled)) -{ - m_device = nullptr; - m_error = 0; -} - -URLRequestCustomJob::~URLRequestCustomJob() -{ - m_proxy->m_client = nullptr; - if (m_device && m_device->isOpen()) - m_device->close(); - m_device = nullptr; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy)); -} - -void URLRequestCustomJob::Start() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - HttpRequestHeaders requestHeaders = request()->extra_request_headers(); - std::map<std::string, std::string> headers; - net::HttpRequestHeaders::Iterator it(requestHeaders); - while (it.GetNext()) - headers.emplace(it.name(), it.value()); - if (!request()->referrer().empty()) - headers.emplace("Referer", request()->referrer()); - - // TODO: handle UploadDataStream, for instance using a QIODevice wrapper. - - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&URLRequestCustomJobProxy::initialize, - m_proxy, - request()->url(), - request()->method(), - request()->initiator(), - std::move(headers))); -} - -void URLRequestCustomJob::Kill() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - m_proxy->m_client = nullptr; - 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; - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&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; -} - -void URLRequestCustomJob::GetResponseInfo(HttpResponseInfo *info) -{ - // Based on net::URLRequestRedirectJob::StartAsync() - - if (m_error) - return; - - std::string headers; - if (m_redirect.is_valid()) { - headers += "HTTP/1.1 303 See Other\n"; - headers += base::StringPrintf("Location: %s\n", m_redirect.spec().c_str()); - } else { - headers += base::StringPrintf("HTTP/1.1 %i OK\n", 200); - if (m_mimeType.size() > 0) { - headers += base::StringPrintf("Content-Type: %s", m_mimeType.c_str()); - if (m_charset.size() > 0) - headers += base::StringPrintf("; charset=%s", m_charset.c_str()); - headers += "\n"; - } - } - if (m_corsEnabled) { - std::string origin; - if (request_->extra_request_headers().GetHeader("Origin", &origin)) { - headers += base::StringPrintf("Access-Control-Allow-Origin: %s\n", origin.c_str()); - headers += "Access-Control-Allow-Credentials: true\n"; - } - } - - info->headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders(headers)); -} - -bool URLRequestCustomJob::IsRedirectResponse(GURL *location, int *http_status_code, bool * /*insecure_scheme_was_upgraded*/) -{ - 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::notifyExpectedContentSize(qint64 size) -{ - set_expected_content_size(size); -} - -void URLRequestCustomJob::notifyHeadersComplete() -{ - NotifyHeadersComplete(); -} - -void URLRequestCustomJob::notifyCanceled() -{ - NotifyCanceled(); -} - -void URLRequestCustomJob::notifyAborted() -{ - NotifyStartError(URLRequestStatus(URLRequestStatus::CANCELED, net::ERR_ABORTED)); -} - -void URLRequestCustomJob::notifyStartFailure(int error) -{ - NotifyStartError(URLRequestStatus::FromError(error)); -} - -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(); -} - -base::TaskRunner *URLRequestCustomJob::taskRunner() -{ - return m_taskRunner.get(); -} - -} // namespace diff --git a/src/core/net/url_request_custom_job.h b/src/core/net/url_request_custom_job.h deleted file mode 100644 index 071a0a84f..000000000 --- a/src/core/net/url_request_custom_job.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** 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 "url_request_custom_job_proxy.h" - -#include <QtCore/QPointer> - -QT_FORWARD_DECLARE_CLASS(QIODevice) - -namespace QtWebEngineCore { - -class ProfileAdapter; -class URLRequestCustomJobDelegate; -class URLRequestCustomJobProxy; - -// A request job that handles reading custom URL schemes -class URLRequestCustomJob : public net::URLRequestJob, private URLRequestCustomJobProxy::Client -{ -public: - URLRequestCustomJob(net::URLRequest *request, - net::NetworkDelegate *networkDelegate, - const std::string &scheme, - QPointer<ProfileAdapter> profileAdapter); - // net::URLRequestJob: - 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; - void GetResponseInfo(net::HttpResponseInfo *info) override; - bool IsRedirectResponse(GURL *location, int *http_status_code, bool *insecure_scheme_was_upgraded) override; - -protected: - virtual ~URLRequestCustomJob(); - -private: - // URLRequestCustomJobProxy::Client: - void notifyExpectedContentSize(qint64 size) override; - void notifyHeadersComplete() override; - void notifyCanceled() override; - void notifyAborted() override; - void notifyStartFailure(int error) override; - void notifyReadyRead() override; - base::TaskRunner *taskRunner() override; - - scoped_refptr<base::TaskRunner> m_taskRunner; - scoped_refptr<URLRequestCustomJobProxy> m_proxy; - int m_pendingReadSize; - int m_pendingReadPos; - net::IOBuffer *m_pendingReadBuffer; - const bool m_corsEnabled; - - 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_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp index cd7e173ee..f734db645 100644 --- a/src/core/net/url_request_custom_job_proxy.cpp +++ b/src/core/net/url_request_custom_job_proxy.cpp @@ -96,9 +96,13 @@ void URLRequestCustomJobProxy::reply(std::string mimeType, QIODevice *device) if (m_client->m_device && !m_client->m_device->isReadable()) m_client->m_device->open(QIODevice::ReadOnly); - qint64 size = m_client->m_device ? m_client->m_device->size() : -1; - if (size > 0) - m_client->notifyExpectedContentSize(size); + if (m_client->m_firstBytePosition > 0) + m_client->m_device->seek(m_client->m_firstBytePosition); + + qint64 deviceSize = m_client->m_device ? m_client->m_device->size() : -1; + if (deviceSize > 0) + m_client->notifyExpectedContentSize(deviceSize); + if (m_client->m_device && m_client->m_device->isReadable()) { m_started = true; m_client->notifyHeadersComplete(); diff --git a/src/core/net/url_request_custom_job_proxy.h b/src/core/net/url_request_custom_job_proxy.h index 7091c8319..b14322f91 100644 --- a/src/core/net/url_request_custom_job_proxy.h +++ b/src/core/net/url_request_custom_job_proxy.h @@ -42,7 +42,7 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" -#include "base/task_runner.h" +#include "base/sequenced_task_runner.h" #include "url/gurl.h" #include "url/origin.h" #include <QtCore/QPointer> @@ -67,6 +67,7 @@ public: std::string m_charset; GURL m_redirect; QIODevice *m_device; + int64_t m_firstBytePosition; int m_error; virtual void notifyExpectedContentSize(qint64 size) = 0; virtual void notifyHeadersComplete() = 0; @@ -74,7 +75,7 @@ public: virtual void notifyAborted() = 0; virtual void notifyStartFailure(int) = 0; virtual void notifyReadyRead() = 0; - virtual base::TaskRunner *taskRunner() = 0; + virtual base::SequencedTaskRunner *taskRunner() = 0; }; URLRequestCustomJobProxy(Client *client, @@ -100,7 +101,7 @@ public: std::string m_scheme; URLRequestCustomJobDelegate *m_delegate; QPointer<ProfileAdapter> m_profileAdapter; - scoped_refptr<base::TaskRunner> m_ioTaskRunner; + scoped_refptr<base::SequencedTaskRunner> m_ioTaskRunner; }; } // namespace QtWebEngineCore diff --git a/src/core/net/url_request_notification.cpp b/src/core/net/url_request_notification.cpp deleted file mode 100644 index 74c56254e..000000000 --- a/src/core/net/url_request_notification.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "url_request_notification.h" - -#include "base/supports_user_data.h" -#include "base/task/post_task.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_thread.h" -#include "net/url_request/url_request.h" - -#include "api/qwebengineurlrequestinfo_p.h" -#include "profile_io_data_qt.h" -#include "type_conversion.h" -#include "web_contents_adapter_client.h" -#include "web_contents_view_qt.h" - -#include <QVariant> - -namespace QtWebEngineCore { - -// Calls cancel() when the URLRequest is destroyed. -class UserData : public base::SupportsUserData::Data -{ -public: - UserData(URLRequestNotification *ptr) : m_ptr(ptr) {} - ~UserData() { m_ptr->cancel(); } - static const char key[]; - -private: - URLRequestNotification *m_ptr; -}; - -const char UserData::key[] = "QtWebEngineCore::URLRequestNotification"; - -URLRequestNotification::URLRequestNotification(net::URLRequest *request, bool isMainFrameRequest, GURL *newUrl, - QWebEngineUrlRequestInfo &&requestInfo, - content::ResourceRequestInfo::WebContentsGetter webContentsGetter, - net::CompletionOnceCallback callback, QPointer<ProfileAdapter> adapter) - : m_request(request) - , m_isMainFrameRequest(isMainFrameRequest) - , m_newUrl(newUrl) - , m_originalUrl(requestInfo.requestUrl()) - , m_requestInfo(std::move(requestInfo)) - , m_webContentsGetter(webContentsGetter) - , m_callback(std::move(callback)) - , m_profileAdapter(adapter) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - m_request->SetUserData(UserData::key, std::make_unique<UserData>(this)); - - base::PostTaskWithTraits( - FROM_HERE, - {content::BrowserThread::UI}, - base::BindOnce(&URLRequestNotification::notify, base::Unretained(this))); -} - - -void URLRequestNotification::notify() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // May run concurrently with cancel() so no peeking at m_request here. - - int result = net::OK; - content::WebContents *webContents = m_webContentsGetter.Run(); - - if (webContents) { - if (m_profileAdapter && m_profileAdapter->requestInterceptor()) { - QWebEngineUrlRequestInterceptor *interceptor = m_profileAdapter->requestInterceptor(); - if (!interceptor->property("deprecated").toBool()) - interceptor->interceptRequest(m_requestInfo); - } - - WebContentsAdapterClient *client = - WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); - - if (!m_requestInfo.changed()) { - client->interceptRequest(m_requestInfo); - } - - if (m_requestInfo.changed()) { - result = m_requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK; - // We handle the rest of the changes later when we are back in I/O thread - } - } - - // Run the callback on the IO thread. - base::PostTaskWithTraits( - FROM_HERE, - {content::BrowserThread::IO}, - base::BindOnce(&URLRequestNotification::complete, base::Unretained(this), result)); -} - -void URLRequestNotification::cancel() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - // May run concurrently with notify() but we only touch m_request here. - - m_request = nullptr; -} - -void URLRequestNotification::complete(int error) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (m_request) { - if (m_requestInfo.changed()) { - if (m_originalUrl != m_requestInfo.d_ptr->url) - *m_newUrl = toGurl(m_requestInfo.d_ptr->url); - - if (!m_requestInfo.d_ptr->extraHeaders.isEmpty()) { - auto end = m_requestInfo.d_ptr->extraHeaders.constEnd(); - for (auto header = m_requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header) { - std::string h = header.key().toStdString(); - if (base::LowerCaseEqualsASCII(h, "referer")) { - m_request->SetReferrer(header.value().toStdString()); - } else { - m_request->SetExtraRequestHeaderByName(h, header.value().toStdString(), /* overwrite */ true); - } - } - } - } - - if (m_request->status().status() != net::URLRequestStatus::CANCELED) - std::move(m_callback).Run(error); - m_request->RemoveUserData(UserData::key); - } - - delete this; -} - -} diff --git a/src/core/net/webui_controller_factory_qt.cpp b/src/core/net/webui_controller_factory_qt.cpp index 8c045bb7b..b645a6d72 100644 --- a/src/core/net/webui_controller_factory_qt.cpp +++ b/src/core/net/webui_controller_factory_qt.cpp @@ -44,39 +44,37 @@ #include "webui_controller_factory_qt.h" +#include "build_config_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/accessibility/accessibility_ui.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/devtools_ui.h" +#include "chrome/browser/ui/webui/net_internals/net_internals_ui.h" #include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h" +#include "chrome/browser/ui/webui/user_actions/user_actions_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/buildflags/buildflags.h" #include "media/media_buildflags.h" #include "ppapi/buildflags/buildflags.h" #include "printing/buildflags/buildflags.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" +#include "chrome/browser/ui/webui/sandbox/sandbox_internals_ui.h" +#endif + +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +#include "chrome/browser/ui/webui/media/webrtc_logs_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" @@ -119,6 +117,8 @@ std::unique_ptr<WebUIController> NewWebUI(WebUI *web_ui, const GURL & /*url*/) // with it. WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, const GURL &url) { + Q_UNUSED(web_ui); + Q_UNUSED(profile); // 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)) @@ -126,6 +126,9 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, co // We must compare hosts only since some of the Web UIs append extra stuff // after the host name. + if (url.host() == chrome::kChromeUINetInternalsHost) + return &NewWebUI<NetInternalsUI>; + if (url.host() == chrome::kChromeUIQuotaInternalsHost) return &NewWebUI<QuotaInternalsUI>; @@ -137,8 +140,9 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, co if (url.host() == chrome::kChromeUIAccessibilityHost) return &NewWebUI<AccessibilityUI>; -// if (url.host_piece() == chrome::kChromeUIUserActionsHost) -// return &NewWebUI<UserActionsUI>; + if (url.host_piece() == chrome::kChromeUIUserActionsHost) + return &NewWebUI<UserActionsUI>; + // if (url.host_piece() == chrome::kChromeUIInspectHost) // return &NewWebUI<InspectUI>; // @@ -150,20 +154,16 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, co // 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 QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) + 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>; diff --git a/src/core/net/webui_controller_factory_qt.h b/src/core/net/webui_controller_factory_qt.h index 1cc76349b..6dfc612e1 100644 --- a/src/core/net/webui_controller_factory_qt.h +++ b/src/core/net/webui_controller_factory_qt.h @@ -42,16 +42,8 @@ #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 { |