Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WPF Address Binding causing Error Aborted #2300

Closed
fuzzykiller opened this issue Mar 6, 2018 · 9 comments
Closed

WPF Address Binding causing Error Aborted #2300

fuzzykiller opened this issue Mar 6, 2018 · 9 comments
Labels
Milestone

Comments

@fuzzykiller
Copy link
Contributor

  • What version of the product are you using?
    63, master at ad9944a

  • What architecture x86 or x64?
    x86

  • On what operating system?
    Windows 10 1709 x64

  • Are you using WinForms, WPF or OffScreen?
    WPF

  • What steps will reproduce the problem?

  1. Set Address attribute in XAML to file:// URI

Example code here: https://github.com/fuzzykiller/CefSharp.MinimalExample/tree/load_twice_demo
(Diff)

  • What is the expected output? What do you see instead?
    Expected: Console message should appear once.
    Actual: Console message appears twice

  • Please provide any additional information below.
    This is because the page is loaded twice: Once in ChromiumWebBrowser.CreateOffscreenBrowser and then after the browser is created in ChromiumWebBrowser.OnAfterBrowserCreated again. Generally, these two calls happen so fast that the first load never finishes, especially over the Internet.

However, when loading from file:// URIs, the load apparently is finished synchronously (or whatever) and the page is “executed” twice. I wasn’t able to observe this behavior when loading over the network or even from a custom scheme.

Proposed solution

When the address is passed to managedCefBrowserAdapter.CreateOffscreenBrowser, it should be saved. In OnAfterBrowserCreated, only when the address has changed from this saved value should Load be called.

@amaitland
Copy link
Member

I'd rather not add another variable it if can be helped. I'd first check if the browser main frame url, hopefully that's set sufficiently early.

By all means submit a PR.

@fuzzykiller
Copy link
Contributor Author

Upon further though, I discovered a common scenario where checking the main frame URL isn’t enough: Redirects.

There also is a possible race condition with how ClientAdapter::OnAddressChange could probably be called before ClientAdapter::OnAfterCreated, resulting in a comparison that’ll always return “equal”.

As such, I think a new field is indeed required. It also helps with URL normalization, like it happens with file:// URLs.

@fuzzykiller
Copy link
Contributor Author

Well, since I haven’t been able to reproduce the issue on master, I’m closing this. There must have been some other change that accidentally fixed this.

browser.MainFrame.Url isn’t set yet in OnAfterBrowserCreated, by the way.

@cplotts
Copy link

cplotts commented Aug 22, 2018

I was using CefSharp 63.0.2 and was utilizing WPF data binding to bind an Url property (on the view model) to the Address property on the ChromiumWebBrowser. When I did this, I saw two pairs of LoadingStateChanged events (a pair meaning IsLoading = true and then IsLoading = false). Inside the first pair, I also got a LoadError with ERR_ABORTED as the error.

LoadingStateChanged IsLoading True
ERR_ABORTED
LoadingStateChanged IsLoading False
LoadingStateChanged IsLoading True
LoadingStateChanged IsLoading False

This forced me to create a ILifeSpanHandler object and to set the Address in the OnAfterCreated method (instead of using WPF data binding). Doing this resulted in an expected sequence of events.

LoadingStateChanged IsLoading True
FrameLoadEnd True
LoadingStateChanged IsLoading False
and no ERR_ABORTED at all.

I then upgraded to 65.0.1 ... and retried setting the Address property with data binding. At this point, I got only one pair of LoadingStateChanged events ... but I was still seeing an ERR_ABORTED ... again forcing me to use the ILifeSpanHandler.OnAfterCreated to set the Address.

LoadingStateChanged IsLoading True
ERR_ABORTED
LoadingStateChanged IsLoading False

@amaitland amaitland changed the title Race condition with WPF control initialization WPF Address Binding causing Error Aborted Aug 23, 2018
@amaitland amaitland added the wpf label Aug 23, 2018
@amaitland
Copy link
Member

Not seeing this when using MainWindow.xaml in CefSharp.Wpf.Example, it is reproducible with
SimpleMainWindow.xaml

Address is passed to CreateOffscreenBrowser and then later in OnAfterBrowserCreated a subsequent call to Load is made.
https://github.com/cefsharp/CefSharp/blob/cefsharp/67/CefSharp.Wpf/ChromiumWebBrowser.cs#L1689
https://github.com/cefsharp/CefSharp/blob/cefsharp/67/CefSharp.Wpf/ChromiumWebBrowser.cs#L998

The quick fix is to pass an empty address to CreateOffscreenBrowser and rely exclusively on OnAfterBrowserCreated to load the Url.

@fuzzykiller
Copy link
Contributor Author

My workaround for this issue was to create a derived class with the Address dependency property hidden. This new property would only pass its value upstream after browser initialization has finished.

This way, no double loading accours and XAML usability remains unaffected. Alternatively, you could also create an attached property that has the same behavior.

Unfortunately, I’m currently not working on projects that involve CefSharp, so I don’t have any more recent experience.

amaitland added a commit that referenced this issue Aug 23, 2018
amaitland added a commit that referenced this issue Aug 23, 2018
@amaitland amaitland added this to the 67.0.0 milestone Aug 23, 2018
@amaitland
Copy link
Member

Quick fix applied with 60afa0b

Long term I may end up going with this solution as it keeps things clean and simple. I cannot think of any downsides at the moment, will leave open for a little bit.

@cplotts
Copy link

cplotts commented Aug 23, 2018

Glad I could help figure this one out!

@amaitland
Copy link
Member

Closing as I'm happy with this solution for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants