Changeset 291938 in webkit
- Timestamp:
- Mar 26, 2022 8:55:18 AM (4 months ago)
- Location:
- trunk
- Files:
-
- 45 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/http/tests/workers/service/resources/postmessage-echo-worker.js (modified) (1 diff)
-
LayoutTests/http/tests/workers/service/resources/serviceworkerclients-get-worker.js (modified) (1 diff)
-
LayoutTests/http/tests/workers/service/serviceworkerclients-matchAll-worker.js (modified) (1 diff)
-
LayoutTests/http/tests/workers/service/serviceworkerclients-matchAll.https-expected.txt (modified) (1 diff)
-
LayoutTests/http/tests/workers/service/serviceworkerclients-matchAll.https.html (modified) (1 diff)
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/testing/ServiceWorkerInternals.cpp (modified) (2 diffs)
-
Source/WebCore/testing/ServiceWorkerInternals.h (modified) (3 diffs)
-
Source/WebCore/testing/js/WebCoreTestSupport.cpp (modified) (1 diff)
-
Source/WebCore/workers/service/ServiceWorkerClient.cpp (modified) (2 diffs)
-
Source/WebCore/workers/service/ServiceWorkerClient.h (modified) (1 diff)
-
Source/WebCore/workers/service/ServiceWorkerClientData.h (modified) (1 diff)
-
Source/WebCore/workers/service/ServiceWorkerClients.cpp (modified) (6 diffs)
-
Source/WebCore/workers/service/ServiceWorkerClients.h (modified) (1 diff)
-
Source/WebCore/workers/service/ServiceWorkerGlobalScope.cpp (modified) (4 diffs)
-
Source/WebCore/workers/service/ServiceWorkerGlobalScope.h (modified) (4 diffs)
-
Source/WebCore/workers/service/ServiceWorkerWindowClient.cpp (modified) (2 diffs)
-
Source/WebCore/workers/service/ServiceWorkerWindowClient.h (modified) (1 diff)
-
Source/WebCore/workers/service/ServiceWorkerWindowClient.idl (modified) (1 diff)
-
Source/WebCore/workers/service/context/SWContextManager.h (modified) (1 diff)
-
Source/WebCore/workers/service/context/ServiceWorkerThread.cpp (modified) (1 diff)
-
Source/WebCore/workers/service/server/SWServer.h (modified) (1 diff)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp (modified) (1 diff)
-
Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h (modified) (1 diff)
-
Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp (modified) (1 diff)
-
Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h (modified) (1 diff)
-
Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.messages.in (modified) (1 diff)
-
Source/WebKit/UIProcess/API/APIUIClient.h (modified) (1 diff)
-
Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h (modified) (1 diff)
-
Source/WebKit/UIProcess/Cocoa/UIDelegate.h (modified) (2 diffs)
-
Source/WebKit/UIProcess/Cocoa/UIDelegate.mm (modified) (3 diffs)
-
Source/WebKit/UIProcess/WebPageProxy.cpp (modified) (1 diff)
-
Source/WebKit/UIProcess/WebPageProxy.h (modified) (1 diff)
-
Source/WebKit/UIProcess/WebPageProxy.messages.in (modified) (1 diff)
-
Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp (modified) (2 diffs)
-
Source/WebKit/WebProcess/Storage/WebSWClientConnection.h (modified) (1 diff)
-
Source/WebKit/WebProcess/Storage/WebSWClientConnection.messages.in (modified) (1 diff)
-
Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp (modified) (2 diffs)
-
Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r291901 r291938 1 2022-03-26 Youenn Fablet <youenn@apple.com> 2 3 Implement ServiceWorkerWindowClient.focus 4 https://bugs.webkit.org/show_bug.cgi?id=238319 5 <rdar://90616490> 6 7 Reviewed by Brady Eidson. 8 9 Update tests to cover the fact we no longer reuse Client objects. 10 11 * http/tests/workers/service/resources/postmessage-echo-worker.js: 12 * http/tests/workers/service/resources/serviceworkerclients-get-worker.js: 13 * http/tests/workers/service/serviceworkerclients-matchAll-worker.js: 14 * http/tests/workers/service/serviceworkerclients-matchAll.https-expected.txt: 15 * http/tests/workers/service/serviceworkerclients-matchAll.https.html: 16 1 17 2022-03-25 Alexander Mikhaylenko <alexm@gnome.org> 2 18 -
trunk/LayoutTests/http/tests/workers/service/resources/postmessage-echo-worker.js
r225403 r291938 7 7 return; 8 8 } 9 } else if (client !== event.source) {9 } else if (client.id !== event.source.id) { 10 10 event.source.postMessage("FAIL: client source of the second message is not the same as the first message"); 11 return; 12 } else if (client === event.source) { 13 event.source.postMessage("FAIL: client source of the second message is the same object as for the first message"); 11 14 return; 12 15 } -
trunk/LayoutTests/http/tests/workers/service/resources/serviceworkerclients-get-worker.js
r225427 r291938 20 20 } 21 21 22 if (retrievedClient !== client) {23 event.source.postMessage("FAIL: client is different from the one retrieved through self.clients.get");22 if (retrievedClient === client) { 23 event.source.postMessage("FAIL: reusing same client object in different self.clients.get calls"); 24 24 return; 25 25 } -
trunk/LayoutTests/http/tests/workers/service/serviceworkerclients-matchAll-worker.js
r288093 r291938 42 42 { 43 43 try { 44 if (event.data.test === "checkNewClientObject") { 45 const clients1 = await self.clients.matchAll({ includeUncontrolled : true }); 46 const clients2 = await self.clients.matchAll({ includeUncontrolled : true }); 47 if (!clients1.length || !clients2.length) { 48 event.source.postMessage("no clients"); 49 return; 50 } 51 for (let client1 of clients1) { 52 for (let client2 of clients2) { 53 if (client1 === client2) { 54 event.source.postMessage("FAIL: reusing client objects"); 55 return; 56 } 57 } 58 } 59 event.source.postMessage("PASS"); 60 return; 61 } 62 44 63 if (event.data.test !== "checkClientIsUncontrolled") { 45 64 event.source.postMessage("FAIL: received unexpected message from client"); -
trunk/LayoutTests/http/tests/workers/service/serviceworkerclients-matchAll.https-expected.txt
r267644 r291938 1 1 2 2 PASS Setup worker 3 PASS Test self.clients.matchAll create new client object every time 3 4 PASS Test self.clients.matchAll 4 5 -
trunk/LayoutTests/http/tests/workers/service/serviceworkerclients-matchAll.https.html
r288093 r291938 28 28 29 29 promise_test(async (test) => { 30 var promise = new Promise((resolve, reject) => { 31 navigator.serviceWorker.addEventListener("message", test.step_func((event) => { 32 assert_equals(event.data, "PASS"); 33 resolve(); 34 })); 35 }); 36 37 activeWorker.postMessage({test: "checkNewClientObject"}); 38 await promise; 39 }, "Test self.clients.matchAll create new client object every time"); 40 41 promise_test(async (test) => { 30 42 const serviceWorkerClientIdentifier = internals.serviceWorkerClientInternalIdentifier(document); 31 43 var promise = new Promise((resolve, reject) => { -
trunk/Source/WTF/ChangeLog
r291937 r291938 1 2022-03-26 Youenn Fablet <youenn@apple.com> 2 3 Implement ServiceWorkerWindowClient.focus 4 https://bugs.webkit.org/show_bug.cgi?id=238319 5 <rdar://90616490> 6 7 Reviewed by Brady Eidson. 8 9 * Scripts/Preferences/WebPreferencesInternal.yaml: 10 1 11 2022-03-26 Yusuke Suzuki <ysuzuki@apple.com> 2 12 -
trunk/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml
r291473 r291938 844 844 default: false 845 845 846 ServiceWorkersUserGestureEnabled: 847 type: bool 848 humanReadableName: "Validate UserGesture requirements in Service Workers" 849 humanReadableDescription: "Validate UserGesture requirements in Service Workers" 850 condition: ENABLE(SERVICE_WORKER) 851 defaultValue: 852 WebKitLegacy: 853 default: false 854 WebKit: 855 default: true 856 WebCore: 857 default: true 858 846 859 SimpleLineLayoutEnabled: 847 860 type: bool -
trunk/Source/WebCore/ChangeLog
r291937 r291938 1 2022-03-26 Youenn Fablet <youenn@apple.com> 2 3 Implement ServiceWorkerWindowClient.focus 4 https://bugs.webkit.org/show_bug.cgi?id=238319 5 <rdar://90616490> 6 7 Reviewed by Brady Eidson. 8 9 Add support for service worker focus: 10 - Implement user gesture requirement by introducing a flag in ServiceWorkerGlobalScope that is turned on for some time 11 when receiving specific events like notification click event. The max time is currently set to 2 seconds. 12 We might want to improve handling of user activation in non-document contexts but this is a fuzzy area right now so a service worker 13 solution seems good for now. 14 - Remove the map of service worker client since we need to create new ones every time. 15 - focus will go its context manager that will send an IPC message to the network process to actually trigger focus. 16 We are missing focused check at promise resolution, this will be done in a follow-up. 17 18 Covered by API test. 19 20 * testing/ServiceWorkerInternals.cpp: 21 * testing/ServiceWorkerInternals.h: 22 * testing/js/WebCoreTestSupport.cpp: 23 * workers/service/ServiceWorkerClient.cpp: 24 * workers/service/ServiceWorkerClient.h: 25 * workers/service/ServiceWorkerClientData.h: 26 * workers/service/ServiceWorkerClients.cpp: 27 * workers/service/ServiceWorkerClients.h: 28 * workers/service/ServiceWorkerGlobalScope.cpp: 29 * workers/service/ServiceWorkerGlobalScope.h: 30 * workers/service/ServiceWorkerWindowClient.cpp: 31 * workers/service/ServiceWorkerWindowClient.h: 32 * workers/service/ServiceWorkerWindowClient.idl: 33 * workers/service/context/SWContextManager.h: 34 * workers/service/context/ServiceWorkerThread.cpp: 35 * workers/service/server/SWServer.h: 36 1 37 2022-03-26 Yusuke Suzuki <ysuzuki@apple.com> 2 38 -
trunk/Source/WebCore/testing/ServiceWorkerInternals.cpp
r291467 r291938 35 35 #include "SWContextManager.h" 36 36 #include "ServiceWorkerClient.h" 37 #include "ServiceWorkerGlobalScope.h" 37 38 #include "ServiceWorkerRegistration.h" 38 39 #include <wtf/ProcessID.h> … … 40 41 namespace WebCore { 41 42 42 ServiceWorkerInternals::ServiceWorkerInternals(ServiceWorker Identifier identifier)43 ServiceWorkerInternals::ServiceWorkerInternals(ServiceWorkerGlobalScope& globalScope, ServiceWorkerIdentifier identifier) 43 44 : m_identifier(identifier) 44 45 { 46 globalScope.setIsProcessingUserGestureForTesting(true); 45 47 } 46 48 -
trunk/Source/WebCore/testing/ServiceWorkerInternals.h
r291467 r291938 41 41 class PushSubscription; 42 42 class ScriptExecutionContext; 43 class ServiceWorkerGlobalScope; 43 44 class ServiceWorkerClient; 44 45 … … 47 48 class WEBCORE_TESTSUPPORT_EXPORT ServiceWorkerInternals : public RefCounted<ServiceWorkerInternals>, public CanMakeWeakPtr<ServiceWorkerInternals> { 48 49 public: 49 static Ref<ServiceWorkerInternals> create(ServiceWorker Identifier identifier) { return adoptRef(*new ServiceWorkerInternals {identifier }); }50 static Ref<ServiceWorkerInternals> create(ServiceWorkerGlobalScope& globalScope, ServiceWorkerIdentifier identifier) { return adoptRef(*new ServiceWorkerInternals { globalScope, identifier }); } 50 51 ~ServiceWorkerInternals(); 51 52 … … 77 78 78 79 private: 79 explicit ServiceWorkerInternals(ServiceWorkerIdentifier);80 ServiceWorkerInternals(ServiceWorkerGlobalScope&, ServiceWorkerIdentifier); 80 81 81 82 ServiceWorkerIdentifier m_identifier; -
trunk/Source/WebCore/testing/js/WebCoreTestSupport.cpp
r287737 r291938 229 229 JSLockHolder locker(vm); 230 230 auto* contextWrapper = script->globalScopeWrapper(); 231 contextWrapper->putDirect(vm, Identifier::fromString(vm, Internals::internalsId), toJS(&globalObject, contextWrapper, ServiceWorkerInternals::create( identifier)));231 contextWrapper->putDirect(vm, Identifier::fromString(vm, Internals::internalsId), toJS(&globalObject, contextWrapper, ServiceWorkerInternals::create(globalScope, identifier))); 232 232 }); 233 233 #else -
trunk/Source/WebCore/workers/service/ServiceWorkerClient.cpp
r291888 r291938 40 40 namespace WebCore { 41 41 42 Ref<ServiceWorkerClient> ServiceWorkerClient:: getOrCreate(ServiceWorkerGlobalScope& context, ServiceWorkerClientData&& data)42 Ref<ServiceWorkerClient> ServiceWorkerClient::create(ServiceWorkerGlobalScope& context, ServiceWorkerClientData&& data) 43 43 { 44 if (auto* client = context.serviceWorkerClient(data.identifier)) {45 // Temporary fix until we remove reusing of same ServiceWorkerClient objects.46 client->m_data = WTFMove(data);47 return *client;48 }49 50 44 if (data.type == ServiceWorkerClientType::Window) 51 45 return ServiceWorkerWindowClient::create(context, WTFMove(data)); … … 58 52 , m_data(WTFMove(data)) 59 53 { 60 context.addServiceWorkerClient(*this);61 54 } 62 55 63 56 ServiceWorkerClient::~ServiceWorkerClient() 64 57 { 65 if (auto* context = scriptExecutionContext())66 downcast<ServiceWorkerGlobalScope>(*context).removeServiceWorkerClient(*this);67 58 } 68 59 -
trunk/Source/WebCore/workers/service/ServiceWorkerClient.h
r291888 r291938 53 53 using FrameType = ServiceWorkerClientFrameType; 54 54 55 static Ref<ServiceWorkerClient> getOrCreate(ServiceWorkerGlobalScope&, ServiceWorkerClientData&&);55 static Ref<ServiceWorkerClient> create(ServiceWorkerGlobalScope&, ServiceWorkerClientData&&); 56 56 57 57 ~ServiceWorkerClient(); -
trunk/Source/WebCore/workers/service/ServiceWorkerClientData.h
r291888 r291938 54 54 ServiceWorkerClientData isolatedCopy() &&; 55 55 56 static ServiceWorkerClientData from(ScriptExecutionContext&);56 WEBCORE_EXPORT static ServiceWorkerClientData from(ScriptExecutionContext&); 57 57 58 58 template<class Encoder> void encode(Encoder&) const; -
trunk/Source/WebCore/workers/service/ServiceWorkerClients.cpp
r291888 r291938 46 46 } 47 47 48 promise.resolve<IDLInterface<ServiceWorkerClient>>(ServiceWorkerClient:: getOrCreate(scope, WTFMove(*clientData)));48 promise.resolve<IDLInterface<ServiceWorkerClient>>(ServiceWorkerClient::create(scope, WTFMove(*clientData))); 49 49 } 50 50 … … 53 53 auto serviceWorkerIdentifier = downcast<ServiceWorkerGlobalScope>(context).thread().identifier(); 54 54 55 auto promisePointer = promise.ptr(); 56 m_pendingPromises.add(promisePointer, WTFMove(promise)); 57 58 callOnMainThread([promisePointer, serviceWorkerIdentifier, id = id.isolatedCopy()] () { 55 callOnMainThread([promiseIdentifier = addPendingPromise(WTFMove(promise)), serviceWorkerIdentifier, id = id.isolatedCopy()] () { 59 56 auto connection = SWContextManager::singleton().connection(); 60 connection->findClientByVisibleIdentifier(serviceWorkerIdentifier, id, [promise Pointer, serviceWorkerIdentifier] (auto&& clientData) {61 SWContextManager::singleton().postTaskToServiceWorker(serviceWorkerIdentifier, [promise Pointer, data = crossThreadCopy(WTFMove(clientData))] (auto& context) mutable {62 if (auto promise = context.clients(). m_pendingPromises.take(promisePointer))57 connection->findClientByVisibleIdentifier(serviceWorkerIdentifier, id, [promiseIdentifier, serviceWorkerIdentifier] (auto&& clientData) { 58 SWContextManager::singleton().postTaskToServiceWorker(serviceWorkerIdentifier, [promiseIdentifier, data = crossThreadCopy(WTFMove(clientData))] (auto& context) mutable { 59 if (auto promise = context.clients().takePendingPromise(promiseIdentifier)) 63 60 didFinishGetRequest(context, *promise, WTFMove(data)); 64 61 }); … … 71 68 { 72 69 auto clients = WTF::map(clientsData, [&] (auto&& clientData) { 73 return ServiceWorkerClient:: getOrCreate(scope, WTFMove(clientData));70 return ServiceWorkerClient::create(scope, WTFMove(clientData)); 74 71 }); 75 72 std::sort(clients.begin(), clients.end(), [&] (auto& a, auto& b) { … … 81 78 void ServiceWorkerClients::matchAll(ScriptExecutionContext& context, const ClientQueryOptions& options, Ref<DeferredPromise>&& promise) 82 79 { 83 auto promisePointer = promise.ptr();84 m_pendingPromises.add(promisePointer, WTFMove(promise));85 86 80 auto serviceWorkerIdentifier = downcast<ServiceWorkerGlobalScope>(context).thread().identifier(); 87 81 88 callOnMainThread([promise Pointer, serviceWorkerIdentifier, options] () mutable {82 callOnMainThread([promiseIdentifier = addPendingPromise(WTFMove(promise)), serviceWorkerIdentifier, options] () mutable { 89 83 auto connection = SWContextManager::singleton().connection(); 90 connection->matchAll(serviceWorkerIdentifier, options, [promise Pointer, serviceWorkerIdentifier] (auto&& clientsData) mutable {91 SWContextManager::singleton().postTaskToServiceWorker(serviceWorkerIdentifier, [promise Pointer, clientsData = crossThreadCopy(WTFMove(clientsData))] (auto& scope) mutable {92 if (auto promise = scope.clients(). m_pendingPromises.take(promisePointer))84 connection->matchAll(serviceWorkerIdentifier, options, [promiseIdentifier, serviceWorkerIdentifier] (auto&& clientsData) mutable { 85 SWContextManager::singleton().postTaskToServiceWorker(serviceWorkerIdentifier, [promiseIdentifier, clientsData = crossThreadCopy(WTFMove(clientsData))] (auto& scope) mutable { 86 if (auto promise = scope.clients().takePendingPromise(promiseIdentifier)) 93 87 matchAllCompleted(scope, *promise, WTFMove(clientsData)); 94 88 }); … … 105 99 void ServiceWorkerClients::claim(ScriptExecutionContext& context, Ref<DeferredPromise>&& promise) 106 100 { 107 auto & serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(context);101 auto serviceWorkerIdentifier = downcast<ServiceWorkerGlobalScope>(context).thread().identifier(); 108 102 109 auto serviceWorkerIdentifier = serviceWorkerGlobalScope.thread().identifier(); 110 111 auto promisePointer = promise.ptr(); 112 m_pendingPromises.add(promisePointer, WTFMove(promise)); 113 114 callOnMainThread([promisePointer, serviceWorkerIdentifier] () mutable { 103 callOnMainThread([promiseIdentifier = addPendingPromise(WTFMove(promise)), serviceWorkerIdentifier] () mutable { 115 104 auto connection = SWContextManager::singleton().connection(); 116 connection->claim(serviceWorkerIdentifier, [promise Pointer, serviceWorkerIdentifier](auto&& result) mutable {117 SWContextManager::singleton().postTaskToServiceWorker(serviceWorkerIdentifier, [promise Pointer, result = crossThreadCopy(WTFMove(result))](auto& scope) mutable {118 if (auto promise = scope.clients(). m_pendingPromises.take(promisePointer)) {105 connection->claim(serviceWorkerIdentifier, [promiseIdentifier, serviceWorkerIdentifier](auto&& result) mutable { 106 SWContextManager::singleton().postTaskToServiceWorker(serviceWorkerIdentifier, [promiseIdentifier, result = crossThreadCopy(WTFMove(result))](auto& scope) mutable { 107 if (auto promise = scope.clients().takePendingPromise(promiseIdentifier)) { 119 108 DOMPromiseDeferred<void> pendingPromise { promise.releaseNonNull() }; 120 109 pendingPromise.settle(WTFMove(result)); … … 125 114 } 126 115 116 ServiceWorkerClients::PromiseIdentifier ServiceWorkerClients::addPendingPromise(Ref<DeferredPromise>&& promise) 117 { 118 auto identifier = PromiseIdentifier::generateThreadSafe(); 119 m_pendingPromises.add(identifier, WTFMove(promise)); 120 return identifier; 121 } 122 123 RefPtr<DeferredPromise> ServiceWorkerClients::takePendingPromise(PromiseIdentifier identifier) 124 { 125 return m_pendingPromises.take(identifier); 126 } 127 127 128 } // namespace WebCore 128 129 -
trunk/Source/WebCore/workers/service/ServiceWorkerClients.h
r286012 r291938 55 55 void claim(ScriptExecutionContext&, Ref<DeferredPromise>&&); 56 56 57 enum PromiseIdentifierType { }; 58 using PromiseIdentifier = ObjectIdentifier<PromiseIdentifierType>; 59 60 PromiseIdentifier addPendingPromise(Ref<DeferredPromise>&&); 61 RefPtr<DeferredPromise> takePendingPromise(PromiseIdentifier); 62 57 63 private: 58 64 ServiceWorkerClients() = default; 59 65 60 HashMap< DeferredPromise*, Ref<DeferredPromise>> m_pendingPromises;66 HashMap<PromiseIdentifier, Ref<DeferredPromise>> m_pendingPromises; 61 67 }; 62 68 -
trunk/Source/WebCore/workers/service/ServiceWorkerGlobalScope.cpp
r289726 r291938 69 69 , m_sessionID(sessionID) 70 70 , m_notificationClient(WTFMove(notificationClient)) 71 , m_userGestureTimer(*this, &ServiceWorkerGlobalScope::resetUserGesture) 71 72 { 72 73 } … … 135 136 } 136 137 137 ServiceWorkerClient* ServiceWorkerGlobalScope::serviceWorkerClient(ScriptExecutionContextIdentifier identifier)138 {139 return m_clientMap.get(identifier);140 }141 142 void ServiceWorkerGlobalScope::addServiceWorkerClient(ServiceWorkerClient& client)143 {144 auto result = m_clientMap.add(client.identifier(), &client);145 ASSERT_UNUSED(result, result.isNewEntry);146 }147 148 void ServiceWorkerGlobalScope::removeServiceWorkerClient(ServiceWorkerClient& client)149 {150 auto isRemoved = m_clientMap.remove(client.identifier());151 ASSERT_UNUSED(isRemoved, isRemoved);152 }153 154 138 // https://w3c.github.io/ServiceWorker/#update-service-worker-extended-events-set-algorithm 155 139 void ServiceWorkerGlobalScope::updateExtendedEventsSet(ExtendableEvent* newEvent) … … 225 209 case NotificationEventType::Click: 226 210 eventName = eventNames().notificationclickEvent; 211 downcast<ServiceWorkerGlobalScope>(scope).recordUserGesture(); 227 212 break; 228 213 case NotificationEventType::Close: … … 238 223 #endif 239 224 225 void ServiceWorkerGlobalScope::recordUserGesture() 226 { 227 m_isProcessingUserGesture = true; 228 m_userGestureTimer.startOneShot(userGestureLifetime); 229 } 230 240 231 } // namespace WebCore 241 232 -
trunk/Source/WebCore/workers/service/ServiceWorkerGlobalScope.h
r290815 r291938 68 68 ServiceWorkerThread& thread(); 69 69 70 ServiceWorkerClient* serviceWorkerClient(ScriptExecutionContextIdentifier);71 void addServiceWorkerClient(ServiceWorkerClient&);72 void removeServiceWorkerClient(ServiceWorkerClient&);73 74 70 void updateExtendedEventsSet(ExtendableEvent* newEvent = nullptr); 75 71 … … 93 89 void setHasPendingSilentPushEvent(bool value) { m_hasPendingSilentPushEvent = value; } 94 90 91 constexpr static Seconds userGestureLifetime { 2_s }; 92 bool isProcessingUserGesture() const { return m_isProcessingUserGesture; } 93 void recordUserGesture(); 94 void setIsProcessingUserGestureForTesting(bool value) { m_isProcessingUserGesture = value; } 95 95 96 private: 96 97 ServiceWorkerGlobalScope(ServiceWorkerContextData&&, ServiceWorkerData&&, const WorkerParameters&, Ref<SecurityOrigin>&&, ServiceWorkerThread&, Ref<SecurityOrigin>&& topOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*, std::unique_ptr<NotificationClient>&&, PAL::SessionID); … … 104 105 std::optional<PAL::SessionID> sessionID() const final { return m_sessionID; } 105 106 107 void resetUserGesture() { m_isProcessingUserGesture = false; } 108 106 109 ServiceWorkerContextData m_contextData; 107 110 Ref<ServiceWorkerRegistration> m_registration; 108 111 Ref<ServiceWorker> m_serviceWorker; 109 112 Ref<ServiceWorkerClients> m_clients; 110 HashMap<ScriptExecutionContextIdentifier, ServiceWorkerClient*> m_clientMap;111 113 Vector<Ref<ExtendableEvent>> m_extendedEvents; 112 114 … … 116 118 std::unique_ptr<NotificationClient> m_notificationClient; 117 119 bool m_hasPendingSilentPushEvent { false }; 120 bool m_isProcessingUserGesture { false }; 121 Timer m_userGestureTimer; 118 122 }; 119 123 -
trunk/Source/WebCore/workers/service/ServiceWorkerWindowClient.cpp
r291888 r291938 30 30 31 31 #include "JSDOMPromiseDeferred.h" 32 #include "JSServiceWorkerWindowClient.h" 33 #include "SWContextManager.h" 34 #include "ServiceWorkerClients.h" 35 #include "ServiceWorkerThread.h" 32 36 33 37 namespace WebCore { … … 38 42 } 39 43 40 void ServiceWorkerWindowClient::focus( Ref<DeferredPromise>&& promise)44 void ServiceWorkerWindowClient::focus(ScriptExecutionContext& context, Ref<DeferredPromise>&& promise) 41 45 { 42 promise->reject(Exception { NotSupportedError, "windowClient.focus() is not yet supported"_s }); 46 auto& serviceWorkerContext = downcast<ServiceWorkerGlobalScope>(context); 47 48 if (context.settingsValues().serviceWorkersUserGestureEnabled && !serviceWorkerContext.isProcessingUserGesture()) { 49 promise->reject(Exception { InvalidAccessError, "WindowClient focus requires a user gesture"_s }); 50 return; 51 } 52 53 auto promiseIdentifier = serviceWorkerContext.clients().addPendingPromise(WTFMove(promise)); 54 callOnMainThread([clientIdentifier = identifier(), promiseIdentifier, serviceWorkerIdentifier = serviceWorkerContext.thread().identifier()]() mutable { 55 SWContextManager::singleton().connection()->focus(clientIdentifier, [promiseIdentifier, serviceWorkerIdentifier](auto result) mutable { 56 SWContextManager::singleton().postTaskToServiceWorker(serviceWorkerIdentifier, [promiseIdentifier, result = crossThreadCopy(WTFMove(result))](auto& serviceWorkerContext) mutable { 57 auto promise = serviceWorkerContext.clients().takePendingPromise(promiseIdentifier); 58 if (!promise) 59 return; 60 61 // FIXME: Check isFocused state and reject if not focused. 62 if (!result) { 63 promise->reject(Exception { TypeError, "WindowClient focus failed"_s }); 64 return; 65 } 66 67 promise->template resolve<IDLInterface<ServiceWorkerWindowClient>>(ServiceWorkerWindowClient::create(serviceWorkerContext, WTFMove(*result))); 68 }); 69 }); 70 }); 43 71 } 44 72 45 void ServiceWorkerWindowClient::navigate( const String& url, Ref<DeferredPromise>&& promise)73 void ServiceWorkerWindowClient::navigate(ScriptExecutionContext&, const String& url, Ref<DeferredPromise>&& promise) 46 74 { 47 75 UNUSED_PARAM(url); -
trunk/Source/WebCore/workers/service/ServiceWorkerWindowClient.h
r291888 r291938 46 46 bool isFocused() const { return data().isFocused; } 47 47 48 void focus( Ref<DeferredPromise>&&);49 void navigate( const String& url, Ref<DeferredPromise>&&);48 void focus(ScriptExecutionContext&, Ref<DeferredPromise>&&); 49 void navigate(ScriptExecutionContext&, const String& url, Ref<DeferredPromise>&&); 50 50 51 51 private: -
trunk/Source/WebCore/workers/service/ServiceWorkerWindowClient.idl
r290304 r291938 33 33 [ImplementedAs=isFocused] readonly attribute boolean focused; 34 34 35 [NewObject ] Promise<ServiceWorkerWindowClient> focus();36 [NewObject ] Promise<ServiceWorkerWindowClient> navigate(USVString url);35 [NewObject, CallWith=CurrentScriptExecutionContext] Promise<ServiceWorkerWindowClient> focus(); 36 [NewObject, CallWith=CurrentScriptExecutionContext] Promise<ServiceWorkerWindowClient> navigate(USVString url); 37 37 }; -
trunk/Source/WebCore/workers/service/context/SWContextManager.h
r291467 r291938 68 68 virtual void matchAll(ServiceWorkerIdentifier, const ServiceWorkerClientQueryOptions&, ServiceWorkerClientsMatchAllCallback&&) = 0; 69 69 virtual void claim(ServiceWorkerIdentifier, CompletionHandler<void(ExceptionOr<void>&&)>&&) = 0; 70 71 virtual void focus(ScriptExecutionContextIdentifier, CompletionHandler<void(std::optional<WebCore::ServiceWorkerClientData>&&)>&&) = 0; 70 72 71 73 virtual void didFailHeartBeatCheck(ServiceWorkerIdentifier) = 0; -
trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp
r290815 r291938 152 152 ExtendableMessageEventSource source; 153 153 if (std::holds_alternative<ServiceWorkerClientData>(sourceData)) { 154 RefPtr<ServiceWorkerClient> sourceClient = ServiceWorkerClient:: getOrCreate(serviceWorkerGlobalScope, WTFMove(std::get<ServiceWorkerClientData>(sourceData)));154 RefPtr<ServiceWorkerClient> sourceClient = ServiceWorkerClient::create(serviceWorkerGlobalScope, WTFMove(std::get<ServiceWorkerClientData>(sourceData))); 155 155 156 156 RELEASE_ASSERT(!sourceClient->url().protocolIsInHTTPFamily() || !serviceWorkerGlobalScope->url().protocolIsInHTTPFamily() || protocolHostAndPortAreEqual(serviceWorkerGlobalScope->url(), sourceClient->url())); -
trunk/Source/WebCore/workers/service/server/SWServer.h
r291888 r291938 92 92 virtual void notifyClientsOfControllerChange(const HashSet<ScriptExecutionContextIdentifier>& contextIdentifiers, const ServiceWorkerData& newController) = 0; 93 93 virtual void postMessageToServiceWorkerClient(ScriptExecutionContextIdentifier, const MessageWithMessagePorts&, ServiceWorkerIdentifier, const String& sourceOrigin) = 0; 94 virtual void focusServiceWorkerClient(ScriptExecutionContextIdentifier, CompletionHandler<void(std::optional<ServiceWorkerClientData>&&)>&&) = 0; 94 95 95 96 virtual void contextConnectionCreated(SWServerToContextConnection&) = 0; -
trunk/Source/WebKit/ChangeLog
r291937 r291938 1 2022-03-26 Youenn Fablet <youenn@apple.com> 2 3 Implement ServiceWorkerWindowClient.focus 4 https://bugs.webkit.org/show_bug.cgi?id=238319 5 <rdar://90616490> 6 7 Reviewed by Brady Eidson. 8 9 Support new IPC message flow to focus from a service worker to network process to service worker client process to UIProcess. 10 Introduce a new delegate _focusWebViewFromServiceWorker as the scope is specific to service worker and usage is different from existing _focusWebView and other delegates. 11 12 The overall flow is like this: 13 - ServiceWorker process to NetworkProcess to Client WebProcess process to UIProcess (do the actual focus) to NetworkProcess to ServiceWorker process 14 We might want to directly go from NetworkProcess to UIProcess but we need to handle potential race conditions in that case. 15 16 * NetworkProcess/ServiceWorker/WebSWServerConnection.cpp: 17 * NetworkProcess/ServiceWorker/WebSWServerConnection.h: 18 * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp: 19 * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h: 20 * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.messages.in: 21 * UIProcess/API/APIUIClient.h: 22 * UIProcess/API/Cocoa/WKUIDelegatePrivate.h: 23 * UIProcess/Cocoa/UIDelegate.h: 24 * UIProcess/Cocoa/UIDelegate.mm: 25 * UIProcess/WebPageProxy.cpp: 26 * UIProcess/WebPageProxy.h: 27 * UIProcess/WebPageProxy.messages.in: 28 * WebProcess/Storage/WebSWClientConnection.cpp: 29 * WebProcess/Storage/WebSWClientConnection.h: 30 * WebProcess/Storage/WebSWClientConnection.messages.in: 31 * WebProcess/Storage/WebSWContextManagerConnection.cpp: 32 * WebProcess/Storage/WebSWContextManagerConnection.h: 33 1 34 2022-03-26 Yusuke Suzuki <ysuzuki@apple.com> 2 35 -
trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp
r291492 r291938 660 660 } 661 661 662 void WebSWServerConnection::focusServiceWorkerClient(WebCore::ScriptExecutionContextIdentifier clientIdentifier, CompletionHandler<void(std::optional<ServiceWorkerClientData>&&)>&& callback) 663 { 664 sendWithAsyncReply(Messages::WebSWClientConnection::FocusServiceWorkerClient { clientIdentifier }, WTFMove(callback)); 665 } 666 662 667 } // namespace WebKit 663 668 -
trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h
r288416 r291938 84 84 void fetchTaskTimedOut(WebCore::ServiceWorkerIdentifier); 85 85 86 void focusServiceWorkerClient(WebCore::ScriptExecutionContextIdentifier, CompletionHandler<void(std::optional<WebCore::ServiceWorkerClientData>&&)>&&); 87 86 88 private: 87 89 // Implement SWServer::Connection (Messages to the client WebProcess) -
trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp
r290776 r291938 218 218 } 219 219 220 void WebSWServerToContextConnection::focus(ScriptExecutionContextIdentifier clientIdentifier, CompletionHandler<void(std::optional<WebCore::ServiceWorkerClientData>&&)>&& callback) 221 { 222 auto* server = this->server(); 223 auto* connection = server ? server->connection(clientIdentifier.processIdentifier()) : nullptr; 224 if (!connection) { 225 callback({ }); 226 return; 227 } 228 connection->focusServiceWorkerClient(clientIdentifier, WTFMove(callback)); 229 } 230 220 231 } // namespace WebKit 221 232 -
trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h
r290776 r291938 99 99 void firePushEvent(WebCore::ServiceWorkerIdentifier, const std::optional<Vector<uint8_t>>&, CompletionHandler<void(bool)>&&) final; 100 100 void close() final; 101 void focus(WebCore::ScriptExecutionContextIdentifier, CompletionHandler<void(std::optional<WebCore::ServiceWorkerClientData>&&)>&&); 101 102 102 103 void connectionIsNoLongerNeeded() final; -
trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.messages.in
r291467 r291938 36 36 MatchAll(uint64_t matchAllRequestIdentifier, WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, struct WebCore::ServiceWorkerClientQueryOptions options); 37 37 Claim(WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier) -> (std::optional<WebCore::ExceptionData> result) 38 Focus(WebCore::ScriptExecutionContextIdentifier serviceWorkerClientIdentifier) -> (std::optional<WebCore::ServiceWorkerClientData> result) 38 39 SetScriptResource(WebCore::ServiceWorkerIdentifier identifier, URL scriptURL, WebCore::ServiceWorkerContextData::ImportedScript script) 39 40 PostMessageToServiceWorkerClient(WebCore::ScriptExecutionContextIdentifier destination, struct WebCore::MessageWithMessagePorts message, WebCore::ServiceWorkerIdentifier source, String sourceOrigin) -
trunk/Source/WebKit/UIProcess/API/APIUIClient.h
r289612 r291938 102 102 virtual void focus(WebKit::WebPageProxy*) { } 103 103 virtual void unfocus(WebKit::WebPageProxy*) { } 104 virtual bool focusFromServiceWorker(WebKit::WebPageProxy&) { return false; } 104 105 105 106 virtual void runJavaScriptAlert(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function<void()>&& completionHandler) { completionHandler(); } -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h
r289694 r291938 273 273 - (void)_showWebView:(WKWebView *)webView WK_API_AVAILABLE(macos(10.13.4)); 274 274 - (void)_focusWebView:(WKWebView *)webView WK_API_AVAILABLE(macos(10.13.4)); 275 - (bool)_focusWebViewFromServiceWorker:(WKWebView *)webView WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 275 276 - (void)_unfocusWebView:(WKWebView *)webView WK_API_AVAILABLE(macos(10.13.4)); 276 277 - (void)_webViewDidScroll:(WKWebView *)webView WK_API_AVAILABLE(macos(10.13.4)); -
trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.h
r289694 r291938 117 117 void focus(WebPageProxy*) final; 118 118 void unfocus(WebPageProxy*) final; 119 bool focusFromServiceWorker(WebKit::WebPageProxy&) final; 120 119 121 bool canRunModal() const final; 120 122 void runModal(WebPageProxy&) final; … … 210 212 bool showWebView : 1; 211 213 bool focusWebView : 1; 214 bool focusWebViewFromServiceWorker : 1; 212 215 bool unfocusWebView : 1; 213 216 bool webViewRunModal : 1; -
trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
r290146 r291938 126 126 m_delegateMethods.showWebView = [delegate respondsToSelector:@selector(_showWebView:)]; 127 127 m_delegateMethods.focusWebView = [delegate respondsToSelector:@selector(_focusWebView:)]; 128 m_delegateMethods.focusWebViewFromServiceWorker = [delegate respondsToSelector:@selector(_focusWebViewFromServiceWorker:)]; 128 129 m_delegateMethods.unfocusWebView = [delegate respondsToSelector:@selector(_unfocusWebView:)]; 129 130 m_delegateMethods.webViewRunModal = [delegate respondsToSelector:@selector(_webViewRunModal:)]; … … 832 833 } 833 834 835 bool UIDelegate::UIClient::focusFromServiceWorker(WebKit::WebPageProxy& proxy) 836 { 837 bool hasImplementation = m_uiDelegate && m_uiDelegate->m_delegateMethods.focusWebViewFromServiceWorker && m_uiDelegate->m_delegate.get(); 838 if (!hasImplementation) { 839 auto* webView = m_uiDelegate ? m_uiDelegate->m_webView.get().get() : nullptr; 840 if (!webView || !webView.window) 841 return false; 842 843 #if PLATFORM(MAC) 844 [webView.window makeKeyAndOrderFront:nil]; 845 #else 846 [webView.window makeKeyAndVisible]; 847 #endif 848 [[webView window] makeFirstResponder:webView]; 849 return true; 850 } 851 852 return [(id <WKUIDelegatePrivate>)m_uiDelegate->m_delegate.get() _focusWebViewFromServiceWorker:m_uiDelegate->m_webView.get().get()]; 853 } 854 834 855 void UIDelegate::UIClient::focus(WebPageProxy*) 835 856 { … … 843 864 if (!delegate) 844 865 return; 845 866 846 867 [(id <WKUIDelegatePrivate>)delegate _focusWebView:m_uiDelegate->m_webView.get().get()]; 847 868 } -
trunk/Source/WebKit/UIProcess/WebPageProxy.cpp
r291784 r291938 7416 7416 send(Messages::WebPage::DidCancelCheckingText(requestID)); 7417 7417 } 7418 7419 void WebPageProxy::focusFromServiceWorker(CompletionHandler<void()>&& callback) 7420 { 7421 if (!m_uiClient->focusFromServiceWorker(*this)) { 7422 callback(); 7423 return; 7424 } 7425 7426 #if PLATFORM(COCOA) 7427 makeFirstResponder(); 7428 #endif 7429 7430 if (m_activityState.contains(ActivityState::IsVisible)) { 7431 callback(); 7432 return; 7433 } 7434 installActivityStateChangeCompletionHandler(WTFMove(callback)); 7435 } 7436 7418 7437 // Other 7419 7438 -
trunk/Source/WebKit/UIProcess/WebPageProxy.h
r291784 r291938 1693 1693 void getLoadDecisionForIcon(const WebCore::LinkIcon&, WebKit::CallbackID); 1694 1694 1695 void focusFromServiceWorker(CompletionHandler<void()>&&); 1695 1696 void setFocus(bool focused); 1696 1697 void setWindowFrame(const WebCore::FloatRect&); -
trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in
r291393 r291938 42 42 SetFocus(bool focused) 43 43 TakeFocus(uint8_t direction) 44 FocusFromServiceWorker() -> () 44 45 FocusedFrameChanged(std::optional<WebCore::FrameIdentifier> frameID) 45 46 SetRenderTreeSize(uint64_t treeSize) -
trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp
r291003 r291938 42 42 #include <WebCore/Document.h> 43 43 #include <WebCore/DocumentLoader.h> 44 #include <WebCore/FocusController.h> 45 #include <WebCore/Frame.h> 44 46 #include <WebCore/ProcessIdentifier.h> 45 47 #include <WebCore/SecurityOrigin.h> … … 302 304 } 303 305 306 void WebSWClientConnection::focusServiceWorkerClient(ScriptExecutionContextIdentifier clientIdentifier, CompletionHandler<void(std::optional<ServiceWorkerClientData>&&)>&& callback) 307 { 308 auto* client = Document::allDocumentsMap().get(clientIdentifier); 309 auto* page = client ? client->page() : nullptr; 310 if (!page) { 311 callback({ }); 312 return; 313 } 314 315 WebPage::fromCorePage(*page).sendWithAsyncReply(Messages::WebPageProxy::FocusFromServiceWorker { }, [clientIdentifier, callback = WTFMove(callback)]() mutable { 316 auto* client = Document::allDocumentsMap().get(clientIdentifier); 317 auto* frame = client ? client->frame() : nullptr; 318 auto* page = frame ? frame->page() : nullptr; 319 if (!page) { 320 callback({ }); 321 return; 322 } 323 page->focusController().setFocusedFrame(frame); 324 callback(ServiceWorkerClientData::from(*client)); 325 }); 326 } 327 304 328 } // namespace WebKit 305 329 -
trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.h
r291003 r291938 100 100 void setNavigationPreloadHeaderValue(WebCore::ServiceWorkerRegistrationIdentifier, String&&, ExceptionOrVoidCallback&&) final; 101 101 void getNavigationPreloadState(WebCore::ServiceWorkerRegistrationIdentifier, ExceptionOrNavigationPreloadStateCallback&&) final; 102 void focusServiceWorkerClient(WebCore::ScriptExecutionContextIdentifier, CompletionHandler<void(std::optional<WebCore::ServiceWorkerClientData>&&)>&&); 102 103 103 104 void scheduleStorageJob(const WebCore::ServiceWorkerJobData&); -
trunk/Source/WebKit/WebProcess/Storage/WebSWClientConnection.messages.in
r290903 r291938 40 40 41 41 SetDocumentIsControlled(WebCore::ScriptExecutionContextIdentifier temporaryDocumentIdentifier, struct WebCore::ServiceWorkerRegistrationData data) -> (bool isSuccess) 42 43 FocusServiceWorkerClient(WebCore::ScriptExecutionContextIdentifier clientIdentifier) -> (std::optional<WebCore::ServiceWorkerClientData> result) 42 44 } 43 45 -
trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp
r291467 r291938 333 333 } 334 334 335 void WebSWContextManagerConnection::claim( WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, CompletionHandler<void(ExceptionOr<void>&&)>&& callback)335 void WebSWContextManagerConnection::claim(ServiceWorkerIdentifier serviceWorkerIdentifier, CompletionHandler<void(ExceptionOr<void>&&)>&& callback) 336 336 { 337 337 m_connectionToNetworkProcess->sendWithAsyncReply(Messages::WebSWServerToContextConnection::Claim { serviceWorkerIdentifier }, [callback = WTFMove(callback)](auto&& result) mutable { … … 340 340 } 341 341 342 void WebSWContextManagerConnection::focus(ScriptExecutionContextIdentifier clientIdentifier, CompletionHandler<void(std::optional<WebCore::ServiceWorkerClientData>&&)>&& callback) 343 { 344 m_connectionToNetworkProcess->sendWithAsyncReply(Messages::WebSWServerToContextConnection::Focus { clientIdentifier }, WTFMove(callback)); 345 } 346 342 347 void WebSWContextManagerConnection::close() 343 348 { -
trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h
r291467 r291938 82 82 void matchAll(WebCore::ServiceWorkerIdentifier, const WebCore::ServiceWorkerClientQueryOptions&, WebCore::ServiceWorkerClientsMatchAllCallback&&) final; 83 83 void claim(WebCore::ServiceWorkerIdentifier, CompletionHandler<void(WebCore::ExceptionOr<void>&&)>&&) final; 84 void focus(WebCore::ScriptExecutionContextIdentifier, CompletionHandler<void(std::optional<WebCore::ServiceWorkerClientData>&&)>&&) final; 84 85 void skipWaiting(WebCore::ServiceWorkerIdentifier, CompletionHandler<void()>&&) final; 85 86 void setScriptResource(WebCore::ServiceWorkerIdentifier, const URL&, const WebCore::ServiceWorkerContextData::ImportedScript&) final; -
trunk/Tools/ChangeLog
r291937 r291938 1 2022-03-26 Youenn Fablet <youenn@apple.com> 2 3 Implement ServiceWorkerWindowClient.focus 4 https://bugs.webkit.org/show_bug.cgi?id=238319 5 <rdar://90616490> 6 7 Reviewed by Brady Eidson. 8 9 * TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm: 10 1 11 2022-03-26 Yusuke Suzuki <ysuzuki@apple.com> 2 12 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm
r287223 r291938 47 47 #import <WebKit/WebKit.h> 48 48 #import <WebKit/_WKExperimentalFeature.h> 49 #import <WebKit/_WKInternalDebugFeature.h> 49 50 #import <WebKit/_WKProcessPoolConfiguration.h> 50 51 #import <WebKit/_WKRemoteObjectInterface.h> … … 2803 2804 TestWebKitAPI::Util::run(&done); 2804 2805 } 2806 2807 static const char* ServiceWorkerWindowClientFocusMain = 2808 "<div>test page</div>" 2809 "<script>" 2810 "let worker;" 2811 "async function test() {" 2812 " try {" 2813 " const registration = await navigator.serviceWorker.register('/sw.js');" 2814 " if (registration.active) {" 2815 " worker = registration.active;" 2816 " alert('already active');" 2817 " return;" 2818 " }" 2819 " worker = registration.installing;" 2820 " worker.addEventListener('statechange', () => {" 2821 " if (worker.state == 'activated')" 2822 " alert('successfully registered');" 2823 " });" 2824 " } catch(e) {" 2825 " alert('Exception: ' + e);" 2826 " }" 2827 "}" 2828 "window.onload = test;" 2829 "" 2830 "function focusClient() {" 2831 " worker.postMessage('start');" 2832 " navigator.serviceWorker.onmessage = (event) => {" 2833 " window.webkit.messageHandlers.sw.postMessage(event.data);" 2834 " }" 2835 "}" 2836 "" 2837 "function checkFocusValue(value, name) {" 2838 " window.webkit.messageHandlers.sw.postMessage(document.hasFocus() === value ? 'PASS' : 'FAIL: expected ' + value + ' for ' + name);" 2839 "}" 2840 "</script>"; 2841 static const char* ServiceWorkerWindowClientFocusJS = 2842 "self.addEventListener('message', (event) => {" 2843 " event.source.focus().then((client) => {" 2844 " event.source.postMessage('focused');" 2845 " }, (error) => {" 2846 " event.source.postMessage('not focused');" 2847 " });" 2848 "});"; 2849 2850 TEST(ServiceWorker, ServiceWorkerWindowClientFocus) 2851 { 2852 [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins]; 2853 2854 // Start with a clean slate data store 2855 [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() { 2856 done = true; 2857 }]; 2858 TestWebKitAPI::Util::run(&done); 2859 done = false; 2860 2861 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 2862 auto preferences = [configuration preferences]; 2863 2864 for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) { 2865 if ([feature.key isEqualToString:@"ServiceWorkersUserGestureEnabled"]) 2866 [preferences _setEnabled:NO forInternalDebugFeature:feature]; 2867 } 2868 2869 auto messageHandler = adoptNS([[SWMessageHandlerWithExpectedMessage alloc] init]); 2870 [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"]; 2871 2872 auto webView1 = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]); 2873 auto webView2 = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]); 2874 2875 TestWebKitAPI::HTTPServer server({ 2876 { "/", { ServiceWorkerWindowClientFocusMain } }, 2877 { "/sw.js", { {{ "Content-Type", "application/javascript" }}, ServiceWorkerWindowClientFocusJS } } 2878 }); 2879 2880 [webView1 loadRequest:server.request()]; 2881 EXPECT_WK_STREQ([webView1 _test_waitForAlert], "successfully registered"); 2882 2883 [webView2 loadRequest:server.request()]; 2884 EXPECT_WK_STREQ([webView2 _test_waitForAlert], "already active"); 2885 2886 #if PLATFORM(MAC) 2887 [[webView1 hostWindow] miniaturize:[webView1 hostWindow]]; 2888 [[webView2 hostWindow] miniaturize:[webView2 hostWindow]]; 2889 EXPECT_FALSE([webView1 hostWindow].isVisible); 2890 EXPECT_FALSE([webView2 hostWindow].isVisible); 2891 #endif 2892 2893 done = false; 2894 expectedMessage = "focused"; 2895 [webView1 evaluateJavaScript:@"focusClient()" completionHandler: nil]; 2896 TestWebKitAPI::Util::run(&done); 2897 #if PLATFORM(MAC) 2898 EXPECT_TRUE([webView1 hostWindow].isVisible); 2899 EXPECT_FALSE([webView2 hostWindow].isVisible); 2900 EXPECT_FALSE([webView1 hostWindow].isMiniaturized); 2901 EXPECT_TRUE([webView2 hostWindow].isMiniaturized); 2902 2903 // FIXME: We should be able to run these tests in iOS once pages are actually visible. 2904 done = false; 2905 expectedMessage = "PASS"; 2906 [webView1 evaluateJavaScript:@"checkFocusValue(true, 'webView1')" completionHandler:nil]; 2907 TestWebKitAPI::Util::run(&done); 2908 2909 done = false; 2910 expectedMessage = "PASS"; 2911 [webView2 evaluateJavaScript:@"checkFocusValue(false, 'webView2')" completionHandler:nil]; 2912 TestWebKitAPI::Util::run(&done); 2913 #endif 2914 2915 done = false; 2916 expectedMessage = "focused"; 2917 [webView2 evaluateJavaScript:@"focusClient()" completionHandler: nil]; 2918 TestWebKitAPI::Util::run(&done); 2919 #if PLATFORM(MAC) 2920 EXPECT_TRUE([webView2 hostWindow].isVisible); 2921 EXPECT_FALSE([webView1 hostWindow].isMiniaturized); 2922 EXPECT_FALSE([webView2 hostWindow].isMiniaturized); 2923 2924 // FIXME: We should be able to run these tests in iOS once pages are actually visible. 2925 done = false; 2926 expectedMessage = "PASS"; 2927 [webView2 evaluateJavaScript:@"checkFocusValue(true, 'webView2')" completionHandler:nil]; 2928 TestWebKitAPI::Util::run(&done); 2929 #endif 2930 } 2931 2932 TEST(ServiceWorker, ServiceWorkerWindowClientFocusRequiresUserGesture) 2933 { 2934 [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins]; 2935 2936 // Start with a clean slate data store 2937 [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() { 2938 done = true; 2939 }]; 2940 TestWebKitAPI::Util::run(&done); 2941 done = false; 2942 2943 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 2944 auto preferences = [configuration preferences]; 2945 2946 for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) { 2947 if ([feature.key isEqualToString:@"ServiceWorkersUserGestureEnabled"]) 2948 [preferences _setEnabled:YES forInternalDebugFeature:feature]; 2949 } 2950 2951 auto messageHandler = adoptNS([[SWMessageHandlerWithExpectedMessage alloc] init]); 2952 [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"]; 2953 2954 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]); 2955 2956 TestWebKitAPI::HTTPServer server({ 2957 { "/", { ServiceWorkerWindowClientFocusMain } }, 2958 { "/sw.js", { {{ "Content-Type", "application/javascript" }}, ServiceWorkerWindowClientFocusJS } } 2959 }); 2960 2961 [webView loadRequest:server.request()]; 2962 EXPECT_WK_STREQ([webView _test_waitForAlert], "successfully registered"); 2963 2964 done = false; 2965 expectedMessage = "not focused"; 2966 [webView evaluateJavaScript:@"focusClient()" completionHandler: nil]; 2967 TestWebKitAPI::Util::run(&done); 2968 }
Note: See TracChangeset
for help on using the changeset viewer.