Changeset 169799 in webkit


Ignore:
Timestamp:
Jun 11, 2014 12:38:35 AM (10 years ago)
Author:
Carlos Garcia Campos
Message:

[GTK] Use a different user agent string depending on the site
https://bugs.webkit.org/show_bug.cgi?id=132681

Reviewed by Anders Carlsson.

Source/WebCore:
We have changed the user agent string several times to try to fix
broken websites that require specific things in the UA string to
properly work. But everytime we change the UA string to fix a
website we break others. We could use different UA string
depending on the website. UserAgentGtk code has also been cleaned
up, using NeverDestroyed instead of DEPRECATED_DEFINE_STATIC_LOCAL
and avoiding unneeded conversions to UTF-8.

  • platform/gtk/UserAgentGtk.cpp:

(WebCore::UserAgentQuirks::UserAgentQuirks): New helper private
class to handle user agent quirks.
(WebCore::UserAgentQuirks::add):
(WebCore::UserAgentQuirks::contains):
(WebCore::UserAgentQuirks::isEmpty):
(WebCore::platformForUAString): Bring back this method that was
removed to always pretend to be Macintosh.
(WebCore::platformVersionForUAString): Return a different platform
version depending on the actual platform.
(WebCore::versionForUAString): Return the WebKit version.
(WebCore::buildUserAgentString): Helper function to build the user
agent taking into account the UserAgentQuirks received.
(WebCore::standardUserAgentStatic): Standard user agent string
when no quirks are present.
(WebCore::standardUserAgent):
(WebCore::standardUserAgentForURL): New method that returns the
user agent string for the given URL.

  • platform/gtk/UserAgentGtk.h:

Source/WebKit2:

  • UIProcess/API/gtk/WebKitSettings.cpp:

(webkit_settings_class_init): Enable site specific quirks setting
by default.

  • WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:

(WebKit::WebFrameLoaderClient::userAgent): Pass the given URL to WebPage.

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::userAgent): Try to get the user agent for the
URL received falling back to the current one otherwise.

  • WebProcess/WebPage/WebPage.h:

(WebKit::WebPage::platformUserAgent): Added.

  • WebProcess/WebPage/efl/WebPageEfl.cpp:

(WebKit::WebPage::platformUserAgent): Return null String.

  • WebProcess/WebPage/gtk/WebPageGtk.cpp:

(WebKit::WebPage::platformUserAgent): Use WebCore::standardUserAgentForURL() when site specific quirks
setting is enabled.

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::platformUserAgent): Return null String.

  • WebProcess/WebPage/mac/WebPageMac.mm:

(WebKit::WebPage::platformUserAgent): Return null String.

Tools:
Add a unit test to check user agent quirks.

  • TestWebKitAPI/PlatformGTK.cmake:
  • TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp: Added.

(TestWebKitAPI::TEST):

  • TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp:

(testWebKitSettings): Site specific quirks setting is now enabled
by default.

