【问题标题】:WPF Cefsharp Allow browser notifications programmaticallyWPF Cefsharp 以编程方式允许浏览器通知
【发布时间】:2021-10-29 14:59:30
【问题描述】:

我正在使用 CefSharp 铬浏览器开发 WPF 应用程序。我有一个 TabControl,其中每个选项卡项都包含铬浏览器并托管不同的网站。

问题: 我在一个标签项中看到一个网站的空白屏幕,而同一网站在独立浏览器(Google chrome/Microsoft Edge)中加载正常。

观察/分析: 当网站在独立浏览器(Google chrome/Microsoft Edge)中加载时,我收到一个浏览器弹出窗口,要求允许或阻止通知,但我的应用程序中没有这个弹出窗口。 当我在我的应用程序中打开特定 chromium 浏览器的开发工具时,我在控制台中发现以下错误: ERROR ReferenceError:未定义通知

我知道我们可以允许或阻止来自 C# 代码的麦克风/摄像头,如下所示:

CefSettings settings = new CefSettings();
settings.CefCommandLineArgs.Add("enable-media-stream", "1");
Cef.Initialize(settings);

是否有任何命令参数可以像上面的代码一样允许/阻止通知? 请帮忙。

【问题讨论】:

标签: c# wpf cefsharp


【解决方案1】:

CEFSharp 不支持通知 API。 https://github.com/cefsharp/CefSharp/issues/2890 但是你可以自己实现。 使用 JavaScript 覆盖 Notification 构造函数,并将消息从 CEFSharp 发送到您的代码,方法是将其预先打包为 JSON。

public void OnFrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
Browser.ExecuteScriptAsync(@"(function(){ class Notification {
    static permission = 'granted';
    static maxActions = 2;
    static name = 'Notification';
    constructor(title, options) {
        let packageSet = new Set();
        packageSet.add(title).add(options);
        let json_package = JSON.stringify([...packageSet]);
        CefSharp.PostMessage(json_package);
        //alert(title);
    }
    static requestPermission() {
        return new Promise((res, rej) => {
            res('granted');
        })
    }   
};
window.Notification = Notification;
})();");
}

接收消息并将其放入队列中。我使用Newtonsoft 从 JSON 中解包。

private void OnBrowserJavascriptMessageReceived(object sender, JavascriptMessageReceivedEventArgs e)
{
    object[] objArray = JsonConvert.DeserializeObject<object[]>(e.Message.ToString());
    Options options = JsonConvert.DeserializeObject<Options>(objArray[1].ToString(), new ImageConverter());
    // Add to Notification queue
    MessageQueue.Enqueue(new object[] { objArray[0], options });
}

MessageQueue 是数组对象的简单队列,然后我们在另一个线程中处理。

public Queue<object[]> MessageQueue = new Queue<object[]>();

通知结构。

public class Options
{
    public byte[] icon { get; set; }               
    public string body { get; set; }               
    public string tag { get; set; }                
    public bool canReply { get; set; }             
    public bool silent { get; set; }               
    public bool requireInteraction { get; set; }
}

图像转换器

public class ImageConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(byte[]);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var str = reader.Value.ToString();
        var index = reader.Value.ToString().IndexOf("base64,");
        if (index == -1)
        {
            try
            {
                // Download the icon
                Task<byte[]> task = App.ImageDownloaderObj.GetImageBytesAsync(new Uri(str));
                task.Wait(500);
                return task.Result;
            }
            catch { return new byte[] { }; }
        }
        else
        {
            var m = new MemoryStream(Convert.FromBase64String(str.Substring(index + 7)));
            return m.ToArray();
        }
        //return (Bitmap)Image.FromStream(m);
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Bitmap bmp = (Bitmap)value;
        MemoryStream m = new MemoryStream();
        bmp.Save(m, System.Drawing.Imaging.ImageFormat.Png);

        writer.WriteValue(Convert.ToBase64String(m.ToArray()));
    }
}

【讨论】:

  • 几个cmets,JavascriptMessageReceived在线程池上被调用,所以不推荐调用MessageBox.Show,因为没有消息循环在运行,最好使用UI线程处理所有与UI相关的事情。如果示例实际发送通知文本而不是固定字符串,那就太好了。
  • 感谢您的评论,我进行了更改。现在它实际上是在其中一个项目中运行的代码。
猜你喜欢
  • 2022-11-01
  • 2010-10-30
  • 1970-01-01
  • 1970-01-01
  • 2017-08-05
  • 2013-08-02
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
相关资源
最近更新 更多