Example #1
0
        private void CreateFunction(CefV8Value parent, CefV8Handler method, String name)
        {
            // Create the {name} function.
            CefV8Value value = CefV8Value.CreateFunction(name, method);

            // Add the {name} function to the {parent} object.
            parent.SetValue(name, value, CefV8PropertyAttribute.None);
        }
Example #2
0
        /// <summary>
        /// 通过反射机制 注册c#函数到JS
        /// </summary>
        public void RegisterJs()
        {
            JsEvent js = new JsEvent(mainView);

            Cef = new CefJsV8Handler(js);

            string javascriptCode = CefJavaScriptEx.CreateJsCodeByObject(js, "Cef");

            CefRuntime.RegisterExtension("Cef", javascriptCode, Cef);
        }
Example #3
0
        /// <summary>
        /// 创建JavaScript方法
        /// </summary>
        /// <param name="handler">处理程序</param>
        /// <param name="javascriptObject">经过V8 JS引擎处理后的对象</param>
        /// <param name="methodNames">方法键值对集合</param>
        public static void CreateJavascriptMethods(CefV8Handler handler, CefV8Value javascriptWrapper, IList <String> methodNames)
        {
            var unmanagedWrapper = (UnmanagedWrapper)(javascriptWrapper.GetUserData());

            foreach (string methodName in methodNames)
            {
                string jsMethodName = LowercaseFirst(methodName);
                //unmanagedWrapper.AddMethodMapping(methodName, jsMethodName);
                javascriptWrapper.SetValue(jsMethodName, CefV8Value.CreateFunction(jsMethodName, handler), CefV8PropertyAttribute.None);
            }
        }
Example #4
0
 private void RegisterAsyncFunction(CefV8Value jsObject, string functionName, CefV8Handler handler)
 {
     jsObject.SetValue(functionName, CefV8Value.CreateFunction(functionName, handler));
 }
