웹엔진 위젯 권한 브라우저 예제
웹사이트 권한 요청을 처리하고 기존 권한을 관리하는 방법을 보여줍니다.
권한 브라우저는 QWebEnginePermission 클래스를 사용하여 웹사이트 권한을 관리하는 방법을 보여줍니다. 이 예시에는 들어오는 권한 요청을 처리하는 코드와 이미 존재하는 권한을 수정하는 코드가 포함되어 있습니다. 또한 QWebEngineProfile 클래스 내에 정의된 다양한 권한 지속성 정책의 효과도 설명합니다.
예제 실행하기
에서 예제를 실행하려면 Qt Creator에서 Welcome 모드를 열고 Examples 에서 예제를 선택합니다. 자세한 내용은 예제 빌드 및 실행하기를 참조하세요.
클래스 정의
MainWindow
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에서 "새로 만들기" 버튼을 클릭하면 팝업 창이 나타나 사용자가 알려진 출처에 권한을 미리 부여할 수 있습니다. 이 팝업은 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, 그리고 해당 권한의 현재 상태가 표시됩니다. 또한 권한을 허용하거나 거부하는 버튼도 있습니다. 권한 상태는 (기본적으로) 기억되므로 삭제 버튼을 사용하면 기본 저장소에서 권한을 제거할 수 있습니다.
이 모든 작업을 수행하려면 먼저 QWebEnginePage 의 permissionRequested
신호를 MainWindow
의 handlePermissionRequested
슬롯에 연결합니다:
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::persistentPermissionsPolicy 이 AskEveryTime
으로 설정된 경우 기존 권한 목록에 아무것도 추가하지 않습니다.
참고: 어떤 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를 사용하여 수정됩니다.
권한 사전 부여
출처와 권한 유형을 알고 있는 경우 특정 권한을 미리 부여할 수 있습니다. 오른쪽 상단의 '새로 만들기' 버튼을 클릭하면 이를 수행할 수 있는 팝업 대화 상자가 나타납니다. 이 대화 상자는 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 을 채웁니다. 영구적이지 않은 권한 유형은 사전 부여가 지원되지 않으므로 반드시 필터링해야 합니다.
대화 상자를 표시하고 MainWindow::handleNewClicked
슬롯 내부의 UI에 결과 PermissionWidget
표시를 추가합니다. 새 권한은 웹사이트가 요청했을 때와 동일한 방식으로 처리됩니다. handlePermissionRequested()
을 호출하여 처리합니다.
void MainWindow::handleNewClicked() { PermissionDialog dialog(m_profile); if (dialog.exec() == QDialog::Accepted) { handlePermissionRequested(dialog.permission()); } }
권한 지속성 정책 변경하기
기본적으로 권한은 명명된 모든 QWebEngineProfile 에 대해 디스크에 저장되고, 명명되지 않은/기록되지 않은 모든 권한은 메모리에 저장됩니다. 일반적으로 이 설정은 런타임에 변경되지 않지만 이 예에서는 각 옵션의 효과를 살펴봅니다.
- QWebEngineProfile::StoreOnDisk 기본값은 현재 애플리케이션 실행에서 부여된 모든 권한이 다음 시작 시 다시 로드되도록 합니다. 권한은 한 번만 부여하면 되며, 이후 애플리케이션이 QWebEnginePermission::reset()를 호출할 때까지 요청을 트리거한 API의 사용은 자동으로 부여됩니다.
- QWebEngineProfile::StoreInMemory 위와 동작은 동일하지만, 애플리케이션 종료 시 권한이 삭제되고 디스크에 커밋되지 않는다는 점이 다릅니다.
- QWebEngineProfile::AskEveryTime 는 권한이 기억되지 않고 모두 비영구적인 것처럼 동작합니다. 따라서 웹 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(); }
© 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.