Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
// Some apps serve their app (and register their notification service worker)
// on a subdomain, but users pin the apex. A tile at the apex would never match
// the origin its notifications are stored under. These aliases redirect the
// apex (and www) to that app origin. Kept explicit rather than collapsing to a
// registrable domain, which would wrongly merge unrelated siblings such as
// Google's mail/calendar/docs onto a single tile.
const ORIGIN_ALIASES = new Map([
]);
// Stable reference so selectors don't return a fresh array on every store
// update for sites with no notifications.
const EMPTY_IDS = Object.freeze([]);
/**
* @param {string} url
* @returns {?string} The http(s) origin, or null for other schemes / bad input.
*/
export function originFromUrl(url) {
try {
const parsed = new URL(url);
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
return null;
}
return parsed.origin;
} catch (e) {
return null;
}
}
/**
* The origin a tile's notifications are stored under, resolving known apex
* aliases. Unknown origins pass through unchanged, so the worst case is an
* exact-match miss, never a wrong-app match.
*
* @param {string} url
* @returns {?string}
*/
export function notificationKeyForUrl(url) {
const siteOrigin = originFromUrl(url);
if (!siteOrigin) {
return null;
}
return ORIGIN_ALIASES.get(siteOrigin) ?? siteOrigin;
}
/**
* The stored notification ids for the site a tile points at.
*
* @param {object} state Newtab Redux state.
* @param {string} url The tile's url.
* @returns {string[]}
*/
export function getNotificationIdsForUrl(state, url) {
const key = notificationKeyForUrl(url);
return (key && state.WebNotifications.byOrigin[key]) || EMPTY_IDS;
}
/**
* Whether to render any web notifications surface. The feature has to exist for
* this profile (`system.showWebNotifications`, or a trainhop enrollment via
* `trainhopConfig.webNotifications.enabled`, which is also what decides whether
* the customize toggle is offered at all) and the user has to want it
* (`showWebNotifications`, what that toggle writes).
*
* @param {object} state Newtab Redux state.
* @returns {boolean}
*/
export function isWebNotificationsEnabled(state) {
const prefs = state.Prefs.values;
const systemEnabled =
prefs["system.showWebNotifications"] ||
prefs.trainhopConfig?.webNotifications?.enabled;
return Boolean(systemEnabled && prefs.showWebNotifications);
}