【问题标题】:Intercept HTML5 Web Notifications in a browser environment在浏览器环境中拦截 HTML5 Web 通知
【发布时间】:2019-12-22 17:39:09
【问题描述】:

我想拦截HTML5 Web Notifications。我已阅读以下answer,其中用户建议可以用您自己的对象覆盖window.Notification 对象,该对象将充当代理。我试图这样做,但无法让它发挥作用。下面是我在页面加载时注入的 JavaScript 代码:

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);
    }
})

【问题讨论】:

    标签: javascript html web browser web-notifications


    【解决方案1】:

    问题是箭头函数不能用作构造函数(Source)。

    使用此代码的项目仍然有一个箭头函数:https://github.com/jiahaog/nativefier/blob/master/app/src/static/preload.js,但它在 Electron 中运行,这可能解释了为什么它的行为不同。

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

    (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');
        }
    });
    

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

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

    (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');
        }
    });
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-27
      • 2012-03-13
      • 1970-01-01
      • 2020-01-17
      相关资源
      最近更新 更多