Skip to content

Commit f910011

Browse files
committed
Core - Add IRequestContext.SetProxyAsync
Can be called on any Thread to change the proxy at runtime
1 parent 4730041 commit f910011

File tree

4 files changed

+168
-1
lines changed

4 files changed

+168
-1
lines changed

CefSharp.Test/OffScreen/OffScreenBrowserBasicFacts.cs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,5 +432,89 @@ public async Task CanLoadHttpWebsiteUsingProxy()
432432
output.WriteLine("Url {0}", mainFrame.Url);
433433
}
434434
}
435+
436+
[SkipIfRunOnAppVeyorFact]
437+
public async Task CanLoadHttpWebsiteUsingSetProxyAsync()
438+
{
439+
fixture.StartProxyServerIfRequired();
440+
441+
var tcs = new TaskCompletionSource<bool>();
442+
443+
var requestContext = RequestContext
444+
.Configure()
445+
.OnInitialize((ctx) =>
446+
{
447+
tcs.SetResult(true);
448+
})
449+
.Create();
450+
451+
//Wait for our RequestContext to have initialized.
452+
await tcs.Task;
453+
454+
var setProxyResponse = await requestContext.SetProxyAsync("127.0.0.1", 8080);
455+
456+
Assert.True(setProxyResponse.Success);
457+
458+
using (var browser = new ChromiumWebBrowser("http://cefsharp.github.io/", requestContext: requestContext))
459+
{
460+
await browser.LoadPageAsync();
461+
462+
var mainFrame = browser.GetMainFrame();
463+
Assert.True(mainFrame.IsValid);
464+
Assert.Contains("cefsharp.github.io", mainFrame.Url);
465+
466+
output.WriteLine("Url {0}", mainFrame.Url);
467+
}
468+
}
469+
470+
[SkipIfRunOnAppVeyorFact]
471+
public async Task CanLoadHttpWebsiteUsingSetProxyOnUiThread()
472+
{
473+
fixture.StartProxyServerIfRequired();
474+
475+
var tcs = new TaskCompletionSource<bool>();
476+
477+
var requestContext = RequestContext
478+
.Configure()
479+
.OnInitialize((ctx) =>
480+
{
481+
tcs.SetResult(true);
482+
})
483+
.Create();
484+
485+
//Wait for our RequestContext to have initialized.
486+
await tcs.Task;
487+
488+
var success = false;
489+
490+
//To execute on the CEF UI Thread you can use
491+
await Cef.UIThreadTaskFactory.StartNew(delegate
492+
{
493+
string errorMessage;
494+
495+
if (!requestContext.CanSetPreference("proxy"))
496+
{
497+
//Unable to set proxy, if you set proxy via command line args it cannot be modified.
498+
success = false;
499+
500+
return;
501+
}
502+
503+
success = requestContext.SetProxy("127.0.0.1", 8080, out errorMessage);
504+
});
505+
506+
Assert.True(success);
507+
508+
using (var browser = new ChromiumWebBrowser("http://cefsharp.github.io/", requestContext: requestContext))
509+
{
510+
await browser.LoadPageAsync();
511+
512+
var mainFrame = browser.GetMainFrame();
513+
Assert.True(mainFrame.IsValid);
514+
Assert.Contains("cefsharp.github.io", mainFrame.Url);
515+
516+
output.WriteLine("Url {0}", mainFrame.Url);
517+
}
518+
}
435519
}
436520
}

CefSharp/CefSharp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
<Compile Include="JavascriptBinding\IJavascriptNameConverter.cs" />
131131
<Compile Include="JavascriptBinding\LegacyCamelCaseJavascriptNameConverter.cs" />
132132
<Compile Include="ModelBinding\IAsyncMethodInterceptor.cs" />
133+
<Compile Include="Preferences\SetProxyResponse.cs" />
133134
<Compile Include="Preferences\SetPreferenceResponse.cs" />
134135
<Compile Include="ResourceRequestHandlerFactory.cs" />
135136
<Compile Include="ResourceRequestHandlerFactoryItem.cs" />
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright © 2021 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
namespace CefSharp.Preferences
6+
{
7+
/// <summary>
8+
/// Response when <see cref="RequestContextExtensions.SetProxyAsync(IRequestContext, string, string, int?, out string)"/>
9+
/// is called.
10+
/// </summary>
11+
public class SetProxyResponse : SetPreferenceResponse
12+
{
13+
/// <summary>
14+
/// Default constructor
15+
/// </summary>
16+
/// <param name="success">success</param>
17+
/// <param name="errorMessage">error message</param>
18+
public SetProxyResponse(bool success, string errorMessage) : base(success, errorMessage)
19+
{
20+
}
21+
}
22+
}

