Sur cette page

WebEngine Widgets Permission Browser Exemple

Démontre comment gérer les demandes de permissions du site web et gérer les permissions existantes.

Navigateur de permissions avec une page web présentant les sections presse-papiers, notifications et polices sur la gauche et le panneau des permissions sur la droite avec les options d'octroi et de suppression.

Permission Browser montre comment utiliser la classe QWebEnginePermission pour gérer les permissions d'un site web. L'exemple comprend du code pour gérer les demandes d'autorisation entrantes, ainsi que pour modifier les autorisations existantes. Il montre également les effets des différentes politiques de persistance des permissions définies dans la classe QWebEngineProfile.

Exécution de l'exemple

Pour exécuter l'exemple à partir de Qt Creatorouvrez le mode Welcome et sélectionnez l'exemple de Examples. Pour plus d'informations, voir Qt Creator: Tutoriel : Construire et exécuter.

Définitions des classes

Fenêtre principale

La classe MainWindow hérite de QMainWindow. À l'intérieur, nous déclarons un pointeur de commodité vers le site QVBoxLayout qui présentera les widgets utilisés pour manipuler les autorisations individuelles, ainsi qu'un autre pointeur de commodité vers le widget affichant la demande d'autorisation en cours. Nous déclarons également un QWebEngineView, qui sera utilisé pour afficher le contenu de la page web.

class MainWindow : public QMainWindow, public Ui_MainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(const QUrl &url);
    ~MainWindow();

private slots:
    void handlePermissionRequested(QWebEnginePermission permission);
    void handleUrlChanged(const QUrl &url);

    void handlePermissionModified(PermissionWidget *widget);
    void handleDeleteAllClicked();
    void handleNewClicked();
    void handleRefreshClicked();
    void handleBackClicked();
    void handleForwardClicked();
    void handlePolicyComboBoxIndexChanged(int);

private:
    bool containsPermission(const QWebEnginePermission &permission);
    PermissionWidget *createPermissionWidget(const QWebEnginePermission &permission);
    void loadStoredPermissions();

    QVBoxLayout *m_layout;
    QWebEngineProfile *m_profile;
    QWebEngineView *m_webview;
    PermissionWidget *m_pendingWidget;
};

Le reste de la présentation de l'application est défini dans mainwindow.ui et a été créé en utilisant le mode Qt Creator Design . MainWindow est une classe enfant de Ui_MainWindow, qui est une classe C++ générée au moment de la compilation à partir des définitions trouvées dans mainwindow.ui.

PermissionWidget et PermissionDialog

La classe PermissionWidget définit un widget correspondant à une seule instance de QWebEnginePermission. Pour des raisons de commodité, l'objet QWebEnginePermission est stocké à l'intérieur. Le widget lui-même dispose de commandes permettant d'accorder, de refuser ou de supprimer la permission ; tout cela est défini à l'intérieur de PermissionWidget.ui.

class PermissionWidget : public QWidget, public Ui_PermissionWidget
{
    Q_OBJECT
public:
    PermissionWidget(const QWebEnginePermission &permission, QWidget *parent = nullptr);

    QWebEnginePermission m_permission;

signals:
    void permissionModified(PermissionWidget *widget);

private:
    void updateState();
};

En cliquant sur le bouton "Nouveau" dans l'interface utilisateur de la fenêtre principale, une fenêtre contextuelle apparaît, permettant à l'utilisateur d'accorder au préalable une autorisation à une origine connue. Cette fenêtre contextuelle est définie par la classe PermissionDialog:

class PermissionDialog : public QDialog, public Ui_PermissionDialog
{
    Q_OBJECT
public:
    PermissionDialog(const QWebEngineProfile *profile, QWidget *parent = nullptr);
    QWebEnginePermission permission() const;

private:
    const QWebEngineProfile *m_profile;
};

Traitement des demandes de permission entrantes

Chaque fois qu'un site web utilise une API susceptible de compromettre la vie privée de l'utilisateur, le navigateur est censé lui montrer une invite lui demandant d'accorder ou de refuser l'autorisation. L'exemple PermissionBrowser dispose d'une section dédiée en bas à droite, qui est remplie par une adresse PermissionWidget chaque fois que cela se produit.

Le site PermissionWidget affiche l'origine de la permission, la demande QWebEnginePermission::PermissionType, ainsi que l'état actuel de cette permission. Il comporte également des boutons permettant d'accorder ou de refuser la permission. Étant donné que l'état de la permission est (par défaut) mémorisé, le bouton de suppression permet à l'utilisateur de supprimer la permission du stockage sous-jacent.

Pour réaliser tout cela, nous connectons d'abord le signal permissionRequested de QWebEnginePage à l'emplacement handlePermissionRequested de MainWindow:

    connect(m_webview->page(), &QWebEnginePage::permissionRequested, this, &MainWindow::handlePermissionRequested);

Le gestionnaire du signal est relativement simple : il tente de créer une instance PermissionWidget pour l'objet QWebEnginePermission fourni et, s'il y parvient, il insère ce widget dans l'emplacement QFrame désigné pour les autorisations en attente. Nous souscrivons également au signal permissionModified de PermissionWidget afin de pouvoir déplacer plus tard le PermissionWidget du bas à droite vers la liste des widgets existants ci-dessus.

