Skip to content

📢 FBro JavaScript对话框控制指南

完全控制网页中的JavaScript弹窗对话框,包括alert、confirm、prompt等所有类型的弹窗


📋 概述

FBro浏览器提供了强大的JavaScript对话框拦截功能,通过重写OnJSDialog方法,开发者可以完全控制网页中所有JavaScript弹窗的行为。这个功能对于自动化脚本、无人值守应用和用户体验优化非常重要。

🎯 主要功能

  • 完全阻止JavaScript弹窗
  • 自动处理弹窗并返回预设值
  • 记录和分析弹窗内容
  • 自定义弹窗响应逻辑

🔧 核心实现

OnJSDialog方法详解

csharp
/// <summary>
/// JavaScript对话框事件处理器
/// 当网页尝试显示JavaScript对话框时触发
/// </summary>
/// <param name="browser">触发对话框的浏览器实例</param>
/// <param name="origin_url">触发对话框的页面URL</param>
/// <param name="dialog_type">对话框类型(alert、confirm、prompt)</param>
/// <param name="message_text">对话框显示的消息文本</param>
/// <param name="default_prompt_text">prompt对话框的默认输入值</param>
/// <param name="callback">对话框回调接口,用于响应用户操作</param>
/// <param name="suppress_message">是否抑制消息显示</param>
/// <returns>true表示已处理该对话框,false表示使用默认处理</returns>
public override bool OnJSDialog(IFBroSharpBrowser browser, 
    string origin_url, 
    FBroJsDialogType dialog_type, 
    string message_text, 
    string default_prompt_text, 
    IFBroSharpJSDialogCallback callback, 
    ref bool suppress_message)
{
    // 记录对话框信息
    Console.WriteLine($"JS对话框 - 类型: {dialog_type}, URL: {origin_url}");
    Console.WriteLine($"消息: {message_text}");
    
    // 根据对话框类型执行不同的处理逻辑
    switch (dialog_type)
    {
        case FBroJsDialogType.JSDIALOGTYPE_ALERT:
            return HandleAlert(callback, message_text, origin_url);
            
        case FBroJsDialogType.JSDIALOGTYPE_CONFIRM:
            return HandleConfirm(callback, message_text, origin_url);
            
        case FBroJsDialogType.JSDIALOGTYPE_PROMPT:
            return HandlePrompt(callback, message_text, default_prompt_text, origin_url);
            
        default:
            return HandleDefault(callback);
    }
}

📖 参数说明

参数名类型说明
browserIFBroSharpBrowser触发对话框的浏览器实例
origin_urlstring触发对话框的页面URL
dialog_typeFBroJsDialogType对话框类型枚举值
message_textstring对话框显示的消息内容
default_prompt_textstringprompt对话框的默认输入值
callbackIFBroSharpJSDialogCallback对话框响应回调接口
suppress_messageref bool是否抑制消息显示(引用参数)

FBroJsDialogType枚举值

枚举值说明JavaScript对应
JSDIALOGTYPE_ALERT警告对话框alert()
JSDIALOGTYPE_CONFIRM确认对话框confirm()
JSDIALOGTYPE_PROMPT输入对话框prompt()

🎯 处理策略实现

1. Alert对话框处理

csharp
/// <summary>
/// 处理alert对话框
/// </summary>
/// <param name="callback">对话框回调</param>
/// <param name="message">消息内容</param>
/// <param name="url">来源URL</param>
/// <returns>是否已处理</returns>
private bool HandleAlert(IFBroSharpJSDialogCallback callback, string message, string url)
{
    Console.WriteLine($"Alert对话框被拦截: {message}");
    
    // 记录alert信息到日志
    LogDialogInfo("ALERT", message, url);
    
    // 自动确认alert对话框
    callback.Continue(true, string.Empty);
    
    return true; // 表示已处理,不显示原生对话框
}

2. Confirm对话框处理

