GtkSharp / GtkSharp

.NET wrapper for Gtk and other related libraries
Other
887 stars 98 forks source link

add JavaScriptCoreSharp #274

Open lytico opened 3 years ago

jwosty commented 2 years ago

I've taken this branch and lytico:lytico/webkit2 and merged them into one branch (jwosty:jwosty/frankenbranch) to see how they are working together - it builds. WebView.RunJavascript(string) is working fine, which is super cool.

I'm trying to get script message handlers to work, but getting this runtime error:

Marshaling script-message-received signal
Exception in Gtk# callback delegate
  Note: Applications can use GLib.ExceptionManager.UnhandledException to handle the exception.
System.Exception: Unknown type WebKitJavascriptResult
   at GLib.Value.ToBoxed()
   at GLib.Value.get_Val()
   at GLib.SignalClosure.MarshalCallback(IntPtr raw_closure, IntPtr return_val, UInt32 n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data)
   at GLib.ExceptionManager.RaiseUnhandledException(Exception e, Boolean is_terminal)
   at GLib.SignalClosure.MarshalCallback(IntPtr raw_closure, IntPtr return_val, UInt32 n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data)
   at Gtk.Application.Run()
   at Examples.Gtk.WebKit.Main.main(String[] _arg1) in /home/jwostenberg/Code/Interstellar/Examples/Examples.Gtk.WebKit/Program.fs:line 23

The program '[7152] Examples.Gtk.WebKit.dll' has exited with code 0 (0x0).

What does this mean? I'd love to try to fix this, but I don't have experience working with GLib->.NET bindings. JavascriptResult.cs is being generated.

Here's the code that registers the handler (it's F#):

webView.Settings.EnableDeveloperExtras <- true
webView.Settings.EnableWriteConsoleMessagesToStdout <- true
webView.UserContentManager.ScriptMessageReceived.Add (fun e ->
    printfn "%A" e
    ()
)
if not (webView.UserContentManager.RegisterScriptMessageHandler("interstellarBridge")) then
    eprintfn "Failed to register script message handler; JS bridge will not work"

And the JS I used to trigger the handler (just execute via the JS console in the inspector in the app):

window.webkit.interstellarBridge.postMessage('hello')

Any pointers on what needs fixing?

jwosty commented 2 years ago

FWIW, this is my use case:

  1. I have a .NET desktop app running on macOS and Windows which I'm attempting to port to Linux
  2. It uses web frontend tech for the UI
  3. On Windows, it uses WinForms + CefSharp (Chromium) to embed the UI in a native window (via Interstellar)
  4. On macOS, it uses Xamarin.Mac + Apple WebKit to embed the UI (also via Interstellar)
  5. On both platforms, it relies on injecting JS into the page, and installing custom message handlers to facilitate communication between the JS and F#. Those should be the only two things it needs to work.

Your two PRs seem to enable most of this to work (great job so for); the script message handler seems to be the last thing holding it back.

Do these parts already work in the mono library? I'd be happy to use that for now, but I'd want to switch back to this fork ASAP, since .NET Core compatibility is a huge plus.

lytico commented 1 year ago

https://webkitgtk.org/reference/webkit2gtk/2.5.1/WebKitWebView.html#WebKitJavascriptResult https://github.com/WebKit/WebKit/blob/webkitgtk/2.34/Source/WebKit/UIProcess/API/glib/WebKitJavascriptResult.cpp

lytico commented 1 year ago

seems to be a problem with namespaces in WebkitGtkSharp-api.xml

missing type is generated in namespace WebKit struct JavascriptResult

in WebkitGtkSharp-api.xml it's typed as WebKitJavascriptResult and marked as missing

it's never registered with GLib.GType.Register (...)

3D-aero-sbahr commented 1 year ago

Happy to see you looking into this again. BlazorWebView for GTK would be so great!

lytico commented 1 year ago

the problem seems to be in JavaScriptCore.Result as soon as its referenced, the programm crashes:

test is Samples.WebviewSection

generated Code in JavascriptResult (slightly changed for debugging):

        public JavaScriptCore.Value JsValue {
            get {
                IntPtr this_as_native = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(this));
                System.Runtime.InteropServices.Marshal.StructureToPtr(this, this_as_native, false);
                IntPtr raw_ret = webkit_javascript_result_get_js_value(this_as_native);
                var glibobj = GLib.Object.GetObject(raw_ret);
                JavaScriptCore.Value ret = glibobj != null ? glibobj as JavaScriptCore.Value : default;

                ReadNative(this_as_native, ref this);
                System.Runtime.InteropServices.Marshal.FreeHGlobal(this_as_native);

                return ret;
            }
        }

then, in GLib.Object.GetObject(raw_ret) GLib.Object.GetObject(raw_ret,false)

it crashes calling g_object_is_floating(o)


            if (!owned_ref && !g_object_is_floating(o))
                g_object_ref (o);
            else if (owned_ref && g_object_is_floating(o))
                unexpected_owned_floating = true;
lytico commented 1 year ago

hint: try a wait-loop

https://github.com/tryphotino/photino.Native/blob/24be1c50d3dcb4c92c33a0081160ecc10959553c/Photino.Native/Photino.Linux.cpp#L410-L428

lytico commented 1 year ago

hint: https://github.com/JBildstein/SpiderEye/tree/master/Source/SpiderEye.Linux