void MainWindow::handlePermissionRequested(QWebEnginePermission permission)
{
    PermissionWidget *widget = createPermissionWidget(permission);
    if (widget) {
        m_pendingFrame->layout()->addWidget(widget);
        connect(widget, &PermissionWidget::permissionModified, this, &MainWindow::handlePermissionModified);

        if (m_pendingWidget)
            m_pendingWidget->deleteLater();

        m_pendingWidget = widget;
    }
}

Nous ne créons un nouveau PermissionWidget que si nous n'en avons pas déjà un :

PermissionWidget *MainWindow::createPermissionWidget(const QWebEnginePermission &permission)
{
    if (containsPermission(permission))
        return nullptr;

    return new PermissionWidget(permission, this);
}

Modifier une autorisation et l'afficher à l'utilisateur

L'interface QWebEnginePermission fournit les fonctions grant() et deny(), qui suffisent à modifier l'état d'une permission. Si l'application doit oublier une permission, nous utilisons la fonction reset().

Dans le constructeur PermissionWidget, nous connectons ces fonctions au signal clicked des boutons, afin de pouvoir exécuter la fonctionnalité correspondante sur l'objet QWebEnginePermission.

Chaque fois qu'un bouton est pressé, nous émettons le signal permissionModified, que MainWindow utilise pour savoir quand il doit déplacer le widget du bas à droite vers la liste des autorisations existantes. Nous veillons également à appeler updateState(), qui gère les mises à jour visuelles du widget. Lorsque le bouton de suppression est actionné, nous veillons également à marquer le widget pour suppression, puisque nous voulons seulement afficher les autorisations existantes à l'utilisateur.

PermissionWidget::PermissionWidget(const QWebEnginePermission &permission, QWidget *parent)
    : QWidget(parent)
    , m_permission(permission)
{
    setupUi(this);
    connect(m_deleteButton, &QPushButton::clicked, [this]() {
        m_permission.reset();
        emit permissionModified(this);
        deleteLater();
    });

    connect(m_grantButton, &QPushButton::clicked, [this]() {
        m_permission.grant();
        updateState();
        emit permissionModified(this);
    });

    connect(m_denyButton, &QPushButton::clicked, [this]() {
        m_permission.deny();
        updateState();
        emit permissionModified(this);
    });

    updateState();
}

La fonction updateState() affiche les données fournies par QWebEnginePermission à l'utilisateur. Elle s'assure également que, lorsqu'une autorisation est dans l'état QWebEnginePermission::Invalid, les boutons permettant de l'accorder ou de la refuser sont désactivés.

void PermissionWidget::updateState()
{
    switch (m_permission.state()) {
    case QWebEnginePermission::State::Invalid:
        m_stateLabel->setText("<font color='gray'>Invalid</font>");
        m_grantButton->setEnabled(false);
        m_denyButton->setEnabled(false);
        break;
    case QWebEnginePermission::State::Ask:
        m_stateLabel->setText("<font color='yellow'>Waiting for response</font>");
        break;
    case QWebEnginePermission::State::Granted:
        m_stateLabel->setText("<font color='green'>Granted</font>");
        break;
    case QWebEnginePermission::State::Denied:
        m_stateLabel->setText("<font color='red'>Denied</font>");
        break;
    }

    m_typeLabel->setText(QMetaEnum::fromType<QWebEnginePermission::PermissionType>().valueToKey((quint8)m_permission.permissionType()));
    m_originLabel->setText(m_permission.origin().toDisplayString());
}

Lorsqu'une autorisation en attente est accordée ou refusée, nous voulons déplacer le widget associé vers la liste ci-dessus, qui contient toutes les autorisations existantes. Nous le faisons dans l'emplacement MainWindow::handlePermissionModified.

void MainWindow::handlePermissionModified(PermissionWidget *widget)
{
    if (!m_pendingWidget || m_pendingWidget != widget)
        return;

    m_pendingFrame->layout()->removeWidget(widget);
    m_pendingWidget = nullptr;

    if (!QWebEnginePermission::isPersistent(widget->m_permission.permissionType())
        || widget->m_permission.state() == QWebEnginePermission::State::Ask
        || m_profile->persistentPermissionsPolicy() == QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime) {

        widget->deleteLater();
        return;
    }

    m_layout->insertWidget(0, widget);
}

Notamment, nous ne faisons cela que dans les cas où nous savons que l'autorisation est mémorisée ; certaines adresses PermissionTypes ne sont pas persistantes, ce qui signifie qu'une invite d'autorisation doit être montrée à l'utilisateur à chaque fois qu'elles sont utilisées. Nous excluons également les autorisations dont l'état est QWebEnginePermission::Ask, ce qui indique que l'autorisation était reset(), et nous n'ajoutons rien à la liste des autorisations existantes lorsque QWebEngineProfile::persistentPermissionsPolicy est défini comme AskEveryTime.

Remarque : consultez la documentation de QWebEnginePermission::PermissionType pour savoir quels sont les PermissionTypes qui sont persistants.

