Пример #1
0
 public ChromiumFxDispatcher(CfrBrowser browser, CfrV8Context context, IWebSessionLogger logger)
 {
     _Logger           = logger;
     _Browser          = browser;
     _Context          = context;
     TaskRunner        = _Context.TaskRunner;
     _CfrTask          = new CfrTask();
     _CfrTask.Execute += CfrTask_Execute;
 }
Пример #2
0
        /// <summary>
        /// Post a task for execution on the specified thread. Equivalent to using
        /// CfrTaskRunner.GetForThread(threadId).PostTask(task).
        /// </summary>
        /// <remarks>
        /// See also the original CEF documentation in
        /// <see href="https://bitbucket.org/chromiumfx/chromiumfx/src/tip/cef/include/capi/cef_task_capi.h">cef/include/capi/cef_task_capi.h</see>.
        /// </remarks>
        public static bool PostTask(CfxThreadId threadId, CfrTask task)
        {
            var call = new CfxRuntimePostTaskRenderProcessCall();

            call.threadId = (int)threadId;
            call.task     = CfrObject.Unwrap(task);
            call.RequestExecution(CfxRemoteCallContext.CurrentContext.connection);
            return(call.__retval);
        }
Пример #3
0
 /// <summary>
 /// Post a task for delayed execution on the specified thread. Equivalent to
 /// using CfrTaskRunner.GetForThread(threadId).PostDelayedTask(task,
 /// delay_ms).
 /// </summary>
 /// <remarks>
 /// See also the original CEF documentation in
 /// <see href="https://bitbucket.org/chromiumfx/chromiumfx/src/tip/cef/include/capi/cef_task_capi.h">cef/include/capi/cef_task_capi.h</see>.
 /// </remarks>
 public static bool PostDelayedTask(CfxThreadId threadId, CfrTask task, long delayMs)
 {
     var call = new CfxRuntimePostDelayedTaskRenderProcessCall();
     call.threadId = (int)threadId;
     call.task = CfrObject.Unwrap(task);
     call.delayMs = delayMs;
     call.RequestExecution(CfxRemoteCallContext.CurrentContext.connection);
     return call.__retval;
 }
 public ChromiumFxTask(Action perform)
 {
     var task = new CfrTask();
     task.Execute += (sender, args) =>
     {
         perform();
         Clean?.Invoke();
     };
     Task = task;
 }
Пример #5
0
        public ChromiumFxTask(Action perform)
        {
            var task = new CfrTask();

            task.Execute += (sender, args) =>
            {
                perform();
                Clean?.Invoke();
            };
            Task = task;
        }
Пример #6
0
 public ChromiumFxTask(Action perform)
 {
     Task          = new CfrTask();
     Task.Execute += (sender, args) =>
     {
         perform();
         Clean?.Invoke();
         Task.Dispose();
         Task = null;
     };
 }
Пример #7
0
        private CfrTask AddTask(Action action)
        {
            var task = new CfrTask();

            task.Execute += (o, e) =>
            {
                action();
                RemoveTask(task);
            };

            lock (_Locker)
                _Tasks.Add(task);

            return(task);
        }
Пример #8
0
        protected void CallCallback(CfrV8Value callback, CfrV8Context v8Context, params KeyValuePair <string, object>[] par)
        {
            if (callback != null)
            {
                //get render process context
                var rc = callback.CreateRemoteCallContext();

                //enter render process
                rc.Enter();

                //create render task
                var task = new CfrTask();
                task.Execute += (_, taskArgs) =>
                {
                    //enter saved context
                    v8Context.Enter();

                    var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor());

                    foreach (var val in par)
                    {
                        var validValue = ConvertValue(val.Value);
                        callbackArgs.SetValue(val.Key, validValue, CfxV8PropertyAttribute.ReadOnly);
                    }

                    //execute callback
                    callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs });

                    v8Context.Exit();

                    //lock task from gc
                    lock (task)
                    {
                        Monitor.PulseAll(task);
                    }
                };

                lock (task)
                {
                    //post task to render process
                    v8Context.TaskRunner.PostTask(task);
                }

                rc.Exit();

                GC.KeepAlive(task);
            }
        }
