[Cocoa] Set HTTPOnly flag when converting Cookie to NSHTTPCookie
[WebKit-https.git] / Source / WebCore / platform / network / cocoa / NetworkStorageSessionCocoa.mm
1 /*
2  * Copyright (C) 2015-2018 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 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 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 "NetworkStorageSession.h"
28
29 #import "Cookie.h"
30 #import "CookieStorageObserver.h"
31 #import "URL.h"
32 #import <pal/spi/cf/CFNetworkSPI.h>
33 #import <wtf/BlockObjCExceptions.h>
34 #import <wtf/ProcessPrivilege.h>
35
36 namespace WebCore {
37
38 void NetworkStorageSession::setCookie(const Cookie& cookie)
39 {
40     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
41
42     BEGIN_BLOCK_OBJC_EXCEPTIONS;
43     [nsCookieStorage() setCookie:(NSHTTPCookie *)cookie];
44     END_BLOCK_OBJC_EXCEPTIONS;
45 }
46
47 void NetworkStorageSession::setCookies(const Vector<Cookie>& cookies, const URL& url, const URL& mainDocumentURL)
48 {
49     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
50
51     RetainPtr<NSMutableArray> nsCookies = adoptNS([[NSMutableArray alloc] initWithCapacity:cookies.size()]);
52     for (const auto& cookie : cookies)
53         [nsCookies addObject:(NSHTTPCookie *)cookie];
54
55     BEGIN_BLOCK_OBJC_EXCEPTIONS;
56     [nsCookieStorage() setCookies:nsCookies.get() forURL:(NSURL *)url mainDocumentURL:(NSURL *)mainDocumentURL];
57     END_BLOCK_OBJC_EXCEPTIONS;
58 }
59
60 void NetworkStorageSession::deleteCookie(const Cookie& cookie)
61 {
62     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
63     [nsCookieStorage() deleteCookie:(NSHTTPCookie *)cookie];
64 }
65
66 static Vector<Cookie> nsCookiesToCookieVector(NSArray<NSHTTPCookie *> *nsCookies)
67 {
68     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
69
70     Vector<Cookie> cookies;
71     cookies.reserveInitialCapacity(nsCookies.count);
72     for (NSHTTPCookie *nsCookie in nsCookies)
73         cookies.uncheckedAppend(nsCookie);
74
75     return cookies;
76 }
77
78 Vector<Cookie> NetworkStorageSession::getAllCookies()
79 {
80     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
81     return nsCookiesToCookieVector(nsCookieStorage().cookies);
82 }
83
84 Vector<Cookie> NetworkStorageSession::getCookies(const URL& url)
85 {
86     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
87     return nsCookiesToCookieVector([nsCookieStorage() cookiesForURL:(NSURL *)url]);
88 }
89
90 void NetworkStorageSession::flushCookieStore()
91 {
92     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
93     [nsCookieStorage() _saveCookies];
94 }
95
96 NSHTTPCookieStorage *NetworkStorageSession::nsCookieStorage() const
97 {
98     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
99     auto cfCookieStorage = cookieStorage();
100     if (!cfCookieStorage || [NSHTTPCookieStorage sharedHTTPCookieStorage]._cookieStorage == cfCookieStorage)
101         return [NSHTTPCookieStorage sharedHTTPCookieStorage];
102
103     return [[[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:cfCookieStorage.get()] autorelease];
104 }
105
106 CookieStorageObserver& NetworkStorageSession::cookieStorageObserver() const
107 {
108     if (!m_cookieStorageObserver)
109         m_cookieStorageObserver = CookieStorageObserver::create(nsCookieStorage());
110
111     return *m_cookieStorageObserver;
112 }
113
114 CFURLStorageSessionRef createPrivateStorageSession(CFStringRef identifier)
115 {
116     const void* sessionPropertyKeys[] = { _kCFURLStorageSessionIsPrivate };
117     const void* sessionPropertyValues[] = { kCFBooleanTrue };
118     auto sessionProperties = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, sessionPropertyKeys, sessionPropertyValues, sizeof(sessionPropertyKeys) / sizeof(*sessionPropertyKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
119     auto storageSession = adoptCF(_CFURLStorageSessionCreate(kCFAllocatorDefault, identifier, sessionProperties.get()));
120
121     if (!storageSession)
122         return nullptr;
123
124     // The private storage session should have the same properties as the default storage session,
125     // with the exception that it should be in-memory only storage.
126
127     // FIXME 9199649: If any of the storages do not exist, do no use the storage session.
128     // This could occur if there is an issue figuring out where to place a storage on disk (e.g. the
129     // sandbox does not allow CFNetwork access).
130
131     auto cache = adoptCF(_CFURLStorageSessionCopyCache(kCFAllocatorDefault, storageSession.get()));
132     if (!cache)
133         return nullptr;
134
135     CFURLCacheSetDiskCapacity(cache.get(), 0); // Setting disk cache size should not be necessary once <rdar://problem/12656814> is fixed.
136     CFURLCacheSetMemoryCapacity(cache.get(), [[NSURLCache sharedURLCache] memoryCapacity]);
137
138     if (!NetworkStorageSession::processMayUseCookieAPI())
139         return storageSession.leakRef();
140
141     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
142
143     auto cookieStorage = adoptCF(_CFURLStorageSessionCopyCookieStorage(kCFAllocatorDefault, storageSession.get()));
144     if (!cookieStorage)
145         return nullptr;
146
147     // FIXME: Use _CFHTTPCookieStorageGetDefault when USE(CFNETWORK) is defined in WebKit for consistency.
148     CFHTTPCookieStorageSetCookieAcceptPolicy(cookieStorage.get(), [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookieAcceptPolicy]);
149
150     return storageSession.leakRef();
151 }
152
153 } // namespace WebCore