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

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

问题描述

我想拦截 HTML5 Web通知。我已阅读以下答案,其中用户建议可以覆盖窗口。 对象与您自己的对象(将充当代理)。我尝试这样做,但是无法使其正常工作。以下是页面加载后我要注入的JavaScript代码:

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).

使用此代码的项目仍具有箭头功能: https://github.com/jiahaog/nativefier/blob/master/app/src/ static / preload.js ,但它在电子中运行,这也许可以解释其行为不同的原因。

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 ,标题);
}

const OldNotify = window.Notification;

函数newNotify(title,opt){
notifyCallback(title,opt);
返回新的OldNotify(title,opt);
}

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

窗口。Notification= newNotify;
})();

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

这样创建的代理将在其他代码/库调用 new时生效Notification()如我的示例。我已将代理逻辑移到了顶层,以确保其他代码/库在用户接受接收通知之前不会保留对本机 Notification 的引用。

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.

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

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

它具有更大的可扩展性(当 Notification 将来的ECMAScript版本中的API发生了变化,因为它允许操作本机的通知而不是手工的)。

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天全站免登陆