Пример #9
0
        void CfrTaskStressTest()
        {
            if (remoteBrowser == null)
            {
                return;
            }

            var ctx = remoteBrowser.CreateRemoteCallContext();

            ctx.Enter();
            try {
                int taskExecutionCounter = 0;

                for (int i = 0; i < 10000; ++i)
                {
                    var task = new CfrTask();
                    task.Execute += (s, e1) => {
                        ++taskExecutionCounter;
                        if (taskExecutionCounter % 1000 == 0)
                        {
                            LogWriteLine($"CfrTask stress test: {taskExecutionCounter}/10000 tasks executed.");
                        }
                    };
                    if (i % 2 == 0)
                    {
                        CfrRuntime.PostTask(CfxThreadId.Renderer, task);
                    }
                    else
                    {
                        var tr = CfrTaskRunner.GetForThread(CfxThreadId.Renderer);
                        tr.PostTask(task);
                    }
                    if (i % 1000 == 0)
                    {
                        LogWriteLine($"CfrTask stress test: {i}/10000 tasks posted.");
                    }
                }
            } catch {
                LogWriteLine($"CfrTask stress test: Exception cought, aborting.");
            } finally {
                ctx.Exit();
            }
        }
Пример #10
0
        private void AsyncTestFunctionCallback(CfrV8Value function, CfrV8Context v8Context)
        {
            LogWriteLine("AsyncTestFunctionCallback: sleep 2 secs, don't browse away...");
            Thread.Sleep(2000);

            var rpcContext = function.CreateRemoteCallContext();

            rpcContext.Enter();

            // since v8 values can only be accessed from the thread on which they are created, the task
            // has to be posted for execution on the remote renderer thread (see CfxV8Value summary)

            var    task   = new CfrTask();
            string result = null;

            task.Execute += (s, e) => {
                v8Context.Enter();
                LogWriteLine("AsyncTestFunctionCallback -> task.Execute: function.FunctionName = " + function.FunctionName);
                var args   = new CfrV8Value[] { "This is the alert text." };
                var retval = function.ExecuteFunction(null, args);
                result = retval.StringValue;
                v8Context.Exit();
                // release the waiting thread.
                lock (task) {
                    Monitor.PulseAll(task);
                }
            };

            // wait until the return value is available.
            lock (task) {
                CfrTaskRunner.GetForThread(CfxThreadId.Renderer).PostTask(task);
                Monitor.Wait(task);
            }

            rpcContext.Exit();

            LogWriteLine("AsyncTestFunctionCallback: result from callback = " + result);
            LogWriteLine("AsyncTestFunctionCallback: done.");
        }
Пример #11
0
        private void RunInContextUnsafe(Action action)
        {
            if (CfxRemoteCallContext.IsInContext)
            {
                action();
                return;
            }

            _Actions.Enqueue(action);

            if (_IsExecutingActions)
            {
                return;
            }

            using (GetRemoteContext())
            {
                var task = new CfrTask();
                task.Execute += CfrTask_Execute;
                CfrRuntime.PostTask(CfxThreadId.Renderer, task);
            }
        }
