在浏览器环境中拦截 HTML5 Web 通知 [英] Intercept HTML5 Web Notifications in a browser environment

查看:33
本文介绍了在浏览器环境中拦截 HTML5 Web 通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想拦截 HTML5 网络通知.我已阅读以下 answer,其中用户建议可以覆盖 window.Notification 对象与您自己的将充当代理的对象.我试图这样做,但无法使其正常工作.下面是我在加载页面时注入的 JavaScript 代码:

function setNotificationCallback(callback) {const OldNotify = window.Notification;OldNotify.requestPermission();const newNotify = (title, opt) =>{回调(标题,选择);返回新的旧通知(标题,选择);};newNotify.requestPermission = OldNotify.requestPermission.bind(OldNotify);Object.defineProperty(newNotify, 'permission', {得到:() =>{返回 OldNotify.permission;}});window.Notification = newNotify;}函数通知回调(标题,选择){console.log("title", title);//这永远不会被调用}window.Notification.requestPermission(函数(权限){如果(权限 ===授予"){setNotificationCallback(notifyCallback);}})

解决方案

问题是箭头函数不能用作构造函数 (来源).

使用这段代码的项目还有箭头功能:https://github.com/jiahaog/nativefier/blob/master/app/src/static/preload.js 但它在 Electron 这可能解释了为什么它的行为不同.

如果针对最近的浏览器,不如使用这样的命名函数:

(function () {函数通知回调(标题,选择){控制台日志(标题",标题);}const OldNotify = window.Notification;功能新通知(标题,选择){通知回调(标题,选择);返回新的旧通知(标题,选择);}newNotify.requestPermission = OldNotify.requestPermission.bind(OldNotify);Object.defineProperty(newNotify, 'permission', {得到:函数(){返回 OldNotify.permission;}});window.Notification = newNotify;})();Notification.requestPermission(功能(权限){如果(权限 ===已授予"){const notif = new Notification('我的标题');}});

这样创建的代理将在其他代码/库调用 new Notification() 时生效,就像我的例子一样.我已将代理逻辑移至顶层,以确保其他代码/库在用户接受接收通知之前不会保留对本机 Notification 的引用.您还必须将代码放在首位以保证这一点.

如果您的目标浏览器支持 ECMAScript 6,还有一种更优雅的方式来实现:

(函数(){函数通知回调(标题,选择){控制台日志(标题",标题);}常量处理程序 = {构造(目标,参数){notifyCallback(...args);返回新目标(...参数);}};const ProxifiedNotification = new Proxy(Notification, handler);window.Notification = ProxifiedNotification;})();Notification.requestPermission(功能(权限){如果(权限 ===已授予"){const notif = new Notification('我的标题');}});

它的可扩展性更强(当 Notification API 在未来的 ECMAScript 版本中发生变化时不会产生影响,因为它允许操作原生的 Notification 而不是手工制作的).>

I would like to intercept HTML5 Web Notifications. I have read the following answer where a user suggests that it is possible to override the window.Notification object with your own object that will act as a proxy. I tried to do that but couldn't manage it to work. Below is the JavaScript code I am injecting when a page has been loaded:

function setNotificationCallback(callback) {

    const OldNotify = window.Notification;
    OldNotify.requestPermission();

    const newNotify = (title, opt) => {
        callback(title, opt);
        return new OldNotify(title, opt);
    };
    newNotify.requestPermission = OldNotify.requestPermission.bind(OldNotify);
    Object.defineProperty(newNotify, 'permission', {
        get: () => {
            return OldNotify.permission;
        }
    });

    window.Notification = newNotify;
}
function notifyCallback(title, opt) {
    console.log("title", title); // this never gets called
}

window.Notification.requestPermission(function (permission) {
    if (permission === "granted") {
        setNotificationCallback(notifyCallback);
    }
})

解决方案

The problem is that an arrow function can't be used as a constructor (Source).

The project that uses this code still has an arrow function: https://github.com/jiahaog/nativefier/blob/master/app/src/static/preload.js but it runs in Electron which might explain why it behaves differently.

If targeting recent browsers, rather use a named function like this:

(function () {

    function notifyCallback(title, opt) {
        console.log("title", title);
    }

    const OldNotify = window.Notification;

    function newNotify(title, opt) {
        notifyCallback(title, opt);
        return new OldNotify(title, opt);
    }

    newNotify.requestPermission = OldNotify.requestPermission.bind(OldNotify);
    Object.defineProperty(newNotify, 'permission', {
        get: function() {
            return OldNotify.permission;
        }
    });

    window.Notification = newNotify;
})();

Notification.requestPermission(function (permission) {
    if (permission === "granted") {
        const notif = new Notification('My title');
    }
});

The proxy thus created will then be effective when other code/libraries call new Notification() like in my example. I have moved the proxifying logic to the top-level to ensure that the other code/libraries won't keep a reference on the native Notification before the user accepts to receive notifications. You must also put the code at the very first place to guarantee that.

And if your target browsers support ECMAScript 6, there is a much more elegant way to do it:

(function () {

    function notifyCallback(title, opt) {
        console.log("title", title);
    }

    const handler = {
        construct(target, args) {
            notifyCallback(...args);
            return new target(...args);
        }
    };

    const ProxifiedNotification = new Proxy(Notification, handler);

    window.Notification = ProxifiedNotification;
})();

Notification.requestPermission(function (permission) {
    if (permission === "granted") {
        const notif = new Notification('My title');
    }
});

It's much more scalable (no impact when the Notification API changes in future ECMAScript versions since it allows to manipulate the native Notification rather than a handmade one).

这篇关于在浏览器环境中拦截 HTML5 Web 通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