Skip to content

Commit

Permalink
Merge r169799 - [GTK] Use a different user agent string depending on …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
carlosgcampos committed Jul 1, 2014
1 parent 211a5a9 commit d890643
Show file tree
Hide file tree
Showing 15 changed files with 303 additions and 71 deletions.
35 changes: 35 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,38 @@
2014-06-11 Carlos Garcia Campos <cgarcia@igalia.com>

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

Reviewed by Anders Carlsson.

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:

2014-06-13 Sergio Villar Senin <svillar@igalia.com>

[Gtk] [Stable] Fix the "Safari" part of the UA
Expand Down
135 changes: 119 additions & 16 deletions Source/WebCore/platform/gtk/UserAgentGtk.cpp
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2012 Igalia S.L.
* Copyright (C) 2012, 2014 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand All @@ -26,14 +26,49 @@
#include "config.h"
#include "UserAgentGtk.h"

#include <glib.h>
#include "URL.h"
#include <wtf/NeverDestroyed.h>
#include <wtf/text/StringBuilder.h>

#if OS(UNIX)
#include <sys/utsname.h>
#endif

namespace WebCore {

class UserAgentQuirks {
public:
enum UserAgentQuirk {
NeedsMacintoshPlatform,

NumUserAgentQuirks
};

UserAgentQuirks()
: m_quirks(0)
{
COMPILE_ASSERT(sizeof(m_quirks) * 8 >= NumUserAgentQuirks, not_enough_room_for_quirks);
}

void add(UserAgentQuirk quirk)
{
ASSERT(quirk >= 0);
ASSERT_WITH_SECURITY_IMPLICATION(quirk < NumUserAgentQuirks);

m_quirks |= (1 << quirk);
}

bool contains(UserAgentQuirk quirk) const
{
return m_quirks & (1 << quirk);
}

bool isEmpty() const { return !m_quirks; }

private:
uint32_t m_quirks;
};

static const char* cpuDescriptionForUAString()
{
#if CPU(PPC) || CPU(PPC64)
Expand All @@ -47,16 +82,74 @@ static const char* cpuDescriptionForUAString()
#endif
}

static String platformVersionForUAString()
static const char* platformForUAString()
{
DEFINE_STATIC_LOCAL(String, uaOSVersion, (String()));
if (!uaOSVersion.isEmpty())
return uaOSVersion;
#if PLATFORM(X11)
return "X11";
#elif OS(WINDOWS)
return "";
#elif PLATFORM(MAC)
return "Macintosh";
#elif defined(GDK_WINDOWING_DIRECTFB)
return "DirectFB";
#else
return "Unknown";
#endif
}

// We will always claim to be Safari in Mac OS X, since Safari in Linux triggers the iOS path on
// some websites.
uaOSVersion = String::format("%s Mac OS X", cpuDescriptionForUAString());
static const String platformVersionForUAString()
{
#if OS(UNIX)
struct utsname name;
uname(&name);
static NeverDestroyed<const String> uaOSVersion(String::format("%s %s", name.sysname, name.machine));
return uaOSVersion;
#else
// We will always claim to be Safari in Mac OS X, since Safari in Linux triggers the iOS path on some websites.
static NeverDestroyed<const String> uaOSVersion(String::format("%s Mac OS X", cpuDescriptionForUAString()));
return uaOSVersion;
#endif
}

static const String versionForUAString()
{
static NeverDestroyed<const String> uaVersion(String::format("%i.%i", USER_AGENT_GTK_MAJOR_VERSION, USER_AGENT_GTK_MINOR_VERSION));
return uaVersion;
}

static String buildUserAgentString(const UserAgentQuirks& quirks)
{
StringBuilder uaString;
uaString.appendLiteral("Mozilla/5.0 ");
uaString.append('(');

if (quirks.contains(UserAgentQuirks::NeedsMacintoshPlatform))
uaString.appendLiteral("Macintosh");
else
uaString.append(platformForUAString());

uaString.appendLiteral("; ");

if (quirks.contains(UserAgentQuirks::NeedsMacintoshPlatform)) {
uaString.append(cpuDescriptionForUAString());
uaString.appendLiteral(" Mac OS X");
} else
uaString.append(platformVersionForUAString());

uaString.appendLiteral(") AppleWebKit/");
uaString.append(versionForUAString());
// Version/X is mandatory *before* Safari/X to be a valid Safari UA. See
// https://bugs.webkit.org/show_bug.cgi?id=133403 for details.
uaString.appendLiteral(" (KHTML, like Gecko) Version/8.0 Safari/");
uaString.append(versionForUAString());

return uaString.toString();
}

static const String standardUserAgentStatic()
{
static NeverDestroyed<const String> uaStatic(buildUserAgentString(UserAgentQuirks()));
return uaStatic;
}

String standardUserAgent(const String& applicationName, const String& applicationVersion)
Expand All @@ -69,18 +162,28 @@ String standardUserAgent(const String& applicationName, const String& applicatio
// browsers that are "Safari" but not running on OS X are the Safari iOS browse. Getting this
// wrong can cause sites to load the wrong JavaScript, CSS, or custom fonts. In some cases
// sites won't load resources at all.
DEFINE_STATIC_LOCAL(const CString, uaVersion, (String::format("%i.%i", USER_AGENT_GTK_MAJOR_VERSION, USER_AGENT_GTK_MINOR_VERSION).utf8()));
DEFINE_STATIC_LOCAL(const String, staticUA, (String::format("Mozilla/5.0 (Macintosh; %s) AppleWebKit/%s (KHTML, like Gecko) Version/8.0 Safari/%s",
platformVersionForUAString().utf8().data(), uaVersion.data(), uaVersion.data())));

if (applicationName.isEmpty())
return staticUA;
return standardUserAgentStatic();

String finalApplicationVersion = applicationVersion;
if (finalApplicationVersion.isEmpty())
finalApplicationVersion = uaVersion.data();
finalApplicationVersion = versionForUAString();

return standardUserAgentStatic() + ' ' + applicationName + '/' + finalApplicationVersion;
}

String standardUserAgentForURL(const URL& url)
{
ASSERT(!url.isNull());
UserAgentQuirks quirks;
if (url.host().endsWith(".yahoo.com")) {
// www.yahoo.com redirects to the mobile version when Linux is present in the UA,
// use always Macintosh as platform. See https://bugs.webkit.org/show_bug.cgi?id=125444.
quirks.add(UserAgentQuirks::NeedsMacintoshPlatform);
}

return String::format("%s %s/%s", staticUA.utf8().data(), applicationName.utf8().data(), finalApplicationVersion.utf8().data());
// The null string means we don't need a specific UA for the given URL.
return quirks.isEmpty() ? String() : buildUserAgentString(quirks);
}

} // namespace WebCore
Expand Down
7 changes: 4 additions & 3 deletions Source/WebCore/platform/gtk/UserAgentGtk.h
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2012 Igalia S.L.
* Copyright (C) 2012, 2014 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand All @@ -26,12 +26,13 @@
#ifndef UserAgentGtk_h
#define UserAgentGtk_h

