Proxy for only one browser with CefSharp Offscreen

2019-08-27 16:53发布

I am trying to set a proxy for a ChromiumWebBrowser() without changing the settings of other browsers.

My code looks like this :

CEF initialization

Here I will initialize CefSharp and call the method that will test to set the proxy

public CFTryOut()
    {
        var settings = new CefSettings()
        {
            CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache"),
        };

        CefSharpSettings.ShutdownOnExit = true;

        Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);

        ProxyTest();

    }

ProxyTest

Here I want to create two ChromiumWebBrowser() and set a proxy to only one of them

async Task ProxyTest()
    {
        ChromiumWebBrowser firstbrowser = new ChromiumWebBrowser();
        ChromiumWebBrowser secondbrowser = new ChromiumWebBrowser();

        waitini:
        if (!firstbrowser.IsBrowserInitialized && !secondbrowser.IsBrowserInitialized)
        {
            Thread.Sleep(100);
            goto waitini;
        }

        firstbrowser.LoadingStateChanged += FirstBrowserLoadingStateChanged;
        secondbrowser.LoadingStateChanged += SecondBrowserLoadingStateChanged;

        OpenSync("http://icanhazip.com/", firstbrowser);
        string x = await firstbrowser.GetBrowser().MainFrame.GetSourceAsync();

        //Set the Proxy
        await Cef.UIThreadTaskFactory.StartNew(delegate
        {
            var rc = firstbrowser.GetBrowser().GetHost().RequestContext;
            var v = new Dictionary<string, object>();
            v["mode"] = "fixed_servers";
            v["server"] = "http://45.77.248.104:8888";
            string error;
            bool success = rc.SetPreference("proxy", v, out error);
        });

        OpenSync("http://icanhazip.com/", firstbrowser);
        string y = await firstbrowser.GetBrowser().MainFrame.GetSourceAsync();

        OpenSync("http://icanhazip.com/", secondbrowser);
        string z = await secondbrowser.GetBrowser().MainFrame.GetSourceAsync();


    }

Here, the First/SecondBrowserLoadingStateChangedallow me to flag when the page loading is finished in order for OpenSync to wait for page loading to end before returning :

public void OpenSync(string url, ChromiumWebBrowser browser)
    {
        IsLoading = true;
        browser.Load(url);
        SpinWait.SpinUntil(() => !IsLoading);
    }

What I expect

x = my ip - xx.xx.xx.xx

y = proxy's ip - 45.77.248.104

z = my ip - xx.xx.xx.xx

What I got

x = my ip - xx.xx.xx.xx

y = proxy's ip - 45.77.248.104

z = proxy's ip - 45.77.248.104

The thing is I did not set any proxy on the secondbrowser yet the request goes through the proxy. I guess that's because they share the same host.

So

1) how can I specify a dedicated proxy for each ChromiumWebBrowser ?

or

2) how can I specify a different host for each new ChromiumWebBrowser ?

3条回答
祖国的老花朵
2楼-- · 2019-08-27 17:27

/Perfectionism Mode On

using System.Threading.Tasks;
using System.Collections.Generic;
using CefSharp;

namespace Extensions
{
    public static class WebBrowserExtensions
    {
        public static Task SetProxy(this IWebBrowser webBrowser, string address)
        {
            return Cef.UIThreadTaskFactory.StartNew(() =>
            {
                var context = webBrowser.GetBrowser().GetHost().RequestContext;

                context.SetPreference("proxy", new Dictionary<string, object>
                {
                    ["mode"] = "fixed_servers",
                    ["server"] = address
                }, out _);
            });
        }
    }
}

Usage:

await browser.SetProxy("111.111.111.111:1111")  
查看更多
太酷不给撩
3楼-- · 2019-08-27 17:36

That's right, but when using ("asyn") remember

   async private Task SetProxy(ChromiumWebBrowser cwb, string Address)
    {
        await Cef.UIThreadTaskFactory.StartNew(delegate
        {
            var rc = cwb.GetBrowser().GetHost().RequestContext;
            var v = new Dictionary<string, object>();
            v["mode"] = "fixed_servers";
            v["server"] = Address;
            string error;
            bool success = rc.SetPreference("proxy", v, out error);
        });
    }

Sample use:

   public async void dd1()
    {
      await SetProxy(firstbrowser, "123.123.123.123:1234")  
    }
查看更多
SAY GOODBYE
4楼-- · 2019-08-27 17:41

Thanks to @amaitland it was pretty easy actually.

My problem was that I was trying to set the RequestContext after the browser initialization, while it's read only.

But it can be passed as a parameter in the constructor :

        var rc1 = new RequestContext();
        ChromiumWebBrowser firstbrowser = new ChromiumWebBrowser("", null, rc1);
        var rc2 = new RequestContext();
        ChromiumWebBrowser secondbrowser = new ChromiumWebBrowser("", null, rc2);

All credit to Amaitland

For a more reusable way, the process to set the proxy can be deported like this :

    async private Task SetProxy(ChromiumWebBrowser cwb, string Address)
    {
        await Cef.UIThreadTaskFactory.StartNew(delegate
        {
            var rc = cwb.GetBrowser().GetHost().RequestContext;
            var v = new Dictionary<string, object>();
            v["mode"] = "fixed_servers";
            v["server"] = Address;
            string error;
            bool success = rc.SetPreference("proxy", v, out error);
        });
    }

Then I can call :

SetProxy(firstbrowser, "123.123.123.123:1234")
查看更多
登录 后发表回答