[iOS] The default application name for user agent when requesting desktop content...
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 9 Jun 2019 03:55:01 +0000 (03:55 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 9 Jun 2019 03:55:01 +0000 (03:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=198693
<rdar://problem/51555371>

Reviewed by Tim Horton.

Source/WebKit:

Fixes the bug by introducing an applicationNameForDesktopUserAgent member to WebPageProxy. This
applicationNameForDesktopUserAgent is set alongside the regular applicationNameForUserAgent; however, in the
case where it is being set via WKWebViewConfiguration, use WKWebViewConfiguration's
_applicationNameForDesktopUserAgent instead. See below for more details.

Tested by adding to the existing API test PreferredContentMode.ApplicationNameForDesktopUserAgent.

* UIProcess/API/APIWebsitePolicies.cpp:
(API::WebsitePolicies::copy const):
* UIProcess/API/APIWebsitePolicies.h:

Drive-by fix: rename applicationNameForUserAgentWithModernCompatibility to applicationNameForDesktopUserAgent in
a few places.

* UIProcess/API/Cocoa/WKBrowsingContextController.mm:
(-[WKBrowsingContextController setApplicationNameForUserAgent:]):
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]):
(-[WKWebView _setApplicationNameForUserAgent:]):
* UIProcess/API/Cocoa/WKWebViewConfiguration.mm:

Change _applicationNameForUserAgent into an Optional<RetainPtr<NSString>>. A value of WTF::nullopt allows us to
know that the default application name should be used (which is different when requesting desktop content).

(-[WKWebViewConfiguration encodeWithCoder:]):
(-[WKWebViewConfiguration initWithCoder:]):
(-[WKWebViewConfiguration copyWithZone:]):
(-[WKWebViewConfiguration _applicationNameForDesktopUserAgent]):

Add _applicationNameForDesktopUserAgent to the web view configuration. This behaves like
applicationNameForUserAgent, with one exception: in the case where the default applicationNameForUserAgent is
used (i.e. the client has not specified any application name), default to `nil` as the application name for user
agent, rather than "Mobile/15E148".

(-[WKWebViewConfiguration applicationNameForUserAgent]):
(-[WKWebViewConfiguration setApplicationNameForUserAgent:]):
* UIProcess/API/Cocoa/WKWebViewConfigurationInternal.h:
* UIProcess/API/Cocoa/WKWebpagePreferences.mm:
(-[WKWebpagePreferences _applicationNameForUserAgentWithModernCompatibility]):
(-[WKWebpagePreferences _setApplicationNameForUserAgentWithModernCompatibility:]):
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::setApplicationNameForDesktopUserAgent):
(WebKit::WebPageProxy::applicationNameForDesktopUserAgent const):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::effectiveContentModeAfterAdjustingPolicies):

Tools:

Augment an existing API test to exercise three additional scenarios:
    -   The web view configuration's application name is never set; the default should not include
        "Mobile/15E148" in desktop mode.
    -   The application name is explicitly set to nil; the default application name should still not include
        "Mobile/15E148".
    -   The application name is explicitly set to the default value, "Mobile/15E148". WKWebView should honor
        this when generating the user agent, even in desktop mode.

* TestWebKitAPI/ios/PreferredContentMode.mm:
(TestWebKitAPI::setUpWebViewForPreferredContentModeTestingWithoutNavigationDelegate):
(TestWebKitAPI::setUpWebViewForPreferredContentModeTesting):
(TestWebKitAPI::TEST):

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

12 files changed:
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/APIWebsitePolicies.cpp
Source/WebKit/UIProcess/API/APIWebsitePolicies.h
Source/WebKit/UIProcess/API/Cocoa/WKBrowsingContextController.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationInternal.h
Source/WebKit/UIProcess/API/Cocoa/WKWebpagePreferences.mm
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Tools/ChangeLog
Tools/TestWebKitAPI/ios/PreferredContentMode.mm

