Skip to content

Commit

Permalink
Browser+LibWeb: Add support for spoofing the browser user agent
Browse files Browse the repository at this point in the history
This is helpful when testing certain sites like twitter.com which
display differently based on the user agent.
  • Loading branch information
IdanHo authored and awesomekling committed Apr 14, 2021
1 parent aab99d5 commit bc9cd55
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 1 deletion.
47 changes: 47 additions & 0 deletions Userland/Applications/Browser/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Button.h>
#include <LibGUI/Clipboard.h>
#include <LibGUI/InputBox.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Menubar.h>
#include <LibGUI/Statusbar.h>
Expand Down Expand Up @@ -476,6 +477,52 @@ Tab::Tab(Type type)
}
}));

m_user_agent_spoof_actions.set_exclusive(true);
auto& spoof_user_agent_menu = debug_menu.add_submenu("Spoof User Agent");
m_disable_user_agent_spoofing = GUI::Action::create_checkable("Disabled", [&](auto&) {
if (m_type == Type::InProcessWebView) {
Web::ResourceLoader::the().set_user_agent(Web::default_user_agent);
} else {
m_web_content_view->debug_request("spoof-user-agent", Web::default_user_agent);
}
});
m_disable_user_agent_spoofing->set_checked(true);
spoof_user_agent_menu.add_action(*m_disable_user_agent_spoofing);
m_user_agent_spoof_actions.add_action(*m_disable_user_agent_spoofing);

auto add_user_agent = [&](auto& name, auto& user_agent) {
auto action = GUI::Action::create_checkable(name, [&](auto&) {
if (m_type == Type::InProcessWebView) {
Web::ResourceLoader::the().set_user_agent(user_agent);
} else {
m_web_content_view->debug_request("spoof-user-agent", user_agent);
}
});
spoof_user_agent_menu.add_action(action);
m_user_agent_spoof_actions.add_action(action);
};
add_user_agent("Chrome Linux Desktop", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36");
add_user_agent("Firefox Linux Desktop", "Mozilla/5.0 (X11; Linux i686; rv:87.0) Gecko/20100101 Firefox/87.0");
add_user_agent("Safari macOS Desktop", "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15");
add_user_agent("Chrome Android Mobile", "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.66 Mobile Safari/537.36");
add_user_agent("Firefox Android Mobile", "Mozilla/5.0 (Android 11; Mobile; rv:68.0) Gecko/68.0 Firefox/86.0");
add_user_agent("Safari iOS Mobile", "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1");

auto custom_user_agent = GUI::Action::create_checkable("Custom", [&](auto&) {
String user_agent;
if (GUI::InputBox::show(window(), user_agent, "Enter User Agent:", "Custom User Agent") != GUI::InputBox::ExecOK || user_agent.is_empty() || user_agent.is_null()) {
m_disable_user_agent_spoofing->activate();
return;
}
if (m_type == Type::InProcessWebView) {
Web::ResourceLoader::the().set_user_agent(user_agent);
} else {
m_web_content_view->debug_request("spoof-user-agent", user_agent);
}
});
spoof_user_agent_menu.add_action(custom_user_agent);
m_user_agent_spoof_actions.add_action(custom_user_agent);

auto& help_menu = m_menubar->add_menu("&Help");
help_menu.add_action(WindowActions::the().about_action());

Expand Down
4 changes: 4 additions & 0 deletions Userland/Applications/Browser/Tab.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "History.h"
#include <AK/URL.h>
#include <LibGUI/ActionGroup.h>
#include <LibGUI/Widget.h>
#include <LibGfx/ShareableBitmap.h>
#include <LibHTTP/HttpJob.h>
Expand Down Expand Up @@ -115,6 +116,9 @@ class Tab final : public GUI::Widget {
Gfx::ShareableBitmap m_image_context_menu_bitmap;
URL m_image_context_menu_url;

GUI::ActionGroup m_user_agent_spoof_actions;
RefPtr<GUI::Action> m_disable_user_agent_spoofing;

RefPtr<GUI::Menu> m_tab_context_menu;
RefPtr<GUI::Menu> m_page_context_menu;

Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ ResourceLoader& ResourceLoader::the()

ResourceLoader::ResourceLoader()
: m_protocol_client(Protocol::Client::construct())
, m_user_agent("Mozilla/4.0 (SerenityOS; x86) LibWeb+LibJS (Not KHTML, nor Gecko) LibWeb")
, m_user_agent(default_user_agent)
{
}

Expand Down
3 changes: 3 additions & 0 deletions Userland/Libraries/LibWeb/Loader/ResourceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class Client;

namespace Web {

constexpr auto default_user_agent = "Mozilla/4.0 (SerenityOS; x86) LibWeb+LibJS (Not KHTML, nor Gecko) LibWeb";

class ResourceLoader : public Core::Object {
C_OBJECT(ResourceLoader)
public:
Expand All @@ -55,6 +57,7 @@ class ResourceLoader : public Core::Object {
Protocol::Client& protocol_client() { return *m_protocol_client; }

const String& user_agent() const { return m_user_agent; }
void set_user_agent(const String& user_agent) { m_user_agent = user_agent; }

void clear_cache();

Expand Down
4 changes: 4 additions & 0 deletions Userland/Services/WebContent/ClientConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ void ClientConnection::handle(const Messages::WebContentServer::DebugRequest& me
if (message.request() == "clear-cache") {
Web::ResourceLoader::the().clear_cache();
}

if (message.request() == "spoof-user-agent") {
Web::ResourceLoader::the().set_user_agent(message.argument());
}
}

void ClientConnection::handle(const Messages::WebContentServer::GetSource&)
Expand Down

0 comments on commit bc9cd55

Please sign in to comment.