Example #5
0
        static CefWin()
        {
            string exefile = CurrentProcess.MainModule.FileName;

            ApplicationIcon = System.Drawing.Icon.ExtractAssociatedIcon(exefile);

            SearchLibCefRootFolderList.Add(Path.GetDirectoryName(exefile));
            SearchLibCefRootFolderList.Add(Environment.CurrentDirectory);

            // * * single-process is not recommanded by chromium team , If you get any strange issue , try removing this option:
            // * * see https://peter.sh/experiments/chromium-command-line-switches/ for more
            // * * ERROR msg in https://github.com/chromium/chromium/blob/bd61bd83c9ebcfdb162a447e4a01637d259ea358/chrome/browser/net/system_network_context_manager.cc
            CefAdditionArguments.Add("--single-process");               //use single process , memory usage is 170MB , otherwise 340MB
            CefAdditionArguments.Add("--winhttp-proxy-resolver");
            CefAdditionArguments.Add("--no-proxy-server");              //https://code.google.com/archive/p/chromiumembedded/issues/81

            CefAdditionArguments.Add("--disable-gpu-shader-disk-cache");
            CefAdditionArguments.Add("--allow-running-insecure-content");

            CefAdditionArguments.Add("--enable-speech-input");
            CefAdditionArguments.Add("--enable-media-stream");            //TODO: ??? must work with --enable-usermedia-screen-capturing
            CefAdditionArguments.Add("--enable-usermedia-screen-capturing");

            CefAdditionArguments.Add("--enable-aggressive-domstorage-flushing");                //save data more quickly

            // more tested :
            //  --proxy-server=http://127.0.0.1:8080


            new WF.Panel().Handle.ToString();               //Activate  WindowsFormsSynchronizationContext
            MainThreadSynchronizationContext = SynchronizationContext.Current;


            Console.CancelKeyPress += delegate
            {
                //CTRL+C
                WriteDebugLine("Console.CancelKeyPress");
                ApplicationCTS.Cancel();
            };
            WF.Application.ApplicationExit += delegate
            {
                _winformsExitFired = true;
                WriteDebugLine("Warning:do not call Application.Exit()");
                ApplicationCTS.Cancel();
            };



            LibCefInterop.App.RenderProcessHandler.WebKitInitialized += delegate
            {
                CefV8Handler handler = new CefV8Handler();
                AddStaticObject(handler);

                ConcurrentDictionary <string, Assembly> dllmap = new ConcurrentDictionary <string, Assembly>();

                Assembly[] existAsms = null;

                object HandleExecute(CefV8Handler self, string name, CefV8Value[] args)
                {
                    if (SettingsTrustedWebsiteHosts == null)
                    {
                        throw new Exception("TrustedWebsiteHosts is not configured");
                    }

                    //TODO: v8c get current , get browser
                    CefV8Context ctx = CefV8Context.GetCurrent();

                    if (ctx == null)
                    {
                        throw new Exception("no current v8context");
                    }
                    string url = ctx.GetFrame().Url;
                    Uri    uri = new Uri(url);

                    if (!SettingsTrustedWebsiteHosts.Contains(uri.Host))
                    {
                        if (!SettingsTrustedWebsiteHosts.Contains(uri.Host + ":" + uri.Port))
                        {
                            throw (new Exception(uri.Host + ":" + uri.Port + " is not trusted in TrustedWebsiteHosts"));
                        }
                    }

                    if (existAsms == null)
                    {
                        existAsms = AppDomain.CurrentDomain.GetAssemblies();
                    }

                    if (name == "_compileAssembly")
                    {
                        string dllname = args[0].GetStringValue();
                        string code    = args[1].GetStringValue();

                        WriteDebugLine("_compileAssembly:" + dllname + ":" + code.Length);

                        if (!SettingAllowCompileCSharpCode)
                        {
                            throw new Exception("AllowCompileCSharpCode is not setted to true");
                        }

                        if (dllname.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) != -1)
                        {
                            throw new Exception("Invalid dllname.");
                        }

                        dllmap[dllname] = CompileCode(existAsms, dllname, code);
                    }
                    else if (name == "_installAssembly")
                    {
                        string dllname = args[0].GetStringValue();
                        string base64  = args[1].GetStringValue();

                        WriteDebugLine("_installAssembly:" + dllname + ":" + base64.Length);

                        if (SettingTrustedPublicKeyTokens == null)
                        {
                            throw new Exception("CefWin.PublicKeyTokenList is not configured");
                        }

                        byte[]   data      = Convert.FromBase64String(base64);
                        Assembly asm       = AppDomain.CurrentDomain.Load(data);
                        byte[]   tokendata = asm.GetName().GetPublicKeyToken();
                        if (tokendata == null)
                        {
                            throw new Exception("the dll " + dllname + " must signed for a PublicKeyToken and register it into CefWin.PublicKeyTokenList ");
                        }
                        string token = BitConverter.ToString(tokendata).Replace("-", "").ToLower();
                        if (!SettingTrustedPublicKeyTokens.Contains(token))
                        {
                            throw new Exception("Invalid dll , " + token + " is not in CefWin.PublicKeyTokenList");
                        }

                        WriteDebugLine("new assembly installed : " + asm.FullName);

                        dllmap[dllname] = asm;
                    }
                    else if (name == "_executeAssembly")
                    {
                        string dllname = args[0].GetStringValue();
                        string clsname = args[1].GetStringValue();
                        string method  = args[2].GetStringValue();

                        WriteDebugLine("_executeAssembly:" + dllname + ":" + clsname + ":" + method);

                        object[] methodargs = (object[])args[3].ToObject() ?? Array.Empty <object>();
                        Assembly asm;
                        if (!dllmap.TryGetValue(dllname, out asm))
                        {
                            throw new Exception(dllname + " not exists");
                        }
                        Type type = asm.GetType(clsname);

                        WriteDebugLine("Type : " + type.AssemblyQualifiedName);

                        var members = type.GetMember(method);
                        if (members.Length == 0)
                        {
                            throw new Exception("Method " + method + " not exists in " + type.AssemblyQualifiedName);
                        }
                        if (members.Length != 1)
                        {
                            throw new Exception("Too many member " + method + " in " + type.AssemblyQualifiedName);
                        }

                        var minfo = members[0] as MethodInfo;
                        if (minfo == null)
                        {
                            throw new Exception("Member " + method + " is not a method in " + type.AssemblyQualifiedName);
                        }
                        if (!minfo.IsStatic)
                        {
                            throw new Exception("Method " + method + " is not static in " + type.AssemblyQualifiedName);
                        }
                        if (!minfo.IsPublic)
                        {
                            throw new Exception("Method " + method + " is not public in " + type.AssemblyQualifiedName);
                        }


                        object result = null;

                        InvokeInAppThread(delegate
                        {
                            result = minfo.Invoke(null, new object[] { methodargs });
                        });
                    }
                    else
                    {
                        throw new Exception("Invalid func " + name);
                    }
                    return(null);
                }

                handler.Execute = HandleExecute;

                //TODO: shall use async return Promise ... now show dialog will block the JS executing,
                //TODO: Support multi-process :

                int r = CefV8Context.CefRegisterExtension("cefwin_extention", @"
var CefWin={};
(function(){
    var dllmap={};
    CefWin.compileAssembly=function(dllname,code)
    {
        var dllitem=dllmap[dllname];
        if(dllitem!=null&&dllitem.code==code)
        {
            console.log(dllname+' already compiled');
            return;
        }
        console.log(dllname,code.length);
        dllitem={code:code};
        native function _compileAssembly();
        _compileAssembly(dllname, code);
        dllmap[dllname]=dllitem;
    }
    CefWin.installAssembly=function(dllname, base64)
    {
        var dllitem=dllmap[dllname];
        if(dllitem!=null&&dllitem.base64==base64)
        {
            console.log(dllname+' already installed');
            return;
        }
        console.log(dllname,base64.length);
        dllitem={base64:base64};
        native function _installAssembly();
        _installAssembly(dllname, base64);
        dllmap[dllname]=dllitem;
    }
    CefWin.executeAssembly=async function _ExecuteAssembly(dllname, clsname, method, args)
    {
        var dllitem=dllmap[dllname];
        if(!dllitem)throw new Error(dllname+' not installed');
        native function _executeAssembly();
        console.log(dllname,clsname,method);
        _executeAssembly(dllname,clsname,method,args);
        return 'OK'+new Date().getTime();
    }
})();
", handler);
                WriteDebugLine("CefRegisterExtension:" + r);
            };


            //TODO: implement the Notification API
            //LibCefInterop.App.RenderProcessHandler.WebKitInitialized += delegate
            //  {
            //      int r = CefV8Context.CefRegisterExtension("CefWin1", "function cefwin(){alert(123);}");
            //      WriteDebugLine("CefRegisterExtension:" + r);
            //  };
            //LibCefInterop.App.RenderProcessHandler.ContextCreated += (rph, browser, frame, v8c) =>
            //  {
            //      WriteDebugLine("OnContextCreated id:" + browser.Identifier);
            //      WriteDebugLine("send msgfromrenderer");
            //      frame.SendProcessMessage(cef_process_id_t.PID_BROWSER, "msgfromrenderer");
            //      try
            //      {
            //          v8c.Eval("console.log('hello...')");
            //          WriteDebugLine("Eval DONE");
            //      }
            //      catch (Exception x)
            //      {
            //          WriteDebugLine(x);
            //      }
            //  };
        }