Affichage et modification des autorisations existantes

Par défaut, les autorisations sont stockées sur le disque et récupérées au démarrage de l'application. Pour obtenir une liste de toutes les permissions existantes sur le site web, nous appelons QWebEngineProfile::listAllPermissions() :

void MainWindow::loadStoredPermissions()
{
    QList<QWebEnginePermission> permissionsList = m_profile->listAllPermissions();
    for (QWebEnginePermission &permission : permissionsList) {
        PermissionWidget *widget = createPermissionWidget(permission);
        if (widget)
            m_layout->insertWidget(0, widget);
    }
}

Pour chaque permission de la liste, nous construisons simplement un nouveau PermissionWidget, et l'ajoutons à la liste sur le côté droit de l'écran. Les autorisations existantes sont modifiées en utilisant exactement la même API que les autorisations en attente.

Octroi préalable de permissions

Certaines autorisations peuvent être accordées à l'avance, à condition que l'origine et le type d'autorisation soient connus. En cliquant sur le bouton "New" en haut à droite, une fenêtre de dialogue s'ouvre pour vous permettre de le faire. Cette boîte de dialogue est mise en œuvre par la classe PermissionDialog:

PermissionDialog::PermissionDialog(const QWebEngineProfile *profile, QWidget *parent)
    : QDialog(parent), m_profile(profile)
{
    setupUi(this);

    auto metaEnum = QMetaEnum::fromType<QWebEnginePermission::PermissionType>();
    for (int i = 0; i < metaEnum.keyCount(); ++i) {
        auto permissionType = QWebEnginePermission::PermissionType(metaEnum.value(i));
        if (QWebEnginePermission::isPersistent(permissionType))
            m_permissionTypeComboBox->addItem(metaEnum.key(i), QVariant::fromValue(permissionType));
    }
}

Nous remplissons le site QComboBox en utilisant le type QMetaEnum associé à QWebEnginePermission::PermissionType. Nous veillons à filtrer les types de permission non persistants, car leur pré-attribution n'est pas prise en charge.

Nous affichons la boîte de dialogue et ajoutons l'adresse PermissionWidget résultante dans l'interface utilisateur à l'intérieur de l'emplacement MainWindow::handleNewClicked. La nouvelle autorisation est gérée de la même manière que si un site web la demandait : en appelant handlePermissionRequested().

void MainWindow::handleNewClicked()
{
    PermissionDialog dialog(m_profile);
    if (dialog.exec() == QDialog::Accepted) {
        handlePermissionRequested(dialog.permission());
    }
}

Modification de la politique de persistance des autorisations

Par défaut, les autorisations sont stockées sur le disque pour toutes les autorisations nommées QWebEngineProfile, et en mémoire pour toutes les autorisations non nommées/off-the-record. Normalement, ce paramètre ne sera pas modifié lors de l'exécution, mais cet exemple explore les effets de chaque option.

  • QWebEngineProfile::StoreOnDisk est la valeur par défaut et garantit que toutes les autorisations accordées lors de l'exécution de l'application en cours seront rechargées au prochain démarrage. Une permission ne doit être accordée qu'une seule fois, et les utilisations ultérieures de l'API qui a déclenché la demande seront automatiquement accordées, jusqu'à ce que l'application appelle QWebEnginePermission::reset().
  • QWebEngineProfile::StoreInMemory A le même comportement que ci-dessus, sauf que les permissions seront détruites à la sortie de l'application, et non pas enregistrées sur le disque.
  • QWebEngineProfile::AskEveryTime assure que les permissions ne sont jamais mémorisées et qu'elles agissent comme si elles étaient non persistantes. Ainsi, chaque fois qu'une API web a besoin d'une permission, une nouvelle invite sera affichée à l'utilisateur. Cette option est destinée à la rétrocompatibilité et aux applications qui implémentent leur propre stockage de permissions.

Pour s'assurer que l'utilisateur verra les autorisations existantes, nous devons appeler QWebEngineProfile::listAllPermissions() :

void MainWindow::loadStoredPermissions()
{
    QList<QWebEnginePermission> permissionsList = m_profile->listAllPermissions();
    for (QWebEnginePermission &permission : permissionsList) {
        PermissionWidget *widget = createPermissionWidget(permission);
        if (widget)
            m_layout->insertWidget(0, widget);
    }
}

Ceci est fait une fois au démarrage, ainsi qu'à chaque fois que l'utilisateur modifie la politique à partir de QComboBox en haut à droite.

void MainWindow::handlePolicyComboBoxIndexChanged(int)
{
    auto policy =
            m_policyComboBox->currentData().value<QWebEngineProfile::PersistentPermissionsPolicy>();
    if (policy == m_profile->persistentPermissionsPolicy())
        return;

    for (int i = m_layout->count() - 1; i >= 0; i--) {
        PermissionWidget *widget = qobject_cast<PermissionWidget *>(m_layout->itemAt(i)->widget());
        if (!widget)
            continue;

        widget->deleteLater();
    }

    m_profile->setPersistentPermissionsPolicy(policy);
    loadStoredPermissions();
}

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.