1优化拍单逻辑 2优化部分文件位置命名等

This commit is contained in:
wule committed 2026-06-25 16:45:28 +08:00
1 parent 34c51c6fcd
commit 1e27c0b1e1
65 files changed
+2594 -268

No files matched your search

+572
View File
@@ -0,0 +1,572 @@
using CefSharp;
using CefSharp.WinForms;
using NaiBa.CefHelper;
using NaiBa.CefHelper.Handler;
using NaiBa.Util;
using NaiBa.Util.Extension;
using NaiBa.Util.Helper;
using NaiBa.Util.Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Work._29Tools.CefTools
{
public class LocalCEFBrowser
{
public static bool IsKeepGlobalCookie = true; // true 的时候,cookie 会保存在硬盘上,cookie 是持久化的
public static string CefGlobalCachePath = Path.Combine(FileHelper.GetApplicationDir(), "cef_temp");
public static string CefMemoryCachePath = Path.Combine(CefGlobalCachePath, "memory");
public static void Init(string userAgent = "")
{
// 必须在主线程进行初始化
if (NaiBaGlobalConfig.IsDevelopment)
{
FileHelper.DeleteFolder(CefGlobalCachePath);
}
FileHelper.CreateDirectory(CefGlobalCachePath);
CefSharpSettings.WcfEnabled = false;
CefSettings settings = new CefSettings
{
IgnoreCertificateErrors = false,
Locale = "zh-CN",
PersistSessionCookies = true,
//PersistUserPreferences = true, //cef138
LogFile = Path.Combine(CefGlobalCachePath, "debug.log"),
LogSeverity = NaiBaGlobalConfig.IsDevelopment ? LogSeverity.Verbose : LogSeverity.Error,
CachePath = IsKeepGlobalCookie ? CefGlobalCachePath : string.Empty,
RootCachePath = IsKeepGlobalCookie ? CefGlobalCachePath : string.Empty
};
settings.UserAgent = string.IsNullOrEmpty(userAgent) ? NaiBaGlobalConfig.UserAgent : userAgent;
settings.CefCommandLineArgs.Add("disable-gpu", "1");
settings.CefCommandLineArgs.Add("--ignore-ssl-errors");
settings.CefCommandLineArgs.Add("--disable-web-security");
settings.CefCommandLineArgs.Add("--allow-file-access-from-files"); // 允许通过 file:/// 协议访问 Worker
System.Net.IWebProxy webProxy = NaiBaGlobalConfig.GetDevelopProxy();
if (webProxy != null)
{
if (NaiBaGlobalConfig.IsDevelopment)
{
bool isSetFiddlerProxy = false; // 由于店铺可能绑定了代理,浏览器不设置 Fiddler 代理
if (isSetFiddlerProxy)
{
string address = ReflectionHelper.GetObjectPropertyValue(webProxy, "Address").ParseToString();
if (!address.IsNullOrEmpty())
{
address = address.Trim('/');
// Don't set any proxy during initialize,becuase once setting,it couldn't be changed at runtime
settings.CefCommandLineArgs.Add("--proxy-server", address);
}
}
}
}
var rst = Cef.Initialize(settings);
}
/// <summary>
/// 关闭所有Cef进程
/// </summary>
public static void ShutDown()
{
Cef.Shutdown();
}
public static ChromiumWebBrowser CreateChromiumWebBrowser(string url, bool isGlobal = true, bool isPopupNewWindow = true)
{
ChromiumWebBrowser cefBrowser = new ChromiumWebBrowser(url);
if (!isGlobal)
{
cefBrowser.RequestContext = new RequestContext(GetRequestContextIsolateSettings());
}
cefBrowser.BrowserSettings = new BrowserSettings
{
Javascript = CefState.Enabled,
JavascriptAccessClipboard = CefState.Enabled,
JavascriptCloseWindows = CefState.Enabled,
JavascriptDomPaste = CefState.Enabled,
LocalStorage = CefState.Enabled,
//Plugins = CefState.Disabled, //cef138
//FileAccessFromFileUrls = CefState.Enabled, //cef138
//UniversalAccessFromFileUrls = CefState.Enabled //cef138
};
cefBrowser.KeyboardHandler = new KeyboardHandler();
cefBrowser.MenuHandler = new MenuHandler();
cefBrowser.LifeSpanHandler = new LifeSpanHandler(isPopupNewWindow);
return cefBrowser;
}
public static RequestContextSettings GetRequestContextIsolateSettings()
{
RequestContextSettings requestContextSettings = new RequestContextSettings()
{
PersistSessionCookies = true,
CookieableSchemesExcludeDefaults = false,
};
//requestContextSettings.PersistSessionCookies = false;
//requestContextSettings.PersistUserPreferences = false; // cef138
return requestContextSettings;
}
public static void CheckCefPlatform()
{
string executingFolder = FileHelper.GetApplicationDir();
//If libcef.dll doesn't exist in our executing folder then we'll copy the files
//For this method the user must have write permissions to the executing folder.
if (!File.Exists(Path.Combine(executingFolder, "libcef.dll")))
{
var libPath = Path.Combine(executingFolder, Environment.Is64BitProcess ? "x64" : "x86");
if (Directory.Exists(libPath))
{
FileHelper.MoveFolder(libPath, executingFolder);
}
string dir = executingFolder + "x86";
if (Directory.Exists(dir))
{
Directory.Delete(dir, recursive: true);
}
dir = executingFolder + "x64";
if (Directory.Exists(dir))
{
Directory.Delete(dir, recursive: true);
}
}
}
public static async Task<bool> SetProxyAsync(ChromiumWebBrowser cefWebBrowser, string proxyUrl)
{
bool isUseProxy = false;
await Cef.UIThreadTaskFactory.StartNew(() =>
{
try
{
var rc = cefWebBrowser.GetBrowser().GetHost().RequestContext;
var dict = new Dictionary<string, object>();
if (string.IsNullOrEmpty(proxyUrl))
{
dict.Add("mode", "system");
}
else
{
var objProxy = HttpHelper.ResoveProxyServer(proxyUrl);
if (objProxy.Tag == 1)
{
BaseProxyServer baseProxyServer = objProxy.Data;
if (!baseProxyServer.Username.IsNullOrEmpty() && !baseProxyServer.Password.IsNullOrEmpty())
{
CustomRequestHandler customRequestHandler = cefWebBrowser.RequestHandler as CustomRequestHandler;
if (customRequestHandler != null)
{
customRequestHandler.UserName = baseProxyServer.Username;
customRequestHandler.Password = baseProxyServer.Password;
}
}
proxyUrl = string.Format("http://{0}:{1}", baseProxyServer.ServerIP, baseProxyServer.ServerPort);
}
dict.Add("mode", "fixed_servers"); // fixed_servers,pac_script,auto_detect,system,direct
dict.Add("server", proxyUrl);
}
string error;
bool success = rc.SetPreference("proxy", dict, out error);
if (success)
{
isUseProxy = true;
}
}
catch (Exception ex)
{
LogHelper.WriteWithTime(ex);
}
});
return isUseProxy;
}
public static string ParseCookieListToString(List<Cookie> cookieList)
{
string cookies = string.Empty;
foreach (Cookie cookie in cookieList)
{
cookies += string.Format("{0}={1};", cookie.Name, cookie.Value);
}
return cookies;
}
public static List<Cookie> GetCookieList(string domains = "", ICookieManager cookieManager = null)
{
if (cookieManager == null)
{
cookieManager = Cef.GetGlobalCookieManager();
}
CookieVisitor visitor = new CookieVisitor();
if (cookieManager.VisitAllCookies(visitor))
{
visitor.WaitForAllCookie();
}
if (string.IsNullOrEmpty(domains))
{
return visitor.CookieList;
}
else
{
List<Cookie> list = new List<Cookie>();
foreach (string domain in domains.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
list.AddRange(visitor.CookieList.Where(p => p.Domain != null && p.Domain.Contains(domain.Trim())).ToList());
}
return list;
}
}
public static string GetCookie(string domains = "", ICookieManager cookieManager = null)
{
List<Cookie> cookieList = GetCookieList(domains, cookieManager);
string cookies = ParseCookieListToString(cookieList);
return cookies;
}
public static async Task SetCookieAsync(string domain, string cookies, ICookieManager cookieManager = null)
{
try
{
foreach (string cookie in cookies.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
{
int i = cookie.IndexOf('=');
if (i > 0)
{
string name = cookie.Substring(0, i).ToString().Trim();
string value = cookie.Substring(i + 1).ToString().Trim();
if (name.ToLower() == "expires" || name.ToLower() == "path" || name.ToLower() == "domain")
{
continue;
}
Cookie newCookie = new Cookie
{
Domain = domain,
Name = name,
Value = value,
Path = "/"
};
if (cookieManager == null)
{
bool result = await Cef.GetGlobalCookieManager().SetCookieAsync("http://" + domain, newCookie);
}
else
{
bool result = await cookieManager.SetCookieAsync("http://" + domain, newCookie);
}
}
}
}
catch { }
}
public static async Task SetCookieAsync(string cookieList, ICookieManager cookieManager = null)
{
try
{
if (!string.IsNullOrEmpty(cookieList))
{
List<Cookie> list = JsonConvert.DeserializeObject<List<Cookie>>(cookieList);
foreach (Cookie cookie in list)
{
cookie.Secure = false;
if (cookieManager == null)
{
bool result = await Cef.GetGlobalCookieManager().SetCookieAsync("http://" + cookie.Domain.Trim('.'), cookie);
}
else
{
bool result = await cookieManager.SetCookieAsync("http://" + cookie.Domain.Trim('.'), cookie);
}
}
}
}
catch (Exception ex)
{
LogHelper.WriteWithTime(ex);
}
}
public static async Task DeleteCookieAsync(ICookieManager cookieManager, string domain = "", string name = "")
{
string url = string.Empty;
if (!string.IsNullOrEmpty(domain))
{
url = "http://" + domain;
}
if (cookieManager == null)
{
int result = await Cef.GetGlobalCookieManager().DeleteCookiesAsync(url, name);
}
else
{
int result = await cookieManager.DeleteCookiesAsync(url, name);
}
}
public static void DeleteCookie(ICookieManager cookieManager, string domain = "", string name = "")
{
string url = string.Empty;
if (!string.IsNullOrEmpty(domain))
{
url = "http://" + domain;
}
if (cookieManager == null)
{
bool result = Cef.GetGlobalCookieManager().DeleteCookies(url, name);
}
else
{
bool result = cookieManager.DeleteCookies(url, name);
}
}
public static void ExecJavascript(ChromiumWebBrowser cefWebBrowser, string js)
{
// cef138
//List<long> frameIdentifierList = cefWebBrowser.GetBrowser().GetFrameIdentifiers();
//foreach (long identifier in frameIdentifierList)
List<string> frameIdentifierList = cefWebBrowser.GetBrowser().GetFrameIdentifiers();
foreach (string identifier in frameIdentifierList)
{
//IFrame frame = cefWebBrowser.GetBrowser().GetFrame(identifier);
IFrame frame = cefWebBrowser.GetBrowser().GetFrameByIdentifier(identifier);
if (frame.IsMain)
{
frame.ExecuteJavaScriptAsync(js);
break;
}
}
}
public static void ExecJavascript(ChromiumWebBrowser cefWebBrowser, string expectUrl, string js, Func<string, string, bool> checkUrl)
{
// cef138
//List<long> frameIdentifierList = cefWebBrowser.GetBrowser().GetFrameIdentifiers();
//foreach (long identifier in frameIdentifierList)
List<string> frameIdentifierList = cefWebBrowser.GetBrowser().GetFrameIdentifiers();
foreach (string identifier in frameIdentifierList)
{
//IFrame frame = cefWebBrowser.GetBrowser().GetFrame(identifier);
IFrame frame = cefWebBrowser.GetBrowser().GetFrameByIdentifier(identifier);
if (checkUrl(frame.Url, expectUrl))
{
frame.ExecuteJavaScriptAsync(js);
break;
}
}
}
public static void ExecJavascriptEqualsUrl(ChromiumWebBrowser cefWebBrowser, string url, string js)
{
ExecJavascript(cefWebBrowser, url, js, (frameUrl, expectUrl) =>
{
if (frameUrl.Equals(expectUrl))
{
return true;
}
else
{
return true;
}
});
}
public static void ExecJavascriptStartsWithUrl(ChromiumWebBrowser cefWebBrowser, string url, string js)
{
ExecJavascript(cefWebBrowser, url, js, (frameUrl, expectUrl) =>
{
if (frameUrl.StartsWith(expectUrl))
{
return true;
}
else
{
return true;
}
});
}
public static void ExecJavascriptContainsUrl(ChromiumWebBrowser cefWebBrowser, string url, string js)
{
ExecJavascript(cefWebBrowser, url, js, (frameUrl, expectUrl) =>
{
if (frameUrl.Contains(expectUrl))
{
return true;
}
else
{
return false;
}
});
}
public static JavascriptResponse EvaluateScript(ChromiumWebBrowser cefWebBrowser, string js)
{
JavascriptResponse javascriptResponse = null;
Task task = Task.Run(async () =>
{
javascriptResponse = await cefWebBrowser.GetBrowser().MainFrame.EvaluateScriptAsync(js);
return javascriptResponse;
});
task.Wait();
return javascriptResponse;
}
public static async Task<JavascriptResponse> EvaluateScriptAsync(ChromiumWebBrowser cefWebBrowser, string js)
{
JavascriptResponse javascriptResponse = await cefWebBrowser.GetBrowser().MainFrame.EvaluateScriptAsync(js);
return javascriptResponse;
}
public static async Task<JavascriptResponse> EvaluateScriptAsync(ChromiumWebBrowser cefWebBrowser, string url, string js, Func<string, string, bool> checkUrl)
{
// cef138
JavascriptResponse javascriptResponse = new JavascriptResponse();
//List<long> frameIdentifierList = cefWebBrowser.GetBrowser().GetFrameIdentifiers();
//foreach (long identifier in frameIdentifierList)
List<string> frameIdentifierList = cefWebBrowser.GetBrowser().GetFrameIdentifiers();
foreach (string identifier in frameIdentifierList)
{
//IFrame frame = cefWebBrowser.GetBrowser().GetFrame(identifier);
IFrame frame = cefWebBrowser.GetBrowser().GetFrameByIdentifier(identifier);
if (checkUrl(frame.Url, url))
{
javascriptResponse = await frame.EvaluateScriptAsync(js);
}
}
return javascriptResponse;
}
public static string GetElementLocation(ChromiumWebBrowser cefWebBrowser, string elementIdOrClass)
{
string js = @"function getElementLocation() {
var element = document.getElementById('{0}');
if (element == null || element == undefined) {
var elements = document.getElementsByClassName('{0}');
if(elements){
element = elements[0];
}
}
if (element == null || element == undefined)
{
return '0,0,0,0';
}
return element.getBoundingClientRect().left.toString() + ',' + element.getBoundingClientRect().top.toString() + ',' + (element.width?element.width.toString():element.getBoundingClientRect().width) + ',' + (element.height?element.height.toString():element.getBoundingClientRect().height);
}
getElementLocation();
";
string formatJs = js.Replace("{0}", elementIdOrClass);
Task<JavascriptResponse> task = cefWebBrowser.EvaluateScriptAsync(formatJs);
task.Wait(2000);
string location = task.Result.Result.ParseToString();
return location;
}
public static LocationPoint GetElementLocationPoint(ChromiumWebBrowser cefWebBrowser, string elementIdOrClass)
{
LocationPoint locationPoint = new LocationPoint();
string location = GetElementLocation(cefWebBrowser, elementIdOrClass);
if (location.Contains(","))
{
string[] xy = location.Split(',');
locationPoint.Left = xy[0].DecimalPointParseToInt();
locationPoint.Top = xy[1].DecimalPointParseToInt();
locationPoint.Width = xy[2].DecimalPointParseToInt();
locationPoint.Height = xy[3].DecimalPointParseToInt();
}
return locationPoint;
}
public static void SimulateMouseLeftClick(IBrowserHost host, int x, int y)
{
Random random = new Random(Guid.NewGuid().GetHashCode());
host.SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None); // 按下鼠标左键
Thread.Sleep(75 + random.Next(50));
host.SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None); // 松开鼠标左键
Thread.Sleep(300);
}
/// <summary>
/// 模拟鼠标滑动
/// </summary>
/// <param name="host"></param>
/// <param name="fromX">左边缘Left</param>
/// <param name="fromY">左边缘Top</param>
/// <param name="toX">右边缘Left</param>
/// <param name="toY">右边缘Top</param>
/// <param name="slideWidth">滑块的宽度</param>
/// <param name="slideHeight">滑块的高度</param>
public static void SimulateMouseMove(IBrowserHost host, int fromX, int fromY, int toX, int toY, int slideWidth = 0, int slideHeight = 0)
{
Thread.Sleep(RandomHelper.GetRandom(0, 50));
int randomX = 0;
int randomY = 0;
if (slideWidth == 0)
{
randomX = -2 + RandomHelper.GetRandom(0, 5);
}
else
{
randomX = RandomHelper.GetRandom(0, slideWidth);
}
if (slideHeight == 0)
{
randomY = -2 + RandomHelper.GetRandom(0, 5);
}
else
{
randomY = RandomHelper.GetRandom(0, slideHeight);
}
int x = fromX + randomX;
int y = fromY + randomY;
host.SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None); // 按下鼠标左键
Thread.Sleep(200 + RandomHelper.GetRandom(0, 200));
int times = 0;
while (x < toX - 4) // 后半部分
{
times++;
x += 4 + RandomHelper.GetRandom(0, 4);
y = y - 1 + RandomHelper.GetRandom(0, 3);
Thread.Sleep(6 + times / 6 + RandomHelper.GetRandom(0, 4));
host.SendMouseMoveEvent(x, y, false, CefEventFlags.LeftMouseButton); // 移动鼠标
}
x = toX - 1 + RandomHelper.GetRandom(0, 3);
Thread.Sleep(100 + RandomHelper.GetRandom(0, 100));
host.SendMouseMoveEvent(x, y, false, CefEventFlags.LeftMouseButton); // 移动鼠标
Thread.Sleep(400 + RandomHelper.GetRandom(0, 600));
host.SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None); // 抬起鼠标左键
}
public static void SimulateInputChar(IBrowserHost host, int key)
{
Random random = new Random();
host.SendKeyEvent(new KeyEvent() { WindowsKeyCode = key, Type = KeyEventType.KeyDown });
Thread.Sleep(10 + random.Next(10));
host.SendKeyEvent(new KeyEvent() { WindowsKeyCode = key, Type = KeyEventType.Char });
Thread.Sleep(50 + random.Next(40));
host.SendKeyEvent(new KeyEvent() { WindowsKeyCode = key, Type = KeyEventType.KeyUp });
Thread.Sleep(50 + random.Next(40));
}
}
}
@@ -0,0 +1,72 @@
using CefSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Work._29Tools.CefTools
{
public class LocalCookieVisitor : ICookieVisitor
{
public List<Cookie> CookieList;
public ManualResetEvent gotAllCookie = new ManualResetEvent(false);
public LocalCookieVisitor()
{
CookieList = new List<Cookie>();
}
public bool Visit(Cookie cookie, int count, int total, ref bool deleteCookie)
{
CookieList.Add(cookie);
if (count == total - 1)
{
gotAllCookie.Set();
}
return true;
}
public void WaitForAllCookie()
{
gotAllCookie.WaitOne();
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~CookieVisitor()
// {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
void IDisposable.Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
}
@@ -18,16 +18,16 @@ namespace Work._29Tools.CefTools
{
public string Url { get; set; }
}
public class LifeSpanHandlerLocal : ILifeSpanHandler
public class LocalLifeSpanHandler : ILifeSpanHandler
{
private PopWindowType popWindowType = PopWindowType.NewWindow;
public event EventHandler<PopData> OnPop;
public ChromiumWebBrowser parent;
public LifeSpanHandlerLocal()
public LocalLifeSpanHandler()
{
}
public LifeSpanHandlerLocal(PopWindowType _popWindowType)
public LocalLifeSpanHandler(PopWindowType _popWindowType)
{
popWindowType = _popWindowType;
}
+259
View File
@@ -0,0 +1,259 @@
using CefSharp;
using NaiBa.Util;
using NaiBa.Util.Extension;
using NaiBa.Util.Helper;
using NaiBa.Util.Model;
using NaiBa.Util.Winform.Forms;
using NaiBa.Util.Winform.Helper;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Work._29Tools.CefTools
{
public class LocalMenuHandler : IContextMenuHandler
{
public List<CefContextMenu> ContextMenuList;
public Func<List<Cookie>, TData> SaveCookie;
public List<Cookie> CookieList;
void IContextMenuHandler.OnBeforeContextMenu(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model)
{
model.Clear();
bool hasCopyPaste = false;
if ((parameters.EditStateFlags & ContextMenuEditState.CanCopy).ParseToInt() != 0)
{
model.AddItem(CefMenuCommand.Copy, "复制");
hasCopyPaste = true;
}
if ((parameters.EditStateFlags & ContextMenuEditState.CanPaste).ParseToInt() != 0)
{
model.AddItem(CefMenuCommand.Paste, "粘贴");
hasCopyPaste = true;
}
if (hasCopyPaste)
{
model.AddSeparator();
}
model.AddItem(CefMenuCommand.Back, "后退");
model.AddItem(CefMenuCommand.Forward, "前进");
model.AddItem(CefMenuCommand.ReloadNoCache, "刷新");
model.AddSeparator();
model.AddItem(CefMenuCommand.ViewSource, "查看页面源代码");
model.AddSeparator();
model.AddItem((CefMenuCommand)26500, "复制页面地址");
if (parameters.MediaType == ContextMenuMediaType.Image)
{
model.AddSeparator();
model.AddItem((CefMenuCommand)26600, "复制图片地址");
model.AddItem((CefMenuCommand)26601, "保存图片");
if (NaiBaGlobalConfig.IsNewFeature)
{
model.AddSeparator();
model.AddItem((CefMenuCommand)26700, "识别图片文字");
}
}
if ((parameters.EditStateFlags & ContextMenuEditState.CanTranslate).ParseToInt() != 0)
{
model.AddSeparator();
model.AddItem((CefMenuCommand)26800, "翻译网页");
}
if (SaveCookie != null)
{
model.AddSeparator();
model.AddItem((CefMenuCommand)26900, "保存 Cookie");
}
if (ContextMenuList != null && ContextMenuList.Any())
{
model.AddSeparator();
if (ContextMenuList.Where(p => p.CommandCode < 28000 || p.CommandCode > 28500).Any())
{
BaseMsgTipFormHelper.ShowError("Cef右键菜单,无效的 CommandCode,CommandCode 的范围 28000-28500");
return;
}
foreach (var menu in ContextMenuList)
{
model.AddItem((CefMenuCommand)menu.CommandCode, menu.CommandText);
}
}
}
public bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags)
{
if (commandId == (CefMenuCommand)26500)
{
string url = parameters.PageUrl;
if (!string.IsNullOrEmpty(url))
{
Clipboard.SetText(url);
BaseMsgTipFormHelper.ShowInfo("复制页面地址到剪贴板成功");
}
else
{
BaseMsgTipFormHelper.ShowError("复制页面地址到剪贴板失败");
}
return true;
}
if (commandId == (CefMenuCommand)26600)
{
string url = parameters.SourceUrl;
if (!string.IsNullOrEmpty(url))
{
Clipboard.SetText(url);
BaseMsgTipFormHelper.ShowInfo("复制图片地址到剪贴板成功");
}
else
{
BaseMsgTipFormHelper.ShowError("复制图片地址到剪贴板失败");
}
return true;
}
if (commandId == (CefMenuCommand)26601)
{
string url = parameters.SourceUrl;
SaveFileDialog dialog = FormDialogHelper.SaveFileDialogCustom(Path.GetFileNameWithoutExtension(url), Path.GetExtension(url), false, false);
if (dialog != null)
{
try
{
HttpHelper.DownloadFile(new HttpParam { Url = url }, dialog.FileName);
}
catch (Exception ex)
{
LogHelper.WriteWithTime(ex);
}
}
return true;
}
if (commandId == (CefMenuCommand)26700)
{
string url = parameters.SourceUrl;
try
{
if (NaiBaGlobalConfig.ImageOCR != null)
{
var byteArr = HttpHelper.GetByte(new HttpParam { Url = url });
var obj = NaiBaGlobalConfig.ImageOCR(Convert.ToBase64String(byteArr));
if (obj.Tag == 1)
{
FileHelper.OpenNotepad(string.Join(Environment.NewLine, obj.Data));
}
else
{
BaseMsgFormHelper.ShowError(obj.Message);
}
}
}
catch (Exception ex)
{
LogHelper.WriteWithTime(ex);
}
return true;
}
if (commandId == (CefMenuCommand)26800)
{
try
{
string fileName = "NaiBa.CefHelper.Resources.google_translate.js";
string js = FileHelper.GetResourceFileContent(Assembly.GetExecutingAssembly(), fileName);
browser.MainFrame.ExecuteJavaScriptAsync(js);
}
catch (Exception ex)
{
LogHelper.WriteWithTime(ex);
}
return true;
}
if (commandId == (CefMenuCommand)26900)
{
try
{
if (CookieList == null)
{
BaseMsgTipFormHelper.ShowError("未获取到 Cookie,请等待页面加载完后再试");
}
else
{
var obj = SaveCookie(CookieList);
if (obj.Tag == 1)
{
BaseMsgTipFormHelper.ShowInfo("保存 Cookie 成功");
}
else
{
BaseMsgTipFormHelper.ShowError("保存 Cookie 失败:" + obj.Message);
}
}
}
catch (Exception ex)
{
LogHelper.WriteWithTime(ex);
}
return true;
}
if ((int)commandId >= 28000 && (int)commandId <= 28500)
{
if (ContextMenuList != null)
{
var contextMenu = ContextMenuList.Where(p => p.CommandCode == (int)commandId).FirstOrDefault();
if (contextMenu != null)
{
try
{
contextMenu.CommandAction?.Invoke(parameters);
}
catch (Exception ex)
{
LogHelper.WriteWithTime(ex);
}
return true;
}
}
}
// Return false should ignore the selected option of the user !
return false;
}
void IContextMenuHandler.OnContextMenuDismissed(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame)
{
}
bool IContextMenuHandler.RunContextMenu(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback)
{
return false;
}
}
public class CefContextMenu
{
public int CommandCode { get; set; }
public string CommandText { get; set; }
public Action<IContextMenuParams> CommandAction { get; set; }
}
}
@@ -0,0 +1,290 @@
using CefSharp;
using CefSharp.Handler;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace Work._29Tools.CefTools
{
public class LocalRequestHandler : IRequestHandler
{
/// <summary>
/// 代理用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 代理密码
/// </summary>
public string Password { get; set; }
private ResourceRequestHandler resourceRequestHandler;
public LocalRequestHandler()
{
}
public LocalRequestHandler(ResourceRequestHandler customResourceRequestHandler)
{
resourceRequestHandler = customResourceRequestHandler;
}
void IRequestHandler.OnDocumentAvailableInMainFrame(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
}
bool IRequestHandler.OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
{
return OnBeforeBrowse(chromiumWebBrowser, browser, frame, request, userGesture, isRedirect);
}
/// <summary>
/// Called before browser navigation. If the navigation is allowed <see cref="IWebBrowser.FrameLoadStart"/> and
/// <see cref="IWebBrowser.FrameLoadEnd"/>
/// will be called. If the navigation is canceled <see cref="IWebBrowser.LoadError"/> will be called with an ErrorCode value of
/// <see cref="CefErrorCode.Aborted"/>.
/// </summary>
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
/// <param name="browser">the browser object.</param>
/// <param name="frame">The frame the request is coming from.</param>
/// <param name="request">the request object - cannot be modified in this callback.</param>
/// <param name="userGesture">The value will be true if the browser navigated via explicit user gesture (e.g. clicking a link) or
/// false if it navigated automatically (e.g. via the DomContentLoaded event).</param>
/// <param name="isRedirect">has the request been redirected.</param>
/// <returns>
/// Return true to cancel the navigation or false to allow the navigation to proceed.
/// </returns>
protected virtual bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
{
return false;
}
/// <inheritdoc/>
bool IRequestHandler.OnOpenUrlFromTab(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
{
return OnOpenUrlFromTab(chromiumWebBrowser, browser, frame, targetUrl, targetDisposition, userGesture);
}
/// <summary>
/// Called on the UI thread before OnBeforeBrowse in certain limited cases where navigating a new or different browser might be
/// desirable. This includes user-initiated navigation that might open in a special way (e.g. links clicked via middle-click or
/// ctrl + left-click) and certain types of cross-origin navigation initiated from the renderer process (e.g. navigating the top-
/// level frame to/from a file URL).
/// </summary>
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
/// <param name="browser">the browser object.</param>
/// <param name="frame">The frame object.</param>
/// <param name="targetUrl">target url.</param>
/// <param name="targetDisposition">The value indicates where the user intended to navigate the browser based on standard
/// Chromium behaviors (e.g. current tab, new tab, etc).</param>
/// <param name="userGesture">The value will be true if the browser navigated via explicit user gesture (e.g. clicking a link) or
/// false if it navigated automatically (e.g. via the DomContentLoaded event).</param>
/// <returns>
/// Return true to cancel the navigation or false to allow the navigation to proceed in the source browser's top-level frame.
/// </returns>
protected virtual bool OnOpenUrlFromTab(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
{
return false;
}
/// <inheritdoc/>
IResourceRequestHandler IRequestHandler.GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
{
return GetResourceRequestHandler(chromiumWebBrowser, browser, frame, request, isNavigation, isDownload, requestInitiator, ref disableDefaultHandling);
}
/// <summary>
/// Called on the CEF IO thread before a resource request is initiated.
/// </summary>
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
/// <param name="browser">represent the source browser of the request.</param>
/// <param name="frame">represent the source frame of the request.</param>
/// <param name="request">represents the request contents and cannot be modified in this callback.</param>
/// <param name="isNavigation">will be true if the resource request is a navigation.</param>
/// <param name="isDownload">will be true if the resource request is a download.</param>
/// <param name="requestInitiator">is the origin (scheme + domain) of the page that initiated the request.</param>
/// <param name="disableDefaultHandling">[in,out] to true to disable default handling of the request, in which case it will need
/// to be handled via <see cref="IResourceRequestHandler.GetResourceHandler"/> or it will be canceled.</param>
/// <returns>
/// To allow the resource load to proceed with default handling return null. To specify a handler for the resource return a
/// <see cref="IResourceRequestHandler"/> object. If this callback returns null the same method will be called on the associated
/// <see cref="IRequestContextHandler"/>, if any.
/// </returns>
protected virtual IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
{
return resourceRequestHandler;
}
/// <inheritdoc/>
bool IRequestHandler.GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
{
return GetAuthCredentials(chromiumWebBrowser, browser, originUrl, isProxy, host, port, realm, scheme, callback);
}
/// <summary>
/// Called when the browser needs credentials from the user.
/// </summary>
/// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
/// <param name="browser">the browser object.</param>
/// <param name="originUrl">is the origin making this authentication request.</param>
/// <param name="isProxy">indicates whether the host is a proxy server.</param>
/// <param name="host">hostname.</param>
/// <param name="port">port number.</param>
/// <param name="realm">realm.</param>
/// <param name="scheme">scheme.</param>
/// <param name="callback">Callback interface used for asynchronous continuation of authentication requests.</param>
/// <returns>
/// Return true to continue the request and call <see cref="IAuthCallback.Continue(string, string)"/> when the authentication
/// information is available. Return false to cancel the request.
/// </returns>
protected virtual bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
{
if (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password))
{
callback.Continue(UserName, Password);
return true;
}
callback.Dispose();
return false;
}
/// <inheritdoc/>
//bool IRequestHandler.OnQuotaRequest(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, long newSize, IRequestCallback callback)
//{
// return OnQuotaRequest(chromiumWebBrowser, browser, originUrl, newSize, callback);
//}//cef138
/// <summary>
/// Called when JavaScript requests a specific storage quota size via the webkitStorageInfo.requestQuota function. For async
/// processing return true and execute <see cref="IRequestCallback.Continue"/> at a later time to grant or deny the request or
/// <see cref="IRequestCallback.Cancel"/> to cancel.
/// </summary>
/// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
/// <param name="browser">the browser object.</param>
/// <param name="originUrl">the origin of the page making the request.</param>
/// <param name="newSize">is the requested quota size in bytes.</param>
/// <param name="callback">Callback interface used for asynchronous continuation of url requests.</param>
/// <returns>
/// Return false to cancel the request immediately. Return true to continue the request and call
/// <see cref="IRequestCallback.Continue"/> either in this method or at a later time to grant or deny the request.
/// </returns>
protected virtual bool OnQuotaRequest(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, long newSize, IRequestCallback callback)
{
callback.Dispose();
return false;
}
/// <inheritdoc/>
bool IRequestHandler.OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback)
{
return OnCertificateError(chromiumWebBrowser, browser, errorCode, requestUrl, sslInfo, callback);
}
void IRequestHandler.OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status, int errorCode, string errorMessage)
{
//cef138
}
/// <summary>
/// Called to handle requests for URLs with an invalid SSL certificate. Return true and call
/// <see cref="IRequestCallback.Continue"/> either in this method or at a later time to continue or cancel the request.
/// If CefSettings.IgnoreCertificateErrors is set all invalid certificates will be accepted without calling this method.
/// </summary>
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
/// <param name="browser">the browser object.</param>
/// <param name="errorCode">the error code for this invalid certificate.</param>
/// <param name="requestUrl">the url of the request for the invalid certificate.</param>
/// <param name="sslInfo">ssl certificate information.</param>
/// <param name="callback">Callback interface used for asynchronous continuation of url requests. If empty the error cannot be
/// recovered from and the request will be canceled automatically.</param>
/// <returns>
/// Return false to cancel the request immediately. Return true and use <see cref="IRequestCallback"/> to execute in an async
/// fashion.
/// </returns>
protected virtual bool OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback)
{
callback.Dispose();
return false;
}
/// <inheritdoc/>
bool IRequestHandler.OnSelectClientCertificate(IWebBrowser chromiumWebBrowser, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback)
{
return OnSelectClientCertificate(chromiumWebBrowser, browser, isProxy, host, port, certificates, callback);
}
/// <summary>
/// Called when the browser needs user to select Client Certificate for authentication requests (eg. PKI authentication).
/// </summary>
/// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
/// <param name="browser">the browser object.</param>
/// <param name="isProxy">indicates whether the host is a proxy server.</param>
/// <param name="host">hostname.</param>
/// <param name="port">port number.</param>
/// <param name="certificates">List of Client certificates for selection.</param>
/// <param name="callback">Callback interface used for asynchronous continuation of client certificate selection for
/// authentication requests.</param>
/// <returns>
/// Return true to continue the request and call ISelectClientCertificateCallback.Select() with the selected certificate for
/// authentication. Return false to use the default behavior where the browser selects the first certificate from the list.
///
/// </returns>
protected virtual bool OnSelectClientCertificate(IWebBrowser chromiumWebBrowser, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback)
{
callback.Dispose();
return false;
}
/// <inheritdoc/>
//void IRequestHandler.OnPluginCrashed(IWebBrowser chromiumWebBrowser, IBrowser browser, string pluginPath)
//{
// OnPluginCrashed(chromiumWebBrowser, browser, pluginPath);
//}//cef138
/// <summary>
/// Called when a plugin has crashed.
/// </summary>
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control.</param>
/// <param name="browser">the browser object.</param>
/// <param name="pluginPath">path of the plugin that crashed.</param>
protected virtual void OnPluginCrashed(IWebBrowser chromiumWebBrowser, IBrowser browser, string pluginPath)
{
}
/// <inheritdoc/>
void IRequestHandler.OnRenderViewReady(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
OnRenderViewReady(chromiumWebBrowser, browser);
}
/// <summary>
/// Called on the CEF UI thread when the render view associated with browser is ready to receive/handle IPC messages in the
/// render process.
/// </summary>
/// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
/// <param name="browser">the browser object.</param>
protected virtual void OnRenderViewReady(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
}
/// <inheritdoc/>
//void IRequestHandler.OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status)
//{
// OnRenderProcessTerminated(chromiumWebBrowser, browser, status);
//}//cef138
/// <summary>
/// Called when the render process terminates unexpectedly.
/// </summary>
/// <param name="chromiumWebBrowser">The ChromiumWebBrowser control.</param>
/// <param name="browser">the browser object.</param>
/// <param name="status">indicates how the process terminated.</param>
protected virtual void OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status)
{
}
}
}
@@ -53,7 +53,7 @@ namespace Work._29Tools.CefTools
}
}
public class CustomResourceRequestHandlerLocal : BaseResourceRequestHandler
public class LocalResourceRequestHandler : BaseResourceRequestHandler
{
private ConcurrentDictionary<ulong, MemoryStream> responseDict = new ConcurrentDictionary<ulong, MemoryStream>();