index 254cfbe..6847013 100644 (file)
@@ -1,3 +1,57 @@
+2019-06-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] The default application name for user agent when requesting desktop content is still "Mobile/15E148"
+        https://bugs.webkit.org/show_bug.cgi?id=198693
+        <rdar://problem/51555371>
+
+        Reviewed by Tim Horton.
+
+        Fixes the bug by introducing an applicationNameForDesktopUserAgent member to WebPageProxy. This
+        applicationNameForDesktopUserAgent is set alongside the regular applicationNameForUserAgent; however, in the
+        case where it is being set via WKWebViewConfiguration, use WKWebViewConfiguration's
+        _applicationNameForDesktopUserAgent instead. See below for more details.
+
+        Tested by adding to the existing API test PreferredContentMode.ApplicationNameForDesktopUserAgent.
+
+        * UIProcess/API/APIWebsitePolicies.cpp:
+        (API::WebsitePolicies::copy const):
+        * UIProcess/API/APIWebsitePolicies.h:
+
+        Drive-by fix: rename applicationNameForUserAgentWithModernCompatibility to applicationNameForDesktopUserAgent in
+        a few places.
+
+        * UIProcess/API/Cocoa/WKBrowsingContextController.mm:
+        (-[WKBrowsingContextController setApplicationNameForUserAgent:]):
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _initializeWithConfiguration:]):
+        (-[WKWebView _setApplicationNameForUserAgent:]):
+        * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+
+        Change _applicationNameForUserAgent into an Optional<RetainPtr<NSString>>. A value of WTF::nullopt allows us to
+        know that the default application name should be used (which is different when requesting desktop content).
+
+        (-[WKWebViewConfiguration encodeWithCoder:]):
+        (-[WKWebViewConfiguration initWithCoder:]):
+        (-[WKWebViewConfiguration copyWithZone:]):
+        (-[WKWebViewConfiguration _applicationNameForDesktopUserAgent]):
+
+        Add _applicationNameForDesktopUserAgent to the web view configuration. This behaves like
+        applicationNameForUserAgent, with one exception: in the case where the default applicationNameForUserAgent is
+        used (i.e. the client has not specified any application name), default to `nil` as the application name for user
+        agent, rather than "Mobile/15E148".
+
+        (-[WKWebViewConfiguration applicationNameForUserAgent]):
+        (-[WKWebViewConfiguration setApplicationNameForUserAgent:]):
+        * UIProcess/API/Cocoa/WKWebViewConfigurationInternal.h:
+        * UIProcess/API/Cocoa/WKWebpagePreferences.mm:
+        (-[WKWebpagePreferences _applicationNameForUserAgentWithModernCompatibility]):
+        (-[WKWebpagePreferences _setApplicationNameForUserAgentWithModernCompatibility:]):
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::setApplicationNameForDesktopUserAgent):
+        (WebKit::WebPageProxy::applicationNameForDesktopUserAgent const):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::effectiveContentModeAfterAdjustingPolicies):
+
 2019-06-08  Andy Estes  <aestes@apple.com>
 
         [Apple Pay] If we have a bound interface identifier, set it on new PKPaymentRequests
index c9994db..b0a900c 100644 (file)
@@ -75,7 +75,7 @@ Ref<WebsitePolicies> WebsitePolicies::copy() const
         customHeaderFields.uncheckedAppend(field);
     policies->setCustomHeaderFields(WTFMove(customHeaderFields));
     policies->setAllowSiteSpecificQuirksToOverrideContentMode(m_allowSiteSpecificQuirksToOverrideContentMode);
-    policies->setApplicationNameForUserAgentWithModernCompatibility(m_applicationNameForUserAgentWithModernCompatibility);
+    policies->setApplicationNameForDesktopUserAgent(m_applicationNameForDesktopUserAgent);
     return policies;
 }
 
index 7ad5fe8..1d78d20 100644 (file)
@@ -111,8 +111,8 @@ public:
     bool allowSiteSpecificQuirksToOverrideContentMode() const { return m_allowSiteSpecificQuirksToOverrideContentMode; }
     void setAllowSiteSpecificQuirksToOverrideContentMode(bool value) { m_allowSiteSpecificQuirksToOverrideContentMode = value; }
 
-    WTF::String applicationNameForUserAgentWithModernCompatibility() const { return m_applicationNameForUserAgentWithModernCompatibility; }
-    void setApplicationNameForUserAgentWithModernCompatibility(const WTF::String& applicationName) { m_applicationNameForUserAgentWithModernCompatibility = applicationName; }
+    WTF::String applicationNameForDesktopUserAgent() const { return m_applicationNameForDesktopUserAgent; }
+    void setApplicationNameForDesktopUserAgent(const WTF::String& applicationName) { m_applicationNameForDesktopUserAgent = applicationName; }
 
 private:
     WebsitePolicies(bool contentBlockersEnabled, OptionSet<WebKit::WebsiteAutoplayQuirk>, WebKit::WebsiteAutoplayPolicy, Vector<WebCore::HTTPHeaderField>&&, Vector<WebCore::CustomHeaderFields>&&, WebKit::WebsitePopUpPolicy, RefPtr<WebsiteDataStore>&&);
