source: webkit/trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm@ 286777

Last change on this file since 286777 was 286777, checked in by commit-queue@webkit.org, 3 years ago

Unreviewed, reverting r286764.
https://bugs.webkit.org/show_bug.cgi?id=234081

broke the build

Reverted changeset:

"Add ability to inject messages into webpushd"
https://bugs.webkit.org/show_bug.cgi?id=233988
https://commits.webkit.org/r286764

File size: 13.7 KB
Line 
1/*
2 * Copyright (C) 2021 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 "DaemonTestUtilities.h"
29#import "Test.h"
30#import "TestURLSchemeHandler.h"
31#import "TestWKWebView.h"
32#import "Utilities.h"
33#import <WebKit/WKPreferencesPrivate.h>
34#import <WebKit/WKUIDelegatePrivate.h>
35#import <WebKit/WKWebsiteDataStorePrivate.h>
36#import <WebKit/_WKExperimentalFeature.h>
37#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
38#import <array>
39#import <mach/mach_init.h>
40#import <mach/task.h>
41
42#if PLATFORM(MAC) || PLATFORM(IOS)
43
44static bool alertReceived = false;
45@interface NotificationPermissionDelegate : NSObject<WKUIDelegatePrivate>
46@end
47
48@implementation NotificationPermissionDelegate
49
50- (void)_webView:(WKWebView *)webView requestNotificationPermissionForSecurityOrigin:(WKSecurityOrigin *)securityOrigin decisionHandler:(void (^)(BOOL))decisionHandler
51{
52 decisionHandler(true);
53}
54
55- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
56{
57 alertReceived = true;
58 completionHandler();
59}
60
61@end
62
63namespace TestWebKitAPI {
64
65static RetainPtr<NSURL> testWebPushDaemonLocation()
66{
67 return [currentExecutableDirectory() URLByAppendingPathComponent:@"webpushd" isDirectory:NO];
68}
69
70#if HAVE(OS_LAUNCHD_JOB)
71
72static RetainPtr<xpc_object_t> testWebPushDaemonPList(NSURL *storageLocation)
73{
74 auto currentDirectory = currentExecutableDirectory();
75
76 auto plist = adoptNS(xpc_dictionary_create(nullptr, nullptr, 0));
77 xpc_dictionary_set_string(plist.get(), "_ManagedBy", "TestWebKitAPI");
78 xpc_dictionary_set_string(plist.get(), "Label", "org.webkit.webpushtestdaemon");
79 xpc_dictionary_set_bool(plist.get(), "LaunchOnlyOnce", true);
80 xpc_dictionary_set_bool(plist.get(), "RootedSimulatorPath", true);
81 xpc_dictionary_set_string(plist.get(), "StandardErrorPath", [storageLocation URLByAppendingPathComponent:@"daemon_stderr"].path.fileSystemRepresentation);
82
83 {
84 auto environmentVariables = adoptNS(xpc_dictionary_create(nullptr, nullptr, 0));
85 xpc_dictionary_set_string(environmentVariables.get(), "DYLD_FRAMEWORK_PATH", currentDirectory.get().fileSystemRepresentation);
86 xpc_dictionary_set_value(plist.get(), "EnvironmentVariables", environmentVariables.get());
87 }
88 {
89 auto machServices = adoptNS(xpc_dictionary_create(nullptr, nullptr, 0));
90 xpc_dictionary_set_bool(machServices.get(), "org.webkit.webpushtestdaemon.service", true);
91 xpc_dictionary_set_value(plist.get(), "MachServices", machServices.get());
92 }
93 {
94 auto programArguments = adoptNS(xpc_array_create(nullptr, 0));
95 auto executableLocation = testWebPushDaemonLocation();
96#if PLATFORM(MAC)
97 xpc_array_set_string(programArguments.get(), XPC_ARRAY_APPEND, executableLocation.get().fileSystemRepresentation);
98#else
99 xpc_array_set_string(programArguments.get(), XPC_ARRAY_APPEND, [currentDirectory URLByAppendingPathComponent:@"webpushd"].path.fileSystemRepresentation);
100#endif
101 xpc_array_set_string(programArguments.get(), XPC_ARRAY_APPEND, "--machServiceName");
102 xpc_array_set_string(programArguments.get(), XPC_ARRAY_APPEND, "org.webkit.webpushtestdaemon.service");
103 xpc_dictionary_set_value(plist.get(), "ProgramArguments", programArguments.get());
104 }
105 return plist;
106}
107
108#else // HAVE(OS_LAUNCHD_JOB)
109
110static RetainPtr<NSDictionary> testWebPushDaemonPList(NSURL *storageLocation)
111{
112 return @{
113 @"Label" : @"org.webkit.pcmtestdaemon",
114 @"LaunchOnlyOnce" : @YES,
115 @"StandardErrorPath" : [storageLocation URLByAppendingPathComponent:@"daemon_stderr"].path,
116 @"EnvironmentVariables" : @{ @"DYLD_FRAMEWORK_PATH" : currentExecutableDirectory().get().path },
117 @"MachServices" : @{ @"org.webkit.webpushtestdaemon.service" : @YES },
118 @"ProgramArguments" : @[
119 testWebPushDaemonLocation().get().path,
120 @"--machServiceName",
121 @"org.webkit.webpushtestdaemon.service"
122 ]
123 };
124}
125
126#endif // HAVE(OS_LAUNCHD_JOB)
127
128static NSURL *setUpTestWebPushD()
129{
130 NSFileManager *fileManager = [NSFileManager defaultManager];
131 NSURL *tempDir = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"WebPushDaemonTest"] isDirectory:YES];
132 NSError *error = nil;
133 if ([fileManager fileExistsAtPath:tempDir.path])
134 [fileManager removeItemAtURL:tempDir error:&error];
135 EXPECT_NULL(error);
136
137 killFirstInstanceOfDaemon(@"webpushd");
138
139 auto plist = testWebPushDaemonPList(tempDir);
140#if HAVE(OS_LAUNCHD_JOB)
141 registerPlistWithLaunchD(WTFMove(plist));
142#else
143 registerPlistWithLaunchD(WTFMove(plist), tempDir);
144#endif
145
146 return tempDir;
147}
148
149static void cleanUpTestWebPushD(NSURL *tempDir)
150{
151 killFirstInstanceOfDaemon(@"webpushd");
152
153 if (![[NSFileManager defaultManager] fileExistsAtPath:tempDir.path])
154 return;
155
156 NSError *error = nil;
157 [[NSFileManager defaultManager] removeItemAtURL:tempDir error:&error];
158
159 if (error)
160 NSLog(@"Error removing tempDir URL: %@", error);
161
162 EXPECT_NULL(error);
163}
164
165// FIXME: Re-enable this test on Mac once webkit.org/232857 is resolved.
166#if PLATFORM(MAC)
167TEST(WebPushD, DISABLED_BasicCommunication)
168#else
169TEST(WebPushD, BasicCommunication)
170#endif
171{
172 NSURL *tempDir = setUpTestWebPushD();
173
174 auto connection = adoptNS(xpc_connection_create_mach_service("org.webkit.webpushtestdaemon.service", dispatch_get_main_queue(), 0));
175
176 __block bool done = false;
177 xpc_connection_set_event_handler(connection.get(), ^(xpc_object_t request) {
178 if (xpc_get_type(request) != XPC_TYPE_DICTIONARY)
179 return;
180 const char* debugMessage = xpc_dictionary_get_string(request, "debug message");
181 if (!debugMessage)
182 return;
183
184 NSString *nsMessage = [NSString stringWithUTF8String:debugMessage];
185
186 // Ignore possible connections/messages from webpushtool
187 if ([nsMessage hasPrefix:@"[webpushtool "])
188 return;
189
190 bool stringMatches = [nsMessage hasPrefix:@"[com.apple.WebKit.TestWebKitAPI"] || [nsMessage hasPrefix:@"[TestWebKitAPI"];
191 stringMatches = stringMatches && [nsMessage hasSuffix:@" Turned Debug Mode on"];
192
193 EXPECT_TRUE(stringMatches);
194
195 done = true;
196 });
197
198 xpc_connection_activate(connection.get());
199
200 audit_token_t token = { 0, 0, 0, 0, 0, 0, 0, 0 };
201 mach_msg_type_number_t auditTokenCount = TASK_AUDIT_TOKEN_COUNT;
202 kern_return_t result = task_info(mach_task_self(), TASK_AUDIT_TOKEN, (task_info_t)(&token), &auditTokenCount);
203 if (result != KERN_SUCCESS) {
204 EXPECT_TRUE(false);
205 return;
206 }
207
208 // Send configuration with audit token
209 {
210 std::array<uint8_t, 42> encodedMessage;
211 encodedMessage.fill(0);
212 encodedMessage[1] = 1;
213 encodedMessage[2] = 32;
214 memcpy(&encodedMessage[10], &token, sizeof(token));
215 auto dictionary = adoptNS(xpc_dictionary_create(nullptr, nullptr, 0));
216 xpc_dictionary_set_uint64(dictionary.get(), "protocol version", 1);
217 xpc_dictionary_set_uint64(dictionary.get(), "message type", 6);
218 xpc_dictionary_set_data(dictionary.get(), "encoded message", encodedMessage.data(), encodedMessage.size());
219 xpc_connection_send_message(connection.get(), dictionary.get());
220 }
221
222 // Enable debug messages, and wait for the resulting debug message
223 {
224 auto dictionary = adoptNS(xpc_dictionary_create(nullptr, nullptr, 0));
225 std::array<uint8_t, 1> encodedMessage { 1 };
226 xpc_dictionary_set_uint64(dictionary.get(), "protocol version", 1);
227 xpc_dictionary_set_uint64(dictionary.get(), "message type", 5);
228 xpc_dictionary_set_data(dictionary.get(), "encoded message", encodedMessage.data(), encodedMessage.size());
229
230 xpc_connection_send_message(connection.get(), dictionary.get());
231 TestWebKitAPI::Util::run(&done);
232 }
233
234 // Echo and wait for a reply
235 auto dictionary = adoptNS(xpc_dictionary_create(nullptr, nullptr, 0));
236 std::array<uint8_t, 10> encodedString { 5, 0, 0, 0, 1, 'h', 'e', 'l', 'l', 'o' };
237 xpc_dictionary_set_uint64(dictionary.get(), "protocol version", 1);
238 xpc_dictionary_set_uint64(dictionary.get(), "message type", 1);
239 xpc_dictionary_set_data(dictionary.get(), "encoded message", encodedString.data(), encodedString.size());
240
241 done = false;
242 xpc_connection_send_message_with_reply(connection.get(), dictionary.get(), dispatch_get_main_queue(), ^(xpc_object_t reply) {
243 if (xpc_get_type(reply) != XPC_TYPE_DICTIONARY) {
244 NSLog(@"Unexpected non-dictionary: %@", reply);
245 done = true;
246 EXPECT_TRUE(FALSE);
247 return;
248 }
249
250 size_t dataSize = 0;
251 const void* data = xpc_dictionary_get_data(reply, "encoded message", &dataSize);
252 EXPECT_EQ(dataSize, 15u);
253 std::array<uint8_t, 15> expectedReply { 10, 0, 0, 0, 1, 'h', 'e', 'l', 'l', 'o' , 'h', 'e', 'l', 'l', 'o' };
254 EXPECT_FALSE(memcmp(data, expectedReply.data(), expectedReply.size()));
255 done = true;
256 });
257 TestWebKitAPI::Util::run(&done);
258
259 cleanUpTestWebPushD(tempDir);
260}
261
262static const char* mainBytes = R"WEBPUSHRESOURCE(
263<script>
264 Notification.requestPermission().then(() => { alert("done") })
265</script>
266)WEBPUSHRESOURCE";
267
268// FIXME: Re-enable this test on Mac once webkit.org/232857 is resolved.
269#if PLATFORM(MAC)
270TEST(WebPushD, DISABLED_PermissionManagement)
271#else
272TEST(WebPushD, PermissionManagement)
273#endif
274{
275 NSURL *tempDirectory = setUpTestWebPushD();
276
277 auto dataStoreConfiguration = adoptNS([_WKWebsiteDataStoreConfiguration new]);
278 dataStoreConfiguration.get().webPushMachServiceName = @"org.webkit.webpushtestdaemon.service";
279 dataStoreConfiguration.get().webPushDaemonUsesMockBundlesForTesting = YES;
280 auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:dataStoreConfiguration.get()]);
281
282 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
283 configuration.get().websiteDataStore = dataStore.get();
284 [configuration.get().preferences _setNotificationsEnabled:YES];
285 for (_WKExperimentalFeature *feature in [WKPreferences _experimentalFeatures]) {
286 if ([feature.key isEqualToString:@"BuiltInNotificationsEnabled"])
287 [[configuration preferences] _setEnabled:YES forFeature:feature];
288 }
289
290 auto handler = adoptNS([[TestURLSchemeHandler alloc] init]);
291 [configuration setURLSchemeHandler:handler.get() forURLScheme:@"testing"];
292
293 [handler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
294 auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
295 [task didReceiveResponse:response.get()];
296 [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
297 [task didFinish];
298 }];
299
300 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
301 auto uiDelegate = adoptNS([[NotificationPermissionDelegate alloc] init]);
302 [webView setUIDelegate:uiDelegate.get()];
303
304 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"testing://main/index.html"]]];
305 TestWebKitAPI::Util::run(&alertReceived);
306
307 static bool originOperationDone = false;
308 static RetainPtr<WKSecurityOrigin> origin;
309 [dataStore _getOriginsWithPushAndNotificationPermissions:^(NSSet<WKSecurityOrigin *> *origins) {
310 EXPECT_EQ([origins count], 1u);
311 origin = [origins anyObject];
312 originOperationDone = true;
313 }];
314
315 TestWebKitAPI::Util::run(&originOperationDone);
316
317 EXPECT_TRUE([origin.get().protocol isEqualToString:@"testing"]);
318 EXPECT_TRUE([origin.get().host isEqualToString:@"main"]);
319
320 // If we failed to retrieve an expected origin, we will have failed the above checks
321 if (!origin) {
322 cleanUpTestWebPushD(tempDirectory);
323 return;
324 }
325
326 originOperationDone = false;
327 [dataStore _deletePushAndNotificationRegistration:origin.get() completionHandler:^(NSError *error) {
328 EXPECT_FALSE(!!error);
329 originOperationDone = true;
330 }];
331
332 TestWebKitAPI::Util::run(&originOperationDone);
333
334 originOperationDone = false;
335 [dataStore _getOriginsWithPushAndNotificationPermissions:^(NSSet<WKSecurityOrigin *> *origins) {
336 EXPECT_EQ([origins count], 0u);
337 originOperationDone = true;
338 }];
339 TestWebKitAPI::Util::run(&originOperationDone);
340
341 cleanUpTestWebPushD(tempDirectory);
342}
343
344} // namespace TestWebKitAPI
345
346#endif // PLATFORM(MAC) || PLATFORM(IOS)
Note: See TracBrowser for help on using the repository browser.