Location:
trunk
Files:
1 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r169797 r169799  
     12014-06-11  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK] Use a different user agent string depending on the site
     4        https://bugs.webkit.org/show_bug.cgi?id=132681
     5
     6        Reviewed by Anders Carlsson.
     7
     8        We have changed the user agent string several times to try to fix
     9        broken websites that require specific things in the UA string to
     10        properly work. But everytime we change the UA string to fix a
     11        website we break others. We could use different UA string
     12        depending on the website. UserAgentGtk code has also been cleaned
     13        up, using NeverDestroyed instead of DEPRECATED_DEFINE_STATIC_LOCAL
     14        and avoiding unneeded conversions to UTF-8.
     15
     16        * platform/gtk/UserAgentGtk.cpp:
     17        (WebCore::UserAgentQuirks::UserAgentQuirks): New helper private
     18        class to handle user agent quirks.
     19        (WebCore::UserAgentQuirks::add):
     20        (WebCore::UserAgentQuirks::contains):
     21        (WebCore::UserAgentQuirks::isEmpty):
     22        (WebCore::platformForUAString): Bring back this method that was
     23        removed to always pretend to be Macintosh.
     24        (WebCore::platformVersionForUAString): Return a different platform
     25        version depending on the actual platform.
     26        (WebCore::versionForUAString): Return the WebKit version.
     27        (WebCore::buildUserAgentString): Helper function to build the user
     28        agent taking into account the UserAgentQuirks received.
     29        (WebCore::standardUserAgentStatic): Standard user agent string
     30        when no quirks are present.
     31        (WebCore::standardUserAgent):
     32        (WebCore::standardUserAgentForURL): New method that returns the
     33        user agent string for the given URL.
     34        * platform/gtk/UserAgentGtk.h:
     35
    1362014-06-11  Alex Christensen  <achristensen@webkit.org>
    237
  • trunk/Source/WebCore/platform/gtk/UserAgentGtk.cpp

    r166405 r169799  
    11/*
    2  * Copyright (C) 2012 Igalia S.L.
     2 * Copyright (C) 2012, 2014 Igalia S.L.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#include "UserAgentGtk.h"
    2828
    29 #include <glib.h>
     29#include "URL.h"
     30#include <wtf/NeverDestroyed.h>
     31#include <wtf/text/StringBuilder.h>
    3032
    3133#if OS(UNIX)
     
    3436
    3537namespace WebCore {
     38
     39class UserAgentQuirks {
     40public:
     41    enum UserAgentQuirk {
     42        NeedsSafariVersion6,
     43        NeedsMacintoshPlatform,
     44
     45        NumUserAgentQuirks
     46    };
     47
     48    UserAgentQuirks()
     49        : m_quirks(0)
     50    {
     51        COMPILE_ASSERT(sizeof(m_quirks) * 8 >= NumUserAgentQuirks, not_enough_room_for_quirks);
     52    }
     53
     54    void add(UserAgentQuirk quirk)
     55    {
     56        ASSERT(quirk >= 0);
     57        ASSERT_WITH_SECURITY_IMPLICATION(quirk < NumUserAgentQuirks);
     58
     59        m_quirks |= (1 << quirk);
     60    }
     61
     62    bool contains(UserAgentQuirk quirk) const
     63    {
     64        return m_quirks & (1 << quirk);
     65    }
     66
     67    bool isEmpty() const { return !m_quirks; }
     68
     69private:
     70    uint32_t m_quirks;
     71};
    3672
    3773static const char* cpuDescriptionForUAString()
     
    4884}
    4985
    50 static String platformVersionForUAString()
     86static const char* platformForUAString()
    5187{
    52     DEPRECATED_DEFINE_STATIC_LOCAL(String, uaOSVersion, (String()));
    53     if (!uaOSVersion.isEmpty())
    54         return uaOSVersion;
     88#if PLATFORM(X11)
     89    return "X11";
     90#elif OS(WINDOWS)
     91    return "";
     92#elif PLATFORM(MAC)
     93    return "Macintosh";
     94#elif defined(GDK_WINDOWING_DIRECTFB)
     95    return "DirectFB";
     96#else
     97    return "Unknown";
     98#endif
     99}
    55100
    56     // We will always claim to be Safari in Mac OS X, since Safari in Linux triggers the iOS path on
    57     // some websites.
    58     uaOSVersion = String::format("%s Mac OS X", cpuDescriptionForUAString());
     101static const String platformVersionForUAString()
     102{
     103#if OS(UNIX)
     104    struct utsname name;
     105    uname(&name);
     106    static NeverDestroyed<const String> uaOSVersion(String::format("%s %s", name.sysname, name.machine));
    59107    return uaOSVersion;
     108#else
     109    // We will always claim to be Safari in Mac OS X, since Safari in Linux triggers the iOS path on some websites.
     110    static NeverDestroyed<const String> uaOSVersion(String::format("%s Mac OS X", cpuDescriptionForUAString()));
     111    return uaOSVersion;
     112#endif
     113}
     114
     115static const String versionForUAString()
     116{
     117    static NeverDestroyed<const String> uaVersion(String::format("%i.%i", USER_AGENT_GTK_MAJOR_VERSION, USER_AGENT_GTK_MINOR_VERSION));
     118    return uaVersion;
     119}
     120
     121static String buildUserAgentString(const UserAgentQuirks& quirks)
     122{
     123    StringBuilder uaString;
     124    uaString.appendLiteral("Mozilla/5.0 ");
     125    uaString.append('(');
     126
     127    if (quirks.contains(UserAgentQuirks::NeedsMacintoshPlatform))
     128        uaString.appendLiteral("Macintosh");
     129    else
     130        uaString.append(platformForUAString());
     131
     132    uaString.appendLiteral("; ");
     133
     134    if (quirks.contains(UserAgentQuirks::NeedsMacintoshPlatform)) {
     135        uaString.append(cpuDescriptionForUAString());
     136        uaString.appendLiteral(" Mac OS X");
     137    } else
     138        uaString.append(platformVersionForUAString());
     139
     140    uaString.appendLiteral(") AppleWebKit/");
     141    uaString.append(versionForUAString());
     142    uaString.appendLiteral(" (KHTML, like Gecko) Safari/");
     143    uaString.append(versionForUAString());
     144
     145    if (quirks.contains(UserAgentQuirks::NeedsSafariVersion6))
     146        uaString.appendLiteral(" Version/6.0");
     147
     148    return uaString.toString();
     149}
     150
     151static const String standardUserAgentStatic()
     152{
     153    static NeverDestroyed<const String> uaStatic(buildUserAgentString(UserAgentQuirks()));
     154    return uaStatic;
    60155}
    61156
     
    70165    // wrong can cause sites to load the wrong JavaScript, CSS, or custom fonts. In some cases
    71166    // sites won't load resources at all.
    72     DEPRECATED_DEFINE_STATIC_LOCAL(const CString, uaVersion, (String::format("%i.%i", USER_AGENT_GTK_MAJOR_VERSION, USER_AGENT_GTK_MINOR_VERSION).utf8()));
    73     DEPRECATED_DEFINE_STATIC_LOCAL(const String, staticUA, (String::format("Mozilla/5.0 (Macintosh; %s) AppleWebKit/%s (KHTML, like Gecko) Safari/%s Version/6.0",
    74         platformVersionForUAString().utf8().data(), uaVersion.data(), uaVersion.data())));
    75 
    76167    if (applicationName.isEmpty())
    77         return staticUA;
     168        return standardUserAgentStatic();
    78169
    79170    String finalApplicationVersion = applicationVersion;
    80171    if (finalApplicationVersion.isEmpty())
    81         finalApplicationVersion = uaVersion.data();
     172        finalApplicationVersion = versionForUAString();
    82173
    83     return String::format("%s %s/%s", staticUA.utf8().data(), applicationName.utf8().data(), finalApplicationVersion.utf8().data());
     174    return standardUserAgentStatic() + applicationName + '/' + finalApplicationVersion;
     175}
     176
     177String standardUserAgentForURL(const URL& url)
     178{
     179    ASSERT(!url.isNull());
     180    UserAgentQuirks quirks;
     181    if (url.host().endsWith(".yahoo.com")) {
     182        // www.yahoo.com redirects to the mobile version when Linux is present in the UA,
     183        // use always Macintosh as platform. See https://bugs.webkit.org/show_bug.cgi?id=125444.
     184        quirks.add(UserAgentQuirks::NeedsMacintoshPlatform);
     185    } else if (url.host().endsWith(".globalforestwatch.org")) {
     186        // www.globalforestwatch.org fails to redirect when Safari Version 6 is not present in the UA.
     187        // See https://bugs.webkit.org/show_bug.cgi?id=129681.
     188        quirks.add(UserAgentQuirks::NeedsSafariVersion6);
     189    }
     190
     191    // The null string means we don't need a specific UA for the given URL.
     192    return quirks.isEmpty() ? String() : buildUserAgentString(quirks);
    84193}
    85194
  • trunk/Source/WebCore/platform/gtk/UserAgentGtk.h

    r165676 r169799  
    11/*
    2  * Copyright (C) 2012 Igalia S.L.
     2 * Copyright (C) 2012, 2014 Igalia S.L.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#define UserAgentGtk_h
    2828
    29 #include <wtf/text/CString.h>
    3029#include <wtf/text/WTFString.h>
    3130
    3231namespace WebCore {
     32class URL;
    3333
    34 String standardUserAgent(const String& applicationName = "", const String& applicationVersion = "");
     34String standardUserAgent(const String& applicationName = emptyString(), const String& applicationVersion = emptyString());
     35String standardUserAgentForURL(const URL&);
    3536
    3637}
  • trunk/Source/WebKit2/ChangeLog

    r169791 r169799  
     12014-06-11  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK] Use a different user agent string depending on the site
     4        https://bugs.webkit.org/show_bug.cgi?id=132681
     5
     6        Reviewed by Anders Carlsson.
     7
     8        * UIProcess/API/gtk/WebKitSettings.cpp:
     9        (webkit_settings_class_init): Enable site specific quirks setting
     10        by default.
     11        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
     12        (WebKit::WebFrameLoaderClient::userAgent): Pass the given URL to WebPage.
     13        * WebProcess/WebPage/WebPage.cpp:
     14        (WebKit::WebPage::userAgent): Try to get the user agent for the
     15        URL received falling back to the current one otherwise.
     16        * WebProcess/WebPage/WebPage.h:
     17        (WebKit::WebPage::platformUserAgent): Added.
     18        * WebProcess/WebPage/efl/WebPageEfl.cpp:
     19        (WebKit::WebPage::platformUserAgent): Return null String.
     20        * WebProcess/WebPage/gtk/WebPageGtk.cpp:
     21        (WebKit::WebPage::platformUserAgent): Use WebCore::standardUserAgentForURL() when site specific quirks
     22        setting is enabled.
     23        * WebProcess/WebPage/ios/WebPageIOS.mm:
     24        (WebKit::WebPage::platformUserAgent): Return null String.
     25        * WebProcess/WebPage/mac/WebPageMac.mm:
     26        (WebKit::WebPage::platformUserAgent): Return null String.
     27
    1282014-06-10  Benjamin Poulain  <benjamin@webkit.org>
    229
  • trunk/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp

    r168988 r169799  
    10571057     * special-case this and other cases to make some specific sites work.
    10581058     */
    1059     g_object_class_install_property(gObjectClass,
    1060                                     PROP_ENABLE_SITE_SPECIFIC_QUIRKS,
    1061                                     g_param_spec_boolean("enable-site-specific-quirks",
    1062                                                          _("Enable Site Specific Quirks"),
    1063                                                          _("Enables the site-specific compatibility workarounds"),
    1064                                                          FALSE,
    1065                                                          readWriteConstructParamFlags));
     1059    g_object_class_install_property(
     1060        gObjectClass,
     1061        PROP_ENABLE_SITE_SPECIFIC_QUIRKS,
     1062        g_param_spec_boolean(
     1063            "enable-site-specific-quirks",
     1064            _("Enable Site Specific Quirks"),
     1065            _("Enables the site-specific compatibility workarounds"),
     1066            TRUE,
     1067            readWriteConstructParamFlags));
    10661068
    10671069    /**
  • trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp

    r169603 r169799  
    11821182}
    11831183
    1184 String WebFrameLoaderClient::userAgent(const URL&)
     1184String WebFrameLoaderClient::userAgent(const URL& url)
    11851185{
    11861186    WebPage* webPage = m_frame->page();
     
    11881188        return String();
    11891189
    1190     return webPage->userAgent();
     1190    return webPage->userAgent(url);
    11911191}
    11921192
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp

    r169728 r169799  
    22852285}
    22862286
     2287String WebPage::userAgent(const URL& url) const
     2288{
     2289    String userAgent = platformUserAgent(url);
     2290    if (!userAgent.isEmpty())
     2291        return userAgent;
     2292
     2293    return m_userAgent;
     2294}
     2295
    22872296void WebPage::suspendActiveDOMObjectsAndAnimations()
    22882297{
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h

    r169696 r169799  
    129129class SubstituteData;
    130130class TextCheckingRequest;
     131class URL;
    131132class VisibleSelection;
    132133struct KeypressCommand;
     
    253254    void didFinishLoad(WebFrame*);
    254255    void show();
    255     String userAgent() const { return m_userAgent; }
     256    String userAgent(const WebCore::URL&) const;
     257    String platformUserAgent(const WebCore::URL&) const;
    256258    WebCore::IntRect windowResizerRect() const;
    257259    WebCore::KeyboardUIMode keyboardUIMode();
  • trunk/Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp

    r162756 r169799  
    221221}
    222222
     223String WebPage::platformUserAgent(const URL&) const
     224{
     225    return String();
     226}
     227
    223228} // namespace WebKit
  • trunk/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp

    r162754 r169799  
    4343#include <WebCore/PlatformKeyboardEvent.h>
    4444#include <WebCore/Settings.h>
     45#include <WebCore/UserAgentGtk.h>
    4546#include <wtf/gobject/GUniquePtr.h>
    4647
     
    169170#endif
    170171
     172String WebPage::platformUserAgent(const URL& url) const
     173{
     174    if (url.isNull() || !m_page->settings().needsSiteSpecificQuirks())
     175        return String();
     176
     177    return WebCore::standardUserAgentForURL(url);
     178}
     179
    171180} // namespace WebKit
  • trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm

    r169669 r169799  
    24072407}
    24082408
     2409String WebPage::platformUserAgent(const URL&) const
     2410{
     2411    return String();
     2412}
     2413
    24092414} // namespace WebKit
    24102415
  • trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm

    r167974 r169799  
    762762{
    763763    NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
    764     [request setValue:(NSString*)userAgent() forHTTPHeaderField:@"User-Agent"];
     764    [request setValue:(NSString*)userAgent(url) forHTTPHeaderField:@"User-Agent"];
    765765    NSCachedURLResponse *cachedResponse;
    766766    if (CFURLStorageSessionRef storageSession = corePage()->mainFrame().loader().networkingContext()->storageSession().platformSession())
     
    776776{
    777777    RetainPtr<NSMutableURLRequest> request = adoptNS([[NSMutableURLRequest alloc] initWithURL:url]);
    778     [request setValue:(NSString *)webPage->userAgent() forHTTPHeaderField:@"User-Agent"];
     778    [request setValue:(NSString *)webPage->userAgent(url) forHTTPHeaderField:@"User-Agent"];
    779779
    780780    if (CFURLStorageSessionRef storageSession = webPage->corePage()->mainFrame().loader().networkingContext()->storageSession().platformSession())
     
    10441044#endif
    10451045
     1046String WebPage::platformUserAgent(const URL&) const
     1047{
     1048    return String();
     1049}
     1050
    10461051} // namespace WebKit
    10471052
  • trunk/Tools/ChangeLog

    r169794 r169799  
     12014-06-11  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK] Use a different user agent string depending on the site
     4        https://bugs.webkit.org/show_bug.cgi?id=132681
     5
     6        Reviewed by Anders Carlsson.
     7
     8        Add a unit test to check user agent quirks.
     9
     10        * TestWebKitAPI/PlatformGTK.cmake:
     11        * TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp: Added.
     12        (TestWebKitAPI::TEST):
     13        * TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp:
     14        (testWebKitSettings): Site specific quirks setting is now enabled
     15        by default.
     16
    1172014-06-10  Gyuyoung Kim  <gyuyoung.kim@samsung.com>
    218
  • trunk/Tools/TestWebKitAPI/PlatformGTK.cmake

    r168834 r169799  
    120120    ${WEBCORE_DIR}/platform/gtk/GtkInputMethodFilter.cpp
    121121    ${TESTWEBKITAPI_DIR}/Tests/WebCore/gtk/InputMethodFilter.cpp
     122    ${TESTWEBKITAPI_DIR}/Tests/WebCore/gtk/UserAgentQuirks.cpp
    122123)
    123124
  • trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp

    r161366 r169799  
    234234    g_assert(webkit_settings_get_draw_compositing_indicators(settings));
    235235
    236     // By default, site specific quirks are disabled.
     236    // By default, site specific quirks are enabled.
     237    g_assert(webkit_settings_get_enable_site_specific_quirks(settings));
     238    webkit_settings_set_enable_site_specific_quirks(settings, FALSE);
    237239    g_assert(!webkit_settings_get_enable_site_specific_quirks(settings));
    238     webkit_settings_set_enable_site_specific_quirks(settings, TRUE);
    239     g_assert(webkit_settings_get_enable_site_specific_quirks(settings));
    240240
    241241    // By default, page cache is enabled.
Note: See TracChangeset for help on using the changeset viewer.