Remove StorageProcess
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitCocoa / WebsiteDataStoreCustomPaths.mm
1 /*
2  * Copyright (C) 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
28 #import "PlatformUtilities.h"
29 #import "Test.h"
30 #import <WebKit/WebKit.h>
31
32 #import <WebKit/WKProcessPoolPrivate.h>
33 #import <WebKit/WKUserContentControllerPrivate.h>
34 #import <WebKit/WKWebViewConfigurationPrivate.h>
35 #import <WebKit/WKWebViewPrivate.h>
36 #import <WebKit/WKWebsiteDataStorePrivate.h>
37 #import <WebKit/_WKProcessPoolConfiguration.h>
38 #import <WebKit/_WKUserStyleSheet.h>
39 #import <WebKit/_WKWebsiteDataStoreConfiguration.h>
40 #import <wtf/Deque.h>
41 #import <wtf/RetainPtr.h>
42
43 #if WK_API_ENABLED
44
45 static bool receivedScriptMessage;
46 static Deque<RetainPtr<WKScriptMessage>> scriptMessages;
47
48 @interface WebsiteDataStoreCustomPathsMessageHandler : NSObject <WKScriptMessageHandler, WKNavigationDelegate>
49 @end
50
51 @implementation WebsiteDataStoreCustomPathsMessageHandler
52
53 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
54 {
55     receivedScriptMessage = true;
56     scriptMessages.append(message);
57 }
58
59 - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
60 {
61     // Overwrite the default policy which launches a new web process and reload page on crash.
62 }
63
64 @end
65
66 static WKScriptMessage *getNextMessage()
67 {
68     if (scriptMessages.isEmpty()) {
69         receivedScriptMessage = false;
70         TestWebKitAPI::Util::run(&receivedScriptMessage);
71     }
72
73     return [[scriptMessages.takeFirst() retain] autorelease];
74 }
75
76 TEST(WebKit, WebsiteDataStoreCustomPaths)
77 {
78     RetainPtr<WebsiteDataStoreCustomPathsMessageHandler> handler = adoptNS([[WebsiteDataStoreCustomPathsMessageHandler alloc] init]);
79     RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
80     [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
81
82     NSURL *sqlPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/WebSQL/" stringByExpandingTildeInPath] isDirectory:YES];
83     NSURL *idbPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/IndexedDB/" stringByExpandingTildeInPath] isDirectory:YES];
84     NSURL *localStoragePath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/LocalStorage/" stringByExpandingTildeInPath] isDirectory:YES];
85     NSURL *cookieStorageFile = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/CookieStorage/Cookie.File" stringByExpandingTildeInPath] isDirectory:NO];
86     NSURL *resourceLoadStatisticsPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/ResourceLoadStatistics/" stringByExpandingTildeInPath] isDirectory:YES];
87
88     NSURL *defaultSQLPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/WebSQL/" stringByExpandingTildeInPath] isDirectory:YES];
89     NSURL *defaultIDBPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/IndexedDB/" stringByExpandingTildeInPath] isDirectory:YES];
90     NSURL *defaultLocalStoragePath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/LocalStorage/" stringByExpandingTildeInPath] isDirectory:YES];
91     NSURL *defaultResourceLoadStatisticsPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/ResourceLoadStatistics/" stringByExpandingTildeInPath] isDirectory:YES];
92
93     [[NSFileManager defaultManager] removeItemAtURL:sqlPath error:nil];
94     [[NSFileManager defaultManager] removeItemAtURL:idbPath error:nil];
95     [[NSFileManager defaultManager] removeItemAtURL:localStoragePath error:nil];
96     [[NSFileManager defaultManager] removeItemAtURL:cookieStorageFile error:nil];
97     [[NSFileManager defaultManager] removeItemAtURL:resourceLoadStatisticsPath error:nil];
98     [[NSFileManager defaultManager] removeItemAtURL:defaultSQLPath error:nil];
99     [[NSFileManager defaultManager] removeItemAtURL:defaultIDBPath error:nil];
100     [[NSFileManager defaultManager] removeItemAtURL:defaultLocalStoragePath error:nil];
101     [[NSFileManager defaultManager] removeItemAtURL:defaultResourceLoadStatisticsPath error:nil];
102
103     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:sqlPath.path]);
104     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:idbPath.path]);
105     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:localStoragePath.path]);
106     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:cookieStorageFile.path]);
107     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:resourceLoadStatisticsPath.path]);
108     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultSQLPath.path]);
109     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultIDBPath.path]);
110     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultLocalStoragePath.path]);
111     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsPath.path]);
112
113     RetainPtr<_WKWebsiteDataStoreConfiguration> websiteDataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]);
114     websiteDataStoreConfiguration.get()._webSQLDatabaseDirectory = sqlPath;
115     websiteDataStoreConfiguration.get()._indexedDBDatabaseDirectory = idbPath;
116     websiteDataStoreConfiguration.get()._webStorageDirectory = localStoragePath;
117     websiteDataStoreConfiguration.get()._cookieStorageFile = cookieStorageFile;
118     websiteDataStoreConfiguration.get()._resourceLoadStatisticsDirectory = resourceLoadStatisticsPath;
119
120     configuration.get().websiteDataStore = [[[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()] autorelease];
121
122     RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
123     [webView setNavigationDelegate:handler.get()];
124
125     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"WebsiteDataStoreCustomPaths" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
126     [webView loadRequest:request];
127
128     EXPECT_FALSE([WKWebsiteDataStore _defaultDataStoreExists]);
129
130     // We expect 4 messages, 1 each for WebSQL, IndexedDB, cookies, and localStorage.
131     EXPECT_STREQ([getNextMessage().body UTF8String], "localstorage written");
132     EXPECT_STREQ([getNextMessage().body UTF8String], "cookie written");
133     EXPECT_STREQ([getNextMessage().body UTF8String], "Exception: QuotaExceededError: The quota has been exceeded.");
134     EXPECT_STREQ([getNextMessage().body UTF8String], "Success opening indexed database");
135
136     [[[webView configuration] processPool] _syncNetworkProcessCookies];
137
138     // Forcibly shut down everything of WebKit that we can.
139     auto pid = [webView _webProcessIdentifier];
140     if (pid)
141         kill(pid, SIGKILL);
142
143     webView = nil;
144     handler = nil;
145     configuration = nil;
146
147     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:sqlPath.path]);
148     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:localStoragePath.path]);
149
150 #if PLATFORM(IOS) || (__MAC_OS_X_VERSION_MIN_REQUIRED < 101300)
151     int retryCount = 30;
152     while (retryCount--) {
153         if ([[NSFileManager defaultManager] fileExistsAtPath:cookieStorageFile.path])
154             break;
155         TestWebKitAPI::Util::sleep(0.1);
156     }
157     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:cookieStorageFile.path]);
158
159     // Note: The format of the cookie file on disk is proprietary and opaque, so this is fragile to future changes.
160     // But right now, it is reliable to scan the file for the ASCII string of the cookie name we set.
161     // This helps verify that the cookie file was actually written to as we'd expect.
162     auto data = adoptNS([[NSData alloc] initWithContentsOfURL:cookieStorageFile]);
163     char bytes[] = "testkey";
164     auto cookieKeyData = adoptNS([[NSData alloc] initWithBytes:(void *)bytes length:strlen(bytes)]);
165     auto result = [data rangeOfData:cookieKeyData.get() options:0 range:NSMakeRange(0, data.get().length)];
166     EXPECT_NE((const long)result.location, NSNotFound);
167 #endif
168
169 #if PLATFORM(MAC)
170     // FIXME: The default SQL and LocalStorage paths are being used for something, but they shouldn't be. (theses should be false, not true)
171     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultSQLPath.path]);
172     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultLocalStoragePath.path]);
173 #endif
174
175     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:idbPath.path]);
176     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultIDBPath.path]);
177     RetainPtr<NSURL> fileIDBPath = [idbPath URLByAppendingPathComponent:@"file__0"];
178     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:fileIDBPath.get().path]);
179
180     // Data stores can't delete anything unless a WKProcessPool exists, so make sure the shared data store exists.
181     auto *processPool = [WKProcessPool _sharedProcessPool];
182     RetainPtr<WKWebsiteDataStore> dataStore = [[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()];
183     RetainPtr<NSSet> types = adoptNS([[NSSet alloc] initWithObjects:WKWebsiteDataTypeIndexedDBDatabases, nil]);
184
185     // Subframe of different origins may also create IndexedDB files.
186     RetainPtr<NSURL> url1 = [[NSBundle mainBundle] URLForResource:@"IndexedDB" withExtension:@"sqlite3" subdirectory:@"TestWebKitAPI.resources"];
187     RetainPtr<NSURL> url2 = [[NSBundle mainBundle] URLForResource:@"IndexedDB" withExtension:@"sqlite3-shm" subdirectory:@"TestWebKitAPI.resources"];
188     RetainPtr<NSURL> url3 = [[NSBundle mainBundle] URLForResource:@"IndexedDB" withExtension:@"sqlite3-wal" subdirectory:@"TestWebKitAPI.resources"];
189     
190     RetainPtr<NSURL> frameIDBPath = [[fileIDBPath URLByAppendingPathComponent:@"https_apple.com_0"] URLByAppendingPathComponent:@"WebsiteDataStoreCustomPaths"];
191     [[NSFileManager defaultManager] createDirectoryAtURL:frameIDBPath.get() withIntermediateDirectories:YES attributes:nil error:nil];
192     
193     [[NSFileManager defaultManager] copyItemAtURL:url1.get() toURL:[frameIDBPath.get() URLByAppendingPathComponent:@"IndexedDB.sqlite3"] error:nil];
194     [[NSFileManager defaultManager] copyItemAtURL:url2.get() toURL:[frameIDBPath.get() URLByAppendingPathComponent:@"IndexedDB.sqlite3-shm"] error:nil];
195     [[NSFileManager defaultManager] copyItemAtURL:url3.get() toURL:[frameIDBPath.get() URLByAppendingPathComponent:@"IndexedDB.sqlite3-wal"] error:nil];
196     
197     RetainPtr<NSURL> frameIDBPath2 = [[fileIDBPath URLByAppendingPathComponent:@"https_webkit.org_0"] URLByAppendingPathComponent:@"WebsiteDataStoreCustomPaths"];
198     [[NSFileManager defaultManager] createDirectoryAtURL:frameIDBPath2.get() withIntermediateDirectories:YES attributes:nil error:nil];
199     
200     [[NSFileManager defaultManager] copyItemAtURL:url1.get() toURL:[frameIDBPath2.get() URLByAppendingPathComponent:@"IndexedDB.sqlite3"] error:nil];
201     [[NSFileManager defaultManager] copyItemAtURL:url2.get() toURL:[frameIDBPath2.get() URLByAppendingPathComponent:@"IndexedDB.sqlite3-shm"] error:nil];
202     [[NSFileManager defaultManager] copyItemAtURL:url3.get() toURL:[frameIDBPath2.get() URLByAppendingPathComponent:@"IndexedDB.sqlite3-wal"] error:nil];
203
204     [dataStore fetchDataRecordsOfTypes:types.get() completionHandler:^(NSArray<WKWebsiteDataRecord *> * records) {
205         EXPECT_EQ([records count], (unsigned long)3);
206         for (id record in records) {
207             if ([[record displayName] isEqual: @"apple.com"]) {
208                 [dataStore removeDataOfTypes:types.get() forDataRecords:[NSArray arrayWithObject:record] completionHandler:^() {
209                     receivedScriptMessage = true;
210                     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:frameIDBPath.get().path]);
211                 }];
212             }
213         }
214     }];
215     receivedScriptMessage = false;
216     TestWebKitAPI::Util::run(&receivedScriptMessage);
217
218     [dataStore removeDataOfTypes:types.get() modifiedSince:[NSDate distantPast] completionHandler:[]() {
219         receivedScriptMessage = true;
220     }];
221     receivedScriptMessage = false;
222     TestWebKitAPI::Util::run(&receivedScriptMessage);
223
224     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:fileIDBPath.get().path]);
225
226     // Now, with brand new WKWebsiteDataStores pointing at the same custom cookie storage location,
227     // in newly fired up NetworkProcesses, verify that the fetch and delete APIs work as expected.
228
229     [processPool _terminateNetworkProcess];
230     auto newCustomDataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]);
231
232     [newCustomDataStore fetchDataRecordsOfTypes:[NSSet setWithObjects:WKWebsiteDataTypeCookies, nil] completionHandler:^(NSArray<WKWebsiteDataRecord *> * records) {
233         EXPECT_GT([records count], (unsigned long)0);
234         receivedScriptMessage = true;
235     }];
236
237     receivedScriptMessage = false;
238     TestWebKitAPI::Util::run(&receivedScriptMessage);
239
240     [processPool _terminateNetworkProcess];
241     newCustomDataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]);
242
243     [newCustomDataStore removeDataOfTypes:[NSSet setWithObjects:WKWebsiteDataTypeCookies, nil] modifiedSince:[NSDate distantPast] completionHandler:^ {
244         receivedScriptMessage = true;
245     }];
246
247     receivedScriptMessage = false;
248     TestWebKitAPI::Util::run(&receivedScriptMessage);
249
250     // This time, reuse the same network process but still do a new websitedatastore, to make sure even an existing network process
251     // gets the new datastore.
252     newCustomDataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]);
253
254     [newCustomDataStore fetchDataRecordsOfTypes:[NSSet setWithObjects:WKWebsiteDataTypeCookies, nil] completionHandler:^(NSArray<WKWebsiteDataRecord *> * records) {
255         EXPECT_EQ([records count], (unsigned long)0);
256         receivedScriptMessage = true;
257     }];
258
259     receivedScriptMessage = false;
260     TestWebKitAPI::Util::run(&receivedScriptMessage);
261
262     EXPECT_FALSE([WKWebsiteDataStore _defaultDataStoreExists]);
263 }
264
265 TEST(WebKit, CustomDataStorePathsVersusCompletionHandlers)
266 {
267     // Copy the baked database files to the database directory
268     NSURL *url1 = [[NSBundle mainBundle] URLForResource:@"SimpleServiceWorkerRegistrations-3" withExtension:@"sqlite3" subdirectory:@"TestWebKitAPI.resources"];
269
270     NSURL *swPath = [NSURL fileURLWithPath:[@"~/Library/Caches/TestWebKitAPI/WebKit/ServiceWorkers/" stringByExpandingTildeInPath]];
271     [[NSFileManager defaultManager] removeItemAtURL:swPath error:nil];
272     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:swPath.path]);
273
274     [[NSFileManager defaultManager] createDirectoryAtURL:swPath withIntermediateDirectories:YES attributes:nil error:nil];
275     [[NSFileManager defaultManager] copyItemAtURL:url1 toURL:[swPath URLByAppendingPathComponent:@"ServiceWorkerRegistrations-3.sqlite3"] error:nil];
276
277     auto websiteDataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]);
278     websiteDataStoreConfiguration.get()._serviceWorkerRegistrationDirectory = swPath;
279     auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]);
280
281     // Fetch SW records
282     auto websiteDataTypes = adoptNS([[NSSet alloc] initWithArray:@[WKWebsiteDataTypeServiceWorkerRegistrations]]);
283     static bool readyToContinue;
284     [dataStore fetchDataRecordsOfTypes:websiteDataTypes.get() completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
285         EXPECT_EQ(1U, dataRecords.count);
286         readyToContinue = true;
287     }];
288     TestWebKitAPI::Util::run(&readyToContinue);
289     readyToContinue = false;
290
291     // Fetch records again, this time releasing our reference to the data store while the request is in flight.
292     [dataStore fetchDataRecordsOfTypes:websiteDataTypes.get() completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
293         EXPECT_EQ(1U, dataRecords.count);
294         readyToContinue = true;
295     }];
296     dataStore = nil;
297     TestWebKitAPI::Util::run(&readyToContinue);
298     readyToContinue = false;
299
300     // Delete all SW records, releasing our reference to the data store while the request is in flight.
301     dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]);
302     [dataStore removeDataOfTypes:websiteDataTypes.get() modifiedSince:[NSDate distantPast] completionHandler:^() {
303         readyToContinue = true;
304     }];
305     dataStore = nil;
306     TestWebKitAPI::Util::run(&readyToContinue);
307     readyToContinue = false;
308
309     // The records should have been deleted, and the callback should have been made.
310     // Now refetch the records to verify they are gone.
311     dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]);
312     [dataStore fetchDataRecordsOfTypes:websiteDataTypes.get() completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
313         EXPECT_EQ(0U, dataRecords.count);
314         readyToContinue = true;
315     }];
316     TestWebKitAPI::Util::run(&readyToContinue);
317 }
318
319 TEST(WebKit, CustomDataStoreDestroyWhileFetchingNetworkProcessData)
320 {
321     NSURL *cookieStorageFile = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/CookieStorage/Cookie.File" stringByExpandingTildeInPath] isDirectory:NO];
322     [[NSFileManager defaultManager] removeItemAtURL:cookieStorageFile error:nil];
323
324     auto websiteDataTypes = adoptNS([[NSSet alloc] initWithArray:@[WKWebsiteDataTypeCookies]]);
325     static bool readyToContinue;
326
327     auto websiteDataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]);
328     websiteDataStoreConfiguration.get()._cookieStorageFile = cookieStorageFile;
329
330     @autoreleasepool {
331         auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]);
332
333         // Fetch records
334         [dataStore fetchDataRecordsOfTypes:websiteDataTypes.get() completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
335             EXPECT_EQ((int)dataRecords.count, 0);
336             readyToContinue = true;
337         }];
338         TestWebKitAPI::Util::run(&readyToContinue);
339         readyToContinue = false;
340
341         // Fetch records again, this time releasing our reference to the data store while the request is in flight.
342         [dataStore fetchDataRecordsOfTypes:websiteDataTypes.get() completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
343             EXPECT_EQ((int)dataRecords.count, 0);
344             readyToContinue = true;
345         }];
346         dataStore = nil;
347     }
348     TestWebKitAPI::Util::run(&readyToContinue);
349     readyToContinue = false;
350
351     @autoreleasepool {
352         auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]);
353         [dataStore fetchDataRecordsOfTypes:websiteDataTypes.get() completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
354             EXPECT_EQ((int)dataRecords.count, 0);
355             readyToContinue = true;
356         }];
357
358         // Terminate the network process while a query is pending.
359         auto* allProcessPools = [WKProcessPool _allProcessPoolsForTesting];
360         ASSERT_EQ(1U, [allProcessPools count]);
361         auto* processPool = allProcessPools[0];
362         while (![processPool _networkProcessIdentifier])
363             TestWebKitAPI::Util::sleep(0.01);
364         kill([processPool _networkProcessIdentifier], SIGKILL);
365         allProcessPools = nil;
366         dataStore = nil;
367     }
368
369     TestWebKitAPI::Util::run(&readyToContinue);
370     readyToContinue = false;
371 }
372
373 TEST(WebKit, WebsiteDataStoreEphemeral)
374 {
375     RetainPtr<WebsiteDataStoreCustomPathsMessageHandler> handler = adoptNS([[WebsiteDataStoreCustomPathsMessageHandler alloc] init]);
376     RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
377     [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
378
379     NSURL *defaultResourceLoadStatisticsPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/ResourceLoadStatistics/" stringByExpandingTildeInPath] isDirectory:YES];
380
381     [[NSFileManager defaultManager] removeItemAtURL:defaultResourceLoadStatisticsPath error:nil];
382
383     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsPath.path]);
384
385     configuration.get().websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
386     [configuration.get().websiteDataStore _setResourceLoadStatisticsEnabled:YES];
387
388     // We expect the directory to be created by starting up the data store machinery, but not the data file.
389     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsPath.path]);
390
391     NSURL *defaultResourceLoadStatisticsFilePath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/ResourceLoadStatistics/full_browsing_session_resourceLog.plist" stringByExpandingTildeInPath] isDirectory:NO];
392     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsFilePath.path]);
393
394     RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
395
396     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"WebsiteDataStoreCustomPaths" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
397     [webView loadRequest:request];
398
399     [[[webView configuration] processPool] _syncNetworkProcessCookies];
400
401     // Forcibly shut down everything of WebKit that we can.
402     auto pid = [webView _webProcessIdentifier];
403     if (pid)
404         kill(pid, SIGKILL);
405
406     webView = nil;
407     handler = nil;
408     configuration = nil;
409
410     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsPath.path]);
411     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsFilePath.path]);
412 }
413
414 #endif