/// <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); }
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(); } } }
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); // } // }; }
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); }