Do not go to the storage process when registering a service worker client if there...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Jan 2018 22:58:48 +0000 (22:58 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Jan 2018 22:58:48 +0000 (22:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181740
<rdar://problem/36650400>

Patch by Youenn Fablet <youenn@apple.com> on 2018-01-19
Reviewed by Chris Dumez.

Source/WebCore:

Register a document as service worker client only if there is an existing service worker connection.
This allows not creating any connection if no service worker is registered.

Add internals API to test whether a service worker connection was created or not.
This is used by API tests that cover the changes.

* dom/Document.cpp:
(WebCore::Document::privateBrowsingStateDidChange): No need to create a service worker connection if client is not registered yet.
(WebCore::Document::setServiceWorkerConnection): No need to unregister/register if service worker connection is the same.
Similarly, if Document is to be destroyed or suspended, we should not register it.
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::commitData):
* testing/Internals.cpp:
(WebCore::Internals::hasServiceWorkerConnection):
* testing/Internals.h:
* testing/Internals.idl:
* workers/service/ServiceWorkerProvider.cpp:
(WebCore::ServiceWorkerProvider::registerServiceWorkerClients):
* workers/service/ServiceWorkerProvider.h:

Source/WebKit:

UIProcess notifies all web processes to register their service worker clients when spinning the service worker process.
Add private API to set the number of web processes for testing purposes.

* UIProcess/API/Cocoa/WKProcessPool.mm:
(-[WKProcessPool _setMaximumNumberOfProcesses:]):
* UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::establishWorkerContextConnectionToStorageProcess):
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::registerServiceWorkerClients):
* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:

Tools:

Add support for internals inside API tests.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/InjectInternals_Bundle.cpp: Added.
(TestWebKitAPI::InternalsInjectedBundleTest::InternalsInjectedBundleTest):
(TestWebKitAPI::InternalsInjectedBundleTest::initialize):
(TestWebKitAPI::InternalsInjectedBundleTest::didCreatePage):
(TestWebKitAPI::InternalsInjectedBundleTest::didClearWindowForFrame):
* TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm:
(setConfigurationInjectedBundlePath):
(-[RegularPageMessageHandler userContentController:didReceiveScriptMessage:]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@227242 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebCore/workers/service/ServiceWorkerProvider.cpp
Source/WebCore/workers/service/ServiceWorkerProvider.h
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm
Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h
Source/WebKit/UIProcess/WebProcessPool.cpp
Source/WebKit/WebProcess/WebProcess.cpp
Source/WebKit/WebProcess/WebProcess.h
Source/WebKit/WebProcess/WebProcess.messages.in
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/InjectInternals_Bundle.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm

index 55bd757..01c83a0 100644 (file)
@@ -1,3 +1,31 @@
+2018-01-19  Youenn Fablet  <youenn@apple.com>
+
+        Do not go to the storage process when registering a service worker client if there is no service worker registered
+        https://bugs.webkit.org/show_bug.cgi?id=181740
+        <rdar://problem/36650400>
+
+        Reviewed by Chris Dumez.
+
+        Register a document as service worker client only if there is an existing service worker connection.
+        This allows not creating any connection if no service worker is registered.
+
+        Add internals API to test whether a service worker connection was created or not.
+        This is used by API tests that cover the changes.
+
+        * dom/Document.cpp:
+        (WebCore::Document::privateBrowsingStateDidChange): No need to create a service worker connection if client is not registered yet.
+        (WebCore::Document::setServiceWorkerConnection): No need to unregister/register if service worker connection is the same.
+        Similarly, if Document is to be destroyed or suspended, we should not register it.
+        * loader/DocumentLoader.cpp:
+        (WebCore::DocumentLoader::commitData):
+        * testing/Internals.cpp:
+        (WebCore::Internals::hasServiceWorkerConnection):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+        * workers/service/ServiceWorkerProvider.cpp:
+        (WebCore::ServiceWorkerProvider::registerServiceWorkerClients):
+        * workers/service/ServiceWorkerProvider.h:
+
 2018-01-19  Dean Jackson  <dino@apple.com>
 
         REGRESSION (r221092): Swipe actions are hard to perform in FastMail app
index fe88676..b14db7a 100644 (file)
@@ -4919,16 +4919,16 @@ void Document::resume(ActiveDOMObject::ReasonForSuspension reason)
 
     resumeScheduledTasks(reason);
 
+    m_visualUpdatesAllowed = true;
+
+    m_isSuspended = false;
+
 #if ENABLE(SERVICE_WORKER)
     if (RuntimeEnabledFeatures::sharedFeatures().serviceWorkerEnabled() && reason == ActiveDOMObject::ReasonForSuspension::PageCache) {
         ASSERT_WITH_MESSAGE(!activeServiceWorker(), "Documents with an active service worker should not go into PageCache in the first place");
-        setServiceWorkerConnection(&ServiceWorkerProvider::singleton().serviceWorkerConnectionForSession(sessionID()));
+        setServiceWorkerConnection(ServiceWorkerProvider::singleton().existingServiceWorkerConnectionForSession(sessionID()));
     }
 #endif
-
-    m_visualUpdatesAllowed = true;
-
-    m_isSuspended = false;
 }
 
 void Document::registerForDocumentSuspensionCallbacks(Element* e)
