-[WKWebsiteDataStore removeDataOfTypes:forDataRecords:completionHandler:] doesn't...
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitCocoa / WKWebsiteDatastore.mm
1 /*
2  * Copyright (C) 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
28 #import "PlatformUtilities.h"
29 #import "TCPServer.h"
30 #import "Test.h"
31 #import "TestWKWebView.h"
32 #import <WebKit/WKProcessPoolPrivate.h>
33 #import <WebKit/WKWebsiteDataRecordPrivate.h>
34 #import <WebKit/WKWebsiteDataStorePrivate.h>
35 #import <WebKit/WebKit.h>
36 #import <wtf/text/WTFString.h>
37
38 static bool readyToContinue;
39
40 static RetainPtr<NSURLCredential> persistentCredential;
41 static bool usePersistentCredentialStorage = false;
42
43 @interface NavigationTestDelegate : NSObject <WKNavigationDelegate>
44 @end
45
46 @implementation NavigationTestDelegate {
47     bool _hasFinishedNavigation;
48 }
49
50 - (instancetype)init
51 {
52     if (!(self = [super init]))
53         return nil;
54     
55     _hasFinishedNavigation = false;
56     
57     return self;
58 }
59
60 - (void)waitForDidFinishNavigation
61 {
62     TestWebKitAPI::Util::run(&_hasFinishedNavigation);
63 }
64
65 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
66 {
67     _hasFinishedNavigation = true;
68 }
69
70 - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
71 {
72     static bool firstChallenge = true;
73     if (firstChallenge) {
74         firstChallenge = false;
75         persistentCredential = adoptNS([[NSURLCredential alloc] initWithUser:@"username" password:@"password" persistence:(usePersistentCredentialStorage ? NSURLCredentialPersistencePermanent: NSURLCredentialPersistenceForSession)]);
76         return completionHandler(NSURLSessionAuthChallengeUseCredential, persistentCredential.get());
77     }
78     return completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
79 }
80 @end
81
82 namespace TestWebKitAPI {
83
84 TEST(WKWebsiteDataStore, RemoveAndFetchData)
85 {
86     readyToContinue = false;
87     [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore _allWebsiteDataTypesIncludingPrivate] modifiedSince:[NSDate distantPast] completionHandler:^() {
88         readyToContinue = true;
89     }];
90     TestWebKitAPI::Util::run(&readyToContinue);
91     
92     readyToContinue = false;
93     [[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:[WKWebsiteDataStore _allWebsiteDataTypesIncludingPrivate] completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
94         ASSERT_EQ(0u, dataRecords.count);
95         readyToContinue = true;
96     }];
97     TestWebKitAPI::Util::run(&readyToContinue);
98 }
99
100 TEST(WKWebsiteDataStore, RemoveEphemeralData)
101 {
102     auto configuration = adoptNS([WKWebViewConfiguration new]);
103     [configuration setWebsiteDataStore:[WKWebsiteDataStore nonPersistentDataStore]];
104     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
105     [webView synchronouslyLoadTestPageNamed:@"simple"];
106     __block bool done = false;
107     [[configuration websiteDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler: ^{
108         done = true;
109     }];
110     TestWebKitAPI::Util::run(&done);
111 }
112
113 static void respondWithChallengeThenOK(int socket)
114 {
115     char readBuffer[1000];
116     auto bytesRead = ::read(socket, readBuffer, sizeof(readBuffer));
117     EXPECT_GT(bytesRead, 0);
118     EXPECT_TRUE(static_cast<size_t>(bytesRead) < sizeof(readBuffer));
119     
120     const char* challengeHeader =
121     "HTTP/1.1 401 Unauthorized\r\n"
122     "Date: Sat, 23 Mar 2019 06:29:01 GMT\r\n"
123     "Content-Length: 0\r\n"
124     "WWW-Authenticate: Basic realm=\"testrealm\"\r\n\r\n";
125     auto bytesWritten = ::write(socket, challengeHeader, strlen(challengeHeader));
126     EXPECT_EQ(static_cast<size_t>(bytesWritten), strlen(challengeHeader));
127     
128     bytesRead = ::read(socket, readBuffer, sizeof(readBuffer));
129     EXPECT_GT(bytesRead, 0);
130     EXPECT_TRUE(static_cast<size_t>(bytesRead) < sizeof(readBuffer));
131     
132     const char* responseHeader =
133     "HTTP/1.1 200 OK\r\n"
134     "Content-Length: 13\r\n\r\n"
135     "Hello, World!";
136     bytesWritten = ::write(socket, responseHeader, strlen(responseHeader));
137     EXPECT_EQ(static_cast<size_t>(bytesWritten), strlen(responseHeader));
138 }
139     
140 TEST(WKWebsiteDataStore, FetchNonPersistentCredentials)
141 {
142     TCPServer server(respondWithChallengeThenOK);
143     
144     auto configuration = adoptNS([WKWebViewConfiguration new]);
145     auto websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
146     [configuration setWebsiteDataStore:websiteDataStore];
147     auto navigationDelegate = adoptNS([[NavigationTestDelegate alloc] init]);
148     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
149     [webView setNavigationDelegate:navigationDelegate.get()];
150     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()]]]];
151     [navigationDelegate waitForDidFinishNavigation];
152
153     __block bool done = false;
154     [websiteDataStore fetchDataRecordsOfTypes:[NSSet setWithObject:_WKWebsiteDataTypeCredentials] completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
155         int credentialCount = dataRecords.count;
156         ASSERT_EQ(credentialCount, 1);
157         for (WKWebsiteDataRecord *record in dataRecords)
158             ASSERT_TRUE([[record displayName] isEqualToString:@"127.0.0.1"]);
159         done = true;
160     }];
161     TestWebKitAPI::Util::run(&done);
162 }
163
164 TEST(WKWebsiteDataStore, FetchPersistentCredentials)
165 {
166     TCPServer server(respondWithChallengeThenOK);
167     
168     usePersistentCredentialStorage = true;
169     auto websiteDataStore = [WKWebsiteDataStore defaultDataStore];
170     auto navigationDelegate = adoptNS([[NavigationTestDelegate alloc] init]);
171     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
172     [webView setNavigationDelegate:navigationDelegate.get()];
173     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()]]]];
174     [navigationDelegate waitForDidFinishNavigation];
175
176     __block bool done = false;
177     [websiteDataStore fetchDataRecordsOfTypes:[NSSet setWithObject:_WKWebsiteDataTypeCredentials] completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
178         int credentialCount = dataRecords.count;
179         ASSERT_GT(credentialCount, 0);
180         bool foundExpectedRecord = false;
181         for (WKWebsiteDataRecord *record in dataRecords) {
182             auto name = [record displayName];
183             if ([name isEqualToString:@"127.0.0.1"]) {
184                 foundExpectedRecord = true;
185                 break;
186             }
187         }
188         EXPECT_TRUE(foundExpectedRecord);
189         done = true;
190     }];
191     TestWebKitAPI::Util::run(&done);
192     
193     __block bool removedCredential = false;
194     [[[webView configuration] processPool] _removeCredential:persistentCredential.get() forProtectionSpace:[[[NSURLProtectionSpace alloc] initWithHost:@"127.0.0.1" port:server.port() protocol:NSURLProtectionSpaceHTTP realm:@"testrealm" authenticationMethod:NSURLAuthenticationMethodHTTPBasic] autorelease] completionHandler:^{
195         removedCredential = true;
196     }];
197     TestWebKitAPI::Util::run(&removedCredential);
198 }
199
200 TEST(WKWebsiteDataStore, RemovePersistentCredentials)
201 {
202     TCPServer server(respondWithChallengeThenOK);
203     
204     usePersistentCredentialStorage = true;
205     auto websiteDataStore = [WKWebsiteDataStore defaultDataStore];
206     auto navigationDelegate = adoptNS([[NavigationTestDelegate alloc] init]);
207     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
208     [webView setNavigationDelegate:navigationDelegate.get()];
209     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/", server.port()]]]];
210     [navigationDelegate waitForDidFinishNavigation];
211
212     __block bool done = false;
213     __block RetainPtr<WKWebsiteDataRecord> expectedRecord;
214     [websiteDataStore fetchDataRecordsOfTypes:[NSSet setWithObject:_WKWebsiteDataTypeCredentials] completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
215         int credentialCount = dataRecords.count;
216         ASSERT_GT(credentialCount, 0);
217         for (WKWebsiteDataRecord *record in dataRecords) {
218             auto name = [record displayName];
219             if ([name isEqualToString:@"127.0.0.1"]) {
220                 expectedRecord = record;
221                 break;
222             }
223         }
224         EXPECT_TRUE(expectedRecord);
225         done = true;
226     }];
227     TestWebKitAPI::Util::run(&done);
228
229     done = false;
230     [websiteDataStore removeDataOfTypes:[NSSet setWithObject:_WKWebsiteDataTypeCredentials] forDataRecords:[NSArray arrayWithObject:expectedRecord.get()] completionHandler:^(void) {
231         done = true;
232     }];
233     TestWebKitAPI::Util::run(&done);
234
235     done = false;
236     [websiteDataStore fetchDataRecordsOfTypes:[NSSet setWithObject:_WKWebsiteDataTypeCredentials] completionHandler:^(NSArray<WKWebsiteDataRecord *> *dataRecords) {
237         bool foundLocalHostRecord = false;
238         for (WKWebsiteDataRecord *record in dataRecords) {
239             auto name = [record displayName];
240             if ([name isEqualToString:@"127.0.0.1"]) {
241                 foundLocalHostRecord = true;
242                 break;
243             }
244         }
245         EXPECT_FALSE(foundLocalHostRecord);
246         done = true;
247     }];
248     TestWebKitAPI::Util::run(&done);
249 }
250
251 }