Exemple de notifications push de WebEngine

Démontre comment s'abonner et se désabonner des notifications push.

Dans cet exemple, nous allons envoyer des notifications push à l'utilisateur à partir d'un service web push. Il s'agit d'un scénario typique dans lequel les messages sont envoyés depuis le serveur d'application, c'est-à-dire le back-end du site web, par l'intermédiaire d'un service push tiers, pour finalement arriver dans le navigateur de l'utilisateur sous la forme de notifications. Pour démontrer ce flux, nous mettrons en œuvre une simple application serveur de service push, à laquelle l'utilisateur peut s'abonner pour recevoir des messages ping.

Comme nous l'avons déjà mentionné, un tel flux de travail implique trois parties différentes, à savoir

  • le navigateur web de l'utilisateur, qui reçoit les notifications push
  • le service push tiers, qui est défini par un point de terminaison d'abonnement et fait partie de l'implémentation du service push d'un navigateur
  • le serveur d'application, qui stocke les abonnements de l'utilisateur et lance les messages push à l'aide d'un point de terminaison d'abonnement.

L'utilisateur visite un site web, où une application web JavaScript utilise l'API JavaScript Push pour créer un abonnement à la notification push. L'utilisateur est ensuite invité à accorder l'autorisation de recevoir et d'afficher des notifications push. Une fois cette autorisation accordée, l'API Push établit un canal push avec un service push tiers, qui, dans le cas de QtWebEngine, est Firebase Cloud Messaging (FCM). L'abonnement push unique est créé et comprend l'URL du point de terminaison de l'abonnement. Le navigateur envoie ensuite un message d'abonnement au serveur d'application en lui transmettant la configuration du point de terminaison. Le serveur d'application peut maintenant utiliser le point de terminaison de l'abonnement pour envoyer des notifications au navigateur. L'implémentation du service push du navigateur délivrera un message push. Cependant, pour le montrer, un agent de service doit être enregistré. Comme ce service fonctionne en arrière-plan, il permet d'afficher des notifications même si le site web qui l'a installé n'est plus ouvert.

Un diagramme de flux montrant le fonctionnement des notifications push sur le web

Entrons dans les détails de la mise en œuvre. Nous commençons par implémenter notre service push personnalisé en utilisant NodeJS avec deux modules :

  • web-push - fournit l'implémentation du protocole web-push
  • express - fournit le cadre d'application web

Initialisons un nouveau projet et installons les modules requis dans le répertoire racine de cet exemple :

npm init -y
npm install web-push express

Ces commandes devraient créer le fichier package.js, qui définit la commande start :

"start": "node server.js"

Passons maintenant à l'implémentation du back-end du service push dans server.js.

Nous commençons par inclure les modules requis et par effectuer la configuration de base du framework express, que nous utilisons pour créer notre serveur push personnalisé. Pour des raisons de simplicité, nous allons gérer un seul abonnement à la fois. Pour ce faire, nous devons créer des clés VAPID que nous allons générer avec les librairies web-push. La clé publique sera utilisée par le front-end pour s'authentifier auprès du service.

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);

Note : Nous n'allons pas couvrir le cryptage des messages dans cet exemple.

Pour générer des clés, nous pouvons utiliser l'outil fourni avec la librairie web-push, qui est installée par npm dans le répertoire racine de notre exemple.

./node_modules/.bin/web-push generate-vapid-keys

Nous ajoutons maintenant deux routes au serveur push. Un à subscribe et un à unsubscribe, afin que notre front-end puisse envoyer une requête HTTP POST pour gérer l'abonnement au serveur push. Dans la requête d'abonnement, nous obtiendrons subscription dans le corps de la requête et nous récupérerons également l'en-tête personnalisé ping-time qui définit la fréquence à laquelle les messages ping doivent être envoyés à l'utilisateur. Nous conservons l'en-tête subscription pour pouvoir envoyer des notifications push ultérieurement. En guise de confirmation, nous envoyons le code d'état 201 et programmons la première notification push sur la base de la valeur ping-time. La requête unsubscribe supprime simplement un abonnement.

// 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 fonction sendNotication() envoie des messages push à l'aide de la librairie web-push. Nous créons la charge utile avec le message que nous voulons présenter à un utilisateur et planifions le prochain message 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);
}