@@ -4996,7 +4996,7 @@ void Document::privateBrowsingStateDidChange()
         element->privateBrowsingStateDidChange();
 
 #if ENABLE(SERVICE_WORKER)
-    if (RuntimeEnabledFeatures::sharedFeatures().serviceWorkerEnabled())
+    if (RuntimeEnabledFeatures::sharedFeatures().serviceWorkerEnabled() && m_serviceWorkerConnection)
         setServiceWorkerConnection(&ServiceWorkerProvider::singleton().serviceWorkerConnectionForSession(sessionID()));
 #endif
 }
@@ -7720,6 +7720,9 @@ void Document::didLogMessage(const WTFLogChannel& channel, WTFLogLevel level, Ve
 #if ENABLE(SERVICE_WORKER)
 void Document::setServiceWorkerConnection(SWClientConnection* serviceWorkerConnection)
 {
+    if (m_serviceWorkerConnection == serviceWorkerConnection || m_hasPreparedForDestruction || m_isSuspended)
+        return;
+
     if (m_serviceWorkerConnection)
         m_serviceWorkerConnection->unregisterServiceWorkerClient(identifier());
 
index 46a46a6..f0516ad 100644 (file)
@@ -907,7 +907,7 @@ void DocumentLoader::commitData(const char* bytes, size_t length)
             }
 
             if (m_frame->document()->activeServiceWorker() || SchemeRegistry::canServiceWorkersHandleURLScheme(m_frame->document()->url().protocol().toStringWithoutCopying()))
-                m_frame->document()->setServiceWorkerConnection(&ServiceWorkerProvider::singleton().serviceWorkerConnectionForSession(m_frame->page()->sessionID()));
+                m_frame->document()->setServiceWorkerConnection(ServiceWorkerProvider::singleton().existingServiceWorkerConnectionForSession(m_frame->page()->sessionID()));
         }
 #endif
         // Call receivedFirstData() exactly once per load. We should only reach this point multiple times
index 91c8672..cfcb796 100644 (file)
@@ -4309,6 +4309,14 @@ void Internals::terminateServiceWorker(ServiceWorker& worker)
 
     ServiceWorkerProvider::singleton().serviceWorkerConnectionForSession(contextDocument()->sessionID()).syncTerminateWorker(worker.identifier());
 }
+
+bool Internals::hasServiceWorkerConnection()
+{
+    if (!contextDocument())
+        return false;
+
+    return ServiceWorkerProvider::singleton().existingServiceWorkerConnectionForSession(contextDocument()->sessionID());
+}
 #endif
 
 String Internals::timelineDescription(AnimationTimeline& timeline)
index cdf102b..c909c50 100644 (file)
@@ -628,6 +628,7 @@ public:
     using HasRegistrationPromise = DOMPromiseDeferred<IDLBoolean>;
     void hasServiceWorkerRegistration(const String& clientURL, HasRegistrationPromise&&);
     void terminateServiceWorker(ServiceWorker&);
