在浏览器环境中拦截HTML5 Web通知 [英] Intercept HTML5 Web Notifications in a browser environment
问题描述
我想拦截 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屋!