blob: dad9a8db50f6e0189be6bc73b2775435730fc69a [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "cookie_monster_delegate_qt.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "net/cookies/cookie_util.h"
#include "api/qwebenginecookiestore.h"
#include "api/qwebenginecookiestore_p.h"
#include "type_conversion.h"
namespace QtWebEngineCore {
static GURL sourceUrlForCookie(const QNetworkCookie &cookie)
{
QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path());
return net::cookie_util::CookieOriginToURL(urlFragment.toStdString(), /* is_https */ cookie.isSecure());
}
CookieMonsterDelegateQt::CookieMonsterDelegateQt()
: m_client(0)
, m_cookieMonster(nullptr)
{
}
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)));
m_subscriptions.push_back(std::move(sub));
}
bool CookieMonsterDelegateQt::hasCookieMonster()
{
return m_cookieMonster;
}
void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId)
{
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)
{
if (m_cookieMonster)
m_cookieMonster->GetAllCookiesAsync(std::move(callback));
}
void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin)
{
Q_ASSERT(hasCookieMonster());
Q_ASSERT(m_client);
net::CookieStore::SetCookiesCallback callback;
if (callbackId != CallbackDirectory::NoCallbackId)
callback = base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnIOThread, this, callbackId);
GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin);
base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&CookieMonsterDelegateQt::SetCookieOnIOThread, this,
gurl, cookie.toRawForm().toStdString(), std::move(callback)));
}
void CookieMonsterDelegateQt::SetCookieOnIOThread(const GURL &url, const std::string &cookie_line,
net::CookieMonster::SetCookiesCallback callback)
{
net::CookieOptions options;
options.set_include_httponly();
if (m_cookieMonster)
m_cookieMonster->SetCookieWithOptionsAsync(url, cookie_line, options, std::move(callback));
}
void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin)
{
Q_ASSERT(hasCookieMonster());
Q_ASSERT(m_client);
GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin);
base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this,
gurl, cookie.name().toStdString()));
}
void CookieMonsterDelegateQt::DeleteCookieOnIOThread(const GURL &url, const std::string &cookie_name)
{
if (m_cookieMonster) {
net::CookieMonster::GetCookieListCallback callback =
base::BindOnce(&CookieMonsterDelegateQt::GetCookiesToDeleteCallback, this, cookie_name);
m_cookieMonster->GetAllCookiesForURLAsync(url, std::move(callback));
}
}
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);
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)
{
if (m_cookieMonster)
m_cookieMonster->DeleteSessionCookiesAsync(std::move(callback));
}
void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId)
{
Q_ASSERT(hasCookieMonster());
Q_ASSERT(m_client);
net::CookieMonster::DeleteCallback callback =
base::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)
{
if (m_cookieMonster)
m_cookieMonster->DeleteAllAsync(std::move(callback));
}
void CookieMonsterDelegateQt::setCookieMonster(net::CookieMonster *monster)
{
if (monster == m_cookieMonster)
return;
m_subscriptions.clear();
if (monster)
AddStore(monster);
m_cookieMonster = monster;
if (!m_client)
return;
if (monster)
m_client->d_func()->processPendingUserCookies();
else
m_client->d_func()->rejectPendingUserCookies();
}
void CookieMonsterDelegateQt::setClient(QWebEngineCookieStore *client)
{
m_client = client;
if (!m_client)
return;
m_client->d_func()->delegate = this;
if (hasCookieMonster())
m_client->d_func()->processPendingUserCookies();
}
bool CookieMonsterDelegateQt::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &/*cookieLine*/, const QUrl &url) const
{
if (!m_client)
return true;
return m_client->d_func()->canAccessCookies(firstPartyUrl, url);
}
bool CookieMonsterDelegateQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const
{
if (!m_client)
return true;
return m_client->d_func()->canAccessCookies(firstPartyUrl, url);
}
void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie &cookie, net::CookieChangeCause cause)
{
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)
{
QByteArray rawCookies;
for (auto &&cookie : cookies)
rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n");
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId, rawCookies));
}
void CookieMonsterDelegateQt::SetCookieCallbackOnIOThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status)
{
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId, status));
}
void CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies)
{
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId, numCookies));
}
void CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread(qint64 callbackId, const QByteArray &cookies)
{
if (m_client)
m_client->d_func()->onGetAllCallbackResult(callbackId, cookies);
}
void CookieMonsterDelegateQt::SetCookieCallbackOnUIThread(qint64 callbackId, net::CanonicalCookie::CookieInclusionStatus status)
{
if (m_client)
m_client->d_func()->onSetCallbackResult(callbackId,
status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
}
void CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread(qint64 callbackId, uint numCookies)
{
if (m_client)
m_client->d_func()->onDeleteCallbackResult(callbackId, numCookies);
}
}