[webkit-gtk] Calling a native (compiled) subprogram from JavaScript in WebKitGTK

Ludovic Brenta ludovic at ludovic-brenta.org
Tue Sep 12 07:29:20 PDT 2017


Hello,

I am extending a multi-million-line-of-code application written
in Ada with a new WebKitGTK browser window, using the WebKit2GTK
API.

After reading [1]  and [2] I am trying to expose an Ada (or C,
C++, Vala, whatever) subprogram to the JavaScript engine in
WebKit, so that JavaScript code can call it.

[1] http://www.davedoesdev.com/wrapping-webkit-part-1-gtk+-vala/
[2] https://karhm.com/JavaScriptCore_C_API/

The gist of it is: attach a callback to the "load-changed" signal
of the WebKitWebView. If the Load_Event is "finished", create a
new function object (by calling JSObjectMakeFunctionWithCallback);
add to the global object of the WebView a new property whose name
is the name of the function as seen from JavaScript and the value
is the function object.

If I try to call the function thus exported (and aptly named
"exported"), the JavaScript engine throws:

  ReferenceError: Can't find variable: exported

I am suspecting that I'm attaching the property to the wrong
global object.  Since I'm stuck with Red Hat Enterprise Linux
and the webkitgtk3-devel-2.4.9-6.el7.x86_64 package, I have no
debugging info available for WebKit itself (only for the host
application), so I can't easily debug what's happening.  All I
can tell for sure is that Get_Javascript_Global_Context,
Get_Global_Object, String.To_JavaScript etc all return non-null
and that Exceptions remain null after the call to Set_Property.
Am I doing something wrong?  Is this feature even supported with
WebKit2 or should I switch to the deprecated WebKit 1 that does not
use a separate process?

   type Attribute_T is (None, Read_Only, Dont_Enum, Dont_Delete);
   type Attributes_T is array (Attribute_T) of Boolean with Pack, Size 
=> Interfaces.C.unsigned'Size;

   function Get_Global_Object (Ctx : in Context_T) return T
     with Convention => C, Import, External_Name => 
"JSContextGetGlobalObject";

   procedure Set_Property (Ctx           : in     Context_T;
                           Object        : in     T;
                           Property_Name : in     String.T;
                           New_Value     : in     Value.T;
                           Attributes    : in     Attributes_T;
                           Exceptions    :    out Value.T)
     with Convention => C, Import, External_Name => 
"JSObjectSetProperty";

   type Callback_T is access function (Ctx            : in     
Context_T;
                                       Func           : in     T;
                                       This           : in     T;
                                       Argument_Count : in     
Interfaces.C.size_t;
                                       Arguments      : in     
Value.Arrays.Pointer;
                                       Exceptions     :    out Value.T) 
return Value.T with Convention => C;

   function Make_Function_With_Callback (Ctx : in Context_T; Name : in 
String.T; Callback : in Callback_T) return T
     with Convention => C, Import, External_Name => 
"JSObjectMakeFunctionWithCallback";

   procedure Export_Ada_Function_To_Javascript (Ctx             : in 
Context_T;
                                                Javascript_Name : in 
Standard.String;
                                                Ada_Function    : in 
Callback_T) is
     Global : constant T := Get_Global_Object (Ctx);
     Name : constant String.T := String.To_Javascript (Javascript_Name);
     Func_Obj : constant T := Make_Function_With_Callback (Ctx,
                                                           Name => Name,
                                                           Callback => 
Ada_Function);
     Exceptions : Value.T;
   begin
     Set_Property (Ctx,
                   Object        => Global,
                   Property_Name => Name,
                   New_Value     => Value.T (Func_Obj),
                   Attributes    => (Read_Only => True, others => 
False),
                   Exceptions    => Exceptions);
     -- TODO: log Exceptions, possibly raise an Ada exception?
   end Export_Ada_Function_To_Javascript;

     procedure On_Load_Changed (View       : not null access 
Webkit.Web_View.Record_T'Class;
                                Load_Event : in              
Webkit.Web_View.Load_Event_T) is
     begin
       case Load_Event is
         when Webkit.Web_View.Started | Webkit.Web_View.Redirected | 
Webkit.Web_View.Committed => null;
         when Webkit.Web_View.Finished =>
           Javascript.Object.Export_Ada_Function_To_Javascript (Ctx => 
View.Get_Javascript_Global_Context,
                                                                
Javascript_Name => "exported",
                                                                
Ada_Function => Exported'Access);
       end case;
     exception
       when others =>
         UIF_Error.Report (Kind      => UIF_Error.Operation_Aborted,
                           Unit_Name => Display_Name,
                           Message   => "Exception in 
Regulation_Editor.Browser_Window.On_Load_Changed");
     end On_Load_Changed;

-- 
Ludovic Brenta.



More information about the webkit-gtk mailing list