Exemplo n.º 1
0
        /// <summary>
        /// Tool method : Start the windows message loop , and monitor status , close all when any of them stopped.
        /// </summary>
        static public void RunApplication(Action initHandler = null)
        {
            WriteDebugLine("RunApplication : " + ApplicationElapsed);

            bool mainLoopExited = false;

            var aspnetcoretask = ApplicationTask ?? Task.Delay(-1, ApplicationCTS.Token);

            ApplicationCTS.Token.Register(delegate
            {
                if (!aspnetcoretask.IsCompleted && !mainLoopExited && !IsWindowsEventLoopQuitRequested)
                {
                    WriteDebugLine("ApplicationCTS Requested. Waiting ApplicationTask shutdown..");
                }
            });

            aspnetcoretask.ContinueWith(delegate
            {
                ApplicationHost?.Dispose();

                if (!mainLoopExited && !IsWindowsEventLoopQuitRequested)
                {
                    WriteDebugLine("ApplicationTask Exited. Now shutdown CefWin");
                    QuitWindowsEventLoop();
                }
            });

            ////            START Windows Event Loop

            WriteDebugLine("Start WindowsEventLoop()");

            InternalDoEventLoop(initHandler);

            mainLoopExited = true;

            ////            RELEASE and Exiting

            if (!aspnetcoretask.IsCompleted)
            {
                WriteDebugLine("CefWin Exited. Now stop ApplicationCTS.");
                ApplicationCTS.CancelAfter(1);
            }

            ApplicationHost?.Dispose();

            //Thread.Sleep(1000);//Debug wait..

            if (!aspnetcoretask.IsCompleted && !_winformsExitFired)
            {
                WriteDebugLine("Exiting....Wait for ApplicationTask");
                int      loopcount = 0;
                DateTime dts       = DateTime.Now;
                while (!aspnetcoretask.IsCompleted)
                {
                    DoMessageLoopOnce();
                    loopcount++;
                    Thread.Sleep(10);
                    if (DateTime.Now - dts > TimeSpan.FromSeconds(1.5))
                    {
                        WriteDebugLine("timeout..");
                        break;
                    }
                }

                if (!aspnetcoretask.IsCompleted)
                {
                    WriteDebugLine(".....");
                    //CurrentProcess.Kill();
                }
                else
                {
                    WriteDebugLine("ApplicationTask Exited....final loops : " + loopcount);
                }
            }
            else if (!aspnetcoretask.IsCompleted)
            {
                WriteDebugLine("Will not wait ApplicationTask after Application.Exit called.");
            }

            for (int i = 0; i < 5; i++)
            {
                DoMessageLoopOnce();
            }

            CefShutdown();

            WriteDebugLine("RunApplication END");
        }
Exemplo n.º 2
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);
            //      }
            //  };
        }