WebEngine ウィジェット権限ブラウザの例

Webサイトのパーミッション要求を処理し、既存のパーミッションを管理する方法を示します。

Permission Browser は、QWebEnginePermission クラスを使用して Web サイトのパーミッションを管理する方法を示します。この例には、入ってくるパーミッションのリクエストを処理するコードと、すでに存在するパーミッションを修正するコードが含まれています。また、QWebEngineProfile クラスの中で定義された異なるパーミッションの永続化ポリシーの効果も示します。

例の実行

からサンプルを実行するには Qt Creatorからサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Exampleを参照してください。

クラス定義

メインウィンドウ

MainWindow クラスはQMainWindow を継承している。内部では、個々のパーミッションを操作するために使用されるウィジェットをレイアウトするQVBoxLayout への便宜的なポインタと、現在保留中のパーミッション要求を表示するウィジェットへの別の便宜的なポインタを宣言する。また、実際のウェブページ・コンテンツを表示するために使用されるQWebEngineView も宣言します。

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

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

アプリケーションの残りのレイアウトはmainwindow.uiの中で定義され、Qt Creator のデザイン・モードを使って作成されています。MainWindow はUi_MainWindowの子クラスで、mainwindow.uiの中の定義からコンパイル時に生成されるC++クラスです。

PermissionWidgetとPermissionDialog

PermissionWidget クラスは一つのQWebEnginePermission インスタンスに対応するウィジェットを定義します。便宜上、QWebEnginePermission オブジェクトが格納されています。ウィジェット自身はパーミッションを許可、拒否、削除するためのコントロールを持っています; このすべては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();
};

メインウィンドウのUIで "New "ボタンをクリックすると、ポップアップウィンドウが表示され、ユーザーは既知のオリジンに対して事前にパーミッションを付与することができる。このポップアップはPermissionDialog クラスで定義されています:

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

private:
    const QWebEngineProfile *m_profile;
    QWebEnginePermission *m_permission;
};

パーミッション要求の処理

ウェブサイトがユーザーのプライバシーを侵害する可能性のあるAPIを使用するときはいつでも、ブラウザは許可を与えるか拒否するかを尋ねるプロンプトを表示することが期待されています。PermissionBrowserの例では、右下に専用のセクションがあり、そのようなことが起こるたびにPermissionWidget

PermissionWidget は、パーミッションのオリジン、リクエストされたQWebEnginePermission::PermissionType 、パーミッションの現在のステータスを表示します。また、パーミッションの許可と拒否のボタンもあります。パーミッションのステータスは(デフォルトで)記憶されているので、削除ボタンは、ユーザーが基礎となるストレージからパーミッションを削除することを可能にする。

これらすべてを実現するために、まずQWebEnginePagepermissionRequested シグナルをMainWindowhandlePermissionRequested スロットに接続する:

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

このシグナル・ハンドラは比較的単純である。提供されたQWebEnginePermission オブジェクトに対してPermissionWidget インスタンスの作成を試み、成功すれば、保留中のパーミッション用に指定されたQFrame にそのウィジェットをプラグインする。また、PermissionWidget'のpermissionModified シグナルもサブスクライブして、PermissionWidget を右下から上の既存ウィジェットのリストに移動できるようにしています。

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

新しいPermissionWidget を作成するのは、まだ既存のものがない場合だけです:

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

    return new PermissionWidget(permission, this);
}

パーミッションの変更とユーザーへの表示

QWebEnginePermission インターフェースは、grant() とdeny() 関数を提供します。これらは、パーミッションのステータスを変更するために必要なすべてです。アプリケーションがパーミッションのことを忘れる必要がある場合は、reset ()関数を使用します。

PermissionWidget コンストラクタの内部で、これらの関数をボタンのclicked シグナルにフックし、QWebEnginePermission オブジェクト上で関連する機能を実行できるようにします。

ボタンが押されるたびに、permissionModified シグナルを発信します。MainWindow は、ウィジェットを右下から既存のパーミッションのリストに移動する必要があるときに、このシグナルを使用します。また、ウィジェットの視覚的な更新を処理するupdateState() も必ず呼び出します。削除ボタンが押されたとき、ウィジェットを削除するようにマークすることも確認します。

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

