unit utslvclcef; //20230410 {** @explan(说明)封装cef到vcl控件,提供cef窗口的宿主控件,加入了,cookie,download,等功能 %% **} interface uses utslvclcefinterface,tslvcl; type tcefowner = class(tcustomcontrol) protected static fargs; //命令行参数 static fcefapp; //app static fappsetting; //app设置 static finitcef; //初始化标记 static finitcefobj;//初始化标记 static fcefloop; //消息循环 static fcookiemgr; static fcookiewills; static fcefwindows; class function initcef(); //初始化cef begin if not finitcef then begin fcefwindows := array(); finitcef := true; sinit(); fcefloop := new tcefproc(); app := initializeapplication(); app.addExitMessageLoopdo(thisfunction(cef_shutdown)); cef_initialize(fargs._getptr_(), fappsetting._getptr_(), fcefapp._getptr_(),0); fcookiemgr := new cef_cookie_manager_global_t(); if fcookiewills then begin for i,v in fcookiewills do begin if ifnil(v[1]) then begin fcookiemgr.delete_cookies(v[2],v[0],fcookiemgr.callback); end else begin c := new cef_cookie_t(); c.name := v[0]; c.value := v[1]; fcookiemgr.set_cookie(v[2],c,fcookiemgr.callback); end end fcookiewills := array(); end end end class function sinit();override; //初始化 begin if not finitcefobj then begin inherited; finitcefobj := true; fargs := new cef_main_args_t(); fcefapp := new cef_app_t(); fappsetting := new cef_settings_t(); tp := unit(utslvclauxiliary).gettemppath(); fappsetting.log_file := tp+"-ceflogfile-"+datetostr(date())+".log"; //fappsetting.browser_subprocess_path := %% F:\cef_105.3.39\AnalyseNG.NET\cefclient.exe%%; fappsetting.browser_subprocess_path := tslpath()+"tsl_cef_main.exe"; fappsetting.cache_path := tp+"-cefcatche-";// %% F:\cef_105.3.39\tslcache%%; fappsetting.log_severity :=99;//0; end end public function create(AOwner); begin inherited; width := 300; height := 300; fwinfo := new cef_window_info_t(); fclient := new cef_client_t(); {frm := new cef_life_span_handler_t(); frm.on_after_created := function(o,b)begin echo "\r\n craeteted:",b.get_main_frame().get_url(),"<<"; end frm.on_before_close := function(o,b)begin echo "\r\n====doclose:",b.get_main_frame().get_url(); end fclient.on_process_message_received := function()begin echo "\r\n>>>>:messagesabed:",params[4]; //return 1; end fclient.life_span_handler := frm; } d := new cef_download_handler_t(); fdownloader := d; d.can_download := function(o,b,u,m)begin return docandownload(o,b,u,m); //return true; end d.on_before_download := function(o,b,it,s,c)begin c.cont(s,1); end d.on_download_updated := function(o,b,it,c) begin return dodownloadupdate(o,b,it,c); end {fOndownloadupdate := function(o,e)begin echo "\r\n",e.get_id(),e.is_complete(),"=====",e.is_in_progress(),"===",e.is_complete(),"===",e.get_percent_complete(),"====",e.get_suggested_file_name(); end foncandownload := function(o,e)begin echo "\r\n",e.method,"==>>=",e.url; //e.skip := true; end} muh := new cef_context_menu_handler_t(); muh.on_before_context_menu := function(o,b,f,pms,d)begin ppm := PopupMenu; if d then d.remove(132); if ppm then begin fpopupmenushine := array(); createusrmenu(ppm,d,27500); end end muh.on_context_menu_dismissed := function(o,b,f)begin fpopupmenushine := array(); end muh.on_context_menu_command := function(o,b,f,pms,id,flg)begin oi := fpopupmenushine[id]; if oi then begin e := new tuieventbase(0,0,0,0); CallMessgeFunction(oi.onclick,oi,e); return 1; end end fclient.context_menu_handler := muh; fclient.download_handler := d; fbrssetting := new cef_browser_settings_t(); end function checknewchild(c);override; begin return false; end function WMSize(o,e);override; begin if not HandleAllocated() then return ;// ch := _wapi.GetWindow(o.handle,GW_CHILD); if ch then begin rc := ClientRect; _wapi.SetWindowPos(ch,0,rc[0],rc[1],rc[2],rc[3],0); end end function InitializeWnd();override; begin inherited; if HandleAllocated() then begin if not ifarray(fcefwindows) then begin fcefwindows := array(); end fhandlebk := inttostr(handle); fcefwindows[fhandlebk] := self(true); initbrowser(); end end function DestroyHandle();override; begin inherited; reindex(fcefwindows,array(fhandlebk:nil)); fbrower := nil; end function Recycling();override; begin inherited; end function reload(ic); //重新加载,ic 是否忽略缓存 begin if fbrower then begin if ic then fbrower.reload_ignore_cache(); else fbrower.reload(); end end function showdevtools(); //打开调试窗口 begin if fbrower then begin host := fbrower.get_host(); if host then begin host.show_dev_tools(); end end end function closedevtools(); //关闭调试窗口 begin if fbrower then begin host := fbrower.get_host(); if host then begin host.close_dev_tools(); end end end ////////////////cookie/////////////////// function setcookie(n,v,ur);//设置cookie值 begin if not( n and ifstring(n)) then return 0; if not( v and ifstring(v)) then return 0; if not(ur and ifstring(ur)) then begin cur := furl; end else begin cur := ur; end cookie := new cef_cookie_t(); cookie.name := n; cookie.value := v; if fcookiemgr then begin return fcookiemgr.set_cookie(cur,cookie,fcookiemgr.callback); end else begin if not(ifarray( fcookiewills)) then fcookiewills := array(); fcookiewills[length(fcookiewills)] := array(n,v,cur); end end function delcookie(n,ur); //根据名字删除cookie begin if not( n and ifstring(n)) then return 0; if not(ur and ifstring(ur)) then begin cur := furl; end else begin cur := ur; end if fcookiemgr then begin fcookiemgr.delete_cookies(cur,n,fcookiemgr.callback); end else begin if not(ifarray( fcookiewills)) then fcookiewills := array(); fcookiewills[length(fcookiewills)] := array(n,nil,cur); end end published property url:string read furl write seturl; property oncandownload:eventhandler read FOncandownload write FOncandownload; property Ondownloadupdate:eventhandler read FOndownloadupdate write fOndownloadupdate; private function seturl(url); //设置url begin if furl<>url then begin furl := url; if HandleAllocated() then begin if fbrower and (fm := fbrower.get_main_frame()) then begin fm.load_url(url); end else begin initbrowser(); end end end end function initbrowser(); //初始加载url begin if csDesigning in ComponentState then return ; if furl and ifstring(furl) then begin initcef(); r := ClientRect; fwinfo.parent_window := handle; fwinfo.window_name := Caption; fwinfo.bounds.x := r[0]; fwinfo.bounds.y := r[1]; fwinfo.bounds.width := r[2]; fwinfo.bounds.height := r[3]; fbrower := cef_browser_host_create_browser_sync_tsl(fwinfo, fclient,furl, fbrssetting, 0, 0); end end function createusrmenu(mu,d,idx); //构造菜单映射 begin if not mu then return ;// for i,v in mu.items do begin idx++; fpopupmenushine[idx] := v; smu := v.ItemCount; if smu>0 then //存在子节点 begin nd := d.add_sub_menu(idx,v.Caption); if not(v.Enabled) then //处理是否有效 begin d.set_enabled(idx,false); end else createusrmenu(v,nd,idx); //处理子菜单 end else //单个菜单 begin if v.TSeparator then //分割类型 begin d.add_separator(); end else //添加菜单 begin d.add_item(idx,v.Caption); if not(v.Enabled) then d.set_enabled(idx,false); //设置是否enabled end end end end function docandownload(o,b,u,m);//是否可以下载处理 begin if FOncandownload then begin e := new tcandownevent(0,0,0,0); e.url := u; e.method := m; CallMessgeFunction(FOncandownload,self(true),e); return not(e.skip); end else begin return 1; end end function dodownloadupdate(o,b,it,c);//下载过程处理 begin if FOndownloadupdate and it and c then begin e := new tdownupdateevent(0,0,0,0); e.FDownitem := it; e.fcallback := c; CallMessgeFunction(FOndownloadupdate,self(true),e); end end private [weakref]fbrower; [weakref]FOncandownload; [weakref]FOndownloadupdate; [weakref]fdownloader; [weakref]fpopupmenushine; [weakref]fclient; furl; fwinfo; fbrssetting; fhandlebk; class function tslpath(); //tsl.exe 目录 begin p := pluginpath(); iof := iofileseparator(); for i:= length(p)-1 downto 1 do begin if p[i]=iof then return p[1:i]; end return p; end end type tcandownevent = class(tuieventbase) //是否可以下载 function create(m,w,l,h);override; begin inherited; end url; //url method; //post or get end type tdownupdateevent=class(tuieventbase) function create(m,w,l,h);override; begin inherited; end //call--back; function cancel(); begin fcallback.cancel(); end function pause(); begin fcallback.pause(); end function resume(); begin fcallback.resume(); end //down ---- function is_complete();//是否完成 begin return FDownitem.is_complete(); end function is_in_progress();//正在进行 begin return FDownitem.is_in_progress(); end function get_current_speed();//当前速度 begin return FDownitem.get_current_speed(); end function get_percent_complete();//完成进度 begin return FDownitem.get_percent_complete(); end function get_full_path();//路径 begin return FDownitem.get_full_path(); end function get_original_url();//原始路径 begin return FDownitem.get_original_url(); end function get_suggested_file_name();//建议文件名 begin return FDownitem.get_suggested_file_name(); end function get_total_bytes(); //大小 begin return FDownitem.get_total_bytes(); end function get_id(); //序号 begin return FDownitem.get_id(); end FDownitem; fcallback; end implementation initialization end.