csharp
/// <summary>
/// 处理confirm对话框
/// </summary>
/// <param name="callback">对话框回调</param>
/// <param name="message">消息内容</param>
/// <param name="url">来源URL</param>
/// <returns>是否已处理</returns>
private bool HandleConfirm(IFBroSharpJSDialogCallback callback, string message, string url)
{
    Console.WriteLine($"Confirm对话框被拦截: {message}");
    
    // 根据消息内容智能判断响应
    bool shouldConfirm = DetermineConfirmResponse(message, url);
    
    LogDialogInfo("CONFIRM", message, url, shouldConfirm.ToString());
    
    // 响应confirm对话框
    callback.Continue(shouldConfirm, string.Empty);
    
    return true;
}

/// <summary>
/// 智能判断confirm对话框的响应
/// </summary>
/// <param name="message">对话框消息</param>
/// <param name="url">来源URL</param>
/// <returns>是否确认</returns>
private bool DetermineConfirmResponse(string message, string url)
{
    // 可以根据具体需求自定义判断逻辑
    
    // 示例:包含"删除"关键词的确认框返回false
    if (message.Contains("删除") || message.Contains("delete"))
    {
        return false;
    }
    
    // 示例:包含"保存"关键词的确认框返回true
    if (message.Contains("保存") || message.Contains("save"))
    {
        return true;
    }
    
    // 示例:特定网站的默认处理
    if (url.Contains("example.com"))
    {
        return true;
    }
    
    // 默认返回true
    return true;
}

3. Prompt对话框处理

csharp
/// <summary>
/// 处理prompt对话框
/// </summary>
/// <param name="callback">对话框回调</param>
/// <param name="message">消息内容</param>
/// <param name="defaultValue">默认输入值</param>
/// <param name="url">来源URL</param>
/// <returns>是否已处理</returns>
private bool HandlePrompt(IFBroSharpJSDialogCallback callback, string message, 
    string defaultValue, string url)
{
    Console.WriteLine($"Prompt对话框被拦截: {message}");
    Console.WriteLine($"默认值: {defaultValue}");
    
    // 生成智能响应值
    string responseValue = GeneratePromptResponse(message, defaultValue, url);
    
    LogDialogInfo("PROMPT", message, url, responseValue);
    
    // 响应prompt对话框
    callback.Continue(true, responseValue);
    
    return true;
}

/// <summary>
/// 生成prompt对话框的智能响应
/// </summary>
/// <param name="message">对话框消息</param>
/// <param name="defaultValue">默认值</param>
/// <param name="url">来源URL</param>
/// <returns>响应值</returns>
private string GeneratePromptResponse(string message, string defaultValue, string url)
{
    // 优先使用默认值
    if (!string.IsNullOrEmpty(defaultValue))
    {
        return defaultValue;
    }
    
    // 根据消息内容判断合适的响应
    if (message.Contains("用户名") || message.Contains("username"))
    {
        return "AutoUser";
    }
    
    if (message.Contains("密码") || message.Contains("password"))
    {
        return "AutoPassword123";
    }
    
    if (message.Contains("邮箱") || message.Contains("email"))
    {
        return "auto@example.com";
    }
    
    if (message.Contains("数量") || message.Contains("count"))
    {
        return "1";
    }
    
    // 默认返回空字符串
    return string.Empty;
}

4. 默认处理器

csharp
/// <summary>
/// 默认对话框处理器
/// </summary>
/// <param name="callback">对话框回调</param>
/// <returns>是否已处理</returns>
private bool HandleDefault(IFBroSharpJSDialogCallback callback)
{
    Console.WriteLine("未知类型的JS对话框被拦截");
    
    // 默认确认并关闭
    callback.Continue(true, string.Empty);
    
    return true;
}

📝 日志记录系统

对话框日志记录