updateState() 関数は、QWebEnginePermission によって提供されたデータをユーザーに表示します。また、パーミッションがQWebEnginePermission::Invalid の状態にあるとき、許可または拒否のボタンが無効になるようにします。

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

保留中のパーミッションが許可または拒否されたとき、関連するウィジェットを、現在存在するすべてのパーミッションを含む上のリストに移動したい。これは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);
}

PermissionTypes の中には永続的でないものがあります。つまり、使用するたびにパーミッションのプロンプトをユーザーに表示する必要があります。また、QWebEnginePermission::Ask 状態のパーミッションは除外します。これは、パーミッションがreset() であったことを示すものです。QWebEngineProfile::persistentPermissionsPolicyAskEveryTime に設定されている場合、既存のパーミッションのリストに何も追加しません。

注: どのPermissionTypes が永続的であるかはQWebEnginePermission::PermissionType のドキュメントを確認してください。

既存のパーミッションの表示と変更

デフォルトでは、パーミッションはディスクに保存され、アプリケーションの起動時に再度取得されます。既存のすべてのパーミッションのリストを取得するには、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);
    }
}

リスト内のすべてのパーミッションについて、単純に新しいPermissionWidget を作成し、画面右側のリストに追加します。既存のパーミッションは、保留中のものとまったく同じAPIを使用して変更される。

パーミッションの事前付与

特定のパーミッションは、オリジンとパーミッションのタイプがわかっていれば、事前に付与することができる。右上の "New "ボタンをクリックすると、そのためのダイアログがポップアップ表示されます。このダイアログはPermissionDialog クラスによって実装されています:

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

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

QWebEnginePermission::PermissionType に関連づけられたQMetaEnum タイプを使用して、QComboBox に入力します。永続的でないパーミッション・タイプは事前に付与することがサポートされていないため、必ずフィルタリングしてください。

ダイアログを表示し、結果のPermissionWidget をUIのMainWindow::handleNewClicked スロットに追加します。新しいパーミッションは、ウェブサイトから要求された場合と同じように扱われます:handlePermissionRequested() を呼び出すことによって。

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

パーミッションの永続化ポリシーの変更

デフォルトでは、パーミッションはすべての名前付きQWebEngineProfile に対してディスクに保存され、すべての名前なし/記録外のものに対してはメモリに保存される。通常、この設定を実行時に変更することはないが、この例では各オプションの効果を調べる。

  • QWebEngineProfile::StoreOnDisk はデフォルトであり、現在のアプリケー ション実行時に付与されたパーミッションが、次回起動時に確実にロードさ れるようにする。パーミッションは一度だけ付与される必要があり、それ以降、アプリケーションが () を呼び出すまで、リクエストのトリガーとなったAPIの使用は自動的に許可されます。QWebEnginePermission::reset
  • QWebEngineProfile::StoreInMemory アプリケーションの終了時にパーミッションが破棄され、ディスクにコミットされないことを除けば、上記と同じ動作をします。
  • QWebEngineProfile::AskEveryTime は、パーミッションが記憶されず、あたかも永続的でないかのように動作することを確認します。したがって、Web APIがパーミッションを必要とするたびに、新しいプロンプトがユーザーに表示されます。このオプションは後方互換性と、独自のパーミッション保存を実装するアプリケーションを意図しています。

ユーザーに以前に存在したパーミッションが表示されるようにするには、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);
    }
}

これは起動時に一度だけ行われる。また、右上のQComboBox 、ユーザーがポリシーを変更するたびに行われる。

void MainWindow::handlePolicyComboBoxIndexChanged(int index)
{
    QWebEngineProfile::PersistentPermissionsPolicy policy;
    switch (index) {
    case 0:
        policy = QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime;
        break;
    case 1:
        policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory;
        break;
    case 2:
        policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk;
        break;
    }

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

プロジェクト例 @ code.qt.io

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