示例#1
0
        /// <summary>
        /// Creates a "createPromise" function on the JS side.
        /// </summary>
        private CefPromiseFactory CreatePromiseFactory()
        {
            context.Enter();
            context.GetFrame().ExecuteJavaScript(@"
                window.createPromise = function (fn) {
                    return new Promise(fn);
                };
                ", null, 1);

            var global           = context.GetGlobal();
            var promiseFactoryFn = global.GetValue("createPromise");

            var promiseFactory = new CefPromiseFactory(promiseFactoryFn);

            context.Exit();
            return(promiseFactory);
        }
        private PluginMessage CreateMessage(
            CefV8Context context,
            PluginDescriptor targetPlugin,
            string memberName,
            IV8Callback callback)
        {
            var message = new PluginMessage
            {
                PluginId     = targetPlugin.PluginId,
                MemberName   = memberName,
                BrowserId    = context.GetBrowserId(),
                ContextId    = GetIdForContext(context, false),
                FrameId      = context.GetFrame().Identifier,
                V8CallbackId = callback != null ? callback.Identifier : Guid.Empty
            };

            return(message);
        }
示例#3
0
        public void Then(CefV8Value promise, CefV8Context context, Action <PromiseResult> continuation)
        {
            var id = pendingPromises.Save(context.GetFrame().Identifier, new PendingPromise
            {
                Continuation = continuation
            });

            using (new ContextHelper(context))
                using (var global = context.GetGlobal())
                    using (var s = global.GetValue(HelperObjectName))
                    {
                        var userData       = s.GetUserData() as PromiseUserData;
                        var waitForPromise = userData.WaitForPromise;
                        using (var idValue = CefV8Value.CreateString(id.ToString()))
                        {
                            waitForPromise.ExecuteFunctionWithContext(context, null, new[] { promise, idValue }).Dispose();
                        }
                    }
        }
示例#4
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);
            //      }
            //  };
        }
