Skip to content

Commit 6f0f20f

Browse files
committed
DevTools - Add SetMainFrameDocumentContentAsync extension method
- Updated example error handlers to use SetMainFrameDocumentContentAsync for displaying error messages so back/forward navigation works correctly. - DevToolsExtensions updated to use IChromiumWebBrowserBase instead of IWebBrowser so they're usable for WinForms hosted popups Issue #2985
1 parent f90271f commit 6f0f20f

File tree

3 files changed

+71
-10
lines changed

3 files changed

+71
-10
lines changed

CefSharp.WinForms.Example/BrowserTabUserControl.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,28 @@ private void OnBrowserMouseClick(object sender, MouseEventArgs e)
202202

203203
private void OnLoadError(object sender, LoadErrorEventArgs args)
204204
{
205-
//Don't display an error for external protocols that we allow the OS to
206-
//handle in OnProtocolExecution().
205+
//Aborted is generally safe to ignore
206+
//Actions like starting a download will trigger an Aborted error
207+
//which doesn't require any user action.
208+
if(args.ErrorCode == CefErrorCode.Aborted)
209+
{
210+
return;
211+
}
212+
213+
//Don't display an error for external protocols such as mailto which
214+
//we might want to open in the default viewer
207215
if (args.ErrorCode == CefErrorCode.UnknownUrlScheme && args.Frame.Url.StartsWith("mailto"))
208216
{
209217
return;
210218
}
211219

212-
DisplayOutput("Load Error:" + args.ErrorCode + ";" + args.ErrorText);
220+
var errorHtml = string.Format("<html><body><h2>Failed to load URL {0} with error {1} ({2}).</h2></body></html>",
221+
args.FailedUrl, args.ErrorText, args.ErrorCode);
222+
223+
_ = args.Browser.SetMainFrameDocumentContentAsync(errorHtml);
224+
225+
//AddressChanged isn't called for failed Urls so we need to manually update the Url TextBox
226+
this.InvokeOnUiThreadIfRequired(() => urlTextBox.Text = args.FailedUrl);
213227
}
214228

215229
private void OnBrowserConsoleMessage(object sender, ConsoleMessageEventArgs args)

CefSharp.Wpf.Example/Views/BrowserTabView.xaml.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,9 @@ public BrowserTabView()
163163