+    bool hasServiceWorkerConnection();
 #endif
 
 #if ENABLE(APPLE_PAY)
index bedd9d6..33519c4 100644 (file)
@@ -570,6 +570,7 @@ enum EventThrottlingBehavior {
 
     [Conditional=SERVICE_WORKER] Promise<boolean> hasServiceWorkerRegistration(DOMString scopeURL);
     [Conditional=SERVICE_WORKER] void terminateServiceWorker(ServiceWorker worker);
+    [Conditional=SERVICE_WORKER] boolean hasServiceWorkerConnection();
 
     void testIncomingSyncIPCMessageWhileWaitingForSyncReply();
 
index c96ef78..a695f0d 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(SERVICE_WORKER)
 
+#include "SchemeRegistry.h"
+
 namespace WebCore {
 
 static ServiceWorkerProvider* sharedProvider;
@@ -52,6 +54,15 @@ bool ServiceWorkerProvider::mayHaveServiceWorkerRegisteredForOrigin(PAL::Session
     return connection->mayHaveServiceWorkerRegisteredForOrigin(origin);
 }
 
+void ServiceWorkerProvider::registerServiceWorkerClients(PAL::SessionID sessionID)
+{
+    auto& connection = serviceWorkerConnectionForSession(sessionID);
+    for (auto* document : Document::allDocuments()) {
+        if (SchemeRegistry::canServiceWorkersHandleURLScheme(document->url().protocol().toStringWithoutCopying()))
+            document->setServiceWorkerConnection(&connection);
+    }
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SERVICE_WORKER)
index aa16a17..1dff447 100644 (file)
@@ -47,6 +47,8 @@ public:
     virtual SWClientConnection* existingServiceWorkerConnectionForSession(PAL::SessionID) = 0;
     virtual SWClientConnection& serviceWorkerConnectionForSession(PAL::SessionID) = 0;
 
+    WEBCORE_EXPORT void registerServiceWorkerClients(PAL::SessionID);
+
     void setHasRegisteredServiceWorkers(bool value) { m_hasRegisteredServiceWorkers = value; }
 
 private:
index d04da0a..3556075 100644 (file)
@@ -1,3 +1,24 @@
+2018-01-19  Youenn Fablet  <youenn@apple.com>
+
+        Do not go to the storage process when registering a service worker client if there is no service worker registered
+        https://bugs.webkit.org/show_bug.cgi?id=181740
+        <rdar://problem/36650400>
+
+        Reviewed by Chris Dumez.
+
+        UIProcess notifies all web processes to register their service worker clients when spinning the service worker process.
+        Add private API to set the number of web processes for testing purposes.
+
+        * UIProcess/API/Cocoa/WKProcessPool.mm:
+        (-[WKProcessPool _setMaximumNumberOfProcesses:]):
+        * UIProcess/API/Cocoa/WKProcessPoolPrivate.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::establishWorkerContextConnectionToStorageProcess):
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::registerServiceWorkerClients):
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+
 2018-01-19  Dean Jackson  <dino@apple.com>
 
         REGRESSION (r221092): Swipe actions are hard to perform in FastMail app
index 2436236..a3d1a84 100644 (file)
@@ -187,6 +187,11 @@ static WKProcessPool *sharedProcessPool;
     _processPool->registerURLSchemeServiceWorkersCanHandle(scheme);
 }
 