@@ -136,7 +136,7 @@ private:
     WebKit::WebsiteSimulatedMouseEventsDispatchPolicy m_simulatedMouseEventsDispatchPolicy { WebKit::WebsiteSimulatedMouseEventsDispatchPolicy::Default };
     WebKit::WebsiteLegacyOverflowScrollingTouchPolicy m_legacyOverflowScrollingTouchPolicy { WebKit::WebsiteLegacyOverflowScrollingTouchPolicy::Default };
     bool m_allowSiteSpecificQuirksToOverrideContentMode { false };
-    WTF::String m_applicationNameForUserAgentWithModernCompatibility;
+    WTF::String m_applicationNameForDesktopUserAgent;
 };
 
 } // namespace API
index d540cd4..30a8aa8 100644 (file)
@@ -199,6 +199,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END
 
 - (void)setApplicationNameForUserAgent:(NSString *)applicationNameForUserAgent
 {
+    _page->setApplicationNameForDesktopUserAgent(applicationNameForUserAgent);
     _page->setApplicationNameForUserAgent(applicationNameForUserAgent);
 }
 
index 263c359..b2bf98f 100644 (file)
@@ -748,6 +748,8 @@ static void validate(WKWebViewConfiguration *configuration)
     if (NSString *applicationNameForUserAgent = configuration.applicationNameForUserAgent)
         _page->setApplicationNameForUserAgent(applicationNameForUserAgent);
 
+    _page->setApplicationNameForDesktopUserAgent(configuration._applicationNameForDesktopUserAgent);
+
     _navigationState = std::make_unique<WebKit::NavigationState>(self);
     _page->setNavigationClient(_navigationState->createNavigationClient());
 
@@ -4782,6 +4784,7 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
 - (void)_setApplicationNameForUserAgent:(NSString *)applicationNameForUserAgent
 {
     _page->setApplicationNameForUserAgent(applicationNameForUserAgent);
+    _page->setApplicationNameForDesktopUserAgent(applicationNameForUserAgent);
 }
 
 - (NSString *)_customUserAgent
index eec0438..4151021 100644 (file)
@@ -122,7 +122,7 @@ static bool defaultShouldDecidePolicyBeforeLoadingQuickLookPreview()
     WeakObjCPtr<WKWebView> _relatedWebView;
     WeakObjCPtr<WKWebView> _alternateWebViewForNavigationGestures;
     RetainPtr<NSString> _groupIdentifier;
-    LazyInitialized<RetainPtr<NSString>> _applicationNameForUserAgent;
+    Optional<RetainPtr<NSString>> _applicationNameForUserAgent;
     NSTimeInterval _incrementalRenderingSuppressionTimeout;
     BOOL _respectsImageOrientation;
     BOOL _printsBackgrounds;
@@ -286,7 +286,10 @@ static bool defaultShouldDecidePolicyBeforeLoadingQuickLookPreview()
     [coder encodeObject:self.websiteDataStore forKey:@"websiteDataStore"];
 
     [coder encodeBool:self.suppressesIncrementalRendering forKey:@"suppressesIncrementalRendering"];
-    [coder encodeObject:self.applicationNameForUserAgent forKey:@"applicationNameForUserAgent"];
+
+    if (_applicationNameForUserAgent.hasValue())
+        [coder encodeObject:self.applicationNameForUserAgent forKey:@"applicationNameForUserAgent"];
+
     [coder encodeBool:self.allowsAirPlayForMediaPlayback forKey:@"allowsAirPlayForMediaPlayback"];
 
     [coder encodeBool:self._drawsBackground forKey:@"drawsBackground"];
@@ -320,7 +323,10 @@ static bool defaultShouldDecidePolicyBeforeLoadingQuickLookPreview()
     self.websiteDataStore = decodeObjectOfClassForKeyFromCoder([WKWebsiteDataStore class], @"websiteDataStore", coder);
 
     self.suppressesIncrementalRendering = [coder decodeBoolForKey:@"suppressesIncrementalRendering"];
