Title: [280016] trunk
Revision
280016
Author
katherine_che...@apple.com
Date
2021-07-16 20:24:25 -0700 (Fri, 16 Jul 2021)

Log Message

WKWebView _javascript_ injection doesn't work if app includes WKAppBoundDomains
https://bugs.webkit.org/show_bug.cgi?id=227589
<rdar://problem/80327452>

Reviewed by Brent Fulgham.

Source/WebCore:

Update service worker code to always allow workers on localhost to be
registered. Also add logic so localhost registrations aren't added
to the total count of 3 registrations.

* workers/service/server/SWServer.cpp:
(WebCore::SWServer::addRegistration):
We only want to increment the count if this registration is not
already in the mapping, otherwise it gets double counted.

(WebCore::SWServer::removeRegistration):
Ditto for removing a registration, we should only decrement the count
if we find a matching key.

(WebCore::SWServer::validateRegistrationDomain):
(WebCore::SWServer::removeFromScopeToRegistrationMap):
Ditto.

* workers/service/server/SWServer.h:

Source/WebKit:

Apps should not have to specify localhost in their Info.plist in order
to load local content in app-bound mode. This patch adds a check for
localhost or a loopback IP address and forces an app into app-bound
mode in this case.

Since all layout tests use localhost and 127.0.0.1 as test domains,
this patch also adds a check for enableInAppBrowserPrivacyForTesting()
which determines if we are running layout tests and does not trigger
this check in that case so we can test other behavior.

* UIProcess/WebPageProxy.cpp:
(WebKit::shouldTreatURLProtocolAsAppBound):
(WebKit::WebPageProxy::setIsNavigatingToAppBoundDomainAndCheckIfPermitted):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):

Tools:

Added new tests. Removed localhost and 127.0.0.1 from the Info.plist
to avoid false positive tests. Replace them with other domains so we
still test the max count.

* TestWebKitAPI/Info.plist:
* TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm:
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (280015 => 280016)


--- trunk/Source/WebCore/ChangeLog	2021-07-17 01:02:06 UTC (rev 280015)
+++ trunk/Source/WebCore/ChangeLog	2021-07-17 03:24:25 UTC (rev 280016)
@@ -1,3 +1,30 @@
+2021-07-16  Kate Cheney  <katherine_che...@apple.com>
+
+        WKWebView _javascript_ injection doesn't work if app includes WKAppBoundDomains
+        https://bugs.webkit.org/show_bug.cgi?id=227589
+        <rdar://problem/80327452>
+
+        Reviewed by Brent Fulgham.
+
+        Update service worker code to always allow workers on localhost to be
+        registered. Also add logic so localhost registrations aren't added
+        to the total count of 3 registrations.
+
+        * workers/service/server/SWServer.cpp:
+        (WebCore::SWServer::addRegistration):
+        We only want to increment the count if this registration is not
+        already in the mapping, otherwise it gets double counted.
+
+        (WebCore::SWServer::removeRegistration):
+        Ditto for removing a registration, we should only decrement the count
+        if we find a matching key.
+
+        (WebCore::SWServer::validateRegistrationDomain):
+        (WebCore::SWServer::removeFromScopeToRegistrationMap):
+        Ditto.
+
+        * workers/service/server/SWServer.h:
+
 2021-07-16  Alex Christensen  <achristen...@webkit.org>
 
         Network access prevention SPI should prevent preconnecting, and it should first allow injected bundle to change request

Modified: trunk/Source/WebCore/workers/service/server/SWServer.cpp (280015 => 280016)