Example #6
0
        //CsNativeHandlerSwitchTableCodeGen::GenerateHandleNativeReq
        public static void HandleNativeReq(object inst, int met_id, IntPtr args)
        {
            switch ((met_id >> 16))
            {
            case CefAccessibilityHandler._typeNAME:
                CefAccessibilityHandler.HandleNativeReq(inst as CefAccessibilityHandler.I0, inst as CefAccessibilityHandler.I1, met_id, args);
                break;

            case CefBrowserProcessHandler._typeNAME:
                CefBrowserProcessHandler.HandleNativeReq(inst as CefBrowserProcessHandler.I0, inst as CefBrowserProcessHandler.I1, met_id, args);
                break;

            case CefContextMenuHandler._typeNAME:
                CefContextMenuHandler.HandleNativeReq(inst as CefContextMenuHandler.I0, inst as CefContextMenuHandler.I1, met_id, args);
                break;

            case CefDialogHandler._typeNAME:
                CefDialogHandler.HandleNativeReq(inst as CefDialogHandler.I0, inst as CefDialogHandler.I1, met_id, args);
                break;

            case CefDisplayHandler._typeNAME:
                CefDisplayHandler.HandleNativeReq(inst as CefDisplayHandler.I0, inst as CefDisplayHandler.I1, met_id, args);
                break;

            case CefDownloadHandler._typeNAME:
                CefDownloadHandler.HandleNativeReq(inst as CefDownloadHandler.I0, inst as CefDownloadHandler.I1, met_id, args);
                break;

            case CefDragHandler._typeNAME:
                CefDragHandler.HandleNativeReq(inst as CefDragHandler.I0, inst as CefDragHandler.I1, met_id, args);
                break;

            case CefFindHandler._typeNAME:
                CefFindHandler.HandleNativeReq(inst as CefFindHandler.I0, inst as CefFindHandler.I1, met_id, args);
                break;

            case CefFocusHandler._typeNAME:
                CefFocusHandler.HandleNativeReq(inst as CefFocusHandler.I0, inst as CefFocusHandler.I1, met_id, args);
                break;

            case CefGeolocationHandler._typeNAME:
                CefGeolocationHandler.HandleNativeReq(inst as CefGeolocationHandler.I0, inst as CefGeolocationHandler.I1, met_id, args);
                break;

            case CefJSDialogHandler._typeNAME:
                CefJSDialogHandler.HandleNativeReq(inst as CefJSDialogHandler.I0, inst as CefJSDialogHandler.I1, met_id, args);
                break;

            case CefKeyboardHandler._typeNAME:
                CefKeyboardHandler.HandleNativeReq(inst as CefKeyboardHandler.I0, inst as CefKeyboardHandler.I1, met_id, args);
                break;

            case CefLifeSpanHandler._typeNAME:
                CefLifeSpanHandler.HandleNativeReq(inst as CefLifeSpanHandler.I0, inst as CefLifeSpanHandler.I1, met_id, args);
                break;

            case CefLoadHandler._typeNAME:
                CefLoadHandler.HandleNativeReq(inst as CefLoadHandler.I0, inst as CefLoadHandler.I1, met_id, args);
                break;

            case CefPrintHandler._typeNAME:
                CefPrintHandler.HandleNativeReq(inst as CefPrintHandler.I0, inst as CefPrintHandler.I1, met_id, args);
                break;

            case CefRenderHandler._typeNAME:
                CefRenderHandler.HandleNativeReq(inst as CefRenderHandler.I0, inst as CefRenderHandler.I1, met_id, args);
                break;

            case CefRenderProcessHandler._typeNAME:
                CefRenderProcessHandler.HandleNativeReq(inst as CefRenderProcessHandler.I0, inst as CefRenderProcessHandler.I1, met_id, args);
                break;

            case CefRequestContextHandler._typeNAME:
                CefRequestContextHandler.HandleNativeReq(inst as CefRequestContextHandler.I0, inst as CefRequestContextHandler.I1, met_id, args);
                break;

            case CefRequestHandler._typeNAME:
                CefRequestHandler.HandleNativeReq(inst as CefRequestHandler.I0, inst as CefRequestHandler.I1, met_id, args);
                break;

            case CefResourceBundleHandler._typeNAME:
                CefResourceBundleHandler.HandleNativeReq(inst as CefResourceBundleHandler.I0, inst as CefResourceBundleHandler.I1, met_id, args);
                break;

            case CefResourceHandler._typeNAME:
                CefResourceHandler.HandleNativeReq(inst as CefResourceHandler.I0, inst as CefResourceHandler.I1, met_id, args);
                break;

            case CefReadHandler._typeNAME:
                CefReadHandler.HandleNativeReq(inst as CefReadHandler.I0, inst as CefReadHandler.I1, met_id, args);
                break;

            case CefWriteHandler._typeNAME:
                CefWriteHandler.HandleNativeReq(inst as CefWriteHandler.I0, inst as CefWriteHandler.I1, met_id, args);
                break;

            case CefV8Handler._typeNAME:
                CefV8Handler.HandleNativeReq(inst as CefV8Handler.I0, inst as CefV8Handler.I1, met_id, args);
                break;
            }
        }
