[WKWebsiteDataStore removeDataOfTypes:...] doesn't work for IndexedDB if the data...
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKit2Cocoa / 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>
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 @end
60
61 static WKScriptMessage *getNextMessage()
62 {
63     if (scriptMessages.isEmpty()) {
64         receivedScriptMessage = false;
65         TestWebKitAPI::Util::run(&receivedScriptMessage);
66     }
67
68     return [[scriptMessages.takeFirst() retain] autorelease];
69 }
70
71 TEST(WebKit2, WebsiteDataStoreCustomPaths)
72 {
73     RetainPtr<WebsiteDataStoreCustomPathsMessageHandler> handler = adoptNS([[WebsiteDataStoreCustomPathsMessageHandler alloc] init]);
74     RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
75     [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
76
77     NSURL *sqlPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/WebSQL/" stringByExpandingTildeInPath] isDirectory:YES];
78     NSURL *idbPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/IndexedDB/" stringByExpandingTildeInPath] isDirectory:YES];
79     NSURL *localStoragePath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/LocalStorage/" stringByExpandingTildeInPath] isDirectory:YES];
80     NSURL *cookieStorageFile = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/CustomWebsiteData/CookieStorage/Cookie.File" stringByExpandingTildeInPath] isDirectory:NO];
81
82     NSURL *defaultSQLPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/WebSQL/" stringByExpandingTildeInPath] isDirectory:YES];
83     NSURL *defaultIDBPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/IndexedDB/" stringByExpandingTildeInPath] isDirectory:YES];
84     NSURL *defaultLocalStoragePath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/LocalStorage/" stringByExpandingTildeInPath] isDirectory:YES];
85
86     [[NSFileManager defaultManager] removeItemAtURL:sqlPath error:nil];
87     [[NSFileManager defaultManager] removeItemAtURL:idbPath error:nil];
88     [[NSFileManager defaultManager] removeItemAtURL:localStoragePath error:nil];
89     [[NSFileManager defaultManager] removeItemAtURL:cookieStorageFile error:nil];
90     [[NSFileManager defaultManager] removeItemAtURL:defaultSQLPath error:nil];
91     [[NSFileManager defaultManager] removeItemAtURL:defaultIDBPath error:nil];
92     [[NSFileManager defaultManager] removeItemAtURL:defaultLocalStoragePath error:nil];
93
94     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:sqlPath.path]);
95     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:idbPath.path]);
96     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:localStoragePath.path]);
97     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:cookieStorageFile.path]);
98     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultSQLPath.path]);
99     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultIDBPath.path]);
100     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultLocalStoragePath.path]);
101
102     RetainPtr<_WKWebsiteDataStoreConfiguration> websiteDataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]);
103     websiteDataStoreConfiguration.get()._webSQLDatabaseDirectory = sqlPath;
104     websiteDataStoreConfiguration.get()._indexedDBDatabaseDirectory = idbPath;
105     websiteDataStoreConfiguration.get()._webStorageDirectory = localStoragePath;
106     websiteDataStoreConfiguration.get()._cookieStorageFile = cookieStorageFile;
107
108     configuration.get().websiteDataStore = [[[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()] autorelease];
109
110     RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
111
112     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"WebsiteDataStoreCustomPaths" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
113     [webView loadRequest:request];
114
115     // We expect 4 messages, 1 each for WebSQL, IndexedDB, cookies, and localStorage.
116     EXPECT_STREQ([getNextMessage().body UTF8String], "localstorage written");
117     EXPECT_STREQ([getNextMessage().body UTF8String], "cookie written");
118     EXPECT_STREQ([getNextMessage().body UTF8String], "Exception: QuotaExceededError (DOM Exception 22): The quota has been exceeded.");
119     EXPECT_STREQ([getNextMessage().body UTF8String], "Success opening indexed database");
120
121     [[[webView configuration] processPool] _syncNetworkProcessCookies];
122
123     // Forcibly shut down everything of WebKit that we can.
124     [[[webView configuration] processPool] _terminateDatabaseProcess];
125     auto pid = [webView _webProcessIdentifier];
126     if (pid)
127         kill(pid, SIGKILL);
128
129     webView = nil;
130     handler = nil;
131     configuration = nil;
132
133     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:sqlPath.path]);
134     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:localStoragePath.path]);
135
136 #if PLATFORM(IOS) || (__MAC_OS_X_VERSION_MIN_REQUIRED < 101300)
137     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:cookieStorageFile.path]);
138
139     // Note: The format of the cookie file on disk is proprietary and opaque, so this is fragile to future changes.
140     // But right now, it is reliable to scan the file for the ASCII string of the cookie name we set.
141     // This helps verify that the cookie file was actually written to as we'd expect.
142     auto data = adoptNS([[NSData alloc] initWithContentsOfURL:cookieStorageFile]);
143     char bytes[] = "testkey";
144     auto cookieKeyData = adoptNS([[NSData alloc] initWithBytes:(void *)bytes length:strlen(bytes)]);
145     auto result = [data rangeOfData:cookieKeyData.get() options:0 range:NSMakeRange(0, data.get().length)];
146     EXPECT_NE((const long)result.location, NSNotFound);
147 #endif
148
149 #if PLATFORM(MAC)
150     // FIXME: The default SQL and LocalStorage paths are being used for something, but they shouldn't be. (theses should be false, not true)
151     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultSQLPath.path]);
152     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultLocalStoragePath.path]);
153 #endif
154
155     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:idbPath.path]);
156     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultIDBPath.path]);
157     RetainPtr<NSURL> fileIDBPath = [idbPath URLByAppendingPathComponent:@"file__0"];
158     EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:fileIDBPath.get().path]);
159
160     // Data stores can't delete anything unless a WKProcessPool exists, so make sure the shared data store exists.
161     auto *processPool = [WKProcessPool _sharedProcessPool];
162     [processPool _terminateDatabaseProcess];
163     RetainPtr<WKWebsiteDataStore> dataStore = [[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()];
164     RetainPtr<NSSet> types = adoptNS([[NSSet alloc] initWithObjects:WKWebsiteDataTypeIndexedDBDatabases, nil]);
165
166     receivedScriptMessage = false;
167     [dataStore removeDataOfTypes:types.get() modifiedSince:[NSDate distantPast] completionHandler:[]() {
168         receivedScriptMessage = true;
169     }];
170     TestWebKitAPI::Util::run(&receivedScriptMessage);
171
172     EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:fileIDBPath.get().path]);
173 }
174
175 #endif