164164
browser.LoadError += (sender, args) =>
165165
{
166-
// Don't display an error for downloaded files.
166+
//Aborted is generally safe to ignore
167+
//Actions like starting a download will trigger an Aborted error
168+
//which doesn't require any user action.
167169
if (args.ErrorCode == CefErrorCode.Aborted)
168170
{
169171
return;
@@ -177,10 +179,17 @@ public BrowserTabView()
177179
}
178180

179181
// Display a load error message.
180-
var errorBody = string.Format("<html><body bgcolor=\"white\"><h2>Failed to load URL {0} with error {1} ({2}).</h2></body></html>",
182+
var errorHtml = string.Format("<html><body><h2>Failed to load URL {0} with error {1} ({2}).</h2></body></html>",
181183
args.FailedUrl, args.ErrorText, args.ErrorCode);
182184

183-
args.Frame.LoadHtml(errorBody, base64Encode: true);
185+
_ = args.Browser.SetMainFrameDocumentContentAsync(errorHtml);
186+
187+
//AddressChanged isn't called for failed Urls so we need to manually update the Url TextBox
188+
Dispatcher.InvokeAsync(() =>
189+
{
190+
var viewModel = (BrowserTabViewModel)this.DataContext;
191+
viewModel.AddressEditable = args.FailedUrl;
192+
});
184193
};
185194

186195
CefExample.RegisterTestResources(browser);

CefSharp/DevToolsExtensions.cs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ public static Task<int> ExecuteDevToolsMethodAsync(this IBrowser browser, int me
9696
/// which may be empty.</param>
9797
/// <returns>return a Task that can be awaited to obtain the assigned message Id. If the message was
9898
/// unsuccessfully submitted for validation, this value will be 0.</returns>
99-
public static Task<int> ExecuteDevToolsMethodAsync(this IWebBrowser chromiumWebBrowser, int messageId, string method, IDictionary<string, object> parameters = null)
99+
public static Task<int> ExecuteDevToolsMethodAsync(this IChromiumWebBrowserBase chromiumWebBrowser, int messageId, string method, IDictionary<string, object> parameters = null)
100100
{
101-
var browser = chromiumWebBrowser.GetBrowser();
101+
var browser = chromiumWebBrowser.BrowserCore;
102102

103103
return browser.ExecuteDevToolsMethodAsync(messageId, method, parameters);
104104
}
@@ -109,9 +109,9 @@ public static Task<int> ExecuteDevToolsMethodAsync(this IWebBrowser chromiumWebB
109109
/// </summary>
110110
/// <param name="chromiumWebBrowser">the chromiumWebBrowser instance</param>
111111
/// <returns>DevToolsClient</returns>
112-
public static DevToolsClient GetDevToolsClient(this IWebBrowser chromiumWebBrowser)
112+
public static DevToolsClient GetDevToolsClient(this IChromiumWebBrowserBase chromiumWebBrowser)
113113
{
114-
var browser = chromiumWebBrowser.GetBrowser();
114+
var browser = chromiumWebBrowser.BrowserCore;
115115

116116
return browser.GetDevToolsClient();
117117
}
@@ -123,6 +123,8 @@ public static DevToolsClient GetDevToolsClient(this IWebBrowser chromiumWebBrows
123123
/// <returns>DevToolsClient</returns>
124124
public static DevToolsClient GetDevToolsClient(this IBrowser browser)
125125
{
126+
WebBrowserExtensions.ThrowExceptionIfBrowserNull(browser);
127+
126128
var browserHost = browser.GetHost();
127129

128130
WebBrowserExtensions.ThrowExceptionIfBrowserHostNull(browserHost);
@@ -135,5 +137,41 @@ public static DevToolsClient GetDevToolsClient(this IBrowser browser)
135137

136138
return devToolsClient;
137139
}
140+
141+
/// <summary>
142+
/// Set the Document Content for the Main Frame using DevTools Protocol.
143+
/// </summary>
144+
/// <param name="chromiumWebBrowser">ChromiumWebBrowser instance</param>
145+
/// <param name="html">html</param>
146+
/// <returns>Task that can be awaited to determine if the content was successfully updated.</returns>
147+
public static Task<bool> SetMainFrameDocumentContentAsync(this IChromiumWebBrowserBase chromiumWebBrowser, string html)
148+
{
149+
var browser = chromiumWebBrowser.BrowserCore;
150+
151+
return browser.SetMainFrameDocumentContentAsync(html);
152+
}
153+
154+
/// <summary>
155+
/// Set the Document Content for the Main Frame using DevTools Protocol.
156+
/// </summary>
157+
/// <param name="browser">the browser instance</param>
158+
/// <param name="html">html</param>
159+
/// <returns>Task that can be awaited to determine if the content was successfully updated.</returns>
160+
public static async Task<bool> SetMainFrameDocumentContentAsync(this IBrowser browser, string html)
161+
{
162+
WebBrowserExtensions.ThrowExceptionIfBrowserNull(browser);
163+
164+
using (var client = browser.GetDevToolsClient())
165+
{
166+
var response = await client.Page.GetFrameTreeAsync().ConfigureAwait(false);
167+
168+
var frames = response.FrameTree;
169+
var mainFrame = frames.Frame;
170+
171+
var setContentResponse = await client.Page.SetDocumentContentAsync(mainFrame.Id, html).ConfigureAwait(false);
172+
173+
return setContentResponse.Success;
174+
}
175+
}
138176
}
139177
}

0 commit comments

Comments
 (0)