CefSharp/RequestContextExtensions.cs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,11 @@ public static void LoadExtensionsFromDirectory(this IRequestContext requestConte
6666
/// problem. This method must be called on the CEF UI thread.
6767
/// Preferences set via the command-line usually cannot be modified.
6868
/// </summary>
69+
/// <param name="requestContext">request context</param>
6970
/// <param name="name">preference key</param>
7071
/// <param name="value">preference value</param>
7172
/// <param name="error">out error</param>
72-
/// <returns>Returns true if the value is set successfully and false otherwise.</returns>
73+
/// <returns>returns <see cref="SetPreferenceResponse.Success"/> true if successfull, false otherwise.</returns>
7374
/// <remarks>Use Cef.UIThreadTaskFactory to execute this method if required,
7475
/// <see cref="IBrowserProcessHandler.OnContextInitialized"/> and ChromiumWebBrowser.IsBrowserInitializedChanged are both
7576
/// executed on the CEF UI thread, so can be called directly.
@@ -98,6 +99,65 @@ public static Task<SetPreferenceResponse> SetPreferenceAsync(this IRequestContex
9899
return CefThread.ExecuteOnUiThread(func);
99100
}
100101

102+
/// <summary>
103+
/// Sets the proxy server for the specified <see cref="IRequestContext"/>.
104+
/// Protocol for the proxy server is http
105+
/// </summary>
106+
/// <param name="requestContext">request context</param>
107+
/// <param name="host">proxy host</param>
108+
/// <param name="port">proxy port</param>
109+
/// <returns>returns <see cref="SetPreferenceResponse.Success"/> true if successfull, false otherwise.</returns>
110+
/// <remarks>Internally calls <seealso cref="IRequestContext.SetPreference(string, object, out string)"/> with
111+
/// preference 'proxy' and mode of 'fixed_servers'</remarks>
112+
public static Task<SetProxyResponse> SetProxyAsync(this IRequestContext requestContext, string host, int? port)
113+
{
114+
return requestContext.SetProxyAsync(null, host, port);
115+
}
116+
117+
/// <summary>
118+
/// Sets the proxy server for the specified <see cref="IRequestContext"/>
119+
/// </summary>
120+
/// <param name="requestContext">request context</param>
121+
/// <param name="scheme">is the protocol of the proxy server, and is one of: 'http', 'socks', 'socks4', 'socks5'. Also note that 'socks' is equivalent to 'socks5'.</param>
122+
/// <param name="host">proxy host</param>
123+
/// <param name="port">proxy port</param>
124+
/// <returns>returns <see cref="SetPreferenceResponse.Success"/> true if successfull, false otherwise.</returns>
125+
/// <remarks>Internally calls <seealso cref="IRequestContext.SetPreference(string, object, out string)"/> with
126+
/// preference 'proxy' and mode of 'fixed_servers'</remarks>
127+
public static Task<SetProxyResponse> SetProxyAsync(this IRequestContext requestContext, string scheme, string host, int? port)
128+
{
129+
if (CefThread.HasShutdown)
130+
{
131+
return Task.FromResult(new SetProxyResponse(false, "Cef.Shutdown has already been called, it is no longer possible to call SetProxyAsync."));
132+
}
133+
134+
Func<SetProxyResponse> func = () =>
135+
{
136+
string error;
137+
bool success = false;
138+
139+
if (requestContext.CanSetPreference("proxy"))
140+
{
141+
var v = GetProxyDictionary(scheme, host, port);
142+
143+
success = requestContext.SetPreference("proxy", v, out error);
144+
}
145+
else
146+
{
147+
error = "Unable to set the proxy preference, it is read-only. If you specified the proxy settings with command line args it is not possible to change the proxy settings via this method.";
148+
}
149+
150+
return new SetProxyResponse(success, error);
151+
};
152+
153+
if (CefThread.CurrentlyOnUiThread)
154+
{
155+
return Task.FromResult(func());
156+
}
157+
158+
return CefThread.ExecuteOnUiThread(func);
159+
}
160+
101161
/// <summary>
102162
/// Sets the proxy server for the specified <see cref="IRequestContext"/>
103163
/// MUST be called on the CEF UI Thread

0 commit comments

Comments
 (0)