Пример #12
0
        public Form1()
            : base("http://res.app.local/www/index.html")
        {
            InitializeComponent();

            LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd;

            //register the "my" object
            var myObject = GlobalObject.AddObject("my");

            //add property "name" to my, you should implemnt the getter/setter of name property by using PropertyGet/PropertySet events.
            var nameProp = myObject.AddDynamicProperty("name");

            nameProp.PropertyGet += (prop, args) =>
            {
                // getter - if js code "my.name" executes, it'll get the string "NanUI".
                args.Retval = CfrV8Value.CreateString("NanUI");
                args.SetReturnValue(true);
            };
            nameProp.PropertySet += (prop, args) =>
            {
                // setter's value from js context, here we do nothing, so it will store or igrone by your mind.
                var value = args.Value;
                args.SetReturnValue(true);
            };


            //add a function showCSharpMessageBox
            var showMessageBoxFunc = myObject.AddFunction("showCSharpMessageBox");

            showMessageBoxFunc.Execute += (func, args) =>
            {
                //it will be raised by js code "my.showCSharpMessageBox(`some text`)" executed.
                //get the first string argument in Arguments, it pass by js function.
                var stringArgument = args.Arguments.FirstOrDefault(p => p.IsString);

                if (stringArgument != null)
                {
                    MessageBox.Show(this, stringArgument.StringValue, "C# Messagebox", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            };

            //add a function getArrayFromCSharp, this function has an argument, it will combind C# string array with js array and return to js context.
            var friends = new string[] { "Mr.JSON", "Mr.Lee", "Mr.BONG" };

            var getArrayFromCSFunc = myObject.AddFunction("getArrayFromCSharp");

            getArrayFromCSFunc.Execute += (func, args) =>
            {
                var jsArray = args.Arguments.FirstOrDefault(p => p.IsArray);



                if (jsArray == null)
                {
                    jsArray = CfrV8Value.CreateArray(friends.Length);
                    for (int i = 0; i < friends.Length; i++)
                    {
                        jsArray.SetValue(i, CfrV8Value.CreateString(friends[i]));
                    }
                }
                else
                {
                    var newArray = CfrV8Value.CreateArray(jsArray.ArrayLength + friends.Length);

                    for (int i = 0; i < jsArray.ArrayLength; i++)
                    {
                        newArray.SetValue(i, jsArray.GetValue(i));
                    }

                    var jsArrayLength = jsArray.ArrayLength;

                    for (int i = 0; i < friends.Length; i++)
                    {
                        newArray.SetValue(i + jsArrayLength, CfrV8Value.CreateString(friends[i]));
                    }


                    jsArray = newArray;
                }


                //return the array to js context

                args.SetReturnValue(jsArray);

                //in js context, use code "my.getArrayFromCSharp()" will get an array like ["Mr.JSON", "Mr.Lee", "Mr.BONG"]
            };

            //add a function getObjectFromCSharp, this function has no arguments, but it will return a Object to js context.
            var getObjectFormCSFunc = myObject.AddFunction("getObjectFromCSharp");

            getObjectFormCSFunc.Execute += (func, args) =>
            {
                //create the CfrV8Value object and the accssor of this Object.
                var jsObjectAccessor = new CfrV8Accessor();
                var jsObject         = CfrV8Value.CreateObject(jsObjectAccessor);

                //create a CfrV8Value array
                var jsArray = CfrV8Value.CreateArray(friends.Length);

                for (int i = 0; i < friends.Length; i++)
                {
                    jsArray.SetValue(i, CfrV8Value.CreateString(friends[i]));
                }

                jsObject.SetValue("libName", CfrV8Value.CreateString("NanUI"), CfxV8PropertyAttribute.ReadOnly);
                jsObject.SetValue("friends", jsArray, CfxV8PropertyAttribute.DontDelete);


                args.SetReturnValue(jsObject);

                //in js context, use code "my.getObjectFromCSharp()" will get an object like { friends:["Mr.JSON", "Mr.Lee", "Mr.BONG"], libName:"NanUI" }
            };


            //add a function with callback

            var callbackTestFunc = GlobalObject.AddFunction("callbackTest");

            callbackTestFunc.Execute += (func, args) => {
                var callback = args.Arguments.FirstOrDefault(p => p.IsFunction);
                if (callback != null)
                {
                    var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor());
                    callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly);
                    callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly);

                    callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs });
                }
            };


            //add a function with async callback
            var asyncCallbackTestFunc = GlobalObject.AddFunction("asyncCallbackTest");

            asyncCallbackTestFunc.Execute += async(func, args) => {
                //save current context
                var v8Context = CfrV8Context.GetCurrentContext();
                var callback  = args.Arguments.FirstOrDefault(p => p.IsFunction);

                //simulate async methods.
                await Task.Delay(5000);

                if (callback != null)
                {
                    //get render process context
                    var rc = callback.CreateRemoteCallContext();

                    //enter render process
                    rc.Enter();

                    //create render task
                    var task = new CfrTask();
                    task.Execute += (_, taskArgs) =>
                    {
                        //enter saved context
                        v8Context.Enter();

                        //create callback argument
                        var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor());
                        callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly);
                        callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly);

                        //execute callback
                        callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs });


                        v8Context.Exit();

                        //lock task from gc
                        lock (task)
                        {
                            Monitor.PulseAll(task);
                        }
                    };

                    lock (task)
                    {
                        //post task to render process
                        v8Context.TaskRunner.PostTask(task);
                    }

                    rc.Exit();

                    GC.KeepAlive(task);
                }
            };
        }
Пример #13
0
 private void RemoveTask(CfrTask task)
 {
     task.Dispose();
     lock (_Locker)
         _Tasks.Remove(task);
 }