csharp
/// <summary>
/// 记录对话框信息到日志
/// </summary>
/// <param name="type">对话框类型</param>
/// <param name="message">消息内容</param>
/// <param name="url">来源URL</param>
/// <param name="response">响应值(可选)</param>
private void LogDialogInfo(string type, string message, string url, string response = null)
{
    var logEntry = new DialogLogEntry
    {
        Timestamp = DateTime.Now,
        Type = type,
        Message = message,
        OriginUrl = url,
        Response = response ?? "N/A"
    };
    
    // 记录到控制台
    Console.WriteLine($"[{logEntry.Timestamp:yyyy-MM-dd HH:mm:ss}] " +
                     $"{type} - {message} (URL: {GetDomainFromUrl(url)})");
    
    // 记录到文件(可选)
    WriteLogToFile(logEntry);
    
    // 记录到内存列表(用于统计分析)
    dialogLogs.Add(logEntry);
}

/// <summary>
/// 对话框日志条目
/// </summary>
public class DialogLogEntry
{
    public DateTime Timestamp { get; set; }
    public string Type { get; set; }
    public string Message { get; set; }
    public string OriginUrl { get; set; }
    public string Response { get; set; }
}

/// <summary>
/// 对话框日志列表
/// </summary>
private readonly List<DialogLogEntry> dialogLogs = new List<DialogLogEntry>();

/// <summary>
/// 从URL提取域名
/// </summary>
/// <param name="url">完整URL</param>
/// <returns>域名</returns>
private string GetDomainFromUrl(string url)
{
    try
    {
        var uri = new Uri(url);
        return uri.Host;
    }
    catch
    {
        return url;
    }
}

/// <summary>
/// 将日志写入文件
/// </summary>
/// <param name="logEntry">日志条目</param>
private void WriteLogToFile(DialogLogEntry logEntry)
{
    try
    {
        var logDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "FBroLogs");
        if (!Directory.Exists(logDir))
        {
            Directory.CreateDirectory(logDir);
        }
        
        var logFile = Path.Combine(logDir, $"JSDialogs_{DateTime.Now:yyyyMMdd}.log");
        var logLine = $"{logEntry.Timestamp:yyyy-MM-dd HH:mm:ss}|{logEntry.Type}|{logEntry.Message}|{logEntry.OriginUrl}|{logEntry.Response}";
        
        File.AppendAllText(logFile, logLine + Environment.NewLine, System.Text.Encoding.UTF8);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"写入日志文件失败: {ex.Message}");
    }
}

⚙️ 配置管理系统

灵活的配置选项

csharp
/// <summary>
/// JavaScript对话框处理配置
/// </summary>
public class JSDialogConfig
{
    /// <summary>
    /// 是否启用对话框拦截
    /// </summary>
    public bool EnableInterception { get; set; } = true;
    
    /// <summary>
    /// 是否记录日志
    /// </summary>
    public bool EnableLogging { get; set; } = true;
    
    /// <summary>
    /// Alert对话框的默认处理方式
    /// </summary>
    public DialogHandleMode AlertHandleMode { get; set; } = DialogHandleMode.AutoConfirm;
    
    /// <summary>
    /// Confirm对话框的默认响应
    /// </summary>
    public bool DefaultConfirmResponse { get; set; } = true;
    
    /// <summary>
    /// Prompt对话框的默认响应值
    /// </summary>
    public string DefaultPromptResponse { get; set; } = "";
    
    /// <summary>
    /// 白名单URL列表(这些URL的对话框将正常显示)
    /// </summary>
    public List<string> WhitelistUrls { get; set; } = new List<string>();
    
    /// <summary>
    /// 黑名单URL列表(这些URL的对话框将被完全阻止)
    /// </summary>
    public List<string> BlacklistUrls { get; set; } = new List<string>();
}

/// <summary>
/// 对话框处理模式
/// </summary>
public enum DialogHandleMode
{
    /// <summary>
    /// 自动确认
    /// </summary>
    AutoConfirm,
    
    /// <summary>
    /// 完全阻止
    /// </summary>
    Block,
    
    /// <summary>
    /// 显示原生对话框
    /// </summary>
    ShowNative,
    
