Push API

chrome:Push API 后台模式。 #enable-push-api-background-mode
// 后台下载,上传

sw 必须是激活的。
navigator.serviceWorker.getRegistrations() 获取SWR // navigator.serviceWorker.getRegistration() 为
navigator.serviceWorker.register() 注册获取SWR

navigator.serviceWorker.ready 等待激活完成(never reject),返回 SWR, 只在 sw scope 中的页面有效
PushManager.subscribe() // pushManager.getSubscription()
ServiceWorkerRegistration.showNotification() // 返回的 promise 完成之后没有NotificationEvent
// getNotifications到的或者NotificationEvent.notification 不能注册事件处理函数,只能 onnotificationclick 注册
ServiceWorkerRegistration.getNotifications() // 获取目前显示的 notify;
// 可以在通知上添加按钮供用户直接选择动作。// other option
浏览器 Push 服务器 + 客户端端点(每次 sw 注册是一个不同字符串) => Capability URLs【(功能性URL)将一个资源的访问授权给任何拥有这个URL的用户】

后端 -> Push服务器 -> 端点(端点URL:PushSubscription.endpoint) , 后端-前端 的消息 需要加密

数据使用对称密钥进行加密(双方使用同一个密钥)
// ssl也是, 双方使用客户端随机生成的密钥,随机密钥传输到服务器时会用服务器的公钥加密。

pushManager.subscribe({userVisibleOnly: true}) //userVisibleOnly 为false时需要notification权限

PushSubscription.getKey() 生成密钥 并导出raw(crypto.subtle.exportKey('raw', Key)) 再 base64url 编码
// p256dh、auth 获得的字符串与端点对应。相当于ssl中的 服务器公钥, 客户端私钥
// Split a byte array into chunks of size.
function chunkArray(array, size) {
var start = array.byteOffset || 0;
array = array.buffer || array;
var index = 0;
var result = [];
while(index + size <= array.byteLength) {
result.push(new Uint8Array(array, start + index, size));
index += size;
}
if (index <= array.byteLength) {
result.push(new Uint8Array(array, start + index));
}
return result;
}
var strmap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
function base64urlEncode(data) {
data = new Uint8Array(data);
var len = Math.ceil(data.length * 4 / 3); // base64
return chunkArray(data, 3).map(chunk => [
chunk[0] >>> 2,
((chunk[0] & 0x3) << 4) | (chunk[1] >>> 4),
((chunk[1] & 0xf) << 2) | (chunk[2] >>> 6),
chunk[2] & 0x3f
].map(v => strmap[v]).join('')).join('').slice(0, len);
}
将 端点url + p256dh、auth 获得的字符串 发送给后端 // 有配套事件 pushsubscriptionchange

后端(代理客户端)在需要发送消息的时候 加密 用 p256dh、auth、 local key 内容 POST 给 PUSH服务器
//另外提供: Local Key (public, raw格式), salt, TTL(用户不在线排队多长时间)
// local key 有什么用?
// VAPID (VAPID is an optional header block that allows senders to "self identify". It consists of a JSON Web Token that contains identification claims. )数据。 // 到底验证什么?怎么验证?

前端收到加密的内容自动解密(getkey -> p256dh、auth) , push.event.data 获得数据

接收消息 还可以通过Channel Messaging API响应到 注册sw 的页面, 页面没关就可以即时更新