-    self.applicationNameForUserAgent = decodeObjectOfClassForKeyFromCoder([NSString class], @"applicationNameForUserAgent", coder);
+
+    if ([coder containsValueForKey:@"applicationNameForUserAgent"])
+        self.applicationNameForUserAgent = decodeObjectOfClassForKeyFromCoder([NSString class], @"applicationNameForUserAgent", coder);
+
     self.allowsAirPlayForMediaPlayback = [coder decodeBoolForKey:@"allowsAirPlayForMediaPlayback"];
 
     if ([coder containsValueForKey:@"drawsBackground"])
@@ -366,7 +372,7 @@ static bool defaultShouldDecidePolicyBeforeLoadingQuickLookPreview()
 #endif
 
     configuration->_suppressesIncrementalRendering = self->_suppressesIncrementalRendering;
-    configuration.applicationNameForUserAgent = self.applicationNameForUserAgent;
+    configuration->_applicationNameForUserAgent = self->_applicationNameForUserAgent;
 
     configuration->_respectsImageOrientation = self->_respectsImageOrientation;
     configuration->_printsBackgrounds = self->_printsBackgrounds;
@@ -495,14 +501,19 @@ static NSString *defaultApplicationNameForUserAgent()
 #endif
 }
 
+- (NSString *)_applicationNameForDesktopUserAgent
+{
+    return _applicationNameForUserAgent.valueOr(nil).get();
+}
+
 - (NSString *)applicationNameForUserAgent
 {
-    return _applicationNameForUserAgent.get([] { return defaultApplicationNameForUserAgent(); });
+    return _applicationNameForUserAgent.valueOr(defaultApplicationNameForUserAgent()).get();
 }
 
 - (void)setApplicationNameForUserAgent:(NSString *)applicationNameForUserAgent
 {
-    _applicationNameForUserAgent.set(adoptNS([applicationNameForUserAgent copy]));
+    _applicationNameForUserAgent.emplace(adoptNS(applicationNameForUserAgent.copy));
 }
 
 - (_WKVisitedLinkStore *)_visitedLinkStore
index db4b2bb..171b4a4 100644 (file)
@@ -35,6 +35,7 @@
 #if PLATFORM(IOS_FAMILY)
 @property (nonatomic, setter=_setContentProviderRegistry:) WKWebViewContentProviderRegistry *_contentProviderRegistry;
 #endif
+@property (nonatomic, readonly) NSString *_applicationNameForDesktopUserAgent;
 
 - (Ref<API::PageConfiguration>)copyPageConfiguration;
 
index 8666be3..53f7660 100644 (file)
@@ -318,12 +318,12 @@ static _WKWebsiteDeviceOrientationAndMotionAccessPolicy toWKWebsiteDeviceOrienta
 
 - (NSString *)_applicationNameForUserAgentWithModernCompatibility
 {
-    return _websitePolicies->applicationNameForUserAgentWithModernCompatibility();
+    return _websitePolicies->applicationNameForDesktopUserAgent();
 }
 
 - (void)_setApplicationNameForUserAgentWithModernCompatibility:(NSString *)applicationName
 {
-    _websitePolicies->setApplicationNameForUserAgentWithModernCompatibility(applicationName);
+    _websitePolicies->setApplicationNameForDesktopUserAgent(applicationName);
 }
 
 - (API::Object&)_apiObject
index ddfad61..64a9586 100644 (file)
@@ -855,6 +855,8 @@ public:
     const String& userAgent() const { return m_userAgent; }
     void setApplicationNameForUserAgent(const String&);
     const String& applicationNameForUserAgent() const { return m_applicationNameForUserAgent; }
+    void setApplicationNameForDesktopUserAgent(const String& applicationName) { m_applicationNameForDesktopUserAgent = applicationName; }
+    const String& applicationNameForDesktopUserAgent() const { return m_applicationNameForDesktopUserAgent; }
     void setCustomUserAgent(const String&);
     const String& customUserAgent() const { return m_customUserAgent; }
     static String standardUserAgent(const String& applicationName = String());
@@ -2145,6 +2147,7 @@ private:
 
     String m_userAgent;
     String m_applicationNameForUserAgent;
+    String m_applicationNameForDesktopUserAgent;
     String m_customUserAgent;
     String m_customTextEncodingName;
     String m_overrideContentSecurityPolicy;