    /// <summary>
    /// 自定义处理
    /// </summary>
    Custom
}

/// <summary>
/// 配置实例
/// </summary>
private JSDialogConfig config = new JSDialogConfig();

/// <summary>
/// 加载配置文件
/// </summary>
public void LoadConfig(string configPath = null)
{
    try
    {
        configPath = configPath ?? Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), 
            "FBro", "JSDialogConfig.json");
        
        if (File.Exists(configPath))
        {
            var json = File.ReadAllText(configPath, System.Text.Encoding.UTF8);
            config = Newtonsoft.Json.JsonConvert.DeserializeObject<JSDialogConfig>(json) ?? new JSDialogConfig();
            Console.WriteLine($"配置文件已加载: {configPath}");
        }
        else
        {
            SaveConfig(configPath); // 保存默认配置
            Console.WriteLine($"创建默认配置文件: {configPath}");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"加载配置失败: {ex.Message},使用默认配置");
        config = new JSDialogConfig();
    }
}

/// <summary>
/// 保存配置文件
/// </summary>
public void SaveConfig(string configPath = null)
{
    try
    {
        configPath = configPath ?? Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), 
            "FBro", "JSDialogConfig.json");
        
        var directory = Path.GetDirectoryName(configPath);
        if (!Directory.Exists(directory))
        {
            Directory.CreateDirectory(directory);
        }
        
        var json = Newtonsoft.Json.JsonConvert.SerializeObject(config, Newtonsoft.Json.Formatting.Indented);
        File.WriteAllText(configPath, json, System.Text.Encoding.UTF8);
        
        Console.WriteLine($"配置文件已保存: {configPath}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"保存配置失败: {ex.Message}");
    }
}

🎯 实际应用场景

场景1:完全阻止所有弹窗

csharp
/// <summary>
/// 简单粗暴的完全阻止模式
/// 适用于自动化脚本和无人值守应用
/// </summary>
public override bool OnJSDialog(IFBroSharpBrowser browser, 
    string origin_url, 
    FBroJsDialogType dialog_type, 
    string message_text, 
    string default_prompt_text, 
    IFBroSharpJSDialogCallback callback, 
    ref bool suppress_message)
{
    // 记录但不显示
    Console.WriteLine($"阻止JS对话框: {dialog_type} - {message_text}");
    
    // 自动确认并提供合理的默认值
    string defaultResponse = dialog_type == FBroJsDialogType.JSDIALOGTYPE_PROMPT ? "auto" : "";
    callback.Continue(true, defaultResponse);
    
    return true; // 完全接管,不显示原生对话框
}

场景2:智能处理模式

csharp
/// <summary>
/// 智能处理模式实现
/// 根据内容和来源智能判断处理方式
/// </summary>
public override bool OnJSDialog(IFBroSharpBrowser browser, 
    string origin_url, 
    FBroJsDialogType dialog_type, 
    string message_text, 
    string default_prompt_text, 
    IFBroSharpJSDialogCallback callback, 
    ref bool suppress_message)
{
    // 检查是否在白名单中
    if (IsUrlInWhitelist(origin_url))
    {
        Console.WriteLine($"白名单URL,显示原生对话框: {origin_url}");
        return false; // 显示原生对话框
    }
    
    // 检查是否在黑名单中
    if (IsUrlInBlacklist(origin_url))
    {
        Console.WriteLine($"黑名单URL,完全阻止: {origin_url}");
        callback.Continue(false, ""); // 取消操作
        return true;
    }
    
    // 检查是否为重要提示
    if (IsImportantMessage(message_text))
    {
        Console.WriteLine($"重要消息,显示原生对话框: {message_text}");
        return false; // 显示原生对话框
    }
    
    // 其他情况自动处理
    return HandleDialog(dialog_type, message_text, default_prompt_text, callback);
}