+- (void)_setMaximumNumberOfProcesses:(NSUInteger)value
+{
+    _processPool->setMaximumNumberOfProcesses(value);
+}
+
 - (void)_setCanHandleHTTPSServerTrustEvaluation:(BOOL)value
 {
     _processPool->setCanHandleHTTPSServerTrustEvaluation(value);
index b96343a..d7e0103 100644 (file)
@@ -96,6 +96,7 @@
 // Test only.
 - (void)_setAllowsAnySSLCertificateForServiceWorker:(BOOL)allows WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (void)_registerURLSchemeServiceWorkersCanHandle:(NSString *)scheme WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (void)_setMaximumNumberOfProcesses:(NSUInteger)value WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 @property (nonatomic, getter=_isCookieStoragePartitioningEnabled, setter=_setCookieStoragePartitioningEnabled:) BOOL _cookieStoragePartitioningEnabled WK_API_AVAILABLE(macosx(10.12.3), ios(10.3));
 @property (nonatomic, getter=_isStorageAccessAPIEnabled, setter=_setStorageAccessAPIEnabled:) BOOL _storageAccessAPIEnabled WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
index a0ea3b6..2c01cf0 100644 (file)
@@ -612,6 +612,7 @@ void WebProcessPool::establishWorkerContextConnectionToStorageProcess(StoragePro
 
     auto serviceWorkerProcessProxy = ServiceWorkerProcessProxy::create(*this, *websiteDataStore);
     m_serviceWorkerProcess = serviceWorkerProcessProxy.ptr();
+    sendToAllProcesses(Messages::WebProcess::RegisterServiceWorkerClients { websiteDataStore->sessionID() });
 
     updateProcessAssertions();
     initializeNewWebProcess(serviceWorkerProcessProxy.get(), *websiteDataStore);
index 183d194..0265a9c 100644 (file)
@@ -1651,6 +1651,12 @@ void WebProcess::establishWorkerContextConnectionToStorageProcess(uint64_t pageI
     auto& ipcConnection = ensureWebToStorageProcessConnection(initialSessionID).connection();
     SWContextManager::singleton().setConnection(std::make_unique<WebSWContextManagerConnection>(ipcConnection, pageID, store));
 }
+
+void WebProcess::registerServiceWorkerClients(PAL::SessionID sessionID)
+{
+    ServiceWorkerProvider::singleton().registerServiceWorkerClients(sessionID);
+}
+
 #endif
 
 } // namespace WebKit
index ab0fe82..01d225a 100644 (file)
@@ -303,7 +303,8 @@ private:
     void setNetworkProxySettings(const WebCore::SoupNetworkProxySettings&);
 #endif
 #if ENABLE(SERVICE_WORKER)
-    void establishWorkerContextConnectionToStorageProcess(uint64_t pageID, const WebPreferencesStore&, PAL::SessionID initialSessionID);
+    void establishWorkerContextConnectionToStorageProcess(uint64_t pageID, const WebPreferencesStore&, PAL::SessionID);
+    void registerServiceWorkerClients(PAL::SessionID);
 #endif
 
     void releasePageCache();
index 4e2b111..be57fdc 100644 (file)
@@ -117,5 +117,6 @@ messages -> WebProcess LegacyReceiver {
 
 #if ENABLE(SERVICE_WORKER)
     EstablishWorkerContextConnectionToStorageProcess(uint64_t pageID, struct WebKit::WebPreferencesStore store, PAL::SessionID initialSessionID)
+    RegisterServiceWorkerClients(PAL::SessionID sessionID)
 #endif
 }
index e0be4a3..eddd6e3 100644 (file)
@@ -1,3 +1,23 @@
+2018-01-19  Youenn Fablet  <youenn@apple.com>
+
+        Do not go to the storage process when registering a service worker client if there is no service worker registered
+        https://bugs.webkit.org/show_bug.cgi?id=181740
+        <rdar://problem/36650400>
+
+        Reviewed by Chris Dumez.
+
+        Add support for internals inside API tests.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/InjectInternals_Bundle.cpp: Added.
+        (TestWebKitAPI::InternalsInjectedBundleTest::InternalsInjectedBundleTest):
+        (TestWebKitAPI::InternalsInjectedBundleTest::initialize):
+        (TestWebKitAPI::InternalsInjectedBundleTest::didCreatePage):
+        (TestWebKitAPI::InternalsInjectedBundleTest::didClearWindowForFrame):
+        * TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm:
+        (setConfigurationInjectedBundlePath):
+        (-[RegularPageMessageHandler userContentController:didReceiveScriptMessage:]):
+
 2018-01-19  John Wilander  <wilander@apple.com>
 
         Resource Load Statistics: Implement callback support for removal of WebsiteDataType::ResourceLoadStatistics
index 3707e87..efd7a8f 100644 (file)
                3FBD1B4A1D3D66AB00E6D6FA /* FullscreenLayoutConstraints.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 3FBD1B491D39D1DB00E6D6FA /* FullscreenLayoutConstraints.html */; };
                3FCC4FE51EC4E8520076E37C /* PictureInPictureDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3FCC4FE41EC4E8520076E37C /* PictureInPictureDelegate.mm */; };
                3FCC4FE81EC4E8CA0076E37C /* PictureInPictureDelegate.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 3FCC4FE61EC4E87E0076E37C /* PictureInPictureDelegate.html */; };
