Changeset 291467 in webkit
- Timestamp:
- Mar 18, 2022 12:33:15 AM (4 months ago)
- Location:
- trunk
- Files:
-
- 19 edited
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/testing/ServiceWorkerInternals.cpp (modified) (1 diff)
-
Source/WebCore/testing/ServiceWorkerInternals.h (modified) (1 diff)
-
Source/WebCore/testing/ServiceWorkerInternals.idl (modified) (1 diff)
-
Source/WebCore/workers/service/context/SWContextManager.cpp (modified) (1 diff)
-
Source/WebCore/workers/service/context/SWContextManager.h (modified) (2 diffs)
-
Source/WebCore/workers/service/context/ServiceWorkerInspectorProxy.cpp (modified) (2 diffs)
-
Source/WebCore/workers/service/server/SWServer.cpp (modified) (4 diffs)
-
Source/WebCore/workers/service/server/SWServer.h (modified) (2 diffs)
-
Source/WebCore/workers/service/server/SWServerToContextConnection.cpp (modified) (1 diff)
-
Source/WebCore/workers/service/server/SWServerToContextConnection.h (modified) (1 diff)
-
Source/WebCore/workers/service/server/SWServerWorker.cpp (modified) (1 diff)
-
Source/WebCore/workers/service/server/SWServerWorker.h (modified) (3 diffs)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.messages.in (modified) (1 diff)
-
Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp (modified) (1 diff)
-
Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r291464 r291467 1 2022-03-18 Youenn Fablet <youenn@apple.com> 2 3 Keep service workers alive when they are inspected even though they should be terminated 4 https://bugs.webkit.org/show_bug.cgi?id=237827 5 <rdar://88313935> 6 7 Reviewed by Alex Christensen. 8 9 Store in SWServerWorker whether a worker is inspected or is processing push events. 10 In that case, we delay termination of workers until it is no longer inspected or no longer processing push events. 11 Two code paths are happening: 12 1. A service worker was triggered with service worker clients, and all service worker clients are removed. 13 At that point, we were previously terminating service workers after a delay. 14 Instead, we now only terminate workers that are no longer inspected or no longer processing push events. 15 We reschedule the timer to continue trying removing the context connection. 16 2. A service worker is not stopped by removal of service worker clients. In that case, we need to terminate 17 the service workers when inspected and/or push counter gets back to regular (not inspected, no push counter). 18 When terminating such a service worker, we try removing the context connection as well. 19 20 To make sure SWServerWorker knows whether inspectable or not, we add connection support to transmit whether inspected from WebProcess. 21 ServiceWorkerInspectorProxy is responsible to update the inspectable value. 22 Introduce internals API to set inspected state of a service worker. 23 24 Covered by new API tests. 25 26 * testing/ServiceWorkerInternals.cpp: 27 * testing/ServiceWorkerInternals.h: 28 * testing/ServiceWorkerInternals.idl: 29 * workers/service/context/SWContextManager.cpp: 30 * workers/service/context/SWContextManager.h: 31 * workers/service/context/ServiceWorkerInspectorProxy.cpp: 32 * workers/service/server/SWServer.cpp: 33 * workers/service/server/SWServer.h: 34 * workers/service/server/SWServerToContextConnection.cpp: 35 * workers/service/server/SWServerToContextConnection.h: 36 * workers/service/server/SWServerWorker.cpp: 37 * workers/service/server/SWServerWorker.h: 38 1 39 2022-03-17 Matt Woodrow <mattwoodrow@apple.com> 2 40 -
trunk/Source/WebCore/testing/ServiceWorkerInternals.cpp
r288416 r291467 200 200 } 201 201 202 void ServiceWorkerInternals::setAsInspected(bool isInspected) 203 { 204 SWContextManager::singleton().setAsInspected(m_identifier, isInspected); 205 } 206 202 207 } // namespace WebCore 203 208 -
trunk/Source/WebCore/testing/ServiceWorkerInternals.h
r288093 r291467 74 74 75 75 String serviceWorkerClientInternalIdentifier(const ServiceWorkerClient&); 76 void setAsInspected(bool); 76 77 77 78 private: -
trunk/Source/WebCore/testing/ServiceWorkerInternals.idl
r289117 r291467 53 53 54 54 DOMString serviceWorkerClientInternalIdentifier(ServiceWorkerClient client); 55 56 undefined setAsInspected(boolean isInspected); 55 57 }; -
trunk/Source/WebCore/workers/service/context/SWContextManager.cpp
r286044 r291467 209 209 } 210 210 211 void SWContextManager::setAsInspected(ServiceWorkerIdentifier identifier, bool isInspected) 212 { 213 if (m_connection) 214 m_connection->setAsInspected(identifier, isInspected); 215 } 216 211 217 } // namespace WebCore 212 218 -
trunk/Source/WebCore/workers/service/context/SWContextManager.h
r289721 r291467 70 70 71 71 virtual void didFailHeartBeatCheck(ServiceWorkerIdentifier) = 0; 72 virtual void setAsInspected(ServiceWorkerIdentifier, bool) = 0; 72 73 73 74 virtual bool isThrottleable() const = 0; … … 111 112 static constexpr Seconds syncWorkerTerminationTimeout { 100_ms }; // Only used by layout tests. 112 113 114 WEBCORE_EXPORT void setAsInspected(ServiceWorkerIdentifier, bool); 115 113 116 private: 114 117 SWContextManager() = default; -
trunk/Source/WebCore/workers/service/context/ServiceWorkerInspectorProxy.cpp
r291123 r291467 62 62 m_channel = &channel; 63 63 64 SWContextManager::singleton().setAsInspected(m_serviceWorkerThreadProxy.identifier(), true); 64 65 m_serviceWorkerThreadProxy.thread().runLoop().postDebuggerTask([] (ScriptExecutionContext& context) { 65 66 downcast<WorkerGlobalScope>(context).inspectorController().connectFrontend(); … … 72 73 m_channel = nullptr; 73 74 75 SWContextManager::singleton().setAsInspected(m_serviceWorkerThreadProxy.identifier(), false); 74 76 m_serviceWorkerThreadProxy.thread().runLoop().postDebuggerTask([] (ScriptExecutionContext& context) { 75 77 downcast<WorkerGlobalScope>(context).inspectorController().disconnectFrontend(DisconnectReason::InspectorDestroyed); -
trunk/Source/WebCore/workers/service/server/SWServer.cpp
r290776 r291467 1039 1039 Vector<SWServerWorker*> workersToTerminate; 1040 1040 for (auto& worker : m_runningOrTerminatingWorkers.values()) { 1041 if (worker->isRunning() && worker->origin() == clientOrigin )1041 if (worker->isRunning() && worker->origin() == clientOrigin && !worker->shouldContinue()) 1042 1042 workersToTerminate.append(worker.ptr()); 1043 1043 } … … 1045 1045 worker->terminate(); 1046 1046 1047 if ( !m_clientsByRegistrableDomain.contains(clientRegistrableDomain)) {1048 if (auto* connection = contextConnectionForRegistrableDomain(clientRegistrableDomain)) {1049 removeContextConnection(*connection);1050 connection->connectionIsNoLongerNeeded();1051 }1047 if (removeContextConnectionIfPossible(clientRegistrableDomain) == ShouldDelayRemoval::Yes) { 1048 auto iterator = m_clientIdentifiersPerOrigin.find(clientOrigin); 1049 ASSERT(iterator != m_clientIdentifiersPerOrigin.end()); 1050 iterator->value.terminateServiceWorkersTimer->startOneShot(m_isProcessTerminationDelayEnabled ? defaultTerminationDelay : defaultPushMessageDuration); 1051 return; 1052 1052 } 1053 1053 … … 1073 1073 1074 1074 m_clientToControllingRegistration.remove(registrationIterator); 1075 } 1076 1077 SWServer::ShouldDelayRemoval SWServer::removeContextConnectionIfPossible(const RegistrableDomain& domain) 1078 { 1079 if (m_clientsByRegistrableDomain.contains(domain)) 1080 return ShouldDelayRemoval::No; 1081 1082 auto* connection = contextConnectionForRegistrableDomain(domain); 1083 if (!connection) 1084 return ShouldDelayRemoval::No; 1085 1086 for (auto& worker : m_runningOrTerminatingWorkers.values()) { 1087 if (worker->isRunning() && worker->registrableDomain() == domain && worker->shouldContinue()) 1088 return ShouldDelayRemoval::Yes; 1089 } 1090 1091 removeContextConnection(*connection); 1092 connection->connectionIsNoLongerNeeded(); 1093 return ShouldDelayRemoval::No; 1075 1094 } 1076 1095 … … 1282 1301 1283 1302 auto serviceWorkerIdentifier = worker->identifier(); 1284 auto terminateWorkerTimer = makeUnique<Timer>([worker = WTFMove(worker)] { 1285 RELEASE_LOG_ERROR(ServiceWorker, "Terminating service worker as processing push event took too much time"); 1286 worker->terminate(); 1303 1304 worker->incrementPushEventCounter(); 1305 auto terminateWorkerTimer = makeUnique<Timer>([worker] { 1306 RELEASE_LOG_ERROR(ServiceWorker, "Service worker is taking too much time to process a push event"); 1307 worker->decrementPushEventCounter(); 1287 1308 }); 1288 terminateWorkerTimer->startOneShot(weakThis && weakThis->m_isProcessTerminationDelayEnabled ? defaultTerminationDelay : 2_s); 1289 connectionOrStatus.value()->firePushEvent(serviceWorkerIdentifier, data, [callback = WTFMove(callback), terminateWorkerTimer = WTFMove(terminateWorkerTimer)](bool succeeded) mutable { 1290 if (terminateWorkerTimer->isActive()) 1309 terminateWorkerTimer->startOneShot(weakThis && weakThis->m_isProcessTerminationDelayEnabled ? defaultTerminationDelay : defaultPushMessageDuration); 1310 connectionOrStatus.value()->firePushEvent(serviceWorkerIdentifier, data, [callback = WTFMove(callback), terminateWorkerTimer = WTFMove(terminateWorkerTimer), worker = WTFMove(worker)](bool succeeded) mutable { 1311 if (terminateWorkerTimer->isActive()) { 1312 worker->decrementPushEventCounter(); 1291 1313 terminateWorkerTimer->stop(); 1314 } 1292 1315 1293 1316 callback(succeeded); -
trunk/Source/WebCore/workers/service/server/SWServer.h
r290776 r291467 219 219 220 220 static constexpr Seconds defaultTerminationDelay = 10_s; 221 static constexpr Seconds defaultPushMessageDuration = 2_s; 221 222 222 223 LastNavigationWasAppInitiated clientIsAppInitiatedForRegistrableDomain(const RegistrableDomain&); … … 231 232 232 233 void forEachServiceWorker(const Function<bool(const SWServerWorker&)>&) const; 234 bool hasClientsWithOrigin(const ClientOrigin& origin) { return m_clientIdentifiersPerOrigin.contains(origin); } 235 236 enum class ShouldDelayRemoval : bool { No, Yes }; 237 ShouldDelayRemoval removeContextConnectionIfPossible(const RegistrableDomain&); 233 238 234 239 private: -
trunk/Source/WebCore/workers/service/server/SWServerToContextConnection.cpp
r290776 r291467 138 138 } 139 139 140 void SWServerToContextConnection::setAsInspected(ServiceWorkerIdentifier identifier, bool isInspected) 141 { 142 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(identifier)) 143 worker->setAsInspected(isInspected); 144 } 145 140 146 void SWServerToContextConnection::terminateWhenPossible() 141 147 { -
trunk/Source/WebCore/workers/service/server/SWServerToContextConnection.h
r290776 r291467 80 80 WEBCORE_EXPORT void setScriptResource(ServiceWorkerIdentifier, URL&& scriptURL, ServiceWorkerContextData::ImportedScript&&); 81 81 WEBCORE_EXPORT void didFailHeartBeatCheck(ServiceWorkerIdentifier); 82 WEBCORE_EXPORT void setAsInspected(ServiceWorkerIdentifier, bool); 82 83 WEBCORE_EXPORT void findClientByVisibleIdentifier(ServiceWorkerIdentifier, const String& clientIdentifier, CompletionHandler<void(std::optional<WebCore::ServiceWorkerClientData>&&)>&&); 83 84 -
trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp
r288093 r291467 398 398 } 399 399 400 void SWServerWorker::decrementPushEventCounter() 401 { 402 ASSERT(m_pushEventCounter); 403 --m_pushEventCounter; 404 terminateIfPossible(); 405 } 406 407 void SWServerWorker::setAsInspected(bool isInspected) 408 { 409 m_isInspected = isInspected; 410 terminateIfPossible(); 411 } 412 413 void SWServerWorker::terminateIfPossible() 414 { 415 if (m_pushEventCounter || m_isInspected || !m_server || m_server->hasClientsWithOrigin(origin())) 416 return; 417 418 terminate(); 419 m_server->removeContextConnectionIfPossible(registrableDomain()); 420 } 421 400 422 } // namespace WebCore 401 423 -
trunk/Source/WebCore/workers/service/server/SWServerWorker.h
r288974 r291467 136 136 WorkerThreadMode workerThreadMode() const; 137 137 138 void incrementPushEventCounter() { ++m_pushEventCounter; } 139 void decrementPushEventCounter(); 140 void setAsInspected(bool); 141 142 bool shouldContinue() const { return !!m_pushEventCounter || m_isInspected; } 143 138 144 private: 139 145 SWServerWorker(SWServer&, SWServerRegistration&, const URL&, const ScriptBuffer&, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const CrossOriginEmbedderPolicy&, String&& referrerPolicy, WorkerType, ServiceWorkerIdentifier, HashMap<URL, ServiceWorkerContextData::ImportedScript>&&); … … 145 151 void terminationTimerFired(); 146 152 void callTerminationCallbacks(); 153 void terminateIfPossible(); 147 154 148 155 WeakPtr<SWServer> m_server; … … 167 174 Timer m_terminationTimer; 168 175 LastNavigationWasAppInitiated m_lastNavigationWasAppInitiated; 176 int m_pushEventCounter { 0 }; 177 bool m_isInspected { false }; 169 178 }; 170 179 -
trunk/Source/WebKit/ChangeLog
r291465 r291467 1 2022-03-18 Youenn Fablet <youenn@apple.com> 2 3 Keep service workers alive when they are inspected even though they should be terminated 4 https://bugs.webkit.org/show_bug.cgi?id=237827 5 <rdar://88313935> 6 7 Reviewed by Alex Christensen. 8 9 * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.messages.in: 10 * WebProcess/Storage/WebSWContextManagerConnection.cpp: 11 * WebProcess/Storage/WebSWContextManagerConnection.h: 12 1 13 2022-03-17 Alex Christensen <achristensen@webkit.org> 2 14 -
trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.messages.in
r290903 r291467 39 39 PostMessageToServiceWorkerClient(WebCore::ScriptExecutionContextIdentifier destination, struct WebCore::MessageWithMessagePorts message, WebCore::ServiceWorkerIdentifier source, String sourceOrigin) 40 40 DidFailHeartBeatCheck(WebCore::ServiceWorkerIdentifier identifier) 41 SetAsInspected(WebCore::ServiceWorkerIdentifier identifier, bool isInspected) 41 42 } 42 43 -
trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp
r290394 r291467 373 373 } 374 374 375 void WebSWContextManagerConnection::setAsInspected(WebCore::ServiceWorkerIdentifier identifier, bool isInspected) 376 { 377 m_connectionToNetworkProcess->send(Messages::WebSWServerToContextConnection::SetAsInspected { identifier, isInspected }, 0); 378 } 379 375 380 } // namespace WebCore 376 381 -
trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h
r289721 r291467 86 86 bool isThrottleable() const final; 87 87 void didFailHeartBeatCheck(WebCore::ServiceWorkerIdentifier) final; 88 void setAsInspected(WebCore::ServiceWorkerIdentifier, bool) final; 88 89 89 90 // IPC messages. -
trunk/Tools/ChangeLog
r291454 r291467 1 2022-03-18 Youenn Fablet <youenn@apple.com> 2 3 Keep service workers alive when they are inspected even though they should be terminated 4 https://bugs.webkit.org/show_bug.cgi?id=237827 5 <rdar://88313935> 6 7 Reviewed by Alex Christensen. 8 9 * TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm: 10 1 11 2022-03-17 Jonathan Bedard <JonWBedard@gmail.com> 2 12 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm
r290815 r291467 368 368 clearWebsiteDataStore([configuration websiteDataStore]); 369 369 } 370 371 #if WK_HAVE_C_SPI 372 373 static const char* pushEventsAndInspectedServiceWorkerScriptBytes = R"SWRESOURCE( 374 let port; 375 self.addEventListener("message", (event) => { 376 port = event.data.port; 377 port.postMessage(self.internals ? "Ready" : "No internals"); 378 }); 379 self.addEventListener("push", (event) => { 380 self.registration.showNotification("notification"); 381 if (event.data.text() === 'first') { 382 self.internals.setAsInspected(true); 383 self.previousMessageData = 'first'; 384 return; 385 } 386 if (event.data.text() === 'second') { 387 self.internals.setAsInspected(false); 388 if (self.previousMessageData !== 'first') 389 event.waitUntil(Promise.reject('expected first')); 390 return; 391 } 392 if (event.data.text() === 'third') { 393 if (self.previousMessageData !== undefined) 394 event.waitUntil(Promise.reject('expected undefined')); 395 return; 396 } 397 self.previousMessageData = event.data.text(); 398 event.waitUntil(Promise.reject('expected a known message')); 399 }); 400 )SWRESOURCE"; 401 402 TEST(PushAPI, pushEventsAndInspectedServiceWorker) 403 { 404 TestWebKitAPI::HTTPServer server({ 405 { "/", { mainBytes } }, 406 { "/sw.js", { {{ "Content-Type", "application/javascript" }}, pushEventsAndInspectedServiceWorkerScriptBytes } } 407 }, TestWebKitAPI::HTTPServer::Protocol::Http); 408 409 [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins]; 410 411 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 412 clearWebsiteDataStore([configuration websiteDataStore]); 413 414 auto context = adoptWK(TestWebKitAPI::Util::createContextForInjectedBundleTest("InternalsInjectedBundleTest")); 415 [configuration setProcessPool:(WKProcessPool *)context.get()]; 416 417 auto provider = TestWebKitAPI::TestNotificationProvider({ [[configuration processPool] _notificationManagerForTesting], WKNotificationManagerGetSharedServiceWorkerNotificationManager() }); 418 provider.setPermission(server.origin(), true); 419 420 auto messageHandler = adoptNS([[PushAPIMessageHandlerWithExpectedMessage alloc] init]); 421 [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"]; 422 423 expectedMessage = "Ready"; 424 auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]); 425 [webView loadRequest:server.request()]; 426 427 TestWebKitAPI::Util::run(&done); 428 429 [webView _close]; 430 webView = nullptr; 431 432 terminateNetworkProcessWhileRegistrationIsStored(configuration.get()); 433 434 // Push event for service worker without any related page. 435 pushMessageProcessed = false; 436 pushMessageSuccessful = false; 437 NSString *message = @"first"; 438 [[configuration websiteDataStore] _processPushMessage:messageDictionary([message dataUsingEncoding:NSUTF8StringEncoding], [server.request() URL]) completionHandler:^(bool result) { 439 pushMessageSuccessful = result; 440 pushMessageProcessed = true; 441 }]; 442 TestWebKitAPI::Util::run(&pushMessageProcessed); 443 EXPECT_TRUE(pushMessageSuccessful); 444 445 pushMessageProcessed = false; 446 pushMessageSuccessful = false; 447 message = @"second"; 448 [[configuration websiteDataStore] _processPushMessage:messageDictionary([message dataUsingEncoding:NSUTF8StringEncoding], [server.request() URL]) completionHandler:^(bool result) { 449 pushMessageSuccessful = result; 450 pushMessageProcessed = true; 451 }]; 452 TestWebKitAPI::Util::run(&pushMessageProcessed); 453 EXPECT_TRUE(pushMessageSuccessful); 454 455 pushMessageProcessed = false; 456 pushMessageSuccessful = false; 457 message = @"third"; 458 [[configuration websiteDataStore] _processPushMessage:messageDictionary([message dataUsingEncoding:NSUTF8StringEncoding], [server.request() URL]) completionHandler:^(bool result) { 459 pushMessageSuccessful = result; 460 pushMessageProcessed = true; 461 }]; 462 TestWebKitAPI::Util::run(&pushMessageProcessed); 463 EXPECT_TRUE(pushMessageSuccessful); 464 } 465 466 static const char* inspectedServiceWorkerWithoutPageScriptBytes = R"SWRESOURCE( 467 let port; 468 self.addEventListener("message", (event) => { 469 port = event.data.port; 470 port.postMessage(self.internals ? "Ready" : "No internals"); 471 }); 472 self.addEventListener("push", async (event) => { 473 self.registration.showNotification("notification"); 474 if (event.data.text() === 'firstmessage-inspected' || event.data.text() === 'firstmessage-not-inspected') { 475 if (event.data.text() === 'firstmessage-inspected') 476 self.internals.setAsInspected(true); 477 if (self.previousMessageData !== undefined) 478 event.waitUntil(Promise.reject('unexpected state with inspected message')); 479 self.previousMessageData = 'inspected'; 480 // Wait for client to go away before resolving the event promise; 481 let resolve; 482 event.waitUntil(new Promise(r => resolve = r)); 483 while (true) { 484 const clients = await self.clients.matchAll({ includeUncontrolled : true }); 485 if (!clients.length) 486 resolve(); 487 } 488 return; 489 } 490 if (event.data.text() === 'not inspected') { 491 setTimeout(() => self.internals.setAsInspected(false), 10); 492 if (self.previousMessageData !== 'inspected') 493 event.waitUntil(Promise.reject('unexpected state with not inspected message')); 494 self.previousMessageData = 'not inspected'; 495 return; 496 } 497 if (event.data.text() === 'last') { 498 if (self.previousMessageData !== undefined) 499 event.waitUntil(Promise.reject('unexpected state with last message')); 500 } 501 }); 502 )SWRESOURCE"; 503 504 static void testInspectedServiceWorkerWithoutPage(bool enableServiceWorkerInspection) 505 { 506 TestWebKitAPI::HTTPServer server({ 507 { "/", { mainBytes } }, 508 { "/sw.js", { {{ "Content-Type", "application/javascript" }}, inspectedServiceWorkerWithoutPageScriptBytes } } 509 }, TestWebKitAPI::HTTPServer::Protocol::Http); 510 511 [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins]; 512 513 auto dataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]); 514 [dataStoreConfiguration setServiceWorkerProcessTerminationDelayEnabled:NO]; 515 auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:dataStoreConfiguration.get()]); 516 517 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 518 configuration.get().websiteDataStore = dataStore.get(); 519 clearWebsiteDataStore([configuration websiteDataStore]); 520 521 auto context = adoptWK(TestWebKitAPI::Util::createContextForInjectedBundleTest("InternalsInjectedBundleTest")); 522 [configuration setProcessPool:(WKProcessPool *)context.get()]; 523 524 auto provider = TestWebKitAPI::TestNotificationProvider({ [[configuration processPool] _notificationManagerForTesting], WKNotificationManagerGetSharedServiceWorkerNotificationManager() }); 525 provider.setPermission(server.origin(), true); 526 527 auto messageHandler = adoptNS([[PushAPIMessageHandlerWithExpectedMessage alloc] init]); 528 [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"]; 529 530 expectedMessage = "Ready"; 531 auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]); 532 [webView loadRequest:server.request()]; 533 534 TestWebKitAPI::Util::run(&done); 535 536 // Push event for service worker without any related page. 537 pushMessageProcessed = false; 538 pushMessageSuccessful = false; 539 NSString *message = @"firstmessage-inspected"; 540 if (!enableServiceWorkerInspection) 541 message = @"firstmessage-not-inspected"; 542 [[configuration websiteDataStore] _processPushMessage:messageDictionary([message dataUsingEncoding:NSUTF8StringEncoding], [server.request() URL]) completionHandler:^(bool result) { 543 pushMessageSuccessful = result; 544 pushMessageProcessed = true; 545 }]; 546 547 // We delay so that the push message will happen before the unregistration of the service worker client. 548 sleep(0.5); 549 550 // Closing the web view should not terminate the service worker as service worker is inspected. 551 [webView _close]; 552 webView = nullptr; 553 554 TestWebKitAPI::Util::run(&pushMessageProcessed); 555 EXPECT_TRUE(pushMessageSuccessful); 556 557 // We delay so that the timer to terminate service worker kicks in, at most up to the max push message allowed time, aka 2 seconds. 558 sleep(3); 559 560 // Send message at which point the service worker will not be inspected anymore and will be closed. 561 pushMessageProcessed = false; 562 pushMessageSuccessful = false; 563 message = @"not inspected"; 564 [[configuration websiteDataStore] _processPushMessage:messageDictionary([message dataUsingEncoding:NSUTF8StringEncoding], [server.request() URL]) completionHandler:^(bool result) { 565 pushMessageSuccessful = result; 566 pushMessageProcessed = true; 567 }]; 568 TestWebKitAPI::Util::run(&pushMessageProcessed); 569 EXPECT_EQ(pushMessageSuccessful, enableServiceWorkerInspection); 570 571 // We delay so that the timer to terminate service worker kicks in, at most up to the max push message allowed time, aka 2 seconds. 572 sleep(3); 573 574 pushMessageProcessed = false; 575 pushMessageSuccessful = false; 576 message = @"last"; 577 [[configuration websiteDataStore] _processPushMessage:messageDictionary([message dataUsingEncoding:NSUTF8StringEncoding], [server.request() URL]) completionHandler:^(bool result) { 578 pushMessageSuccessful = result; 579 pushMessageProcessed = true; 580 }]; 581 582 TestWebKitAPI::Util::run(&pushMessageProcessed); 583 EXPECT_TRUE(pushMessageSuccessful); 584 } 585 586 TEST(PushAPI, inspectedServiceWorkerWithoutPage) 587 { 588 bool enableServiceWorkerInspection = true; 589 testInspectedServiceWorkerWithoutPage(enableServiceWorkerInspection); 590 } 591 592 TEST(PushAPI, uninspectedServiceWorkerWithoutPage) 593 { 594 bool enableServiceWorkerInspection = false; 595 testInspectedServiceWorkerWithoutPage(enableServiceWorkerInspection); 596 } 597 598 #endif // WK_HAVE_C_SPI
Note: See TracChangeset
for help on using the changeset viewer.