#include <wtf/text/CString.h>
#include <wtf/text/WTFString.h>

namespace WebCore {
class URL;

String standardUserAgent(const String& applicationName = "", const String& applicationVersion = "");
String standardUserAgent(const String& applicationName = emptyString(), const String& applicationVersion = emptyString());
String standardUserAgentForURL(const URL&);

}

Expand Down
27 changes: 27 additions & 0 deletions Source/WebKit2/ChangeLog
@@ -1,3 +1,30 @@
2014-06-11 Carlos Garcia Campos <cgarcia@igalia.com>

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

Reviewed by Anders Carlsson.

* 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.

2014-05-26 Carlos Garcia Campos <cgarcia@igalia.com>

[GTK] WebProcess leaked when closing pages with network process enabled
Expand Down
16 changes: 9 additions & 7 deletions Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp
Expand Up @@ -1064,13 +1064,15 @@ static void webkit_settings_class_init(WebKitSettingsClass* klass)
* workarounds. By turning on site-specific quirks, WebKit will
* special-case this and other cases to make some specific sites work.
*/
g_object_class_install_property(gObjectClass,
PROP_ENABLE_SITE_SPECIFIC_QUIRKS,
g_param_spec_boolean("enable-site-specific-quirks",
_("Enable Site Specific Quirks"),
_("Enables the site-specific compatibility workarounds"),
FALSE,
readWriteConstructParamFlags));
g_object_class_install_property(
gObjectClass,
PROP_ENABLE_SITE_SPECIFIC_QUIRKS,
g_param_spec_boolean(
"enable-site-specific-quirks",
_("Enable Site Specific Quirks"),
_("Enables the site-specific compatibility workarounds"),
TRUE,
readWriteConstructParamFlags));