/// <summary>
/// 检查URL是否在白名单中
/// </summary>
private bool IsUrlInWhitelist(string url)
{
    return config.WhitelistUrls.Any(whiteUrl => 
        url.IndexOf(whiteUrl, StringComparison.OrdinalIgnoreCase) >= 0);
}

/// <summary>
/// 检查URL是否在黑名单中
/// </summary>
private bool IsUrlInBlacklist(string url)
{
    return config.BlacklistUrls.Any(blackUrl => 
        url.IndexOf(blackUrl, StringComparison.OrdinalIgnoreCase) >= 0);
}

/// <summary>
/// 检查是否为重要消息
/// </summary>
private bool IsImportantMessage(string message)
{
    string[] importantKeywords = { "错误", "error", "失败", "failed", "警告", "warning" };
    return importantKeywords.Any(keyword => 
        message.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0);
}

场景3:数据收集模式

csharp
/// <summary>
/// 数据收集模式
/// 专门用于分析网站的JavaScript对话框使用情况
/// </summary>
public class DialogAnalyzer
{
    private readonly Dictionary<string, List<DialogData>> dialogsByDomain = new Dictionary<string, List<DialogData>>();
    
    public override bool OnJSDialog(IFBroSharpBrowser browser, 
        string origin_url, 
        FBroJsDialogType dialog_type, 
        string message_text, 
        string default_prompt_text, 
        IFBroSharpJSDialogCallback callback, 
        ref bool suppress_message)
    {
        // 收集对话框数据
        var dialogData = new DialogData
        {
            Timestamp = DateTime.Now,
            Url = origin_url,
            Type = dialog_type,
            Message = message_text,
            DefaultValue = default_prompt_text
        };
        
        var domain = GetDomainFromUrl(origin_url);
        if (!dialogsByDomain.ContainsKey(domain))
        {
            dialogsByDomain[domain] = new List<DialogData>();
        }
        dialogsByDomain[domain].Add(dialogData);
        
        // 自动处理对话框
        callback.Continue(true, GetSmartResponse(dialog_type, message_text, default_prompt_text));
        
        // 定期生成分析报告
        if (dialogsByDomain.Values.Sum(list => list.Count) % 50 == 0)
        {
            GenerateAnalysisReport();
        }
        
        return true;
    }
    
    /// <summary>
    /// 生成分析报告
    /// </summary>
    private void GenerateAnalysisReport()
    {
        Console.WriteLine("\n=== JavaScript对话框分析报告 ===");
        foreach (var domain in dialogsByDomain.Keys)
        {
            var dialogs = dialogsByDomain[domain];
            Console.WriteLine($"\n域名: {domain}");
            Console.WriteLine($"  总对话框数: {dialogs.Count}");
            Console.WriteLine($"  Alert数: {dialogs.Count(d => d.Type == FBroJsDialogType.JSDIALOGTYPE_ALERT)}");
            Console.WriteLine($"  Confirm数: {dialogs.Count(d => d.Type == FBroJsDialogType.JSDIALOGTYPE_CONFIRM)}");
            Console.WriteLine($"  Prompt数: {dialogs.Count(d => d.Type == FBroJsDialogType.JSDIALOGTYPE_PROMPT)}");
            
            // 显示最常见的消息
            var commonMessages = dialogs.GroupBy(d => d.Message)
                .OrderByDescending(g => g.Count())
                .Take(3);
            Console.WriteLine("  常见消息:");
            foreach (var msg in commonMessages)
            {
                Console.WriteLine($"    \"{msg.Key}\" (出现{msg.Count()}次)");
            }
        }
        Console.WriteLine("================================\n");
    }
}

/// <summary>
/// 对话框数据结构
/// </summary>
public class DialogData
{
    public DateTime Timestamp { get; set; }
    public string Url { get; set; }
    public FBroJsDialogType Type { get; set; }
    public string Message { get; set; }
    public string DefaultValue { get; set; }
}

🛠️ 高级功能

自定义对话框替换