Example #7
0
        public void OnContextCreated(CefRenderProcessHandler.OnContextCreatedArgs args)
        {
            //-----------------------
            //this is TEST CODE
            //-----------------------
            return;

            //eg  "<html><head><script>function docload(){ console.log(test001()); console.log(test_myobj.myprop);console.log(test_myobj[12345]);}</script><body onload=\"docload()\"><h1>hello!</h1></body></html>"

            dbugRenderProcessLog.WriteLine("context_created1");
            CefV8Context context = args.context();

            dbugRenderProcessLog.WriteLine("context_cx1");
            //global => window object
            CefV8Value cefV8Global = context.GetGlobal();

            //
            Auto.CefV8Handler funcHandler = new Auto.CefV8Handler(Cef3Binder.MyCefJs_New_V8Handler(Test002));
            CefV8Value        func        = Auto.CefV8Value.CreateFunction("test001", funcHandler);

            cefV8Global.SetValue("test001", func, cef_v8_propertyattribute_t.V8_PROPERTY_ATTRIBUTE_READONLY);
            //-------

            dbugRenderProcessLog.WriteLine("context_cx2");


            dbugRenderProcessLog.WriteLine("context_cx3");
            CefV8Accessor accessor = CefV8Accessor.New((id, argPtr) =>
            {
                //--------------------------
                //this shows the unsafe and low-level interface to native.
                //you can use a 'higher' level wrapper.
                //--------------------------

                //from https://github.com/v8/v8/wiki/Embedder%27s-Guide
                //accessor callbacks are invoked when a specific object property is accessed by a script
                //Accessors
                //An accessor is a C++callback that calculates and returns a value when an object property is accessed by a JavaScript script.
                //Accessors are configured through an object template, using the SetAccessor method.
                //This method takes the name of the property with which it is associated and two callbacks to run when a script attempts to read or write the property.

                CefV8Accessor.GetArgs arg = new CefV8Accessor.GetArgs(argPtr);
                arg.retval(CefV8Value.CreateString("hello! from accessor").nativePtr);
                arg.myext_setRetValue(true);//finish the accessor!
            });

            CefV8Interceptor intercepter = CefV8Interceptor.New((id, argPtr) =>
            {
                //from https://github.com/v8/v8/wiki/Embedder%27s-Guide
                //interceptor callbacks are invoked when any object property is accessed by a script Accessors and interceptors are discussed later in this document.
                //
                //
                //Interceptors
                //  You can also specify a callback for whenever a script accesses any object property. These are called interceptors. For efficiency, there are two types of interceptors:
                //  named property interceptors - called when accessing properties with string names. An example of this, in a browser environment, is document.theFormName.elementName.
                //  indexed property interceptors - called when accessing indexed properties. An example of this, in a browser environment, is document.forms.elements[0].

                //--------------------------
                //this shows the unsafe and low-level interface to native.
                //you can use a 'higher' level wrapper.
                //--------------------------


                if ((id >> 16) != CefV8Interceptor._typeNAME)
                {
                    return;
                }
                //--------------------------
                int met_id = id & 0xffff;
                switch (met_id)
                {
                case CefV8Interceptor.MyCefV8Interceptor_Get_1:
                    {
                        //by name
                        CefV8Interceptor.get_bynameArgs arg = new CefV8Interceptor.get_bynameArgs(argPtr);
                        arg.retval(CefV8Value.CreateString("hello! from intercepter" + arg.name()).nativePtr);
                    }
                    break;

                case CefV8Interceptor.MyCefV8Interceptor_Get_2:
                    {
                        //by indexed property
                    }
                    break;
                }
            });
            //--------
            //The difference between accessors and interceptors is that interceptors handle all properties,
            //while accessors are associated with one specific property.
            //--------
            //
            CefV8Accessor    empty             = new CefV8Accessor();
            CefV8Interceptor empty_interceptor = new CefV8Interceptor();
            CefV8Value       cef_object        = CefV8Value.CreateObject(accessor, empty_interceptor);

            //if you want to use accessor, your must set it with SetValue() like this
            cef_object.SetValue("myprop", cef_v8_accesscontrol_t.V8_ACCESS_CONTROL_DEFAULT, cef_v8_propertyattribute_t.V8_PROPERTY_ATTRIBUTE_NONE);

            //
            //set to global object
            cefV8Global.SetValue("test_myobj", cef_object, cef_v8_propertyattribute_t.V8_PROPERTY_ATTRIBUTE_READONLY);
            //------

            //--------------

            //-------
            //TEST 1: raw, low level interface
            //-------
            IntPtr ret       = IntPtr.Zero;
            IntPtr exception = IntPtr.Zero;
            //string jscode = "(function(){ return function (){return 1.25;}})()";
            string jscode = "(function(){ return function (){ console.log('hello-eval1'); return 1.25;}})()";

            if (context.Eval(jscode, "", 1, ref ret, ref exception))
            {
                dbugRenderProcessLog.WriteLine("eval success");
            }
            else
            {
                dbugRenderProcessLog.WriteLine("eval fail");
            }
            //
            using (CefV8Value cefv8_ret = new CefV8Value(ret))
                using (CefV8Value cefv8_excep = new CefV8Value(exception))
                {
                    if (cefv8_ret.IsFunction())
                    {
                        CefV8Value     obj1            = new CefV8Value(); //empty
                        CefV8ValueList args1           = CefV8ValueList.NewList();
                        CefV8Value     innerFuncResult = cefv8_ret.ExecuteFunction(obj1, args1);
                        Cef3Binder.MyCefDeletePtr(args1.nativePtr);


                        double innerDouble = innerFuncResult.GetDoubleValue();
                    }
                    else
                    {
                        double v8ret_double = cefv8_ret.GetDoubleValue();
                    }
                }


            //low-level example, TODO: make this to O-O style
            //------
            var myfunc2 = MyJsFunc <double> .Create(context,
                                                    "function(a00){ console.log(a00);}");

            myfunc2.Invoke(101);
            //------
            var myfunc3 = MyJsFunc <string> .Create(context,
                                                    "function(a00){ console.log(a00);}");

            myfunc3.Invoke("HELLOO!");
            //------
            //
            var myfunc4 = MyJsFunc <double, string> .Create(context,
                                                            "function(a00,a02){ console.log(a00); console.log(a02);}");

            myfunc4.Invoke(101, "hello_myfunc4");
            //------
            var myfunc5 = MyJsFunc <string, string> .Create(context,
                                                            "function(a00,a02){ console.log(a00); console.log(a02);}");

            myfunc5.Invoke("HELLOO!", "hello_myfunc5");
            //------
            var myfunc6 = MyJsFunc.Create(context,
                                          "function(){ document.title='hello1'; document.write('0'); return document; }");
            var        doc              = myfunc6.Invoke();
            CefV8Value docTitle         = doc.GetValue("title");
            string     docTitleAsString = docTitle.GetStringValue();
            CefV8Value docBody          = doc.GetValue("body");

            if (!docBody.IsNull())
            {
                //get innerHTML property
                CefV8Value innerHtmlProp = docBody.GetValue("innerHTML");
                if (innerHtmlProp.IsString())
                {
                }
                //set innerHTML property
                docBody.SetValue("innerHTML", CefV8Value.CreateString("A_Z"), cef_v8_propertyattribute_t.V8_PROPERTY_ATTRIBUTE_NONE);
            }

            CefV8Value docWrite = doc.GetValue("write");

            if (docWrite.IsFunction()) //try getting 'write' method of the document object
            {
                CefV8ValueList writeArgs = CefV8ValueList.NewList();
                writeArgs.AddElement(CefV8Value.CreateString("Hello_FROM_WRITE"));
                docWrite.ExecuteFunction(doc, writeArgs);
                Cef3Binder.MyCefDeletePtr(writeArgs.nativePtr);
            }
            //------
            //if we write() all
            //we need to get doc again
            doc         = myfunc6.Invoke();
            cefV8Global = context.GetGlobal();

            //low-level example, TODO: make this to O-O style
            CefV8Value cefGlobal_addEventListener = cefV8Global.GetValue("addEventListener");

            if (cefGlobal_addEventListener.IsFunction())
            {
                MyCefCallback cefWindowOnLoad = (id, argsPtr) =>
                {
                    //arg as mouse event args
                    CefV8Handler.ExecuteArgs args2        = new CefV8Handler.ExecuteArgs(argsPtr);
                    CefV8ValueList           argumentList = args2.arguments();
                    int argCount = argumentList.GetListCount();
                };
                _cefCallbackKeeper.Add(cefWindowOnLoad);
                var            v8Handler  = new CefV8Handler(Cef3Binder.MyCefJs_New_V8Handler(cefWindowOnLoad));
                CefV8ValueList handleArgs = CefV8ValueList.NewList();
                //"load"
                handleArgs.AddElement(CefV8Value.CreateString("load"));
                CefV8Value v8Loadhandler = CefV8Value.CreateFunction("mydocload", v8Handler);
                //"eventHandler"
                handleArgs.AddElement(v8Loadhandler);
                cefGlobal_addEventListener.ExecuteFunction(cefV8Global, handleArgs);
                Cef3Binder.MyCefDeletePtr(handleArgs.nativePtr);
            }
            //------
            //low-level example, TODO: make this to O-O style
            CefV8Value doc_addEventListener = doc.GetValue("addEventListener");

            if (doc_addEventListener.IsFunction())
            {
                MyCefCallback mouseDownCallback = (id, argsPtr) =>
                {
                    //arg as mouse event args
                    CefV8Handler.ExecuteArgs args2        = new CefV8Handler.ExecuteArgs(argsPtr);
                    CefV8ValueList           argumentList = args2.arguments();
                    int        argCount = argumentList.GetListCount();
                    CefV8Value v8arg    = argumentList.GetElement(0);
                    //get button propery
                    CefV8Value v8button = v8arg.GetValue("button");
                    if (v8button.IsInt())
                    {
                        int button = v8button.GetIntValue();
                    }
                };
                _cefCallbackKeeper.Add(mouseDownCallback);
                var            v8Handler  = new CefV8Handler(Cef3Binder.MyCefJs_New_V8Handler(mouseDownCallback));
                CefV8ValueList handleArgs = CefV8ValueList.NewList();
                //"load"
                handleArgs.AddElement(CefV8Value.CreateString("mousedown"));
                CefV8Value v8Loadhandler = CefV8Value.CreateFunction("mycallback", v8Handler);
                //"eventHandler"
                handleArgs.AddElement(v8Loadhandler);
                cefGlobal_addEventListener.ExecuteFunction(doc, handleArgs);
                Cef3Binder.MyCefDeletePtr(handleArgs.nativePtr);
            }



            dbugRenderProcessLog.WriteLine("context_created-pass");
        }