Ejemplo de notificaciones push de WebEngine
Demuestra cómo suscribirse y darse de baja de las notificaciones push.
En este ejemplo vamos a enviar notificaciones push desde un servicio web push al usuario. Este es el escenario típico en el que los mensajes se envían desde el servidor de aplicaciones, es decir, el back-end del sitio web, a través de un servicio push de terceros, para llegar finalmente al navegador del usuario en forma de notificaciones. Para demostrar este flujo, implementaremos una sencilla aplicación de servidor de servicio push, a la que el usuario puede suscribirse para recibir mensajes ping.
Como ya se ha mencionado, en este flujo de trabajo intervienen tres partes diferentes
- el navegador web del usuario, donde recibe las notificaciones push
- el servicio push de terceros, que se define mediante un punto final de suscripción y forma parte de la implementación del servicio push de un navegador
- el servidor de aplicaciones, que almacenará las suscripciones del usuario e iniciará los mensajes push mediante un punto final de suscripción
El usuario visita un sitio web, donde una aplicación web JavaScript utiliza la API JavaScript Push para crear una suscripción de notificación push. A continuación, se pide al usuario que conceda un permiso para recibir y mostrar notificaciones push. Una vez aceptado, la API Push establece un canal push con un servicio push de terceros, que en el caso de QtWebEngine es Firebase Cloud Messaging (FCM). Se crea una suscripción push única que incluye la URL del punto final de suscripción. A continuación, el navegador envía un mensaje de suscripción al servidor de aplicaciones reenviando la configuración del punto final. El servidor de aplicaciones puede ahora utilizar el punto final de suscripción para enviar notificaciones al navegador. La implementación del servicio push del navegador entregará un mensaje push. Sin embargo, para mostrarlo, se debe registrar un service worker. Como el service worker se ejecuta en segundo plano, permite mostrar notificaciones incluso si el sitio web que lo ha instalado ya no está abierto.