index 3b1800f..9ec1ad3 100644 (file)
@@ -1382,9 +1382,9 @@ WebContentMode WebPageProxy::effectiveContentModeAfterAdjustingPolicies(API::Web
         return WebContentMode::Mobile;
 
     if (policies.customUserAgent().isEmpty() && customUserAgent().isEmpty()) {
-        auto applicationName = policies.applicationNameForUserAgentWithModernCompatibility();
+        auto applicationName = policies.applicationNameForDesktopUserAgent();
         if (applicationName.isEmpty())
-            applicationName = applicationNameForUserAgent();
+            applicationName = applicationNameForDesktopUserAgent();
         policies.setCustomUserAgent(standardUserAgentWithApplicationName(applicationName, UserAgentType::Desktop));
     }
 
index 50e088f..c6aa70a 100644 (file)
@@ -1,3 +1,24 @@
+2019-06-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] The default application name for user agent when requesting desktop content is still "Mobile/15E148"
+        https://bugs.webkit.org/show_bug.cgi?id=198693
+        <rdar://problem/51555371>
+
+        Reviewed by Tim Horton.
+
+        Augment an existing API test to exercise three additional scenarios:
+            -   The web view configuration's application name is never set; the default should not include
+                "Mobile/15E148" in desktop mode.
+            -   The application name is explicitly set to nil; the default application name should still not include
+                "Mobile/15E148".
+            -   The application name is explicitly set to the default value, "Mobile/15E148". WKWebView should honor
+                this when generating the user agent, even in desktop mode.
+
+        * TestWebKitAPI/ios/PreferredContentMode.mm:
+        (TestWebKitAPI::setUpWebViewForPreferredContentModeTestingWithoutNavigationDelegate):
+        (TestWebKitAPI::setUpWebViewForPreferredContentModeTesting):
+        (TestWebKitAPI::TEST):
+
 2019-06-08  Zalan Bujtas  <zalan@apple.com>
 
         [LFC] Unreviewed test gardening.
index e823940..bebc49b 100644 (file)
@@ -185,20 +185,20 @@ private:
 namespace TestWebKitAPI {
 
 template <typename ViewClass>
-RetainPtr<ViewClass> setUpWebViewForPreferredContentModeTestingWithoutNavigationDelegate(Optional<WKContentMode> defaultContentMode = { }, const String& applicationNameForUserAgent = "TestWebKitAPI", CGSize size = CGSizeMake(1024, 768))
+RetainPtr<ViewClass> setUpWebViewForPreferredContentModeTestingWithoutNavigationDelegate(Optional<WKContentMode> defaultContentMode = { }, Optional<String> applicationNameForUserAgent = { "TestWebKitAPI" }, CGSize size = CGSizeMake(1024, 768))
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     if (defaultContentMode)
         [configuration setDefaultWebpagePreferences:[WKWebpagePreferences preferencesWithContentMode:defaultContentMode.value()]];
-    if (!!applicationNameForUserAgent)
-        [configuration setApplicationNameForUserAgent:applicationNameForUserAgent];
+    if (applicationNameForUserAgent)
+        [configuration setApplicationNameForUserAgent:applicationNameForUserAgent->isNull() ? nil : (NSString *)applicationNameForUserAgent.value()];
     auto webView = adoptNS([[ViewClass alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height) configuration:configuration.get()]);
     EXPECT_TRUE([webView isKindOfClass:WKWebView.class]);
     return webView;
 }
 
 template <typename ViewClass>
