瀏覽代碼

Browser+LibWeb: Add support for spoofing the browser user agent

This is helpful when testing certain sites like twitter.com which
display differently based on the user agent.
Idan Horowitz 4 年之前
父節點
當前提交
bc9cd55da4

+ 47 - 0
Userland/Applications/Browser/Tab.cpp

@@ -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>
@@ -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());
 

+ 4 - 0
Userland/Applications/Browser/Tab.h

@@ -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>
@@ -115,6 +116,9 @@ private:
     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;
 

+ 1 - 1
Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp

@@ -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)
 {
 }
 

+ 3 - 0
Userland/Libraries/LibWeb/Loader/ResourceLoader.h

@@ -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:
@@ -55,6 +57,7 @@ public:
     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();
 

+ 4 - 0
Userland/Services/WebContent/ClientConnection.cpp

@@ -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&)