Clean up which storage cookie jar functions use
[WebKit-https.git] / Source / WebCore / platform / mac / CookieJar.mm
1 /*
2  * Copyright (C) 2003, 2006, 2008, 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "CookieJar.h"
28
29 #if !USE(CFNETWORK)
30
31 #import "BlockExceptions.h"
32 #import "Cookie.h"
33 #import "CookieStorage.h"
34 #import "CookieStorageCFNet.h"
35 #import "Document.h"
36 #import "WebCoreSystemInterface.h"
37
38 namespace WebCore {
39
40 static RetainPtr<NSArray> filterCookies(NSArray *unfilteredCookies)
41 {
42     NSUInteger count = [unfilteredCookies count];
43     RetainPtr<NSMutableArray> filteredCookies(AdoptNS, [[NSMutableArray alloc] initWithCapacity:count]);
44
45     for (NSUInteger i = 0; i < count; ++i) {
46         NSHTTPCookie *cookie = (NSHTTPCookie *)[unfilteredCookies objectAtIndex:i];
47
48         // <rdar://problem/5632883> On 10.5, NSHTTPCookieStorage would store an empty cookie,
49         // which would be sent as "Cookie: =". We have a workaround in setCookies() to prevent
50         // that, but we also need to avoid sending cookies that were previously stored, and
51         // there's no harm to doing this check because such a cookie is never valid.
52         if (![[cookie name] length])
53             continue;
54
55         if ([cookie isHTTPOnly])
56             continue;
57
58         [filteredCookies.get() addObject:cookie];
59     }
60
61     return filteredCookies;
62 }
63
64 String cookies(const Document*, const KURL& url)
65 {
66     BEGIN_BLOCK_OBJC_EXCEPTIONS;
67
68     NSArray *cookies = wkHTTPCookiesForURL(currentCFHTTPCookieStorage().get(), url);
69     return [[NSHTTPCookie requestHeaderFieldsWithCookies:filterCookies(cookies).get()] objectForKey:@"Cookie"];
70
71     END_BLOCK_OBJC_EXCEPTIONS;
72     return String();
73 }
74
75 String cookieRequestHeaderFieldValue(const Document*, const KURL& url)
76 {
77     BEGIN_BLOCK_OBJC_EXCEPTIONS;
78
79     NSArray *cookies = wkHTTPCookiesForURL(currentCFHTTPCookieStorage().get(), url);
80     return [[NSHTTPCookie requestHeaderFieldsWithCookies:cookies] objectForKey:@"Cookie"];
81
82     END_BLOCK_OBJC_EXCEPTIONS;
83     return String();
84 }
85
86 void setCookies(Document* document, const KURL& url, const String& cookieStr)
87 {
88     BEGIN_BLOCK_OBJC_EXCEPTIONS;
89
90     // <rdar://problem/5632883> On 10.5, NSHTTPCookieStorage would store an empty cookie,
91     // which would be sent as "Cookie: =".
92     if (cookieStr.isEmpty())
93         return;
94
95     // <http://bugs.webkit.org/show_bug.cgi?id=6531>, <rdar://4409034>
96     // cookiesWithResponseHeaderFields doesn't parse cookies without a value
97     String cookieString = cookieStr.contains('=') ? cookieStr : cookieStr + "=";
98
99     NSURL *cookieURL = url;
100     RetainPtr<NSArray> filteredCookies = filterCookies([NSHTTPCookie cookiesWithResponseHeaderFields:[NSDictionary dictionaryWithObject:cookieString forKey:@"Set-Cookie"] forURL:cookieURL]);
101     ASSERT([filteredCookies.get() count] <= 1);
102
103     wkSetHTTPCookiesForURL(currentCFHTTPCookieStorage().get(), filteredCookies.get(), cookieURL, document->firstPartyForCookies());
104
105     END_BLOCK_OBJC_EXCEPTIONS;
106 }
107
108 bool cookiesEnabled(const Document*)
109 {
110     BEGIN_BLOCK_OBJC_EXCEPTIONS;
111
112     NSHTTPCookieAcceptPolicy cookieAcceptPolicy = static_cast<NSHTTPCookieAcceptPolicy>(wkGetHTTPCookieAcceptPolicy(currentCFHTTPCookieStorage().get()));
113     return cookieAcceptPolicy == NSHTTPCookieAcceptPolicyAlways || cookieAcceptPolicy == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain;
114
115     END_BLOCK_OBJC_EXCEPTIONS;
116     return false;
117 }
118
119 bool getRawCookies(const Document*, const KURL& url, Vector<Cookie>& rawCookies)
120 {
121     rawCookies.clear();
122     BEGIN_BLOCK_OBJC_EXCEPTIONS;
123
124     NSArray *cookies = wkHTTPCookiesForURL(currentCFHTTPCookieStorage().get(), url);
125     NSUInteger count = [cookies count];
126     rawCookies.reserveCapacity(count);
127     for (NSUInteger i = 0; i < count; ++i) {
128         NSHTTPCookie *cookie = (NSHTTPCookie *)[cookies objectAtIndex:i];
129         NSTimeInterval expires = [[cookie expiresDate] timeIntervalSince1970] * 1000;
130         rawCookies.uncheckedAppend(Cookie([cookie name], [cookie value], [cookie domain], [cookie path], expires,
131             [cookie isHTTPOnly], [cookie isSecure], [cookie isSessionOnly]));
132     }
133
134     END_BLOCK_OBJC_EXCEPTIONS;
135     return true;
136 }
137
138 void deleteCookie(const Document*, const KURL& url, const String& cookieName)
139 {
140     BEGIN_BLOCK_OBJC_EXCEPTIONS;
141
142     NSURL *cookieURL = url;
143     RetainPtr<CFHTTPCookieStorageRef> cookieStorage = currentCFHTTPCookieStorage();
144     NSArray *cookies = wkHTTPCookiesForURL(cookieStorage.get(), cookieURL);
145
146     NSString *cookieNameString = cookieName;
147
148     NSUInteger count = [cookies count];
149     for (NSUInteger i = 0; i < count; ++i) {
150         NSHTTPCookie *cookie = (NSHTTPCookie *)[cookies objectAtIndex:i];
151         if ([[cookie name] isEqualToString:cookieNameString])
152             wkDeleteHTTPCookie(cookieStorage.get(), cookie);
153     }
154
155     END_BLOCK_OBJC_EXCEPTIONS;
156 }
157
158 void getHostnamesWithCookies(HashSet<String>& hostnames)
159 {
160     BEGIN_BLOCK_OBJC_EXCEPTIONS;
161
162     NSArray *cookies = wkHTTPCookies(defaultCFHTTPCookieStorage().get());
163     
164     for (NSHTTPCookie* cookie in cookies)
165         hostnames.add([cookie domain]);
166     
167     END_BLOCK_OBJC_EXCEPTIONS;
168 }
169
170 void deleteCookiesForHostname(const String& hostname)
171 {
172     BEGIN_BLOCK_OBJC_EXCEPTIONS;
173
174     RetainPtr<CFHTTPCookieStorageRef> cookieStorage = defaultCFHTTPCookieStorage();
175     NSArray *cookies = wkHTTPCookies(cookieStorage.get());
176     if (!cookies)
177         return;
178     
179     for (NSHTTPCookie* cookie in cookies) {
180         if (hostname == String([cookie domain]))
181             wkDeleteHTTPCookie(cookieStorage.get(), cookie);
182     }
183     
184     END_BLOCK_OBJC_EXCEPTIONS;
185 }
186
187 void deleteAllCookies()
188 {
189     wkDeleteAllHTTPCookies(defaultCFHTTPCookieStorage().get());
190 }
191
192 }
193
194 #endif // !USE(CFNETWORK)