示例#5
0
            protected override bool Execute(string name, CefV8Value obj, CefV8Value[] arguments, out CefV8Value returnValue, out string exception)
            {
                if (name == _config.JSQueryFunction)
                {
                    if (arguments.Length != 1 || !arguments[0].IsObject)
                    {
                        returnValue = null;
                        exception   = "Invalid arguments; expecting a single object";
                        return(true);
                    }

                    var arg = arguments[0];

                    var requestVal = arg.GetValue(CefMessageRouter.MemberRequest);
                    if (requestVal == null || !requestVal.IsString)
                    {
                        returnValue = null;
                        exception   = "Invalid arguments; object member '" +
                                      CefMessageRouter.MemberRequest + "' is required and must " +
                                      "have type string";
                        return(true);
                    }

                    CefV8Value successVal = null;
                    if (arg.HasValue(CefMessageRouter.MemberOnSuccess))
                    {
                        successVal = arg.GetValue(CefMessageRouter.MemberOnSuccess);
                        if (!successVal.IsFunction)
                        {
                            returnValue = null;
                            exception   = "Invalid arguments; object member '" +
                                          CefMessageRouter.MemberOnSuccess + "' must have type " +
                                          "function";
                            return(true);
                        }
                    }

                    CefV8Value failureVal = null;
                    if (arg.HasValue(CefMessageRouter.MemberOnFailure))
                    {
                        failureVal = arg.GetValue(CefMessageRouter.MemberOnFailure);
                        if (!failureVal.IsFunction)
                        {
                            returnValue = null;
                            exception   = "Invalid arguments; object member '" +
                                          CefMessageRouter.MemberOnFailure + "' must have type " +
                                          "function";
                            return(true);
                        }
                    }

                    CefV8Value persistentVal = null;
                    if (arg.HasValue(CefMessageRouter.MemberPersistent))
                    {
                        persistentVal = arg.GetValue(CefMessageRouter.MemberPersistent);
                        if (!persistentVal.IsBool)
                        {
                            returnValue = null;
                            exception   = "Invalid arguments; object member '" +
                                          CefMessageRouter.MemberPersistent + "' must have type " +
                                          "boolean";
                            return(true);
                        }
                    }

                    var context    = CefV8Context.GetCurrentContext();
                    var contextId  = GetIDForContext(context);
                    var frameId    = context.GetFrame().Identifier;
                    var persistent = (persistentVal != null && persistentVal.GetBoolValue());

                    var requestId = _router.SendQuery(context.GetBrowser(), frameId, contextId,
                                                      requestVal.GetStringValue(), persistent, successVal, failureVal);
                    returnValue = CefV8Value.CreateInt(requestId);
                    exception   = null;
                    return(true);
                }
                else if (name == _config.JSCancelFunction)
                {
                    if (arguments.Length != 1 || !arguments[0].IsInt)
                    {
                        returnValue = null;
                        exception   = "Invalid arguments; expecting a single integer";
                        return(true);
                    }

                    var result    = false;
                    var requestId = arguments[0].GetIntValue();
                    if (requestId != CefMessageRouter.ReservedId)
                    {
                        CefV8Context context   = CefV8Context.GetCurrentContext();
                        var          contextId = GetIDForContext(context);
                        var          frameId   = context.GetFrame().Identifier;

                        result = _router.SendCancel(context.GetBrowser(), frameId, contextId, requestId);
                    }
                    returnValue = CefV8Value.CreateBool(result);
                    exception   = null;
                    return(true);
                }

                returnValue = null;
                exception   = null;
                return(false);
            }
        protected override bool Execute(string name, CefV8Value obj, CefV8Value[] arguments, out CefV8Value returnValue, out string exception)
        {
            if (name == _name)
            {
                var bid = _context.GetBrowser()?.Identifier ?? 0;
                var fid = _context.GetFrame()?.Identifier ?? 0;

                var request = MessageBridgeRequest.Create(JavaScriptCommunicationBridge.EXECUTE_JAVASCRIPT_FUNCTION, bid, fid, _context.GetHashCode());

                request.Arguments.Add(MessageValue.CreateString(_parentKey));
                request.Arguments.Add(MessageValue.CreateString(_name));

                var args = JavaScriptValue.CreateArray();

                var index = 0;

                foreach (var arg in arguments)
                {
                    var value = arg.ToJSValue();

                    if (value != null)
                    {
                        args.SetValue(index++, value);
                    }
                }

                request.Arguments.Add(MessageValue.CreateString(args.ToDefinition()));

                var guid = Guid.NewGuid();

                request.Arguments.Add(MessageValue.CreateString($"{guid}"));

                var response = _bridge.SendExecutionRequest(request);

                if (response.IsSuccess)
                {
                    if (_functionInfo.IsAsync)
                    {
                        var callback = CefV8Value.CreateObject();

                        var successFunc = CefV8Value.CreateFunction("success", new JavaScriptBridgeFunctionCallbackHandler(/*_parentKey, _name,*/ guid, _context));

                        var errorFunc = CefV8Value.CreateFunction("error", new JavaScriptBridgeFunctionCallbackHandler(/*_parentKey, _name,*/ guid, _context));

                        callback.SetValue("success", successFunc);
                        callback.SetValue("error", errorFunc);

                        returnValue = callback;
                        exception   = null;
                    }
                    else
                    {
                        var retval = JavaScriptValue.FromJson(response.Arguments[0].GetString())?.ToCefV8Value();

                        exception = null;

                        if (retval != null)
                        {
                            returnValue = retval;
                        }
                        else
                        {
                            returnValue = CefV8Value.CreateUndefined();
                        }
                    }
                }
                else
                {
                    exception   = response.ExceptionMessage;
                    returnValue = null;
                }

                return(true);
            }

            returnValue = null;
            exception   = $"{name} is not defined.";

            return(true);
        }