--- trunk/Source/WebCore/workers/service/server/SWServer.cpp	2021-07-17 01:02:06 UTC (rev 280015)
+++ trunk/Source/WebCore/workers/service/server/SWServer.cpp	2021-07-17 03:24:25 UTC (rev 280016)
@@ -184,6 +184,9 @@
 
 void SWServer::addRegistration(std::unique_ptr<SWServerRegistration>&& registration)
 {
+    if (!m_scopeToRegistrationMap.contains(registration->key()) && !SecurityOrigin::isLocalHostOrLoopbackIPAddress(registration->key().topOrigin().host))
+        m_uniqueRegistrationCount++;
+
     m_originStore->add(registration->key().topOrigin());
     auto registrationID = registration->identifier();
     ASSERT(!m_scopeToRegistrationMap.contains(registration->key()));
@@ -198,8 +201,11 @@
     ASSERT(registration);
     
     auto it = m_scopeToRegistrationMap.find(registration->key());
-    if (it != m_scopeToRegistrationMap.end() && it->value == registration.get())
+    if (it != m_scopeToRegistrationMap.end() && it->value == registration.get()) {
         m_scopeToRegistrationMap.remove(it);
+        if (!SecurityOrigin::isLocalHostOrLoopbackIPAddress(registration->key().topOrigin().host))
+            m_uniqueRegistrationCount--;
+    }
 
     m_originStore->remove(registration->key().topOrigin());
     if (m_registrationStore)
@@ -343,16 +349,16 @@
 void SWServer::validateRegistrationDomain(WebCore::RegistrableDomain domain, CompletionHandler<void(bool)>&& completionHandler)
 {
     if (m_hasServiceWorkerEntitlement || m_hasReceivedAppBoundDomains) {
-        completionHandler(m_appBoundDomains.contains(domain) && m_scopeToRegistrationMap.keys().size() < maxRegistrationCount);
+        completionHandler(SecurityOrigin::isLocalHostOrLoopbackIPAddress(domain.string()) || (m_appBoundDomains.contains(domain) && m_uniqueRegistrationCount < maxRegistrationCount));
         return;
     }
-    
+
     m_appBoundDomainsCallback([this, weakThis = makeWeakPtr(this), domain = WTFMove(domain), completionHandler = WTFMove(completionHandler)](auto&& appBoundDomains) mutable {
         if (!weakThis)
             return;
         m_hasReceivedAppBoundDomains = true;
         m_appBoundDomains = WTFMove(appBoundDomains);
-        completionHandler(m_appBoundDomains.contains(domain) && m_scopeToRegistrationMap.keys().size() < maxRegistrationCount);
+        completionHandler(SecurityOrigin::isLocalHostOrLoopbackIPAddress(domain.string()) || (m_appBoundDomains.contains(domain) && m_uniqueRegistrationCount < maxRegistrationCount));
     });
 }
 
@@ -1011,6 +1017,9 @@
 
 void SWServer::removeFromScopeToRegistrationMap(const ServiceWorkerRegistrationKey& key)
 {
+    if (m_scopeToRegistrationMap.contains(key) && !SecurityOrigin::isLocalHostOrLoopbackIPAddress(key.topOrigin().host))
+        m_uniqueRegistrationCount--;
+
     m_scopeToRegistrationMap.remove(key);
 }
 

Modified: trunk/Source/WebCore/workers/service/server/SWServer.h (280015 => 280016)


--- trunk/Source/WebCore/workers/service/server/SWServer.h	2021-07-17 01:02:06 UTC (rev 280015)
+++ trunk/Source/WebCore/workers/service/server/SWServer.h	2021-07-17 03:24:25 UTC (rev 280016)
@@ -283,6 +283,7 @@
     HashSet<WebCore::RegistrableDomain> m_appBoundDomains;
     bool m_hasServiceWorkerEntitlement { false };
     bool m_hasReceivedAppBoundDomains { false };
+    unsigned m_uniqueRegistrationCount { 0 };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (280015 => 280016)


--- trunk/Source/WebKit/ChangeLog	2021-07-17 01:02:06 UTC (rev 280015)
+++ trunk/Source/WebKit/ChangeLog	2021-07-17 03:24:25 UTC (rev 280016)
@@ -1,3 +1,26 @@
+2021-07-16  Kate Cheney  <katherine_che...@apple.com>
+
+        WKWebView _javascript_ injection doesn't work if app includes WKAppBoundDomains
+        https://bugs.webkit.org/show_bug.cgi?id=227589
+        <rdar://problem/80327452>
+
+        Reviewed by Brent Fulgham.
+
+        Apps should not have to specify localhost in their Info.plist in order
+        to load local content in app-bound mode. This patch adds a check for
+        localhost or a loopback IP address and forces an app into app-bound
+        mode in this case.
+
+        Since all layout tests use localhost and 127.0.0.1 as test domains,
+        this patch also adds a check for enableInAppBrowserPrivacyForTesting()
+        which determines if we are running layout tests and does not trigger
+        this check in that case so we can test other behavior.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::shouldTreatURLProtocolAsAppBound):
+        (WebKit::WebPageProxy::setIsNavigatingToAppBoundDomainAndCheckIfPermitted):
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+
 2021-07-16  Alex Christensen  <achristen...@webkit.org>
 
         Prevent HSTS tracking mitigation for top level navigation requests

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (280015 => 280016)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-07-17 01:02:06 UTC (rev 280015)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-07-17 03:24:25 UTC (rev 280016)
@@ -3321,9 +3321,15 @@
 };
 
 #if ENABLE(APP_BOUND_DOMAINS)