csharp
/// <summary>
/// 自定义对话框管理器
/// 用自定义UI替换原生JavaScript对话框
/// </summary>
public class CustomDialogManager
{
    /// <summary>
    /// 显示自定义Alert对话框
    /// </summary>
    public void ShowCustomAlert(string message, string title = "提示")
    {
        // 这里可以显示自定义的WPF或WinForms对话框
        System.Windows.Forms.MessageBox.Show(message, title, 
            System.Windows.Forms.MessageBoxButtons.OK, 
            System.Windows.Forms.MessageBoxIcon.Information);
    }
    
    /// <summary>
    /// 显示自定义Confirm对话框
    /// </summary>
    public bool ShowCustomConfirm(string message, string title = "确认")
    {
        var result = System.Windows.Forms.MessageBox.Show(message, title, 
            System.Windows.Forms.MessageBoxButtons.YesNo, 
            System.Windows.Forms.MessageBoxIcon.Question);
        
        return result == System.Windows.Forms.DialogResult.Yes;
    }
    
    /// <summary>
    /// 显示自定义Prompt对话框
    /// </summary>
    public string ShowCustomPrompt(string message, string defaultValue = "", string title = "输入")
    {
        // 这里可以使用自定义的输入对话框
        // 简化示例使用InputBox(需要引用Microsoft.VisualBasic)
        return Microsoft.VisualBasic.Interaction.InputBox(message, title, defaultValue);
    }
}

/// <summary>
/// 带自定义UI的对话框处理
/// </summary>
public override bool OnJSDialog(IFBroSharpBrowser browser, 
    string origin_url, 
    FBroJsDialogType dialog_type, 
    string message_text, 
    string default_prompt_text, 
    IFBroSharpJSDialogCallback callback, 
    ref bool suppress_message)
{
    var customDialog = new CustomDialogManager();
    
    // 在UI线程中显示自定义对话框
    Application.Current.Dispatcher.Invoke(() =>
    {
        switch (dialog_type)
        {
            case FBroJsDialogType.JSDIALOGTYPE_ALERT:
                customDialog.ShowCustomAlert(message_text, "网页消息");
                callback.Continue(true, "");
                break;
                
            case FBroJsDialogType.JSDIALOGTYPE_CONFIRM:
                bool confirmed = customDialog.ShowCustomConfirm(message_text, "网页确认");
                callback.Continue(confirmed, "");
                break;
                
            case FBroJsDialogType.JSDIALOGTYPE_PROMPT:
                string input = customDialog.ShowCustomPrompt(message_text, default_prompt_text, "网页输入");
                callback.Continue(!string.IsNullOrEmpty(input), input ?? "");
                break;
        }
    });
    
    return true; // 阻止原生对话框显示
}

📊 统计分析功能

对话框使用统计

csharp
/// <summary>
/// 对话框统计分析器
/// </summary>
public class DialogStatistics
{
    private readonly Dictionary<FBroJsDialogType, int> dialogCounts = new Dictionary<FBroJsDialogType, int>();
    private readonly Dictionary<string, int> domainCounts = new Dictionary<string, int>();
    private readonly List<DateTime> dialogTimes = new List<DateTime>();
    
    /// <summary>
    /// 记录对话框统计
    /// </summary>
    public void RecordDialog(FBroJsDialogType type, string url)
    {
        // 记录类型统计
        if (dialogCounts.ContainsKey(type))
            dialogCounts[type]++;
        else
            dialogCounts[type] = 1;
        
        // 记录域名统计
        var domain = GetDomainFromUrl(url);
        if (domainCounts.ContainsKey(domain))
            domainCounts[domain]++;
        else
            domainCounts[domain] = 1;
        
        // 记录时间
        dialogTimes.Add(DateTime.Now);
    }
    
