e178dcd6f77be89dffd86e7b150c0222b0fc9aa8
[WebKit-https.git] / Source / WebKit / UIProcess / API / Cocoa / WKWebsiteDataStore.mm
1 /*
2  * Copyright (C) 2014-2019 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 #import "APIString.h"
30 #import "CompletionHandlerCallChecker.h"
31 #import "WKHTTPCookieStoreInternal.h"
32 #import "WKNSArray.h"
33 #import "WKWebViewInternal.h"
34 #import "WKWebsiteDataRecordInternal.h"
35 #import "WebPageProxy.h"
36 #import "WebResourceLoadStatisticsStore.h"
37 #import "WebResourceLoadStatisticsTelemetry.h"
38 #import "WebsiteDataFetchOption.h"
39 #import "_WKWebsiteDataStoreConfiguration.h"
40 #import "_WKWebsiteDataStoreDelegate.h"
41 #import <WebKit/ServiceWorkerProcessProxy.h>
42 #import <wtf/BlockPtr.h>
43 #import <wtf/URL.h>
44 #import <wtf/WeakObjCPtr.h>
45
46 class WebsiteDataStoreClient final : public WebKit::WebsiteDataStoreClient {
47 public:
48     explicit WebsiteDataStoreClient(id <_WKWebsiteDataStoreDelegate> delegate)
49         : m_delegate(delegate)
50         , m_hasRequestStorageSpaceSelector([m_delegate.get() respondsToSelector:@selector(requestStorageSpace: frameOrigin: quota: currentSize: spaceRequired: decisionHandler:)])
51     {
52     }
53
54 private:
55     void requestStorageSpace(const WebCore::SecurityOriginData& topOrigin, const WebCore::SecurityOriginData& frameOrigin, uint64_t quota, uint64_t currentSize, uint64_t spaceRequired, CompletionHandler<void(Optional<uint64_t>)>&& completionHandler) final
56     {
57         if (!m_hasRequestStorageSpaceSelector || !m_delegate) {
58             completionHandler({ });
59             return;
60         }
61
62         auto checker = WebKit::CompletionHandlerCallChecker::create(m_delegate.getAutoreleased(), @selector(requestStorageSpace: frameOrigin: quota: currentSize: spaceRequired: decisionHandler:));
63         auto decisionHandler = makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](unsigned long long quota) mutable {
64             if (checker->completionHandlerHasBeenCalled())
65                 return;
66             checker->didCallCompletionHandler();
67             completionHandler(quota);
68         });
69
70         URL mainFrameURL { URL(), topOrigin.toString() };
71         URL frameURL { URL(), frameOrigin.toString() };
72
73         [m_delegate.getAutoreleased() requestStorageSpace:mainFrameURL frameOrigin:frameURL quota:quota currentSize:currentSize spaceRequired:spaceRequired decisionHandler:decisionHandler.get()];
74     }
75
76     WeakObjCPtr<id <_WKWebsiteDataStoreDelegate> > m_delegate;
77     bool m_hasRequestStorageSpaceSelector { false };
78 };
79
80 @implementation WKWebsiteDataStore
81
82 + (WKWebsiteDataStore *)defaultDataStore
83 {
84     return wrapper(API::WebsiteDataStore::defaultDataStore());
85 }
86
87 + (WKWebsiteDataStore *)nonPersistentDataStore
88 {
89     return wrapper(API::WebsiteDataStore::createNonPersistentDataStore());
90 }
91
92 - (void)dealloc
93 {
94     _websiteDataStore->API::WebsiteDataStore::~WebsiteDataStore();
95
96     [super dealloc];
97 }
98
99 + (BOOL)supportsSecureCoding
100 {
101     return YES;
102 }
103
104 - (instancetype)initWithCoder:(NSCoder *)coder
105 {
106     if (!(self = [super init]))
107         return nil;
108
109     RetainPtr<WKWebsiteDataStore> dataStore;
110     if ([coder decodeBoolForKey:@"isDefaultDataStore"])
111         dataStore = [WKWebsiteDataStore defaultDataStore];
112     else
113         dataStore = [WKWebsiteDataStore nonPersistentDataStore];
114
115     [self release];
116
117     return dataStore.leakRef();
118 }
119
120 - (void)encodeWithCoder:(NSCoder *)coder
121 {
122     if (self == [WKWebsiteDataStore defaultDataStore]) {
123         [coder encodeBool:YES forKey:@"isDefaultDataStore"];
124         return;
125     }
126
127     ASSERT(!self.persistent);
128 }
129
130 - (BOOL)isPersistent
131 {
132     return _websiteDataStore->isPersistent();
133 }
134
135 + (NSSet *)allWebsiteDataTypes
136 {
137     static dispatch_once_t onceToken;
138     static NSSet *allWebsiteDataTypes;
139     dispatch_once(&onceToken, ^{
140         allWebsiteDataTypes = [[NSSet alloc] initWithArray:@[ WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeFetchCache, WKWebsiteDataTypeMemoryCache, WKWebsiteDataTypeOfflineWebApplicationCache, WKWebsiteDataTypeCookies, WKWebsiteDataTypeSessionStorage, WKWebsiteDataTypeLocalStorage, WKWebsiteDataTypeIndexedDBDatabases, WKWebsiteDataTypeServiceWorkerRegistrations, WKWebsiteDataTypeWebSQLDatabases ]];
141     });
142
143     return allWebsiteDataTypes;
144 }
145
146 - (WKHTTPCookieStore *)httpCookieStore
147 {
148     return wrapper(_websiteDataStore->httpCookieStore());
149 }
150
151 static WallTime toSystemClockTime(NSDate *date)
152 {
153     ASSERT(date);
154     return WallTime::fromRawSeconds(date.timeIntervalSince1970);
155 }
156
157 - (void)fetchDataRecordsOfTypes:(NSSet *)dataTypes completionHandler:(void (^)(NSArray<WKWebsiteDataRecord *> *))completionHandler
158 {
159     [self _fetchDataRecordsOfTypes:dataTypes withOptions:0 completionHandler:completionHandler];
160 }
161
162 - (void)removeDataOfTypes:(NSSet *)dataTypes modifiedSince:(NSDate *)date completionHandler:(void (^)(void))completionHandler
163 {
164     auto completionHandlerCopy = makeBlockPtr(completionHandler);
165     _websiteDataStore->websiteDataStore().removeData(WebKit::toWebsiteDataTypes(dataTypes), toSystemClockTime(date ? date : [NSDate distantPast]), [completionHandlerCopy] {
166         completionHandlerCopy();
167     });
168 }
169
170 static Vector<WebKit::WebsiteDataRecord> toWebsiteDataRecords(NSArray *dataRecords)
171 {
172     Vector<WebKit::WebsiteDataRecord> result;
173
174     for (WKWebsiteDataRecord *dataRecord in dataRecords)
175         result.append(dataRecord->_websiteDataRecord->websiteDataRecord());
176
177     return result;
178 }
179
180 - (void)removeDataOfTypes:(NSSet *)dataTypes forDataRecords:(NSArray *)dataRecords completionHandler:(void (^)(void))completionHandler
181 {
182     auto completionHandlerCopy = makeBlockPtr(completionHandler);
183
184     _websiteDataStore->websiteDataStore().removeData(WebKit::toWebsiteDataTypes(dataTypes), toWebsiteDataRecords(dataRecords), [completionHandlerCopy] {
185         completionHandlerCopy();
186     });
187 }
188
189 #pragma mark WKObject protocol implementation
190
191 - (API::Object&)_apiObject
192 {
193     return *_websiteDataStore;
194 }
195
196 @end
197
198 @implementation WKWebsiteDataStore (WKPrivate)
199
200 + (NSSet<NSString *> *)_allWebsiteDataTypesIncludingPrivate
201 {
202     static dispatch_once_t onceToken;
203     static NSSet *allWebsiteDataTypes;
204     dispatch_once(&onceToken, ^ {
205         auto *privateTypes = @[_WKWebsiteDataTypeHSTSCache, _WKWebsiteDataTypeMediaKeys, _WKWebsiteDataTypeSearchFieldRecentSearches, _WKWebsiteDataTypeResourceLoadStatistics, _WKWebsiteDataTypeCredentials, _WKWebsiteDataTypeAdClickAttributions
206 #if !TARGET_OS_IPHONE
207         , _WKWebsiteDataTypePlugInData
208 #endif
209         ];
210
211         allWebsiteDataTypes = [[[self allWebsiteDataTypes] setByAddingObjectsFromArray:privateTypes] retain];
212     });
213
214     return allWebsiteDataTypes;
215 }
216
217 + (BOOL)_defaultDataStoreExists
218 {
219     return API::WebsiteDataStore::defaultDataStoreExists();
220 }
221
222 + (void)_deleteDefaultDataStoreForTesting
223 {
224     return API::WebsiteDataStore::deleteDefaultDataStoreForTesting();
225 }
226
227 - (instancetype)_initWithConfiguration:(_WKWebsiteDataStoreConfiguration *)configuration
228 {
229     if (!(self = [super init]))
230         return nil;
231
232     auto config = configuration.isPersistent ? API::WebsiteDataStore::defaultDataStoreConfiguration() : WebKit::WebsiteDataStoreConfiguration::create();
233
234     RELEASE_ASSERT(config->isPersistent() == configuration.isPersistent);
235
236     if (configuration.isPersistent) {
237         if (configuration._webStorageDirectory)
238             config->setLocalStorageDirectory(configuration._webStorageDirectory.path);
239         if (configuration._webSQLDatabaseDirectory)
240             config->setWebSQLDatabaseDirectory(configuration._webSQLDatabaseDirectory.path);
241         if (configuration._indexedDBDatabaseDirectory)
242             config->setIndexedDBDatabaseDirectory(configuration._indexedDBDatabaseDirectory.path);
243         if (configuration._cookieStorageFile)
244             config->setCookieStorageFile(configuration._cookieStorageFile.path);
245         if (configuration._resourceLoadStatisticsDirectory)
246             config->setResourceLoadStatisticsDirectory(configuration._resourceLoadStatisticsDirectory.path);
247         if (configuration._cacheStorageDirectory)
248             config->setCacheStorageDirectory(configuration._cacheStorageDirectory.path);
249         if (configuration._serviceWorkerRegistrationDirectory)
250             config->setServiceWorkerRegistrationDirectory(configuration._serviceWorkerRegistrationDirectory.path);
251     } else {
252         RELEASE_ASSERT(!configuration._webStorageDirectory);
253         RELEASE_ASSERT(!configuration._webSQLDatabaseDirectory);
254         RELEASE_ASSERT(!configuration._indexedDBDatabaseDirectory);
255         RELEASE_ASSERT(!configuration._cookieStorageFile);
256         RELEASE_ASSERT(!configuration._resourceLoadStatisticsDirectory);
257         RELEASE_ASSERT(!configuration._cacheStorageDirectory);
258         RELEASE_ASSERT(!configuration._serviceWorkerRegistrationDirectory);
259     }
260
261     if (configuration.sourceApplicationBundleIdentifier)
262         config->setSourceApplicationBundleIdentifier(configuration.sourceApplicationBundleIdentifier);
263     if (configuration.sourceApplicationSecondaryIdentifier)
264         config->setSourceApplicationSecondaryIdentifier(configuration.sourceApplicationSecondaryIdentifier);
265     if (configuration.httpProxy)
266         config->setHTTPProxy(configuration.httpProxy);
267     if (configuration.httpsProxy)
268         config->setHTTPSProxy(configuration.httpsProxy);
269     config->setDeviceManagementRestrictionsEnabled(configuration.deviceManagementRestrictionsEnabled);
270     config->setAllLoadsBlockedByDeviceManagementRestrictionsForTesting(configuration.allLoadsBlockedByDeviceManagementRestrictionsForTesting);
271
272     auto sessionID = configuration.isPersistent ? PAL::SessionID::generatePersistentSessionID() : PAL::SessionID::generateEphemeralSessionID();
273
274     API::Object::constructInWrapper<API::WebsiteDataStore>(self, WTFMove(config), sessionID);
275
276     return self;
277 }
278
279 - (void)_fetchDataRecordsOfTypes:(NSSet<NSString *> *)dataTypes withOptions:(_WKWebsiteDataStoreFetchOptions)options completionHandler:(void (^)(NSArray<WKWebsiteDataRecord *> *))completionHandler
280 {
281     auto completionHandlerCopy = makeBlockPtr(completionHandler);
282
283     OptionSet<WebKit::WebsiteDataFetchOption> fetchOptions;
284     if (options & _WKWebsiteDataStoreFetchOptionComputeSizes)
285         fetchOptions.add(WebKit::WebsiteDataFetchOption::ComputeSizes);
286
287     _websiteDataStore->websiteDataStore().fetchData(WebKit::toWebsiteDataTypes(dataTypes), fetchOptions, [completionHandlerCopy = WTFMove(completionHandlerCopy)](auto websiteDataRecords) {
288         Vector<RefPtr<API::Object>> elements;
289         elements.reserveInitialCapacity(websiteDataRecords.size());
290
291         for (auto& websiteDataRecord : websiteDataRecords)
292             elements.uncheckedAppend(API::WebsiteDataRecord::create(WTFMove(websiteDataRecord)));
293
294         completionHandlerCopy(wrapper(API::Array::create(WTFMove(elements))));
295     });
296 }
297
298 - (BOOL)_resourceLoadStatisticsEnabled
299 {
300     return _websiteDataStore->websiteDataStore().resourceLoadStatisticsEnabled();
301 }
302
303 - (void)_setResourceLoadStatisticsEnabled:(BOOL)enabled
304 {
305     _websiteDataStore->websiteDataStore().setResourceLoadStatisticsEnabled(enabled);
306 }
307
308 - (BOOL)_resourceLoadStatisticsDebugMode
309 {
310 #if ENABLE(RESOURCE_LOAD_STATISTICS)
311     return _websiteDataStore->websiteDataStore().resourceLoadStatisticsDebugMode();
312 #else
313     return NO;
314 #endif
315 }
316
317 - (void)_setResourceLoadStatisticsDebugMode:(BOOL)enabled
318 {
319 #if ENABLE(RESOURCE_LOAD_STATISTICS)
320     _websiteDataStore->websiteDataStore().setResourceLoadStatisticsDebugMode(enabled);
321 #else
322     UNUSED_PARAM(enabled);
323 #endif
324 }
325
326 - (NSUInteger)_perOriginStorageQuota
327 {
328     return _websiteDataStore->websiteDataStore().perOriginStorageQuota();
329 }
330
331 - (void)_setPerOriginStorageQuota:(NSUInteger)size
332 {
333     _websiteDataStore->websiteDataStore().setPerOriginStorageQuota(size);
334 }
335
336 - (NSString *)_cacheStorageDirectory
337 {
338     return _websiteDataStore->websiteDataStore().cacheStorageDirectory();
339 }
340
341 - (void)_setCacheStorageDirectory:(NSString *)directory
342 {
343     _websiteDataStore->websiteDataStore().setCacheStorageDirectory(directory);
344 }
345
346 - (NSString *)_serviceWorkerRegistrationDirectory
347 {
348     return _websiteDataStore->websiteDataStore().serviceWorkerRegistrationDirectory();
349 }
350
351 - (void)_setServiceWorkerRegistrationDirectory:(NSString *)directory
352 {
353     _websiteDataStore->websiteDataStore().setServiceWorkerRegistrationDirectory(directory);
354 }
355
356 - (void)_setBoundInterfaceIdentifier:(NSString *)identifier
357 {
358     _websiteDataStore->websiteDataStore().setBoundInterfaceIdentifier(identifier);
359 }
360
361 - (NSString *)_boundInterfaceIdentifier
362 {
363     return _websiteDataStore->websiteDataStore().boundInterfaceIdentifier();
364 }
365
366 - (void)_setAllowsCellularAccess:(BOOL)allows
367 {
368     _websiteDataStore->websiteDataStore().setAllowsCellularAccess(allows ? WebKit::AllowsCellularAccess::Yes : WebKit::AllowsCellularAccess::No);
369 }
370
371 - (BOOL)_allowsCellularAccess
372 {
373     return _websiteDataStore->websiteDataStore().allowsCellularAccess() == WebKit::AllowsCellularAccess::Yes;
374 }
375
376 - (void)_setProxyConfiguration:(NSDictionary *)configuration
377 {
378     _websiteDataStore->websiteDataStore().setProxyConfiguration((__bridge CFDictionaryRef)configuration);
379 }
380
381 - (NSString *)_sourceApplicationBundleIdentifier
382 {
383     return _websiteDataStore->websiteDataStore().sourceApplicationBundleIdentifier();
384 }
385
386 - (void)_setSourceApplicationBundleIdentifier:(NSString *)identifier
387 {
388     if (!_websiteDataStore->websiteDataStore().setSourceApplicationBundleIdentifier(identifier))
389         [NSException raise:NSGenericException format:@"_setSourceApplicationBundleIdentifier cannot be called after networking has begun"];
390 }
391
392 - (NSString *)_sourceApplicationSecondaryIdentifier
393 {
394     return _websiteDataStore->websiteDataStore().sourceApplicationSecondaryIdentifier();
395 }
396
397 - (void)_setSourceApplicationSecondaryIdentifier:(NSString *)identifier
398 {
399     if (!_websiteDataStore->websiteDataStore().setSourceApplicationSecondaryIdentifier(identifier))
400         [NSException raise:NSGenericException format:@"_setSourceApplicationSecondaryIdentifier cannot be called after networking has begun"];
401 }
402
403 - (void)_setAllowsTLSFallback:(BOOL)allows
404 {
405     if (!_websiteDataStore->websiteDataStore().setAllowsTLSFallback(allows))
406         [NSException raise:NSGenericException format:@"_setAllowsTLSFallback cannot be called after networking has begun"];
407 }
408
409 - (BOOL)_allowsTLSFallback
410 {
411     return _websiteDataStore->websiteDataStore().allowsTLSFallback();
412 }
413
414 - (NSDictionary *)_proxyConfiguration
415 {
416     return (__bridge NSDictionary *)_websiteDataStore->websiteDataStore().proxyConfiguration();
417 }
418
419 - (NSURL *)_indexedDBDatabaseDirectory
420 {
421     return [NSURL fileURLWithPath:_websiteDataStore->indexedDBDatabaseDirectory() isDirectory:YES];
422 }
423
424 - (void)_resourceLoadStatisticsSetShouldSubmitTelemetry:(BOOL)value
425 {
426 #if ENABLE(RESOURCE_LOAD_STATISTICS)
427     auto* store = _websiteDataStore->websiteDataStore().resourceLoadStatistics();
428     if (!store)
429         return;
430
431     store->setShouldSubmitTelemetry(value);
432 #endif
433 }
434
435 - (void)_setResourceLoadStatisticsTestingCallback:(void (^)(WKWebsiteDataStore *, NSString *))callback
436 {
437 #if ENABLE(RESOURCE_LOAD_STATISTICS)
438     if (!_websiteDataStore->isPersistent())
439         return;
440
441     if (callback) {
442         _websiteDataStore->websiteDataStore().enableResourceLoadStatisticsAndSetTestingCallback([callback = makeBlockPtr(callback), self](const String& event) {
443             callback(self, (NSString *)event);
444         });
445         return;
446     }
447
448     _websiteDataStore->websiteDataStore().setStatisticsTestingCallback(nullptr);
449 #endif
450 }
451
452 + (void)_allowWebsiteDataRecordsForAllOrigins
453 {
454     WebKit::WebsiteDataStore::allowWebsiteDataRecordsForAllOrigins();
455 }
456
457 - (void)_getAllStorageAccessEntriesFor:(WKWebView *)webView completionHandler:(void (^)(NSArray<NSString *> *domains))completionHandler
458 {
459     if (!webView) {
460         completionHandler({ });
461         return;
462     }
463
464     auto* webPageProxy = [webView _page];
465     if (!webPageProxy) {
466         completionHandler({ });
467         return;
468     }
469
470 #if ENABLE(RESOURCE_LOAD_STATISTICS)
471     _websiteDataStore->websiteDataStore().getAllStorageAccessEntries(webPageProxy->pageID(), [completionHandler = makeBlockPtr(completionHandler)](auto domains) {
472         Vector<RefPtr<API::Object>> apiDomains;
473         apiDomains.reserveInitialCapacity(domains.size());
474         for (auto& domain : domains)
475             apiDomains.uncheckedAppend(API::String::create(domain));
476         completionHandler(wrapper(API::Array::create(WTFMove(apiDomains))));
477     });
478 #else
479     completionHandler({ });
480 #endif
481 }
482
483 - (void)_scheduleCookieBlockingUpdate:(void (^)(void))completionHandler
484 {
485 #if ENABLE(RESOURCE_LOAD_STATISTICS)
486     _websiteDataStore->websiteDataStore().scheduleCookieBlockingUpdate([completionHandler = makeBlockPtr(completionHandler)]() {
487         completionHandler();
488     });
489 #else
490     completionHandler();
491 #endif
492 }
493
494 - (void)_setPrevalentDomain:(NSURL *)domain completionHandler:(void (^)(void))completionHandler
495 {
496 #if ENABLE(RESOURCE_LOAD_STATISTICS)
497     _websiteDataStore->websiteDataStore().setPrevalentResource(URL(domain), [completionHandler = makeBlockPtr(completionHandler)]() {
498         completionHandler();
499     });
500 #else
501     completionHandler();
502 #endif
503 }
504
505 - (void)_getIsPrevalentDomain:(NSURL *)domain completionHandler:(void (^)(BOOL))completionHandler
506 {
507 #if ENABLE(RESOURCE_LOAD_STATISTICS)
508     _websiteDataStore->websiteDataStore().isPrevalentResource(URL(domain), [completionHandler = makeBlockPtr(completionHandler)](bool enabled) {
509         completionHandler(enabled);
510     });
511 #else
512     completionHandler(NO);
513 #endif
514 }
515
516 - (void)_clearPrevalentDomain:(NSURL *)domain completionHandler:(void (^)(void))completionHandler
517 {
518 #if ENABLE(RESOURCE_LOAD_STATISTICS)
519     _websiteDataStore->websiteDataStore().clearPrevalentResource(URL(domain), [completionHandler = makeBlockPtr(completionHandler)]() {
520         completionHandler();
521     });
522 #else
523     completionHandler();
524 #endif
525 }
526
527 - (void)_processStatisticsAndDataRecords:(void (^)(void))completionHandler
528 {
529 #if ENABLE(RESOURCE_LOAD_STATISTICS)
530     _websiteDataStore->websiteDataStore().scheduleStatisticsAndDataRecordsProcessing([completionHandler = makeBlockPtr(completionHandler)]() {
531         completionHandler();
532     });
533 #else
534     completionHandler();
535 #endif
536 }
537
538 - (bool)_hasRegisteredServiceWorker
539 {
540     return WebKit::ServiceWorkerProcessProxy::hasRegisteredServiceWorkers(_websiteDataStore->websiteDataStore().serviceWorkerRegistrationDirectory());
541 }
542
543 - (id <_WKWebsiteDataStoreDelegate>)_delegate
544 {
545     return _delegate.get();
546 }
547
548 - (void)set_delegate:(id <_WKWebsiteDataStoreDelegate>)delegate
549 {
550     _delegate = delegate;
551     _websiteDataStore->websiteDataStore().setClient(makeUniqueRef<WebsiteDataStoreClient>(delegate));
552 }
553
554 @end