+               4135FB842011FAA700332139 /* InjectInternals_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4135FB832011FAA300332139 /* InjectInternals_Bundle.cpp */; };
+               4135FB852011FABF00332139 /* libWebCoreTestSupport.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4135FB862011FABF00332139 /* libWebCoreTestSupport.dylib */; };
                44817A2F1F0486BF00003810 /* WKRequestActivatedElementInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = 44817A2E1F0486BF00003810 /* WKRequestActivatedElementInfo.mm */; };
                448D7E471EA6C55500ECC756 /* EnvironmentUtilitiesTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 448D7E451EA6C55500ECC756 /* EnvironmentUtilitiesTest.cpp */; };
                46397B951DC2C850009A78AE /* DOMNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 46397B941DC2C850009A78AE /* DOMNode.mm */; };
                        dstPath = TestWebKitAPI.resources;
                        dstSubfolderSpec = 7;
                        files = (
-                               0EBBCC661FFF9E0C00FA42AB /* pop-up-check.html in Copy Resources */,
                                1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */,
                                379028B914FAC24C007E6B43 /* acceptsFirstMouse.html in Copy Resources */,
                                1C2B81871C8925A000A5529F /* Ahem.ttf in Copy Resources */,
                                9B7D740F1F8378770006C432 /* paste-rtfd.html in Copy Resources */,
                                3FCC4FE81EC4E8CA0076E37C /* PictureInPictureDelegate.html in Copy Resources */,
                                F415086D1DA040C50044BE9B /* play-audio-on-click.html in Copy Resources */,
+                               0EBBCC661FFF9E0C00FA42AB /* pop-up-check.html in Copy Resources */,
                                F41AB9A81EF4696B0083FA08 /* prevent-operation.html in Copy Resources */,
                                F41AB9A91EF4696B0083FA08 /* prevent-start.html in Copy Resources */,
                                F6FDDDD614241C6F004F1729 /* push-state.html in Copy Resources */,
                3FBD1B491D39D1DB00E6D6FA /* FullscreenLayoutConstraints.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = FullscreenLayoutConstraints.html; sourceTree = "<group>"; };
                3FCC4FE41EC4E8520076E37C /* PictureInPictureDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PictureInPictureDelegate.mm; sourceTree = "<group>"; };
                3FCC4FE61EC4E87E0076E37C /* PictureInPictureDelegate.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = PictureInPictureDelegate.html; sourceTree = "<group>"; };
+               4135FB832011FAA300332139 /* InjectInternals_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InjectInternals_Bundle.cpp; path = Tests/InjectInternals_Bundle.cpp; sourceTree = SOURCE_ROOT; };
+               4135FB862011FABF00332139 /* libWebCoreTestSupport.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libWebCoreTestSupport.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
                41973B5A1AF2286A006C7B36 /* FileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileSystem.cpp; sourceTree = "<group>"; };
                41973B5C1AF22875006C7B36 /* SharedBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SharedBuffer.cpp; sourceTree = "<group>"; };
                440A1D3814A0103A008A66F2 /* URL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URL.cpp; sourceTree = "<group>"; };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               4135FB852011FABF00332139 /* libWebCoreTestSupport.dylib in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                0F4FFAA01ED3D0DE00F7111F /* ImageIO.framework */,
                                CDA3159C1ED5643F009F60D3 /* IOKit.framework */,
                                7C83E0331D0A5F2700FEBCF3 /* libicucore.dylib */,
+                               4135FB862011FABF00332139 /* libWebCoreTestSupport.dylib */,
                                7C83E0291D0A5CDF00FEBCF3 /* libWTF.a */,
                                7A010BCC1D877C0D00EDE72A /* QuartzCore.framework */,
                        );
                                F660AA1415A61ABF003A1243 /* InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp */,
                                9B0786A21C58830F00D159E3 /* InjectedBundleMakeAllShadowRootsOpen.cpp */,
                                9B0786A41C5885C300D159E3 /* InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp */,
