File: /volume1/@appstore/SynologyApplicationService/ui/browser_pair/js/webpush.js
(function (root) {
SYNO = root.SYNO || {};
SYNO.WebPush = {};
/* browser related utils */
SYNO.isChrome = function() {
return (/\bchrome\b/.test(navigator.userAgent.toLowerCase()));
};
SYNO.isSafari = function() {
return !SYNO.isChrome() && (/safari/.test(navigator.userAgent.toLowerCase()));
};
SYNO.isFirefox = function() {
return (navigator.userAgent.toLowerCase().indexOf('firefox') > -1);
};
SYNO.GetBrowserName = function() {
if (SYNO.isChrome()) {
return 'Chrome';
} else if (SYNO.isSafari()) {
return 'Safari';
} else if (SYNO.isFirefox()) {
return 'Firefox';
}
return 'unknown';
};
SYNO.GetBrowserVersion = function() {
var version = 'unknown';
var match;
if (SYNO.isChrome()) {
match = navigator.userAgent.match(/(chrome)\/([\d.]*)/i);
if (match) {
version = match[2];
}
} else if (SYNO.isSafari()) {
match = navigator.userAgent.match(/(safari)\/([\d.]*)/i);
if (match) {
version = match[2];
}
} else if (SYNO.isFirefox()) {
match = navigator.userAgent.match(/(Firefox)\/([\d.]*)/i);
if (match) {
version = match[2];
}
}
return version;
};
SYNO.WebPush.SERVICE_WORKER_URL = './service-worker.js';
SYNO.WebPush.isSupported = function(platform) {
if (location.protocol == "http:") {
// TODO: domain name + valid certificate
return false;
}
if (!SYNO.isChrome() && !SYNO.isFirefox()) {
return false;
}
if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
// Service Worker basic support IE: X, Safari: X, Chrome: 40.0+, Firefox: 44.0+
return false;
}
if (SYNO.isChrome() && (SYNO.GetBrowserVersion() < 52)) {
return false;
}
// Ignore platform not support NodeJS: 6281 and qoriq
if (platform.indexOf('6281') != -1 || platform.indexOf('qoriq') != -1) {
return false;
}
return true;
};
SYNO.WebPush.registerServiceWorker = function() {
if (('serviceWorker' in navigator) && ('PushManager' in window)) {
return navigator.serviceWorker.register(SYNO.WebPush.SERVICE_WORKER_URL, {scope: '/'})
.then(function(reg) {
if (reg.update) {
// 1. install new worker if is not byte-by-byte identical
// 2. bypasses any browser caches if the previous fetch occurred over 24 hours ago
reg.update();
}
return reg;
})['catch'](function(error) {
console.error("serviceWorker.register failed");
return Promise.reject(error);
});
} else {
console.error("browser not support");
return Promise.reject();
}
};
SYNO.WebPush.getSWRegistration = function() {
return navigator.serviceWorker.getRegistration(SYNO.WebPush.SERVICE_WORKER_URL);
};
SYNO.WebPush.getEndpoint = function() {
return SYNO.WebPush.getSWRegistration()
.then(function(reg) {
if (!reg) {
return Promise.reject();
}
return reg.pushManager.getSubscription();
})
.then(function(subscription) {
if (!subscription || !subscription.endpoint) {
return Promise.reject();
}
return Promise.resolve(subscription.endpoint);
});
};
SYNO.WebPush.subscribeNotification = function(reg, appServerKey) {
var appKey = (appServerKey + "====".substr(appServerKey.length % 4))
.replace(/\-/g, "+")
.replace(/\_/g, "/");
return reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: SYNO.SAS.sodium.from_base64(appKey)
})
.then(function(subscription){
var data = {};
if (!subscription.endpoint || !subscription.getKey) {
console.error("no endpoint or getKey, subscription: " + JSON.stringify(subscription));
return Promise.reject();
}
data.endpoint = subscription.endpoint;
try {
data.p256dh = SYNO.SAS.sodium.to_base64(new Uint8Array(subscription.getKey('p256dh')))
.replace(/\=/g, '')
.replace(/\+/g, '-')
.replace(/\//g, '_');
} catch(e) {
console.error("sodium.to_base64() failed of p256dh");
return Promise.reject();
}
try {
data.auth = SYNO.SAS.sodium.to_base64(new Uint8Array(subscription.getKey('auth')))
.replace(/\=/g, '')
.replace(/\+/g, '-')
.replace(/\//g, '_');
} catch (e) {
console.error("sodium.to_base64() failed of auth");
return Promise.reject();
}
return data;
});
};
SYNO.WebPush.unsubscribeNotification = function(reg) {
return reg.pushManager.getSubscription()
.then(function(subscription) {
if (!subscription) {
return true;
}
return subscription.unsubscribe();
})
.then(function(event) {
return true;
})
['catch'](function(error) {
return Promise.reject(error);
});
};
if (typeof module !== 'undefined' && module.exports) {
module.exports = SYNO;
} else if (!root.SYNO) {
root.SYNO = SYNO;
}
})(this);