Resource Load Statistics: Don't create a WebResourceLoadStatisticsStore for ephemeral...
[WebKit-https.git] / Source / WebKit / UIProcess / API / Cocoa / WKWebsiteDataStore.mm
1 /*
2  * Copyright (C) 2014-2017 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WKWebsiteDataStoreInternal.h"
28
29 #if WK_API_ENABLED
30
31 #import "APIString.h"
32 #import "WKHTTPCookieStoreInternal.h"
33 #import "WKNSArray.h"
34 #import "WKWebsiteDataRecordInternal.h"
35 #import "WebResourceLoadStatisticsStore.h"
36 #import "WebResourceLoadStatisticsTelemetry.h"
37 #import "WebsiteDataFetchOption.h"
38 #import "_WKWebsiteDataStoreConfiguration.h"
39 #import <WebCore/URL.h>
40 #import <WebKit/ServiceWorkerProcessProxy.h>
41 #import <wtf/BlockPtr.h>
42
43 using namespace WebCore;
44
45 @implementation WKWebsiteDataStore
46
47 + (WKWebsiteDataStore *)defaultDataStore
48 {
49     return WebKit::wrapper(API::WebsiteDataStore::defaultDataStore().get());
50 }
51
52 + (WKWebsiteDataStore *)nonPersistentDataStore
53 {
54     return [WebKit::wrapper(API::WebsiteDataStore::createNonPersistentDataStore().leakRef()) autorelease];
55 }
56
57 - (void)dealloc
58 {
59     _websiteDataStore->API::WebsiteDataStore::~WebsiteDataStore();
60
61     [super dealloc];
62 }
63
64 + (BOOL)supportsSecureCoding
65 {
66     return YES;
67 }
68
69 - (instancetype)initWithCoder:(NSCoder *)coder
70 {
71     if (!(self = [super init]))
72         return nil;
73
74     RetainPtr<WKWebsiteDataStore> dataStore;
75     if ([coder decodeBoolForKey:@"isDefaultDataStore"])
76         dataStore = [WKWebsiteDataStore defaultDataStore];
77     else
78         dataStore = [WKWebsiteDataStore nonPersistentDataStore];
79
80     [self release];
81
82     return dataStore.leakRef();
83 }
84
85 - (void)encodeWithCoder:(NSCoder *)coder
86 {
87     if (self == [WKWebsiteDataStore defaultDataStore]) {
88         [coder encodeBool:YES forKey:@"isDefaultDataStore"];
89         return;
90     }
91
92     ASSERT(!self.persistent);
93 }
94
95 - (BOOL)isPersistent
96 {
97     return _websiteDataStore->isPersistent();
98 }
99
100 + (NSSet *)allWebsiteDataTypes
101 {
102     static dispatch_once_t onceToken;
103     static NSSet *allWebsiteDataTypes;
104     dispatch_once(&onceToken, ^{
105         allWebsiteDataTypes = [[NSSet alloc] initWithArray:@[ WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeFetchCache, WKWebsiteDataTypeMemoryCache, WKWebsiteDataTypeOfflineWebApplicationCache, WKWebsiteDataTypeCookies, WKWebsiteDataTypeSessionStorage, WKWebsiteDataTypeLocalStorage, WKWebsiteDataTypeIndexedDBDatabases, WKWebsiteDataTypeServiceWorkerRegistrations, WKWebsiteDataTypeWebSQLDatabases ]];
106     });
107
108     return allWebsiteDataTypes;
109 }
110
111 - (WKHTTPCookieStore *)httpCookieStore
112 {
113     return WebKit::wrapper(_websiteDataStore->httpCookieStore());
114 }
115
116 static WallTime toSystemClockTime(NSDate *date)
117 {
118     ASSERT(date);
119     return WallTime::fromRawSeconds(date.timeIntervalSince1970);
120 }
121
122 - (void)fetchDataRecordsOfTypes:(NSSet *)dataTypes completionHandler:(void (^)(NSArray<WKWebsiteDataRecord *> *))completionHandler
123 {
124     [self _fetchDataRecordsOfTypes:dataTypes withOptions:0 completionHandler:completionHandler];
125 }
126
127 - (void)removeDataOfTypes:(NSSet *)dataTypes modifiedSince:(NSDate *)date completionHandler:(void (^)(void))completionHandler
128 {
129     auto completionHandlerCopy = makeBlockPtr(completionHandler);
130     _websiteDataStore->websiteDataStore().removeData(WebKit::toWebsiteDataTypes(dataTypes), toSystemClockTime(date ? date : [NSDate distantPast]), [completionHandlerCopy] {
131         completionHandlerCopy();
132     });
133 }
134
135 static Vector<WebKit::WebsiteDataRecord> toWebsiteDataRecords(NSArray *dataRecords)
136 {
137     Vector<WebKit::WebsiteDataRecord> result;
138
139     for (WKWebsiteDataRecord *dataRecord in dataRecords)
140         result.append(dataRecord->_websiteDataRecord->websiteDataRecord());
141
142     return result;
143 }
144
145 - (void)removeDataOfTypes:(NSSet *)dataTypes forDataRecords:(NSArray *)dataRecords completionHandler:(void (^)(void))completionHandler
146 {
147     auto completionHandlerCopy = makeBlockPtr(completionHandler);
148
149     _websiteDataStore->websiteDataStore().removeData(WebKit::toWebsiteDataTypes(dataTypes), toWebsiteDataRecords(dataRecords), [completionHandlerCopy] {
150         completionHandlerCopy();
151     });
152 }
153
154 #pragma mark WKObject protocol implementation
155
156 - (API::Object&)_apiObject
157 {
158     return *_websiteDataStore;
159 }
160
161 @end
162
163 @implementation WKWebsiteDataStore (WKPrivate)
164
165 + (NSSet<NSString *> *)_allWebsiteDataTypesIncludingPrivate
166 {
167     static dispatch_once_t onceToken;
168     static NSSet *allWebsiteDataTypes;
169     dispatch_once(&onceToken, ^ {
170         auto *privateTypes = @[_WKWebsiteDataTypeHSTSCache, _WKWebsiteDataTypeMediaKeys, _WKWebsiteDataTypeSearchFieldRecentSearches, _WKWebsiteDataTypeResourceLoadStatistics, _WKWebsiteDataTypeCredentials
171 #if !TARGET_OS_IPHONE
172         , _WKWebsiteDataTypePlugInData
173 #endif
174         ];
175
176         allWebsiteDataTypes = [[[self allWebsiteDataTypes] setByAddingObjectsFromArray:privateTypes] retain];
177     });
178
179     return allWebsiteDataTypes;
180 }
181
182 + (BOOL)_defaultDataStoreExists
183 {
184     return API::WebsiteDataStore::defaultDataStoreExists();
185 }
186
187 - (instancetype)_initWithConfiguration:(_WKWebsiteDataStoreConfiguration *)configuration
188 {
189     if (!(self = [super init]))
190         return nil;
191
192     auto config = API::WebsiteDataStore::defaultDataStoreConfiguration();
193
194     if (configuration._webStorageDirectory)
195         config.localStorageDirectory = configuration._webStorageDirectory.path;
196     if (configuration._webSQLDatabaseDirectory)
197         config.webSQLDatabaseDirectory = configuration._webSQLDatabaseDirectory.path;
198     if (configuration._indexedDBDatabaseDirectory)
199         config.indexedDBDatabaseDirectory = configuration._indexedDBDatabaseDirectory.path;
200     if (configuration._cookieStorageFile)
201         config.cookieStorageFile = configuration._cookieStorageFile.path;
202     if (configuration._resourceLoadStatisticsDirectory)
203         config.resourceLoadStatisticsDirectory = configuration._resourceLoadStatisticsDirectory.path;
204     if (configuration._cacheStorageDirectory)
205         config.cacheStorageDirectory = configuration._cacheStorageDirectory.path;
206     if (configuration._serviceWorkerRegistrationDirectory)
207         config.serviceWorkerRegistrationDirectory = configuration._serviceWorkerRegistrationDirectory.path;
208
209     API::Object::constructInWrapper<API::WebsiteDataStore>(self, config, PAL::SessionID::generatePersistentSessionID());
210
211     return self;
212 }
213
214 - (void)_fetchDataRecordsOfTypes:(NSSet<NSString *> *)dataTypes withOptions:(_WKWebsiteDataStoreFetchOptions)options completionHandler:(void (^)(NSArray<WKWebsiteDataRecord *> *))completionHandler
215 {
216     auto completionHandlerCopy = makeBlockPtr(completionHandler);
217
218     OptionSet<WebKit::WebsiteDataFetchOption> fetchOptions;
219     if (options & _WKWebsiteDataStoreFetchOptionComputeSizes)
220         fetchOptions |= WebKit::WebsiteDataFetchOption::ComputeSizes;
221
222     _websiteDataStore->websiteDataStore().fetchData(WebKit::toWebsiteDataTypes(dataTypes), fetchOptions, [completionHandlerCopy = WTFMove(completionHandlerCopy)](auto websiteDataRecords) {
223         Vector<RefPtr<API::Object>> elements;
224         elements.reserveInitialCapacity(websiteDataRecords.size());
225
226         for (auto& websiteDataRecord : websiteDataRecords)
227             elements.uncheckedAppend(API::WebsiteDataRecord::create(WTFMove(websiteDataRecord)));
228
229         completionHandlerCopy(wrapper(API::Array::create(WTFMove(elements))));
230     });
231 }
232
233 - (BOOL)_resourceLoadStatisticsEnabled
234 {
235     return _websiteDataStore->websiteDataStore().resourceLoadStatisticsEnabled();
236 }
237
238 - (void)_setResourceLoadStatisticsEnabled:(BOOL)enabled
239 {
240     _websiteDataStore->websiteDataStore().setResourceLoadStatisticsEnabled(enabled);
241 }
242
243 - (BOOL)_resourceLoadStatisticsDebugMode
244 {
245     return _websiteDataStore->websiteDataStore().resourceLoadStatisticsDebugMode();
246 }
247
248 - (void)_setResourceLoadStatisticsDebugMode:(BOOL)enabled
249 {
250     _websiteDataStore->websiteDataStore().setResourceLoadStatisticsDebugMode(enabled);
251 }
252
253 - (NSUInteger)_cacheStoragePerOriginQuota
254 {
255     return _websiteDataStore->websiteDataStore().cacheStoragePerOriginQuota();
256 }
257
258 - (void)_setCacheStoragePerOriginQuota:(NSUInteger)size
259 {
260     _websiteDataStore->websiteDataStore().setCacheStoragePerOriginQuota(size);
261 }
262
263 - (NSString *)_cacheStorageDirectory
264 {
265     return _websiteDataStore->websiteDataStore().cacheStorageDirectory();
266 }
267
268 - (void)_setCacheStorageDirectory:(NSString *)directory
269 {
270     _websiteDataStore->websiteDataStore().setCacheStorageDirectory(directory);
271 }
272
273 - (NSString *)_serviceWorkerRegistrationDirectory
274 {
275     return _websiteDataStore->websiteDataStore().serviceWorkerRegistrationDirectory();
276 }
277
278 - (void)_setServiceWorkerRegistrationDirectory:(NSString *)directory
279 {
280     _websiteDataStore->websiteDataStore().setServiceWorkerRegistrationDirectory(directory);
281 }
282
283 - (void)_setBoundInterfaceIdentifier:(NSString *)identifier
284 {
285     _websiteDataStore->websiteDataStore().setBoundInterfaceIdentifier(identifier);
286 }
287
288 - (NSString *)_boundInterfaceIdentifier
289 {
290     return _websiteDataStore->websiteDataStore().boundInterfaceIdentifier();
291 }
292
293 - (void)_setAllowsCellularAccess:(BOOL)allows
294 {
295     _websiteDataStore->websiteDataStore().setAllowsCellularAccess(allows ? WebKit::AllowsCellularAccess::Yes : WebKit::AllowsCellularAccess::No);
296 }
297
298 - (BOOL)_allowsCellularAccess
299 {
300     return _websiteDataStore->websiteDataStore().allowsCellularAccess() == WebKit::AllowsCellularAccess::Yes;
301 }
302
303 - (void)_setProxyConfiguration:(NSDictionary *)configuration
304 {
305     _websiteDataStore->websiteDataStore().setProxyConfiguration((__bridge CFDictionaryRef)configuration);
306 }
307
308 - (NSDictionary *)_proxyConfiguration
309 {
310     return (__bridge NSDictionary *)_websiteDataStore->websiteDataStore().proxyConfiguration();
311 }
312
313 - (void)_resourceLoadStatisticsSetShouldSubmitTelemetry:(BOOL)value
314 {
315     auto* store = _websiteDataStore->websiteDataStore().resourceLoadStatistics();
316     if (!store)
317         return;
318
319     store->setShouldSubmitTelemetry(value);
320 }
321
322 - (void)_setResourceLoadStatisticsTestingCallback:(void (^)(WKWebsiteDataStore *, NSString *))callback
323 {
324     if (!_websiteDataStore->isPersistent())
325         return;
326
327     if (callback) {
328         _websiteDataStore->websiteDataStore().enableResourceLoadStatisticsAndSetTestingCallback([callback = makeBlockPtr(callback), self](const String& event) {
329             callback(self, (NSString *)event);
330         });
331         return;
332     }
333
334     auto* store = _websiteDataStore->websiteDataStore().resourceLoadStatistics();
335     if (!store)
336         return;
337
338     store->setStatisticsTestingCallback(nullptr);
339 }
340
341 + (void)_allowWebsiteDataRecordsForAllOrigins
342 {
343     WebKit::WebsiteDataStore::allowWebsiteDataRecordsForAllOrigins();
344 }
345
346 - (void)_getAllStorageAccessEntries:(void (^)(NSArray<NSString *> *domains))completionHandler
347 {
348     _websiteDataStore->websiteDataStore().getAllStorageAccessEntries([completionHandler = makeBlockPtr(completionHandler)](auto domains) {
349         Vector<RefPtr<API::Object>> apiDomains;
350         apiDomains.reserveInitialCapacity(domains.size());
351         for (auto& domain : domains)
352             apiDomains.uncheckedAppend(API::String::create(domain));
353
354         completionHandler(wrapper(API::Array::create(WTFMove(apiDomains))));
355     });
356 }
357
358 - (bool)_hasRegisteredServiceWorker
359 {
360     return WebKit::ServiceWorkerProcessProxy::hasRegisteredServiceWorkers(_websiteDataStore->websiteDataStore().serviceWorkerRegistrationDirectory());
361 }
362
363 @end
364
365 #endif // WK_API_ENABLED