-static bool shouldTreatURLProtocolAsAppBound(const URL& requestURL)
+static bool shouldTreatURLProtocolAsAppBound(const URL& requestURL, bool isRunningTest)
 {
-    return requestURL.protocolIsAbout() || requestURL.protocolIsData() || requestURL.protocolIsBlob() || requestURL.isLocalFile() || requestURL.protocolIsJavaScript();
+    return !isRunningTest
+        && (SecurityOrigin::isLocalHostOrLoopbackIPAddress(requestURL.host())
+            || requestURL.protocolIsAbout()
+            || requestURL.protocolIsData()
+            || requestURL.protocolIsBlob()
+            || requestURL.isLocalFile()
+            || requestURL.protocolIsJavaScript());
 }
 
 bool WebPageProxy::setIsNavigatingToAppBoundDomainAndCheckIfPermitted(bool isMainFrame, const URL& requestURL, std::optional<NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain)
@@ -3341,7 +3347,7 @@
     if (m_ignoresAppBoundDomains)
         return true;
 
-    if (isMainFrame && shouldTreatURLProtocolAsAppBound(requestURL)) {
+    if (isMainFrame && shouldTreatURLProtocolAsAppBound(requestURL, websiteDataStore().configuration().enableInAppBrowserPrivacyForTesting())) {
         isNavigatingToAppBoundDomain = NavigatingToAppBoundDomain::Yes;
         m_limitsNavigationsToAppBoundDomains = true;
     }
@@ -5434,7 +5440,7 @@
     if (shouldExpectSafeBrowsingResult == ShouldExpectSafeBrowsingResult::Yes)
         beginSafeBrowsingCheck(request.url(), frame.isMainFrame(), listener);
 #if ENABLE(APP_BOUND_DOMAINS)
-    bool shouldSendSecurityOriginData = !frame.isMainFrame() && shouldTreatURLProtocolAsAppBound(request.url());
+    bool shouldSendSecurityOriginData = !frame.isMainFrame() && shouldTreatURLProtocolAsAppBound(request.url(), websiteDataStore().configuration().enableInAppBrowserPrivacyForTesting());
     auto host = shouldSendSecurityOriginData ? frameInfo.securityOrigin.host : request.url().host();
     auto protocol = shouldSendSecurityOriginData ? frameInfo.securityOrigin.protocol : request.url().protocol();
     m_websiteDataStore->beginAppBoundDomainCheck(host.toString(), protocol.toString(), listener);

Modified: trunk/Tools/ChangeLog (280015 => 280016)


--- trunk/Tools/ChangeLog	2021-07-17 01:02:06 UTC (rev 280015)
+++ trunk/Tools/ChangeLog	2021-07-17 03:24:25 UTC (rev 280016)
@@ -1,3 +1,19 @@
+2021-07-16  Kate Cheney  <katherine_che...@apple.com>
+
+        WKWebView _javascript_ injection doesn't work if app includes WKAppBoundDomains
+        https://bugs.webkit.org/show_bug.cgi?id=227589
+        <rdar://problem/80327452>
+
+        Reviewed by Brent Fulgham.
+
+        Added new tests. Removed localhost and 127.0.0.1 from the Info.plist
+        to avoid false positive tests. Replace them with other domains so we
+        still test the max count.
+
+        * TestWebKitAPI/Info.plist:
+        * TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm:
+        (TEST):
+
 2021-07-16  Alex Christensen  <achristen...@webkit.org>
 
         Prevent HSTS tracking mitigation for top level navigation requests

Modified: trunk/Tools/TestWebKitAPI/Info.plist (280015 => 280016)


--- trunk/Tools/TestWebKitAPI/Info.plist	2021-07-17 01:02:06 UTC (rev 280015)
+++ trunk/Tools/TestWebKitAPI/Info.plist	2021-07-17 03:24:25 UTC (rev 280016)
@@ -11,10 +11,7 @@
 		<string>apple.com</string>
 		<string>sub.domain.webkit.org/road/to/nowhere/</string>
 		<string>webkit.org</string>
-		<string>localhost:8000</string>
-		<string>localhost/road/to/nowhere/</string>
 		<string>file:///some/file</string>
-		<string>127.0.0.1</string>
 		<string></string>
 		<string>   </string>
 		<string>https://sub.domain.webkit.org</string>
@@ -24,7 +21,9 @@
 		<string>http://www.example.com/</string>
 		<string>http://bar.com/</string>
 		<string>http://foo.com/</string>
+		<string>https://searchforlongboards.biz</string>
 		<string>app-bound-custom-scheme:</string>
+		<string>longboardshop.biz</string>
 		<string>should-not-be-included:</string>
 	</array>
 	<key>CFBundleName</key>

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm (280015 => 280016)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm	2021-07-17 01:02:06 UTC (rev 280015)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm	2021-07-17 03:24:25 UTC (rev 280016)
@@ -271,7 +271,7 @@
     initializeInAppBrowserPrivacyTestSettings();
     isDone = false;
     [[WKWebsiteDataStore defaultDataStore] _appBoundDomains:^(NSArray<NSString *> *domains) {
-        NSArray *domainsToCompare = @[@"127.0.0.1", @"apple.com", @"bar.com", @"example.com", @"foo.com", @"localhost", @"testdomain1",  @"webkit.org"];
+        NSArray *domainsToCompare = @[@"apple.com", @"bar.com", @"example.com", @"foo.com", @"longboardshop.biz", @"searchforlongboards.biz", @"testdomain1",  @"webkit.org"];
 
         NSArray *sortedDomains = [domains sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
 
@@ -361,6 +361,60 @@
     TestWebKitAPI::Util::run(&isDone);
 }
 
+TEST(InAppBrowserPrivacy, LocalHostIsAppBound)
+{
+    initializeInAppBrowserPrivacyTestSettings();
+    isDone = false;
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto schemeHandler = adoptNS([[InAppBrowserSchemeHandler alloc] init]);
+    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"in-app-browser"];
+    [configuration setLimitsNavigationsToAppBoundDomains:YES];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    auto delegate = adoptNS([AppBoundDomainDelegate new]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"in-app-browser://localhost/app-bound-domain-load"]];
+    [webView loadRequest:request];
+    [delegate waitForDidFinishNavigation];
+
+    isDone = false;
+    [webView _isForcedIntoAppBoundMode:^(BOOL isForcedIntoAppBoundMode) {
+        EXPECT_TRUE(isForcedIntoAppBoundMode);
+        cleanUpInAppBrowserPrivacyTestSettings();
+        isDone = true;
+    }];
+    TestWebKitAPI::Util::run(&isDone);
+}
+
+TEST(InAppBrowserPrivacy, LoopbackIPAddressIsAppBound)
+{
+    initializeInAppBrowserPrivacyTestSettings();
+    isDone = false;
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto schemeHandler = adoptNS([[InAppBrowserSchemeHandler alloc] init]);
+    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"in-app-browser"];
+    [configuration setLimitsNavigationsToAppBoundDomains:YES];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    auto delegate = adoptNS([AppBoundDomainDelegate new]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"in-app-browser://127.0.0.1/app-bound-domain-load"]];
+    [webView loadRequest:request];
+    [delegate waitForDidFinishNavigation];
+
+    isDone = false;
+    [webView _isForcedIntoAppBoundMode:^(BOOL isForcedIntoAppBoundMode) {
+        EXPECT_TRUE(isForcedIntoAppBoundMode);
+        cleanUpInAppBrowserPrivacyTestSettings();
+        isDone = true;
+    }];
+    TestWebKitAPI::Util::run(&isDone);
+}
+
 static NSString *styleSheetSource = @"body { background-color: green !important; }";
 static NSString *backgroundColorScript = @"window.getComputedStyle(document.body, null).getPropertyValue('background-color')";
 static const char* redInRGB = "rgb(255, 0, 0)";
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to