-std::pair<RetainPtr<ViewClass>, RetainPtr<ContentModeNavigationDelegate>> setUpWebViewForPreferredContentModeTesting(Optional<WKContentMode> defaultContentMode = { }, const String& applicationNameForUserAgent = "TestWebKitAPI", CGSize size = CGSizeMake(1024, 768))
+std::pair<RetainPtr<ViewClass>, RetainPtr<ContentModeNavigationDelegate>> setUpWebViewForPreferredContentModeTesting(Optional<WKContentMode> defaultContentMode = { }, Optional<String> applicationNameForUserAgent = { "TestWebKitAPI" }, CGSize size = CGSizeMake(1024, 768))
 {
     auto webView = setUpWebViewForPreferredContentModeTestingWithoutNavigationDelegate<ViewClass>(defaultContentMode, applicationNameForUserAgent, size);
     auto navigationDelegate = adoptNS([[ContentModeNavigationDelegate alloc] init]);
@@ -247,7 +247,7 @@ TEST(PreferredContentMode, DesktopModeWithoutNavigationDelegate)
 {
     IPadUserInterfaceSwizzler iPadUserInterface;
 
-    auto webView = setUpWebViewForPreferredContentModeTestingWithoutNavigationDelegate<TestWKWebView>(WKContentModeDesktop, "TestWebKitAPI");
+    auto webView = setUpWebViewForPreferredContentModeTestingWithoutNavigationDelegate<TestWKWebView>(WKContentModeDesktop);
     [webView loadHTMLString:@"<body>Hello world</body>" baseURL:nil];
 
     __block bool finished = false;
@@ -402,7 +402,7 @@ TEST(PreferredContentMode, RecommendedContentModeAtVariousViewWidths)
 
     RetainPtr<TestWKWebView> webView;
     RetainPtr<ContentModeNavigationDelegate> delegate;
-    std::tie(webView, delegate) = setUpWebViewForPreferredContentModeTesting<WKWebView>({ }, "TestWebKitAPI", CGSizeZero);
+    std::tie(webView, delegate) = setUpWebViewForPreferredContentModeTesting<WKWebView>({ }, { "TestWebKitAPI" }, CGSizeZero);
     [webView loadTestPageNamed:@"simple" andExpectEffectiveContentMode:WKContentModeDesktop withPolicyDecisionHandler:nil];
     [[webView navigatorUserAgent] shouldContainStrings:@"Mozilla/5.0 (Macintosh", @"TestWebKitAPI", nil];
 
@@ -428,6 +428,41 @@ TEST(PreferredContentMode, ApplicationNameForDesktopUserAgent)
     }];
     [[webView navigatorUserAgent] shouldContainStrings:@"Mozilla/5.0 (Macintosh", @"DesktopBrowser", nil];
     EXPECT_WK_STREQ("MacIntel", [webView navigatorPlatform]);
+
+    {
+        // Don't attempt to change the application name, but still opt into desktop-class browsing;
+        // the application name should not default to "Mobile/15E148".
+        std::tie(webView, delegate) = setUpWebViewForPreferredContentModeTesting<WKWebView>(WKContentModeDesktop, { });
+        [webView loadTestPageNamed:@"simple" withPolicyDecisionHandler:nil];
+        NSString *userAgent = [webView navigatorUserAgent];
+        EXPECT_FALSE([userAgent containsString:@"Mobile"]);
+        EXPECT_TRUE([userAgent containsString:@"Macintosh"]);
+    }
+    {
+        // Don't attempt to change the application name, but this time, opt into mobile content. The application
+        // name should default to "Mobile/15E148".
+        std::tie(webView, delegate) = setUpWebViewForPreferredContentModeTesting<WKWebView>(WKContentModeMobile, { });
+        [webView loadTestPageNamed:@"simple" withPolicyDecisionHandler:nil];
+        NSString *userAgent = [webView navigatorUserAgent];
+        EXPECT_TRUE([userAgent containsString:@"Mobile"]);
+        EXPECT_FALSE([userAgent containsString:@"Macintosh"]);
+    }
+    {
+        // Manually set the application name for user agent to the default value, Mobile/15E148.
+        std::tie(webView, delegate) = setUpWebViewForPreferredContentModeTesting<WKWebView>(WKContentModeDesktop, { "Mobile/15E148" });
+        [webView loadTestPageNamed:@"simple" withPolicyDecisionHandler:nil];
+        NSString *userAgent = [webView navigatorUserAgent];
+        EXPECT_TRUE([userAgent containsString:@"Mobile"]);
+        EXPECT_TRUE([userAgent containsString:@"Macintosh"]);
+    }
+    {
+        // Manually set the application name for user agent to nil.
+        std::tie(webView, delegate) = setUpWebViewForPreferredContentModeTesting<WKWebView>(WKContentModeDesktop, {{ }});
+        [webView loadTestPageNamed:@"simple" withPolicyDecisionHandler:nil];
+        NSString *userAgent = [webView navigatorUserAgent];
+        EXPECT_FALSE([userAgent containsString:@"Mobile"]);
+        EXPECT_TRUE([userAgent containsString:@"Macintosh"]);
+    }
 }
 
 } // namespace TestWebKitAPI