+                               4135FB832011FAA300332139 /* InjectInternals_Bundle.cpp */,
                                93D3D19D17B1A84200C7C415 /* LayoutMilestonesWithAllContentInFrame.cpp */,
                                7A66BDB51EAF14D000CCC924 /* LimitTitleSize.cpp */,
                                52CB47401448FB9300873995 /* LoadAlternateHTMLStringWithNonDirectoryURL.cpp */,
                                F660AA1515A61ABF003A1243 /* InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp in Sources */,
                                BC575A97126E74F1006F0F12 /* InjectedBundleMain.cpp in Sources */,
                                9B0786A51C5885C300D159E3 /* InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp in Sources */,
+                               4135FB842011FAA700332139 /* InjectInternals_Bundle.cpp in Sources */,
                                33DC89141419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp in Sources */,
                                33BE5AF9137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp in Sources */,
                                93F1DB3414DA20870024C362 /* NewFirstVisuallyNonEmptyLayout_Bundle.cpp in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/InjectInternals_Bundle.cpp b/Tools/TestWebKitAPI/Tests/InjectInternals_Bundle.cpp
new file mode 100644 (file)
index 0000000..0616ae0
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#import "InjectedBundleTest.h"
+
+#import "WebCoreTestSupport.h"
+#import <WebKit/WKBundle.h>
+#import <WebKit/WKBundleFrame.h>
+#import <WebKit/WKBundlePage.h>
+
+namespace TestWebKitAPI {
+
+class InternalsInjectedBundleTest : public TestWebKitAPI::InjectedBundleTest {
+public:
+    InternalsInjectedBundleTest(const std::string& identifier)
+        : InjectedBundleTest(identifier)
+    {
+    }
+
+private:
+    virtual void initialize(WKBundleRef bundle, WKTypeRef)
+    {
+        WKBundleSetServiceWorkerProxyCreationCallback(bundle, WebCoreTestSupport::setupNewlyCreatedServiceWorker);
+    }
+
+    virtual void didCreatePage(WKBundleRef, WKBundlePageRef page)
+    {
+        WKBundlePageLoaderClientV0 loaderClient;
+        memset(&loaderClient, 0, sizeof(loaderClient));
+
+        loaderClient.base.version = 0;
+        loaderClient.base.clientInfo = this;
+        loaderClient.didClearWindowObjectForFrame = didClearWindowForFrame;
+
+        WKBundlePageSetPageLoaderClient(page, &loaderClient.base);
+    }
+    static void didClearWindowForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void*)
+    {
+        JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
+        WebCoreTestSupport::injectInternalsObject(context);
+    }
+};
+
+static TestWebKitAPI::InjectedBundleTest::Register<InternalsInjectedBundleTest> registrar("InternalsInjectedBundleTest");
+
+} // namespace TestWebKitAPI
+
+#endif
index 3d91b1b..f0394c9 100644 (file)
@@ -446,4 +446,130 @@ TEST(ServiceWorkers, FetchAfterRestoreFromDisk)
     done = false;
 }
 
+#if WK_HAVE_C_SPI
+
+void setConfigurationInjectedBundlePath(WKWebViewConfiguration* configuration)
+{
+    WKRetainPtr<WKContextRef> context(AdoptWK, TestWebKitAPI::Util::createContextForInjectedBundleTest("InternalsInjectedBundleTest"));
+    configuration.processPool = (WKProcessPool *)context.get();
+    auto pool = configuration.processPool;
+    [pool _registerURLSchemeServiceWorkersCanHandle:@"sw"];
+    [pool _setMaximumNumberOfProcesses:5];
+
+    configuration.websiteDataStore = (WKWebsiteDataStore *)WKContextGetWebsiteDataStore(context.get());
+}
+
+@interface RegularPageMessageHandler : NSObject <WKScriptMessageHandler>
+@end
+
+@implementation RegularPageMessageHandler
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    EXPECT_TRUE([[message body] isEqualToString:@"PASS"]);
+    done = true;
+}
+@end
+
+static const char* regularPageWithoutConnectionBytes = R"SWRESOURCE(
+<script>
+var result = window.internals.hasServiceWorkerConnection() ? "FAIL" : "PASS";
+window.webkit.messageHandlers.regularPage.postMessage(result);
+</script>
+)SWRESOURCE";
+
+static const char* regularPageWithConnectionBytes = R"SWRESOURCE(
+<script>
+var result = window.internals.hasServiceWorkerConnection() ? "PASS" : "FAIL";
+window.webkit.messageHandlers.regularPage.postMessage(result);
+</script>
+)SWRESOURCE";
+
+TEST(ServiceWorkers, StorageConnectionCreation)
+{
+    ASSERT(mainBytes);
+    ASSERT(scriptBytes);
+
+    [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
+
+    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    setConfigurationInjectedBundlePath(configuration.get());
+
+    done = false;
+
+    [[configuration websiteDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    [[configuration websiteDataStore] fetchDataRecordsOfTypes:[NSSet setWithObject:WKWebsiteDataTypeServiceWorkerRegistrations] completionHandler:^(NSArray<WKWebsiteDataRecord *> *websiteDataRecords) {
+        EXPECT_EQ(0u, [websiteDataRecords count]);
+
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    RetainPtr<SWMessageHandler> messageHandler = adoptNS([[SWMessageHandler alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
+    RetainPtr<RegularPageMessageHandler> regularPageMessageHandler = adoptNS([[RegularPageMessageHandler alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:regularPageMessageHandler.get() name:@"regularPage"];
+
+    RetainPtr<SWSchemes> handler = adoptNS([[SWSchemes alloc] init]);
+    handler->resources.set("sw://host/regularPageWithoutConnection.html", ResourceInfo { @"text/html", regularPageWithoutConnectionBytes });
+    handler->resources.set("sw://host/regularPageWithConnection.html", ResourceInfo { @"text/html", regularPageWithConnectionBytes });
+    handler->resources.set("sw://host/main.html", ResourceInfo { @"text/html", mainBytes });
+    handler->resources.set("sw://host/sw.js", ResourceInfo { @"application/javascript", scriptBytes });
+    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"SW"];
+
+    RetainPtr<WKWebView> regularPageWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    RetainPtr<WKWebView> newRegularPageWebView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    // Test that a regular page does not trigger a service worker connection to storage process if there is no registered service worker.
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"sw://host/regularPageWithoutConnection.html"]];
+
+    [regularPageWebView loadRequest:request];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    // Test that a sw scheme page can register a service worker.
+    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"sw://host/main.html"]];
+
+    [webView loadRequest:request];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    webView = nullptr;
+
+    // Now that a service worker is registered, the regular page should have a service worker connection.
+    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"sw://host/regularPageWithConnection.html"]];
+
+    [regularPageWebView loadRequest:request];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    regularPageWebView = nullptr;
+
+    [newRegularPageWebView loadRequest:request];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    newRegularPageWebView = nullptr;
+
+    [[configuration websiteDataStore] fetchDataRecordsOfTypes:[NSSet setWithObject:WKWebsiteDataTypeServiceWorkerRegistrations] completionHandler:^(NSArray<WKWebsiteDataRecord *> *websiteDataRecords) {
+        EXPECT_EQ(1u, [websiteDataRecords count]);
+        EXPECT_TRUE([websiteDataRecords[0].displayName isEqualToString:@"sw host"]);
+
+        done = true;
+    }];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    [[configuration websiteDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+}
+
+#endif // WK_HAVE_C_SPI
+
 #endif // WK_API_ENABLED