/**
* WebKitSettings:enable-page-cache:
Expand Down
Expand Up @@ -1146,13 +1146,13 @@ void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const URL&
title.string(), url.string(), m_frame->frameID()), 0);
}

String WebFrameLoaderClient::userAgent(const URL&)
String WebFrameLoaderClient::userAgent(const URL& url)
{
WebPage* webPage = m_frame->page();
if (!webPage)
return String();

return webPage->userAgent();
return webPage->userAgent(url);
}

void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame*)
Expand Down
9 changes: 9 additions & 0 deletions Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Expand Up @@ -2169,6 +2169,15 @@ void WebPage::setUserAgent(const String& userAgent)
m_userAgent = userAgent;
}

String WebPage::userAgent(const URL& url) const
{
String userAgent = platformUserAgent(url);
if (!userAgent.isEmpty())
return userAgent;

return m_userAgent;
}

void WebPage::suspendActiveDOMObjectsAndAnimations()
{
m_page->suspendActiveDOMObjectsAndAnimations();
Expand Down
4 changes: 3 additions & 1 deletion Source/WebKit2/WebProcess/WebPage/WebPage.h
Expand Up @@ -124,6 +124,7 @@ namespace WebCore {
class SharedBuffer;
class SubstituteData;
class TextCheckingRequest;
class URL;
class VisibleSelection;
struct KeypressCommand;
struct TextCheckingResult;
Expand Down Expand Up @@ -227,7 +228,8 @@ class WebPage : public API::ObjectImpl<API::Object::Type::BundlePage>, public IP
void didCommitLoad(WebFrame*);
void didFinishLoad(WebFrame*);
void show();
String userAgent() const { return m_userAgent; }
String userAgent(const WebCore::URL&) const;
String platformUserAgent(const WebCore::URL&) const;
WebCore::IntRect windowResizerRect() const;
WebCore::KeyboardUIMode keyboardUIMode();

Expand Down
5 changes: 5 additions & 0 deletions Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp
Expand Up @@ -220,4 +220,9 @@ void WebPage::cancelComposition()
frame.editor().cancelComposition();
}

String WebPage::platformUserAgent(const URL&) const
{
return String();
}

} // namespace WebKit
9 changes: 9 additions & 0 deletions Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp
Expand Up @@ -42,6 +42,7 @@
#include <WebCore/PasteboardHelper.h>
#include <WebCore/PlatformKeyboardEvent.h>
#include <WebCore/Settings.h>
#include <WebCore/UserAgentGtk.h>
#include <wtf/gobject/GUniquePtr.h>

using namespace WebCore;
Expand Down Expand Up @@ -168,4 +169,12 @@ void WebPage::setAcceleratedCompositingWindowId(int64_t nativeWindowHandle)
}
#endif

String WebPage::platformUserAgent(const URL& url) const
{
if (url.isNull() || !m_page->settings().needsSiteSpecificQuirks())
return String();

return WebCore::standardUserAgentForURL(url);
}

} // namespace WebKit
5 changes: 5 additions & 0 deletions Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm
Expand Up @@ -877,4 +877,9 @@ static void computeAutocorrectionContext(Frame& frame, String& contextBefore, St
m_page->setPageScaleFactor(newScale, m_page->mainFrame().view()->scrollPosition());
}

String WebPage::platformUserAgent(const URL&) const
{
return String();
}

} // namespace WebKit

0 comments on commit d890643

Please sign in to comment.