68665b3286ee998f42cdcd2545d1090c25f77958
[WebKit-https.git] / Source / WebCore / platform / 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 "CookieJar.h"
34 #include "Document.h"
35 #include "Frame.h"
36 #include "FrameLoader.h"
37 #include "KURL.h"
38 #include "NetworkingContext.h"
39 #include "ThirdPartyCookiesQt.h"
40 #include <QDateTime>
41 #include <QNetworkAccessManager>
42 #include <QNetworkCookie>
43 #include <QSqlQuery>
44 #include <QStringList>
45 #include <QVariant>
46 #include <wtf/text/WTFString.h>
47
48 namespace WebCore {
49
50 static SharedCookieJarQt* s_sharedCookieJarQt = 0;
51
52 static NetworkingContext* networkingContext(const Document* document)
53 {
54     if (!document)
55         return 0;
56     Frame* frame = document->frame();
57     if (!frame)
58         return 0;
59     FrameLoader* loader = frame->loader();
60     if (!loader)
61         return 0;
62     return loader->networkingContext();
63 }
64
65 void setCookies(Document* document, const KURL& url, const String& value)
66 {
67     NetworkingContext* context = networkingContext(document);
68     if (!context)
69         return;
70     QNetworkCookieJar* jar = context->networkAccessManager()->cookieJar();
71     if (!jar)
72         return;
73
74     QUrl urlForCookies(url);
75     QUrl firstPartyUrl(document->firstPartyForCookies());
76     if (!thirdPartyCookiePolicyPermits(context, urlForCookies, firstPartyUrl))
77         return;
78
79     QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(QString(value).toLatin1());
80     QList<QNetworkCookie>::Iterator it = cookies.begin();
81     while (it != cookies.end()) {
82         if (it->isHttpOnly())
83             it = cookies.erase(it);
84         else
85             ++it;
86     }
87
88     jar->setCookiesFromUrl(cookies, urlForCookies);
89 }
90
91 String cookies(const Document* document, const KURL& url)
92 {
93     NetworkingContext* context = networkingContext(document);
94     if (!context)
95         return String();
96     QNetworkCookieJar* jar = context->networkAccessManager()->cookieJar();
97
98     QUrl urlForCookies(url);
99     QUrl firstPartyUrl(document->firstPartyForCookies());
100     if (!thirdPartyCookiePolicyPermits(context, urlForCookies, firstPartyUrl))
101         return String();
102
103     QList<QNetworkCookie> cookies = jar->cookiesForUrl(urlForCookies);
104     if (cookies.isEmpty())
105         return String();
106
107     QStringList resultCookies;
108     foreach (const QNetworkCookie& networkCookie, cookies) {
109         if (networkCookie.isHttpOnly())
110             continue;
111         resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData()));
112     }
113
114     return resultCookies.join(QLatin1String("; "));
115 }
116
117 String cookieRequestHeaderFieldValue(const Document* document, const KURL &url)
118 {
119     NetworkingContext* context = networkingContext(document);
120     if (!context)
121         return String();
122     QNetworkCookieJar* jar = context->networkAccessManager()->cookieJar();
123
124     QList<QNetworkCookie> cookies = jar->cookiesForUrl(QUrl(url));
125     if (cookies.isEmpty())
126         return String();
127
128     QStringList resultCookies;
129     foreach (QNetworkCookie networkCookie, cookies)
130         resultCookies.append(QString::fromLatin1(networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData()));
131
132     return resultCookies.join(QLatin1String("; "));
133 }
134
135 bool cookiesEnabled(const Document* document)
136 {
137     NetworkingContext* context = networkingContext(document);
138     if (!context)
139         return false;
140     return context->networkAccessManager()->cookieJar();
141 }
142
143 bool getRawCookies(const Document*, const KURL&, Vector<Cookie>& rawCookies)
144 {
145     // FIXME: Not yet implemented
146     rawCookies.clear();
147     return false; // return true when implemented
148 }
149
150 void deleteCookie(const Document*, const KURL&, const String&)
151 {
152     // FIXME: Not yet implemented
153 }
154
155 void getHostnamesWithCookies(HashSet<String>& hostnames)
156 {
157     SharedCookieJarQt* jar = SharedCookieJarQt::shared();
158     if (jar)
159         jar->getHostnamesWithCookies(hostnames);
160 }
161
162 void deleteCookiesForHostname(const String& hostname)
163 {
164     SharedCookieJarQt* jar = SharedCookieJarQt::shared();
165     if (jar)
166         jar->deleteCookiesForHostname(hostname);
167 }
168
169 void deleteAllCookies()
170 {
171     SharedCookieJarQt* jar = SharedCookieJarQt::shared();
172     if (jar)
173         jar->deleteAllCookies();
174 }
175
176 SharedCookieJarQt* SharedCookieJarQt::shared()
177 {
178     return s_sharedCookieJarQt;
179 }
180
181 SharedCookieJarQt* SharedCookieJarQt::create(const String& cookieStorageDirectory)
182 {
183     if (!s_sharedCookieJarQt)
184         s_sharedCookieJarQt = new SharedCookieJarQt(cookieStorageDirectory);
185
186     return s_sharedCookieJarQt;
187 }
188
189 void SharedCookieJarQt::destroy()
190 {
191     delete s_sharedCookieJarQt;
192     s_sharedCookieJarQt = 0;
193 }
194
195 void SharedCookieJarQt::getHostnamesWithCookies(HashSet<String>& hostnames)
196 {
197     QList<QNetworkCookie> cookies = allCookies();
198     foreach (const QNetworkCookie& networkCookie, cookies)
199         hostnames.add(networkCookie.domain());
200 }
201
202 bool SharedCookieJarQt::deleteCookie(const QNetworkCookie& cookie)
203 {
204     if (!QNetworkCookieJar::deleteCookie(cookie))
205         return false;
206
207     if (!m_database.isOpen())
208         return false;
209
210     QSqlQuery sqlQuery(m_database);
211     sqlQuery.prepare(QLatin1String("DELETE FROM cookies WHERE cookieId=:cookieIdvalue"));
212     sqlQuery.bindValue(QLatin1String(":cookieIdvalue"), cookie.domain().append(QLatin1String(cookie.name())));
213     sqlQuery.exec();
214
215     return true;
216 }
217
218 void SharedCookieJarQt::deleteCookiesForHostname(const String& hostname)
219 {
220     if (!m_database.isOpen())
221         return;
222
223     QList<QNetworkCookie> cookies = allCookies();
224     QList<QNetworkCookie>::Iterator it = cookies.begin();
225     QList<QNetworkCookie>::Iterator end = cookies.end();
226     QSqlQuery sqlQuery(m_database);
227     sqlQuery.prepare(QLatin1String("DELETE FROM cookies WHERE cookieId=:cookieIdvalue"));
228     while (it != end) {
229         if (it->domain() == QString(hostname)) {
230             sqlQuery.bindValue(QLatin1String(":cookieIdvalue"), it->domain().append(QLatin1String(it->name())));
231             sqlQuery.exec();
232             it = cookies.erase(it);
233         } else
234             it++;
235     }
236     setAllCookies(cookies);
237 }
238
239 void SharedCookieJarQt::deleteAllCookies()
240 {
241     if (!m_database.isOpen())
242         return;
243
244     QSqlQuery sqlQuery(m_database);
245     sqlQuery.prepare(QLatin1String("DELETE * FROM cookies"));
246     sqlQuery.exec();
247     setAllCookies(QList<QNetworkCookie>());
248 }
249
250 SharedCookieJarQt::SharedCookieJarQt(const String& cookieStorageDirectory)
251 {
252     m_database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"));
253     const QString cookieStoragePath = cookieStorageDirectory;
254     const QString dataBaseName = cookieStoragePath + QLatin1String("/cookies.db");
255     m_database.setDatabaseName(dataBaseName);
256     ensureDatabaseTable();
257     loadCookies();
258 }
259
260 SharedCookieJarQt::~SharedCookieJarQt()
261 {
262     m_database.close();
263 }
264
265 bool SharedCookieJarQt::setCookiesFromUrl(const QList<QNetworkCookie>& cookieList, const QUrl& url)
266 {
267     if (!QNetworkCookieJar::setCookiesFromUrl(cookieList, url))
268         return false;
269
270     if (!m_database.isOpen())
271         return false;
272
273     QSqlQuery sqlQuery(m_database);
274     sqlQuery.prepare(QLatin1String("INSERT OR REPLACE INTO cookies (cookieId, cookie) VALUES (:cookieIdvalue, :cookievalue)"));
275     QVariantList cookiesIds;
276     QVariantList cookiesValues;
277     foreach (const QNetworkCookie &cookie, cookiesForUrl(url)) {
278         if (cookie.isSessionCookie())
279             continue;
280         cookiesIds.append(cookie.domain().append(QLatin1String(cookie.name())));
281         cookiesValues.append(cookie.toRawForm());
282     }
283     sqlQuery.bindValue(QLatin1String(":cookieIdvalue"), cookiesIds);
284     sqlQuery.bindValue(QLatin1String(":cookievalue"), cookiesValues);
285     sqlQuery.execBatch();
286     return true;
287 }
288
289 void SharedCookieJarQt::ensureDatabaseTable()
290 {
291     if (!m_database.open()) {
292         qWarning("Can't open cookie database");
293         return;
294     }
295     m_database.exec(QLatin1String("PRAGMA synchronous=OFF"));
296
297     QSqlQuery sqlQuery(m_database);
298     sqlQuery.prepare(QLatin1String("CREATE TABLE IF NOT EXISTS cookies (cookieId VARCHAR PRIMARY KEY, cookie BLOB);"));
299     sqlQuery.exec();
300 }
301
302 void SharedCookieJarQt::loadCookies()
303 {
304     if (!m_database.isOpen())
305         return;
306
307     QList<QNetworkCookie> cookies;
308     QSqlQuery sqlQuery(m_database);
309     sqlQuery.prepare(QLatin1String("SELECT cookie FROM cookies"));
310     sqlQuery.exec();
311     while (sqlQuery.next())
312         cookies.append(QNetworkCookie::parseCookies(sqlQuery.value(0).toByteArray()));
313     setAllCookies(cookies);
314 }
315
316 #include "moc_CookieJarQt.cpp"
317
318 }
319
320 // vim: ts=4 sw=4 et