    /// <summary>
    /// 获取统计报告
    /// </summary>
    public string GetStatisticsReport()
    {
        var report = new System.Text.StringBuilder();
        report.AppendLine("=== JavaScript对话框统计报告 ===");
        report.AppendLine($"统计时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
        report.AppendLine($"总对话框数: {dialogTimes.Count}");
        
        if (dialogTimes.Count > 0)
        {
            report.AppendLine($"首次记录: {dialogTimes.Min():yyyy-MM-dd HH:mm:ss}");
            report.AppendLine($"最后记录: {dialogTimes.Max():yyyy-MM-dd HH:mm:ss}");
        }
        
        report.AppendLine("\n--- 按类型统计 ---");
        foreach (var kvp in dialogCounts.OrderByDescending(x => x.Value))
        {
            report.AppendLine($"{kvp.Key}: {kvp.Value}次");
        }
        
        report.AppendLine("\n--- 按域名统计 (前10名) ---");
        foreach (var kvp in domainCounts.OrderByDescending(x => x.Value).Take(10))
        {
            report.AppendLine($"{kvp.Key}: {kvp.Value}次");
        }
        
        // 时间分布分析
        if (dialogTimes.Count > 1)
        {
            var hourGroups = dialogTimes.GroupBy(t => t.Hour).OrderBy(g => g.Key);
            report.AppendLine("\n--- 按小时分布 ---");
            foreach (var group in hourGroups)
            {
                report.AppendLine($"{group.Key:D2}:00-{group.Key:D2}:59: {group.Count()}次");
            }
        }
        
        report.AppendLine("================================");
        return report.ToString();
    }
    
    /// <summary>
    /// 清空统计数据
    /// </summary>
    public void ClearStatistics()
    {
        dialogCounts.Clear();
        domainCounts.Clear();
        dialogTimes.Clear();
        Console.WriteLine("统计数据已清空");
    }
}

⚠️ 注意事项

1. 回调处理

  • 必须调用callback.Continue():无论采用何种处理方式,都必须调用callback来响应对话框
  • 线程安全:callback操作必须在正确的线程上下文中执行
  • 资源释放:避免callback被多次调用,确保正确的资源管理

2. 返回值含义

  • 返回true:表示已自定义处理该对话框,不会显示原生JavaScript对话框
  • 返回false:表示使用浏览器默认处理,会显示原生对话框
  • suppress_message:此参数可以控制是否完全抑制消息显示

3. 性能考虑

  • 避免阻塞:处理逻辑应该快速完成,避免长时间阻塞浏览器线程
  • 内存管理:及时清理日志和统计数据,避免内存泄漏
  • 配置优化:合理配置白名单和黑名单,减少不必要的处理

4. 安全注意事项

  • 输入验证:对prompt对话框的响应值进行适当的验证和清理
  • 敏感信息:避免在日志中记录敏感信息如密码等
  • 权限控制:根据安全需求决定是否允许某些域名的对话框正常显示

🏆 最佳实践

1. 配置驱动设计

csharp
// 使用配置文件控制行为,便于动态调整
var config = LoadConfig();
if (config.EnableInterception)
{
    // 执行拦截逻辑
}

2. 分级处理策略

csharp
// 根据重要性和来源采用不同的处理策略
if (IsSystemCritical(url)) return false;      // 显示原生对话框
if (IsUserImportant(message)) return false;   // 显示原生对话框
// 其他情况自动处理

3. 完善的日志记录

csharp
// 记录详细信息用于调试和分析
LogDialog(type, message, url, response, timestamp);

4. 错误处理机制

csharp
try
{
    // 对话框处理逻辑
    callback.Continue(true, response);
}
catch (Exception ex)
{
    // 错误时的安全处理
    Console.WriteLine($"对话框处理错误: {ex.Message}");
    callback.Continue(false, "");
}

通过以上完整的实现方案,您可以全面控制FBro浏览器中的JavaScript对话框行为,实现从简单阻止到智能处理的各种需求。这个功能在自动化测试、网页监控、用户体验优化等场景中都非常有用。

如果文档对您有帮助,欢迎 请喝咖啡 ☕ | 软件发布 | 源码购买