ChromiumWebBrowser - OnBeforeConextMenu Crash

Issue #48 resolved
Shaun Sullivan
created an issue

Hi, if I handle the OnBeforeContextMenu event, any interaction with the passed in CfxOnBeforeContextMenuEventArgs argument (like clearing the model) causes a hard crash:

**** Exception Text ***** Chromium.CfxRemotingException: Remote connection lost. ---> System.IO.EndOfStreamException: Unable to read beyond the end of the stream. at System.IO.BinaryReader.FillBuffer(Int32 numBytes) at System.IO.BinaryReader.ReadUInt16() at StreamHandler.ReadUInt16() at Chromium.Remote.RemoteConnection.ReadLoop() at Chromium.Remote.RemoteConnection.ReadLoopEntry()

Comments (19)

  1. Shaun Sullivan reporter

    Okay, I got by that one, it only happened when using CEF debug binaries.

    Now my issue is that the e.model argument is readonly so there is no way to cancel the context menu by doing e.model.clear() in the CfxOnBeforeContextMenuEventArgs event. In typical CEF scenarios this will result in the context menu not being shown.

    Great project BTW, seems to hold real promise.

    Shaun

  2. wborgsm

    Hi, thanks.

    In the test browser project, BrowserForm.cs, there is ContextMenuHandler_OnBeforeContextMenu handler which does exactly this: clears the context menu.

    void ContextMenuHandler_OnBeforeContextMenu(object sender, CfxOnBeforeContextMenuEventArgs e) {
                if(e.Model.Clear()) {
                    LogWriteLine("Context Menu cleared.");
                } else {
                    LogWriteLine("Context Menu not cleared.");
                }
            }
    

    In the test browser form, it works. In order to test it yourself, you have to start the browser form and check "Clear context menu model" in the Misc menu. After that, the browser won't show context menu.

    So if you see a context menu after clearing the model, the Clear() method probably returns false (no success)? In which way is your use case different from BrowserForm.cs?

  3. Shaun Sullivan reporter

    I will research. The only difference is I am using VB.NET, so let me make sure there is not some difference on event handling vs. delegates there with this one.

    Sorry for the trouble, I will report back regardless.

    Shaun

  4. Shaun Sullivan reporter

    Still trying to track this down. I'm not sure if it helps but debugging this I am seeing that cfx_binary_value_is_valid() in cfx_binary_value.c is returning 0. So something is up with the collection. cm.png

  5. wborgsm

    Call stack is strange because from CfxMenuModel.Clear it should call cfx_menu_model_clear not cfx_binary_value_is_valid. Looks like a mismatch between managed and native binaries, but then again the API hash check should fail and the library should error out early, when loading the native binaries.

    I already downloaded your project and I hope I find some time to look into it by the end of the week. Sorry for the delay.

  6. Shaun Sullivan reporter

    Thanks, I made sure they are not mis-matched. Also, when I use your test program it works perfectly (with the same binaries)

    This is driving me crazy :)

    Hopefully I am not missing something obvious, thanks for the time.

  7. Shaun Sullivan reporter

    Progress!

    Okay I think it is something to do with nuance of the VB.NET / Winforms message loop.

    If I set e.Settings.MultiThreadedMessageLoop = False in onBeforeCfxInitialize and add a Chromium.CfxRuntime.DoMessageLoopWork() in System.Windows.Forms.Application.Idle then the context menu clears just fine.

    Hope that helps!

  8. wborgsm

    Just ran your test project (using my own binaries).

    So far I reproduced the strange behavior. Model.Clear() doesn't work unless MultiThreadedMessageLoop = False.

    I also reproduced the strange call stack when stepping into the native code. The source line for cfx_binary_value_is_valid() appears in both cases, whether Model.Clear() is working or not, so I guess cfx_menu_model_clear() is called (otherwise it wouldn't work in neither case) but the debugger is showing the wrong line, for reasons I don't know yet.

  9. wborgsm

    Found it.

    When MultiThreadedMessageLoop = true, then the OnBeforeContextMenu callback is invoked on the application's UI thread, and it looks like the menu model must be manipulated on the browser's UI thread. When MultiThreadedMessageLoop = false, then the application's UI thread and the browser's UI thread are the same, so there is no problem.

    Quick fix:

    Delete Handles wb.OnBeforeContextMenu from Sub wb_OnBeforeContextMenu

    Add AddHandler wb.ContextMenuHandler.OnBeforeContextMenu, AddressOf wb_OnBeforeContextMenu to Form1_Load

    and it should work as expected.

  10. wborgsm

    Automatic invoking for library callbacks was meant to be a feature so one could call methods on UI objects from within CEF callbacks without explicitly invoking the UI thread. This experience shows that feature to be fundamentally broken because CEF seems to (reasonably) expect that CEF objects passed in are manipulated on the thread performing the callback, especially when the documentation says "Do not keep references to |Params| or |Model| outside of this callback".

    I am going to deprecate those invoked callbacks for the next release. After all it was a bad idea.

  11. wborgsm

    Just a side note: if you do ChromiumWebBrowser.Initialize() within Form1_Load, then all secondary processes will also have to go through Form1_Load. The form doesn't show in the secondary processes because ChromiumWebBrowser.Initialize() never returns, so all secondary processes will run with a fully constructed, half-loaded but hidden form object.

    So if you want to do this, you should use a dedicated assembly for secondary processes (see my comment in Issue #49). Otherwise, you should start your application with a Sub Main.

  12. Shaun Sullivan reporter

    Yes, I do start in sub main just not in that attempt at a simple sample. BTW, I had previously tried what you suggested as a quick fix and it didn't work. I even tried Application.Run() in sub main (to more closely approximate you c# sample) and even that didn't work.

    Thank you so much for all the time you have spent on this issue. I am super excited about this project. For the last few years I have been using my own forked version if Xilium.CefGlue but I had grown tired of adding all the new code needed each time I wanted to move to an updated CEF branch.

    Your project seems like the antidote to my woes :) I probably will just drop down one level and build out my own version of what your web browser control does, that way I'll be able to use any CEF functionality I need and not "wait" for it to be implemented in the current webbrowser control.

    Thanks again for your work on this, and thanks for sharing it with others.

    Shaun

    Founder,

    electric plum

  13. wborgsm

    BTW, I had previously tried what you suggested as a quick fix and it didn't work.

    Are you sure you tried wb.ContextMenuHandler.OnBeforeContextMenu and not wb.OnBeforeContextMenu? The latter is the problematic one.

    Could you please confirm if wb.ContextMenuHandler.OnBeforeContextMenu fixes it for you?

    BTW, the ChromiumWebBrowser control is specifically designed to let you use every single CEF funcionality alongside with the control - it exposes the CfxBrowser object, all client handlers etc. If any CEF funcionality is inacessible due to the use of the web browser control, then it's a bug in the latter :)

    And thank you very much for your positive feedback and for using the library.

  14. Shaun Sullivan reporter

    Are you sure you tried wb.ContextMenuHandler.OnBeforeContextMenu and not wb.OnBeforeContextMenu? The latter is the >problematic one. Could you please confirm if wb.ContextMenuHandler.OnBeforeContextMenu fixes it for you?

    You are 100% correct. Pardon my ignorance as I get comfortable with this library. I can confirm that did fix it.

    BTW, the ChromiumWebBrowser control is specifically designed to let you use every single CEF funcionality alongside with the >control - it exposes the CfxBrowser object, all client handlers etc. If any CEF funcionality is inacessible due to the use of the web >browser control, then it's a bug in the latter :)

    That is excellent! I'll stay the control path then.

    Best, Shaun

  15. Log in to comment