Enfin, nous démarrons le serveur pour qu'il écoute sur le port donné.

server.listen(port, () => console.log(`Push server started at port ${port}`));

Passons maintenant à notre interface. Nous créons une simple page index.html, où l'utilisateur peut indiquer la fréquence à laquelle il souhaite recevoir des messages de notification ping. Nous aurons deux boutons : Ping Me pour s'abonner aux notifications push et Clear pour se désabonner. À la fin, nous chargeons ping.js, dont nous parlerons plus loin.

<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>

Le dernier élément est la création de la logique pour l'abonnement push dans le front-end. Nous avons ici deux fonctions, setup et clear, pour gérer les abonnements. Lorsque l'utilisateur clique sur le bouton Ping Me, setup est appelé. Pour pouvoir recevoir des notifications, le service worker est nécessaire. Ainsi, l'utilisateur peut quitter le site web tout en recevant des notifications, car le service worker travaille en arrière-plan et traite les messages entrants. Pour ce faire, nous devons d'abord en enregistrer un auprès de :

    const register = await navigator.serviceWorker.register('/worker.js', { scope : '/' });

L'appel à cpushManager.subscribe() déclenche une demande d'autorisation, qui est affichée à l'utilisateur. Si l'autorisation est accordée, l'abonnement push est renvoyé. Il comprend un point d'extrémité URL qui permet d'envoyer des notifications au navigateur, où le travailleur de service enregistré attend les messages push.

    var subscription = await register.pushManager.subscribe(
            { userVisibleOnly : true, applicationServerKey : publicVapidKey });

Comme indiqué, l'abonnement est créé pour FCM et doit maintenant être envoyé à notre serveur personnalisé avec une requête HTTP POST. En outre, nous ajoutons à la requête POST l'en-tête HTTP contenant l'adresse ping-time que l'utilisateur a saisie sur notre site web.

    await fetch('/subscribe', {
        method : 'POST',
        body : JSON.stringify(subscription),
        headers : { 'content-type' : 'application/json', 'ping-time' : delay }
    });

La fonction clear se désabonne d'abord de notre serveur push en envoyant une requête HTTP POST, puis du service push tiers (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();

Le reste du code de ping.js n'est que du code standard pour lire une valeur fournie par l'utilisateur et appeler setup() ou clear().

La dernière partie du front-end est un script de travailleur de service, dans lequel nous enregistrons simplement un écouteur d'événements pour les événements push.

self.addEventListener('push', event => {
    const data = event.data.json();
    self.registration.showNotification(data.title, { body : data.text });
});

Lorsqu'un événement push survient, nous utilisons simplement l'API JavaScript Notification pour afficher une notification.

Note : QtWebEngine Notification Example montre comment fournir votre propre gestionnaire et personnaliser l'aspect et la convivialité d'un message de notification.

Une fois l'implémentation en place, nous pouvons démarrer le serveur sur localhost au port 5000. Pour ce faire, nous pouvons simplement entrer dans la console dans le répertoire racine du projet :

npm start

Nous pouvons maintenant examiner l'application de navigation push-notification, qui est basée sur l'exemple de notification de WebEngine:

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();
}

Cette application ouvre simplement la page à l'adresse http:\\localhost:5000. Nous n'entrerons pas dans les détails de l'ouverture d'une notification, car elle est documentée ici. Cependant, vous devez modifier l'application de deux manières. Tout d'abord, QWebEngineProfile ne peut pas être réglé sur off-the-record car la messagerie push serait désactivée. Par conséquent, comme vous pouvez le voir ci-dessus, QWebEngineProfile est initialisé avec le nom. Deuxièmement, vous devez activer la messagerie push avec l'appel QWebEngineProfile::setPushServiceEnabled pour le site créé profile.

Lorsque l'application s'exécute, elle s'affiche :

Application avec champ de texte pour la saisie de l'intervalle de notification

Après avoir accordé la permission, nous pouvons envoyer notre demande de ping :

Dialogue de permission demandant l'accès à la notification

Nous devrions voir la notification push à venir :

Exemple de projet @ code.qt.io

© 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.