CookieJar uses Document class, which is a layering violation
[WebKit-https.git] / Source / WebCore / platform / network / qt / CookieJarQt.cpp
1 /*
2  * Copyright (C) 2006 George Staikos <staikos@kde.org>
3  * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "CookieJarQt.h"
31
32 #include "Cookie.h"
33 #include "KURL.h"
34 #include "NetworkingContext.h"
35 #include "PlatformCookieJar.h"
36 #include "ThirdPartyCookiesQt.h"
37 #include <QDateTime>
38 #include <QNetworkAccessManager>
39 #include <QNetworkCookie>
40 #include <QSqlQuery>
41 #include <QStringList>
42 #include <QVariant>
43 #include <wtf/text/WTFString.h>
44
45 namespace WebCore {
46
47 static SharedCookieJarQt* s_sharedCookieJarQt = 0;
48
49 void setCookiesFromDOM(NetworkingContext* context, const KURL& firstParty, const KURL& url, const String& value)
50 {
51     QNetworkCookieJar* jar = context ? context->networkAccessManager()->cookieJar() : SharedCookieJarQt::shared();
52     if (!jar)
53         return;
54
55     QUrl urlForCookies(url);
56     QUrl firstPartyUrl(firstParty);
57     if (!thirdPartyCookiePolicyPermits(context, urlForCookies, firstPartyUrl))
58         return;
59
60     QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(QString(value).toLatin1());
61     QList<QNetworkCookie>::Iterator it = cookies.begin();
62     while (it != cookies.end()) {
63         if (it->isHttpOnly())
64             it = cookies.erase(it);
65         else
66             ++it;
67     }
68
69     jar->setCookiesFromUrl(cookies, urlForCookies);
70 }
71
72 String cookiesForDOM(NetworkingContext* context, const KURL& firstParty, const KURL& url)
73 {
74     QNetworkCookieJar* jar = context ? context->networkAccessManager()->cookieJar() : SharedCookieJarQt::shared();
75     if (!jar)
76         return String();
77
78     QUrl urlForCookies(url);
79     QUrl firstPartyUrl(firstParty);
80     if (!thirdPartyCookiePolicyPermits(context, urlForCookies, firstPartyUrl))
81         return String();
82
83     QList<QNetworkCookie> cookies = jar->cookiesForUrl(urlForCookies);
84     if (cookies.isEmpty())
85         return String();
86
87     QStringList resultCookies;
88     foreach (const QNetworkCookie& networkCookie, cookies) {
89         if (networkCookie.isHttpOnly())
90             continue;
91         resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData()));
92     }
93
94     return resultCookies.join(QLatin1String("; "));
95 }
96
97 String cookieRequestHeaderFieldValue(NetworkingContext* context, const KURL &url)
98 {
99     QNetworkCookieJar* jar = context ? context->networkAccessManager()->cookieJar() : SharedCookieJarQt::shared();
100     if (!jar)
101         return String();
102
103     QList<QNetworkCookie> cookies = jar->cookiesForUrl(QUrl(url));
104     if (cookies.isEmpty())
105         return String();
106
107     QStringList resultCookies;
108     foreach (QNetworkCookie networkCookie, cookies)
109         resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData()));
110
111     return resultCookies.join(QLatin1String("; "));
112 }
113
114 bool cookiesEnabled(NetworkingContext* context)
115 {
116     QNetworkCookieJar* jar = context ? context->networkAccessManager()->cookieJar() : SharedCookieJarQt::shared();
117     return !!jar;
118 }
119
120 bool getRawCookies(NetworkingContext*, const KURL&, Vector<Cookie>& rawCookies)
121 {
122     // FIXME: Not yet implemented
123     rawCookies.clear();
124     return false; // return true when implemented
125 }
126
127 void deleteCookie(NetworkingContext*, const KURL&, const String&)
128 {
129     // FIXME: Not yet implemented
130 }
131
132 void getHostnamesWithCookies(NetworkingContext* context, HashSet<String>& hostnames)
133 {
134     ASSERT_UNUSED(context, !context); // Not yet implemented for cookie jars other than the shared one.
135     SharedCookieJarQt* jar = SharedCookieJarQt::shared();
136     if (jar)
137         jar->getHostnamesWithCookies(hostnames);
138 }
139
140 void deleteCookiesForHostname(NetworkingContext* context, const String& hostname)
141 {
142     ASSERT_UNUSED(context, !context); // Not yet implemented for cookie jars other than the shared one.
143     SharedCookieJarQt* jar = SharedCookieJarQt::shared();
144     if (jar)
145         jar->deleteCookiesForHostname(hostname);
146 }
147
148 void deleteAllCookies(NetworkingContext* context)
149 {
150     ASSERT_UNUSED(context, !context); // Not yet implemented for cookie jars other than the shared one.
151     SharedCookieJarQt* jar = SharedCookieJarQt::shared();
152     if (jar)
153         jar->deleteAllCookies();
154 }
155
156 SharedCookieJarQt* SharedCookieJarQt::shared()
157 {
158     return s_sharedCookieJarQt;
159 }
160
161 SharedCookieJarQt* SharedCookieJarQt::create(const String& cookieStorageDirectory)
162 {
163     if (!s_sharedCookieJarQt)
164         s_sharedCookieJarQt = new SharedCookieJarQt(cookieStorageDirectory);
165
166     return s_sharedCookieJarQt;
167 }
168
169 void SharedCookieJarQt::destroy()
170 {
171     delete s_sharedCookieJarQt;
172     s_sharedCookieJarQt = 0;
173 }
174
175 void SharedCookieJarQt::getHostnamesWithCookies(HashSet<String>& hostnames)
176 {
177     QList<QNetworkCookie> cookies = allCookies();
178     foreach (const QNetworkCookie& networkCookie, cookies)
179         hostnames.add(networkCookie.domain());
180 }
181
182 bool SharedCookieJarQt::deleteCookie(const QNetworkCookie& cookie)
183 {
184     if (!QNetworkCookieJar::deleteCookie(cookie))
185         return false;
186
187     if (!m_database.isOpen())
188         return false;
189
190     QSqlQuery sqlQuery(m_database);
191     sqlQuery.prepare(QLatin1String("DELETE FROM cookies WHERE cookieId=:cookieIdvalue"));
192     sqlQuery.bindValue(QLatin1String(":cookieIdvalue"), cookie.domain().append(QLatin1String(cookie.name())));
193     sqlQuery.exec();
194
195     return true;
196 }
197
198 void SharedCookieJarQt::deleteCookiesForHostname(const String& hostname)
199 {
200     if (!m_database.isOpen())
201         return;
202
203     QList<QNetworkCookie> cookies = allCookies();
204     QList<QNetworkCookie>::Iterator it = cookies.begin();
205     QList<QNetworkCookie>::Iterator end = cookies.end();
206     QSqlQuery sqlQuery(m_database);
207     sqlQuery.prepare(QLatin1String("DELETE FROM cookies WHERE cookieId=:cookieIdvalue"));
208     while (it != end) {
209         if (it->domain() == QString(hostname)) {
210             sqlQuery.bindValue(QLatin1String(":cookieIdvalue"), it->domain().append(QLatin1String(it->name())));
211             sqlQuery.exec();
212             it = cookies.erase(it);
213         } else
214             it++;
215     }
216     setAllCookies(cookies);
217 }
218
219 void SharedCookieJarQt::deleteAllCookies()
220 {
221     if (!m_database.isOpen())
222         return;
223
224     QSqlQuery sqlQuery(m_database);
225     sqlQuery.prepare(QLatin1String("DELETE * FROM cookies"));
226     sqlQuery.exec();
227     setAllCookies(QList<QNetworkCookie>());
228 }
229
230 SharedCookieJarQt::SharedCookieJarQt(const String& cookieStorageDirectory)
231 {
232     m_database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"));
233     const QString cookieStoragePath = cookieStorageDirectory;
234     const QString dataBaseName = cookieStoragePath + QLatin1String("/cookies.db");
235     m_database.setDatabaseName(dataBaseName);
236     ensureDatabaseTable();
237     loadCookies();
238 }
239
240 SharedCookieJarQt::~SharedCookieJarQt()
241 {
242     m_database.close();
243 }
244
245 bool SharedCookieJarQt::setCookiesFromUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url)
246 {
247     if (!QNetworkCookieJar::setCookiesFromUrl(cookieList, url))
248         return false;
249
250     if (!m_database.isOpen())
251         return false;
252
253     QSqlQuery sqlQuery(m_database);
254     sqlQuery.prepare(QLatin1String("INSERT OR REPLACE INTO cookies (cookieId, cookie) VALUES (:cookieIdvalue, :cookievalue)"));
255     QVariantList cookiesIds;
256     QVariantList cookiesValues;
257     foreach (const QNetworkCookie &cookie, cookiesForUrl(url)) {
258         if (cookie.isSessionCookie())
259             continue;
260         cookiesIds.append(cookie.domain().append(QLatin1String(cookie.name())));
261         cookiesValues.append(cookie.toRawForm());
262     }
263     sqlQuery.bindValue(QLatin1String(":cookieIdvalue"), cookiesIds);
264     sqlQuery.bindValue(QLatin1String(":cookievalue"), cookiesValues);
265     sqlQuery.execBatch();
266     return true;
267 }
268
269 void SharedCookieJarQt::ensureDatabaseTable()
270 {
271     if (!m_database.open()) {
272         qWarning("Can't open cookie database");
273         return;
274     }
275     m_database.exec(QLatin1String("PRAGMA synchronous=OFF"));
276
277     QSqlQuery sqlQuery(m_database);
278     sqlQuery.prepare(QLatin1String("CREATE TABLE IF NOT EXISTS cookies (cookieId VARCHAR PRIMARY KEY, cookie BLOB);"));
279     sqlQuery.exec();
280 }
281
282 void SharedCookieJarQt::loadCookies()
283 {
284     if (!m_database.isOpen())
285         return;
286
287     QList<QNetworkCookie> cookies;
288     QSqlQuery sqlQuery(m_database);
289     sqlQuery.prepare(QLatin1String("SELECT cookie FROM cookies"));
290     sqlQuery.exec();
291     while (sqlQuery.next())
292         cookies.append(QNetworkCookie::parseCookies(sqlQuery.value(0).toByteArray()));
293     setAllCookies(cookies);
294 }
295
296 #include "moc_CookieJarQt.cpp"
297
298 }
299
300 // vim: ts=4 sw=4 et