Search code examples
c#ipcuser-agentcefsharp

CEFSharp Changing User Agent through a custom handler


UNABLE TO DELETE. Wrong approach to the problem. Use the example the code maintainer gives

Still really new to working with the cefsharp project.

I am trying to tie the User Agent to an instance instead of globally.

Currently I am using the following in my Program.cs

var settings = new CefSettings();
settings.CefCommandLineArgs.Add("user-agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1");

While this works, it sets the User Agent globally. I am using 2 forms as I want one to report as mobile and one to report as desktop. Doing so, I am confused on how I would do this. Using the above, it is setting the UserAgent globally. I hate having to comment and uncomment the line setting it.

I tried the following

using CefSharp;
using CefSharp.Handler;

public class CustomRequestHandler : CefSharp.Handler.RequestHandler
{
    protected override bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
    {
        // Intercept only the specific URL
        if (request.Url == "https://www.whatismybrowser.com/detect/what-is-my-user-agent")
        {
            request.SetHeaderByName("user-agent", "MyBrowser CefSharp Browser", true);
        }

        // Always return false to continue the navigation
        return false;
    }
}

I think I adapted it right but now run into the fact IRequest is read-only. Tried several other adaptions always running into read-only problem.

Edit: Ok I think I am onto something here.

using CefSharp;
using CefSharp.Handler;
using System;
using System.Collections.Specialized;

public class CustomRequestHandler : RequestHandler
{
    protected override bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
    {
        if (request.Url == "https://www.whatismybrowser.com/detect/what-is-my-user-agent")
        {
            try
            {
                // Log the interception of the URL
                Console.WriteLine("Intercepted URL: " + request.Url);

                // Create a dictionary to hold the modified headers
                var modifiedHeaders = new NameValueCollection(request.Headers);

                // Modify the user agent
                modifiedHeaders["user-agent"] = "MyBrowser CefSharp Browser";

                // Create a new request with the modified headers
                var modifiedRequest = frame.CreateRequest();
                modifiedRequest.Url = request.Url;
                modifiedRequest.Method = request.Method;
                modifiedRequest.Headers = modifiedHeaders;

                // Copy post data if it exists
                if (request.PostData != null)
                {
                    modifiedRequest.PostData = request.PostData;
                }

                // Load the modified request using the browser
                frame.LoadRequest(modifiedRequest);

                // Log successful loading of the modified request
                Console.WriteLine("Modified request loaded successfully.");

                return true; // Cancel the original request
            }
            catch (Exception ex)
            {
                // Log any exceptions for debugging purposes
                Console.WriteLine("Exception occurred: " + ex.Message);
            }
        }

        return false; // Continue with the original request
    }
}

With this code, it actually will not load the test url but will load other urls. So it is actually handling for the test url. It just wont actually load the page. And its only intercepting the mobile browser as intended. Intercepted URL: https://www.whatismybrowser.com/detect/what-is-my-user-agent Modified request loaded successfully.

With that latest code that seems to be intercepting the url and using my handler, I had to do some logging to get this

OnBeforeBrowse URL: https://www.whatismybrowser.com/detect/what-is-my-user-agent
Intercepted URL: https://www.whatismybrowser.com/detect/what-is-my-user-agent
Modified request loaded successfully.
Load Error: Aborted, ERR_ABORTED, https://www.whatismybrowser.com/detect/what-is-my-user-agent
Loading State Changed: False
[14956:7864:0710/043123.774:ERROR:bad_message.cc(29)] Terminating renderer for bad IPC message, reason 213
GetResourceRequestHandler: https://csm.us5.us.criteo.net/iev?entry=c~Gum.ChromeSyncframe.CookieRead.uid~1&entry=c~Gum.ChromeSyncframe.FragmentData.onetag.Bundle.Origin.undefined~1&entry=c~Gum.ChromeSyncframe.SidReadSuccess~1&entry=h~Gum.ChromeSyncframe.SidReadSuccessDuration~328
Render process terminated: ProcessCrashed

[8352:10124:0710/040922.537:ERROR:bad_message.cc(29)] Terminating renderer for bad IPC message, reason 213
[8352:10124:0710/040922.538:VERBOSE1:browser_info_manager.cc(531)] frame 6-BB0DCBA5339448D1441249D75553904F, pdf_process=0, browser_process_guest=0, print_preview_dialog=0, main=1
[8352:10124:0710/040922.542:VERBOSE1:frame_host_impl.cc(515)] frame A-F5DF7D801E84FDC36BCC535A08C6FD9B (sub) detached (reason=RENDER_FRAME_DELETED, is_connected=1)
[8352:10124:0710/040922.543:VERBOSE1:frame_host_impl.cc(515)] frame 9-870ABD8F28E33A0A82F7D99F90C14289 (sub) detached (reason=RENDER_FRAME_DELETED, is_connected=1)
[18420:11048:0710/040922.543:VERBOSE1:network_delegate.cc(35)] NetworkDelegate::NotifyBeforeURLRequest: https://csm.us5.us.criteo.net/iev?entry=c~Gum.ChromeSyncframe.CookieRead.uid~1&entry=c~Gum.ChromeSyncframe.FragmentData.onetag.Bundle.Origin.undefined~1&entry=c~Gum.ChromeSyncframe.SidReadSuccess~1&entry=h~Gum.ChromeSyncframe.SidReadSuccessDuration~676
[8352:10124:0710/040922.544:VERBOSE1:frame_host_impl.cc(515)] frame 8-A5EA056889DFBED6602D2F909E9971D4 (sub) detached (reason=RENDER_FRAME_DELETED, is_connected=1)

With disable-site-isolation-trials commandline the page still doesn't load and the browser is in a state of constantly refreshing the page in an endless loop.


Solution

  • Ok I dont know why I had so many issues. Maybe its just that I am learning yet and dont really know what I am doing. MY BAD. None of the things I was originally trying was WRONG.

    This solution which amaitland hinted at, worked.

    // Copyright © 2020 The CefSharp Authors. All rights reserved.
    //
    // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
    
    namespace CefSharp.MinimalExample.WinForms
    {
        public class LifeSpanHandler : ILifeSpanHandler
        {
            bool ILifeSpanHandler.DoClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
            {
                return false;
            }
    
            void ILifeSpanHandler.OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser browser)
            {
                using (var client = chromiumWebBrowser.GetDevToolsClient())
                {
                    _ = client.Network.SetUserAgentOverrideAsync("Mozilla/5.0 (iPhone; CPU iPhone OS 17_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1");
                }
            }
    
            void ILifeSpanHandler.OnBeforeClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
            {
    
            }
    
            bool ILifeSpanHandler.OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
            {
                newBrowser = null;
    
                return false;
            }
        }
    }
    
                browser.LifeSpanHandler = new LifeSpanHandler();
    

    The above code is the EXACT CODE FROM MY FORM/CODE but is the exact same the code maintainer has in their link.

    Personally I feel its better to use the link that the code maintainer is better than me copy & pasting here.