Profundicemos en los detalles de la implementación. Comenzamos con la implementación de nuestro servicio push personalizado utilizando NodeJS con dos módulos:
- web-push - proporciona la implementación del protocolo web-push
- express - proporciona el framework de la aplicación web
Vamos a inicializar un nuevo proyecto e instalar los módulos necesarios en el directorio raíz de este ejemplo:
npm init -y npm install web-push express
Estos comandos deberían crear package.js, que define el comando start:
"start": "node server.js"
Ahora pasemos a la implementación del back-end del servicio push en server.js.
Empezaremos incluyendo los módulos necesarios y realizando la configuración básica de express framework, que utilizaremos para crear nuestro servidor push personalizado. Para simplificar vamos a manejar sólo una suscripción a la vez. Para ello necesitamos crear claves VAPID que vamos a generar con web-push libs. La clave pública será utilizada por el front-end para autenticarse en el servicio.
const express = require('express');
const webpush = require('web-push');
// setup server
const port = 5000;
const server = express();
server.use(express.json());
server.use(express.static('content'));
// we support only one subscription at the time
var subscription = null;
// setup vapid keys
const vapidKeys = {
publicKey :
"BNO4fIv439RpvbReeABNlDNiiBD2Maykn7EVnwsPseH7-P5hjnzZLEfnejXVP7Zt6MFoKqKeHm4nV9BHvbgoRPg",
privateKey : "HqhrzsRfG5-SB3j45lyUmV7cYZuy-71r2Bb0tgaOefk"
};
// set vapid keys for webpush libs
webpush.setVapidDetails('mailto:push@qt.io', vapidKeys.publicKey, vapidKeys.privateKey);Nota: No vamos a cubrir el cifrado de mensajes en este ejemplo.
Para generar claves, podemos utilizar la herramienta incluida con la lib web-push, que se instala por npm en el directorio raíz de nuestro ejemplo.
./node_modules/.bin/web-push generate-vapid-keys
Ahora añadimos dos routes al servidor push. Uno a subscribe y otro a unsubscribe, para que nuestro front-end pueda enviar una petición HTTP POST para gestionar la suscripción push. En la petición de suscripción obtendremos subscription en el cuerpo de la petición y también recuperamos la cabecera personalizada ping-time que define la frecuencia con la que los mensajes ping deben ser enviados al usuario. Nos quedamos con subscription para poder enviar notificaciones push más tarde. Como confirmación, enviamos el código de estado 201 y programamos la primera notificación push basándonos en el valor de ping-time. La petición unsubscribe simplemente elimina una suscripción.
// add subscribe route
server.post('/subscribe', (req, res) => {
// subscription request
subscription = req.body;
const delay = req.headers['ping-time'];
console.log('Got subscription with endpoint: ' + subscription.endpoint);
console.log('Ping delay is at: ' + delay);
// confirm resource created
res.status(201).json({});
// schedule notification
setTimeout(() => { sendNotification(delay) }, delay * 1000);
});
// add unsubscribe route
server.post('/unsubscribe', (req, res) => {
console.log('Got unsubscribe with endpoint: ' + req.body.endpoint);
subscription = null;
res.status(201).json({});
});La función sendNotication() envía mensajes push utilizando la librería web-push. Creamos el payload con el mensaje que queremos presentar a un usuario y programamos el siguiente mensaje push.
function sendNotification(delay)
{
if (!subscription)
return;
// create payload text
const payload = JSON.stringify({ title : 'Ping !', text : 'Visit qt.io', url : 'www.qt.io' });
// send notification
console.log('Sending notification !');
webpush.sendNotification(subscription, payload).catch(err => console.error(err));
// schedule next notification
setTimeout(() => { sendNotification(delay) }, delay * 1000);
}Al final iniciamos el servidor para que escuche en el puerto dado.
server.listen(port, () => console.log(`Push server started at port ${port}`));Pasemos ahora a nuestro front-end. Creamos una simple página index.html, donde el usuario puede introducir la frecuencia con la que quiere recibir mensajes de notificación ping. Tendremos dos botones: Ping Me para suscribirse a las notificaciones push y Clear para darse de baja. Al final cargamos ping.js, que veremos a continuación.
<body>
<h1>Push Notification Using NodeJS and QtWebEngine</h1>
<div id="app">
<div id="ping-setup">
<form>
<div>
Ping Me Every [sec]:
</div>
<div class="ping-input">
<input type="number" name="seconds" min="0" max="3600" required="">
</div><button>Ping Me</button>
</form>
</div>
<div id="ping-clear">
<div id="ping-text"></div><button id="ping-clear-button">Clear</button>
</div>
</div>
<script src="ping.js"></script>
</body>La última pieza es crear la lógica para la suscripción push dentro del front-end. Aquí tenemos dos funciones, setup y clear, para manejar las suscripciones. Cuando el usuario hace clic en el botón Ping Me, se llama a setup. Para poder recibir notificaciones, se necesita el service worker. De este modo, el usuario puede abandonar el sitio web y seguir recibiendo notificaciones, ya que el service worker trabaja en segundo plano y gestiona los mensajes entrantes. Para conseguirlo, primero tenemos que registrar uno con:
const register = await navigator.serviceWorker.register('/worker.js', { scope : '/' });La llamada a cpushManager.subscribe() activará una solicitud de permiso, que se mostrará al usuario. Si se concede el permiso, se devuelve la suscripción push. Incluye un endpoint URL que permite enviar notificaciones al navegador, donde el service worker registrado espera los mensajes push.
var subscription = await register.pushManager.subscribe(
{ userVisibleOnly : true, applicationServerKey : publicVapidKey });Como se ha mencionado, la suscripción se crea para FCM y ahora debe enviarse a nuestro servidor personalizado con una solicitud HTTP POST. Además, añadimos a la solicitud POST el encabezado HTTP con el ping-time que el usuario introdujo en nuestro sitio web.
await fetch('/subscribe', {
method : 'POST',
body : JSON.stringify(subscription),
headers : { 'content-type' : 'application/json', 'ping-time' : delay }
});La llamada a la función clear cancela la suscripción primero desde nuestro servidor push enviando una petición HTTP POST y después desde el servicio push de terceros (FCM).
const register = await navigator.serviceWorker.getRegistration();
var subscription = await register.pushManager.getSubscription();
...
await fetch('/unsubscribe', {
method : 'POST',
body : JSON.stringify(subscription),
headers : { 'content-type' : 'application/json' }
});
...
await subscription.unsubscribe();El resto del código en ping.js es sólo código repetitivo para leer un valor proporcionado por el usuario y llamar a setup() o clear().
Como última parte del front-end veamos el interior de un script service worker, donde simplemente registramos un receptor de eventos push.
self.addEventListener('push', event => {
const data = event.data.json();
self.registration.showNotification(data.title, { body : data.text });
});Cuando llega un evento push simplemente usamos la API JavaScript de Notificación para mostrar una notificación.
Nota: QtWebEngine Notification Example muestra cómo proporcionar tu propio manejador y personalizar el aspecto de un mensaje de notificación.
Teniendo la implementación en su lugar, podemos iniciar el servidor en localhost en el puerto 5000. Para ello, podemos simplemente entrar en la consola en el directorio raíz del proyecto:
npm start
Ahora podemos ver la aplicación de navegador push-notification, que está basada en WebEngine Notifications Example:
int main(int argc, char *argv[]) { QCoreApplication::setOrganizationName("QtExamples"); QApplication app(argc, argv); const QString name = QString::fromLatin1("push-notifications.%1").arg(qWebEngineChromiumVersion()); QWebEngineProfileBuilder profileBuilder; QScopedPointer<QWebEngineProfile> profile(profileBuilder.createProfile(name)); QWebEngineView view(profile.data()); auto popup = new NotificationPopup(&view); QObject::connect(view.page(), &QWebEnginePage::permissionRequested, [&](QWebEnginePermission permission) { if (permission.permissionType() != QWebEnginePermission::PermissionType::Notifications) return; permission.grant(); }); profile->setPushServiceEnabled(true); profile->setNotificationPresenter([&](std::unique_ptr<QWebEngineNotification> notification) { popup->present(notification); }); view.resize(640, 480); view.setUrl(QUrl("http://localhost:5000")); view.show(); return app.exec(); }
Esta aplicación simplemente abre la página en http:\\localhost:5000. No vamos a entrar en detalles sobre cómo abrir una notificación, ya que está documentado aquí. Sin embargo, es necesario modificar la aplicación de dos maneras. En primer lugar, QWebEngineProfile no puede configurarse como off-the-record porque se desactivaría la mensajería push. Por lo tanto, como puedes ver arriba, QWebEngineProfile se inicializa con el nombre. En segundo lugar, es necesario habilitar la mensajería push con la llamada QWebEngineProfile::setPushServiceEnabled para la creada profile.
Cuando la aplicación se ejecuta se muestra:

Después de conceder el permiso podemos enviar nuestra petición ping:

Deberíamos ver la notificación push que viene:

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.