Continued porting the web browser. QtWebEngine

Sun, 14 Feb 2016 19:34:05 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 14 Feb 2016 19:34:05 +0100
branch
QtWebEngine
changeset 4742
f9d1090f6ab9
parent 4741
f9e1adc69076
child 4743
f9e2e536d130

Continued porting the web browser.

- added support for feature permissions

WebBrowser/FeaturePermissions/FeaturePermissionBar.py file | annotate | diff | comparison | revisions
WebBrowser/FeaturePermissions/FeaturePermissionManager.py file | annotate | diff | comparison | revisions
WebBrowser/FeaturePermissions/FeaturePermissionsDialog.py file | annotate | diff | comparison | revisions
WebBrowser/FeaturePermissions/FeaturePermissionsDialog.ui file | annotate | diff | comparison | revisions
WebBrowser/FeaturePermissions/__init__.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserPage.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FeaturePermissions/FeaturePermissionBar.py	Sun Feb 14 19:34:05 2016 +0100
@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the feature permission bar widget.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSlot, QUrl
+from PyQt5.QtWidgets import QLabel, QHBoxLayout, QPushButton
+from PyQt5.QtWebEngineWidgets import QWebEnginePage
+
+from E5Gui.E5AnimatedWidget import E5AnimatedWidget
+
+import UI.PixmapCache
+
+
+class FeaturePermissionBar(E5AnimatedWidget):
+    """
+    Class implementing the feature permission bar widget.
+    """
+    DefaultHeight = 30
+    
+    def __init__(self, page, origin, feature, manager):
+        """
+        Constructor
+        
+        @param page reference to the web page
+        @type QWebView
+        @param origin security origin requesting the feature
+        @type QUrl
+        @param feature requested feature
+        @type QWebPage.Feature
+        @param manager reference to the feature permissions manager
+        @type FeaturePermissionManager
+        """
+        super(FeaturePermissionBar, self).__init__(parent=page.view())
+        
+        self.__origin = QUrl(origin)
+        self.__feature = feature
+        self.__page = page
+        self.__manager = manager
+        
+        self.__permissionFeatureTexts = {
+            # TODO: Qt 5.6
+##            QWebEnginePage.Notifications:
+##                self.tr("{0} wants to use desktop notifications."),
+            QWebEnginePage.Geolocation:
+                self.tr("{0} wants to use your position."),
+            QWebEnginePage.MediaAudioCapture:
+                self.tr("{0} wants to use your microphone."),
+            QWebEnginePage.MediaVideoCapture:
+                self.tr("{0} wants to use your camera."),
+            QWebEnginePage.MediaAudioVideoCapture:
+                self.tr("{0} wants to use your microphone and camera."),
+        }
+        self.__permissionFeatureIconNames = {
+            # TODO: Qt 5.6
+##            QWebEnginePage.Notifications: "notification.png",
+            QWebEnginePage.Geolocation: "geolocation.png",
+            QWebEnginePage.MediaAudioCapture: "audiocapture.png",
+            QWebEnginePage.MediaVideoCapture: "camera.png",
+            QWebEnginePage.MediaAudioVideoCapture: "audio-video.png",
+        }
+        
+        self.setAutoFillBackground(True)
+        self.__layout = QHBoxLayout()
+        self.setLayout(self.__layout)
+        self.__layout.setContentsMargins(9, 0, 0, 0)
+        self.__iconLabel = QLabel(self)
+        self.__layout.addWidget(self.__iconLabel)
+        self.__messageLabel = QLabel(self)
+        self.__layout.addWidget(self.__messageLabel)
+        self.__layout.addStretch()
+        self.__rememberButton = QPushButton(self.tr("Remember"), self)
+        self.__rememberButton.setCheckable(True)
+        self.__allowButton = QPushButton(self.tr("Allow"), self)
+        self.__denyButton = QPushButton(self.tr("Deny"), self)
+        self.__discardButton = QPushButton(UI.PixmapCache.getIcon("close.png"),
+                                           "", self)
+        self.__allowButton.clicked.connect(self.__permissionGranted)
+        self.__denyButton.clicked.connect(self.__permissionDenied)
+        self.__discardButton.clicked.connect(self.__permissionUnknown)
+        self.__layout.addWidget(self.__rememberButton)
+        self.__layout.addWidget(self.__allowButton)
+        self.__layout.addWidget(self.__denyButton)
+        self.__layout.addWidget(self.__discardButton)
+        
+        try:
+            self.__iconLabel.setPixmap(UI.PixmapCache.getPixmap(
+                self.__permissionFeatureIconNames[self.__feature]))
+        except KeyError:
+            pass
+        
+        try:
+            self.__messageLabel.setText(
+                self.__permissionFeatureTexts[self.__feature].format(
+                    self.__origin.host()))
+        except KeyError:
+            self.__messageLabel.setText(
+                self.tr("{0} wants to use an unknown feature.").format(
+                    self.__origin.host()))
+        
+        self.__page.loadStarted.connect(self.hide)
+        
+        self.resize(self.__page.view().width(), self.height())
+        self.startAnimation()
+    
+    @pyqtSlot()
+    def hide(self):
+        """
+        Public slot to hide the animated widget.
+        """
+        self.__page.loadStarted.disconnect(self.hide)
+        super(FeaturePermissionBar, self).hide()
+    
+    def __permissionDenied(self):
+        """
+        Private slot handling the user pressing the deny button.
+        """
+        if self.__page is None or self.__manager is None:
+            return
+        
+        self.__page.setFeaturePermission(
+            self.__origin, self.__feature,
+            QWebEnginePage.PermissionDeniedByUser)
+        
+        if self.__rememberButton.isChecked():
+            self.__manager.rememberFeaturePermission(
+                self.__page.url().host(), self.__feature,
+                QWebEnginePage.PermissionDeniedByUser)
+        
+        self.hide()
+    
+    def __permissionGranted(self):
+        """
+        Private slot handling the user pressing the allow button.
+        """
+        if self.__page is None or self.__manager is None:
+            return
+        
+        self.__page.setFeaturePermission(
+            self.__origin, self.__feature,
+            QWebEnginePage.PermissionGrantedByUser)
+        
+        if self.__rememberButton.isChecked():
+            self.__manager.rememberFeaturePermission(
+                self.__page.url().host(), self.__feature,
+                QWebEnginePage.PermissionGrantedByUser)
+        
+        self.hide()
+    
+    def __permissionUnknown(self):
+        """
+        Private slot handling the user closing the dialog without.
+        """
+        if self.__page is None or self.__manager is None:
+            return
+        
+        self.__page.setFeaturePermission(
+            self.__origin, self.__feature,
+            QWebEnginePage.PermissionUnknown)
+        
+        self.hide()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FeaturePermissions/FeaturePermissionManager.py	Sun Feb 14 19:34:05 2016 +0100
@@ -0,0 +1,188 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the feature permission manager object.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import QObject
+from PyQt5.QtWidgets import QDialog
+from PyQt5.QtWebEngineWidgets import QWebEnginePage
+
+import Globals
+import Preferences
+
+
+class FeaturePermissionManager(QObject):
+    """
+    Class implementing the feature permission manager object.
+    """
+    SettingsKeyFormat = "WebBrowser/FeaturePermissions/{0}"
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent object
+        @type QObject
+        """
+        super(FeaturePermissionManager, self).__init__(parent)
+        
+        self.__featurePermissions = {
+            # TODO: Qt 5.6
+##            QWebEnginePage.Notifications: {
+##                QWebEnginePage.PermissionGrantedByUser: [],
+##                QWebEnginePage.PermissionDeniedByUser: [],
+##            },
+            QWebEnginePage.Geolocation: {
+                QWebEnginePage.PermissionGrantedByUser: [],
+                QWebEnginePage.PermissionDeniedByUser: [],
+            },
+            QWebEnginePage.MediaAudioCapture: {
+                QWebEnginePage.PermissionGrantedByUser: [],
+                QWebEnginePage.PermissionDeniedByUser: [],
+            },
+            QWebEnginePage.MediaVideoCapture: {
+                QWebEnginePage.PermissionGrantedByUser: [],
+                QWebEnginePage.PermissionDeniedByUser: [],
+            },
+            QWebEnginePage.MediaAudioVideoCapture: {
+                QWebEnginePage.PermissionGrantedByUser: [],
+                QWebEnginePage.PermissionDeniedByUser: [],
+            },
+        }
+        self.__featurePermissionsKeys = {
+            # TODO: Qt 5.6
+##            (QWebEnginePage.Notifications,
+##             QWebEnginePage.PermissionGrantedByUser):
+##            "NotificationsGranted",
+##            (QWebEnginePage.Notifications,
+##             QWebEnginePage.PermissionDeniedByUser):
+##            "NotificationsDenied",
+            (QWebEnginePage.Geolocation,
+             QWebEnginePage.PermissionGrantedByUser):
+            "GeolocationGranted",
+            (QWebEnginePage.Geolocation,
+             QWebEnginePage.PermissionDeniedByUser):
+            "GeolocationDenied",
+            (QWebEnginePage.MediaAudioCapture,
+             QWebEnginePage.PermissionGrantedByUser):
+            "MediaAudioCaptureGranted",
+            (QWebEnginePage.MediaAudioCapture,
+             QWebEnginePage.PermissionDeniedByUser):
+            "MediaAudioCaptureDenied",
+            (QWebEnginePage.MediaVideoCapture,
+             QWebEnginePage.PermissionGrantedByUser):
+            "MediaVideoCaptureGranted",
+            (QWebEnginePage.MediaVideoCapture,
+             QWebEnginePage.PermissionDeniedByUser):
+            "MediaVideoCaptureDenied",
+            (QWebEnginePage.MediaAudioVideoCapture,
+             QWebEnginePage.PermissionGrantedByUser):
+            "MediaAudioVideoCaptureGranted",
+            (QWebEnginePage.MediaAudioVideoCapture,
+             QWebEnginePage.PermissionDeniedByUser):
+            "MediaAudioVideoCaptureDenied",
+        }
+        
+        self.__loaded = False
+
+    def requestFeaturePermission(self, page, origin, feature):
+        """
+        Public method to request a feature permission.
+        
+        @param page reference to the requesting web page
+        @type QWebEnginePage
+        @param origin security origin requesting the feature
+        @type QUrl
+        @param feature requested feature
+        @type QWebEnginePage.Feature
+        """
+        if origin is None or origin.isEmpty():
+            return
+        
+        if not self.__loaded:
+            self.__loadSettings()
+        
+        host = origin.host()
+        
+        if feature in self.__featurePermissions:
+            for permission in self.__featurePermissions[feature]:
+                if host in self.__featurePermissions[feature][permission]:
+                    page.setFeaturePermission(origin, feature, permission)
+                    return
+        
+        from .FeaturePermissionBar import FeaturePermissionBar
+        bar = FeaturePermissionBar(page, origin, feature, self)
+        bar.show()
+    
+    def rememberFeaturePermission(self, host, feature, permission):
+        """
+        Public method to remember a user decision for a feature permission.
+        
+        @param host host name to remember the decision for
+        @type str
+        @param feature feature to be remembered
+        @type QWebEnginePage.Feature
+        @param permission feature permission to be remembered
+        @type QWebEnginePage.PermissionPolicy
+        """
+        if feature in self.__featurePermissions:
+            if host not in self.__featurePermissions[feature][permission]:
+                self.__featurePermissions[feature][permission].append(host)
+                self.__saveSettings()
+    
+    def __loadSettings(self):
+        """
+        Private method to load the remembered feature permissions.
+        """
+        if self.__loaded:
+            # no reloading allowed
+            return
+        
+        for (feature, permission), key in \
+                self.__featurePermissionsKeys.items():
+            self.__featurePermissions[feature][permission] = \
+                Globals.toList(Preferences.Prefs.settings.value(
+                    FeaturePermissionManager.SettingsKeyFormat.format(key),
+                    []
+                ))
+        
+        self.__loaded = True
+    
+    def __saveSettings(self):
+        """
+        Private method to save the remembered feature permissions.
+        """
+        if not self.__loaded:
+            return
+        
+        import WebBrowser.WebBrowserWindow
+        if WebBrowser.WebBrowserWindow.WebBrowserWindow\
+                .mainWindow().getWindow().isPrivate():
+            return
+        
+        for (feature, permission), key in \
+                self.__featurePermissionsKeys.items():
+            Preferences.Prefs.settings.setValue(
+                FeaturePermissionManager.SettingsKeyFormat.format(key),
+                self.__featurePermissions[feature][permission])
+    
+    def showFeaturePermissionsDialog(self):
+        """
+        Public method to show a dialog to manage the remembered feature
+        permissions.
+        """
+        if not self.__loaded:
+            self.__loadSettings()
+        
+        from .FeaturePermissionsDialog import FeaturePermissionsDialog
+        dlg = FeaturePermissionsDialog(self.__featurePermissions)
+        if dlg.exec_() == QDialog.Accepted:
+            newFeaturePermissions = dlg.getData()
+            self.__featurePermissions = newFeaturePermissions
+            self.__saveSettings()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FeaturePermissions/FeaturePermissionsDialog.py	Sun Feb 14 19:34:05 2016 +0100
@@ -0,0 +1,227 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the feature permission dialog.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSlot, Qt
+from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QTreeWidget, \
+    QAbstractItemView
+from PyQt5.QtWebEngineWidgets import QWebEnginePage
+
+import UI.PixmapCache
+
+from .Ui_FeaturePermissionsDialog import Ui_FeaturePermissionsDialog
+
+
+class FeaturePermissionsDialog(QDialog, Ui_FeaturePermissionsDialog):
+    """
+    Class implementing the feature permission dialog.
+    """
+    def __init__(self, featurePermissions, parent=None):
+        """
+        Constructor
+        
+        @param featurePermissions dictionary with remembered feature
+            permissions
+        @type dict of dict of list
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(FeaturePermissionsDialog, self).__init__(parent)
+        self.setupUi(self)
+        
+        # add the various lists
+        self.notifList = QTreeWidget()
+        self.notifList.setAlternatingRowColors(True)
+        self.notifList.setSelectionMode(QAbstractItemView.ExtendedSelection)
+        self.notifList.setRootIsDecorated(False)
+        self.notifList.setItemsExpandable(False)
+        self.notifList.setAllColumnsShowFocus(True)
+        self.notifList.setObjectName("notifList")
+        self.notifList.setSortingEnabled(True)
+        self.notifList.headerItem().setText(0, self.tr("Host"))
+        self.notifList.headerItem().setText(1, self.tr("Permission"))
+        self.tabWidget.addTab(
+            self.notifList, 
+            UI.PixmapCache.getIcon("notification.png"),
+            self.tr("Notifications"))
+        
+        self.geoList = QTreeWidget()
+        self.geoList.setAlternatingRowColors(True)
+        self.geoList.setSelectionMode(QAbstractItemView.ExtendedSelection)
+        self.geoList.setRootIsDecorated(False)
+        self.geoList.setItemsExpandable(False)
+        self.geoList.setAllColumnsShowFocus(True)
+        self.geoList.setObjectName("geoList")
+        self.geoList.setSortingEnabled(True)
+        self.geoList.headerItem().setText(0, self.tr("Host"))
+        self.geoList.headerItem().setText(1, self.tr("Permission"))
+        self.tabWidget.addTab(
+            self.geoList,
+            UI.PixmapCache.getIcon("geolocation.png"),
+            self.tr("Geolocation"))
+        
+        self.micList = QTreeWidget()
+        self.micList.setAlternatingRowColors(True)
+        self.micList.setSelectionMode(QAbstractItemView.ExtendedSelection)
+        self.micList.setRootIsDecorated(False)
+        self.micList.setItemsExpandable(False)
+        self.micList.setAllColumnsShowFocus(True)
+        self.micList.setObjectName("micList")
+        self.micList.setSortingEnabled(True)
+        self.micList.headerItem().setText(0, self.tr("Host"))
+        self.micList.headerItem().setText(1, self.tr("Permission"))
+        self.tabWidget.addTab(
+            self.micList,
+            UI.PixmapCache.getIcon("audiocapture.png"),
+            self.tr("Microphone"))
+        
+        self.camList = QTreeWidget()
+        self.camList.setAlternatingRowColors(True)
+        self.camList.setSelectionMode(QAbstractItemView.ExtendedSelection)
+        self.camList.setRootIsDecorated(False)
+        self.camList.setItemsExpandable(False)
+        self.camList.setAllColumnsShowFocus(True)
+        self.camList.setObjectName("camList")
+        self.camList.setSortingEnabled(True)
+        self.camList.headerItem().setText(0, self.tr("Host"))
+        self.camList.headerItem().setText(1, self.tr("Permission"))
+        self.tabWidget.addTab(
+            self.camList,
+            UI.PixmapCache.getIcon("camera.png"),
+            self.tr("Camera"))
+        
+        self.micCamList = QTreeWidget()
+        self.micCamList.setAlternatingRowColors(True)
+        self.micCamList.setSelectionMode(QAbstractItemView.ExtendedSelection)
+        self.micCamList.setRootIsDecorated(False)
+        self.micCamList.setItemsExpandable(False)
+        self.micCamList.setAllColumnsShowFocus(True)
+        self.micCamList.setObjectName("micCamList")
+        self.micCamList.setSortingEnabled(True)
+        self.micCamList.headerItem().setText(0, self.tr("Host"))
+        self.micCamList.headerItem().setText(1, self.tr("Permission"))
+        self.tabWidget.addTab(
+            self.micCamList,
+            UI.PixmapCache.getIcon("audio-video.png"),
+            self.tr("Microphone && Camera"))
+        
+        self.setTabOrder(self.tabWidget, self.notifList)
+        self.setTabOrder(self.notifList, self.geoList)
+        self.setTabOrder(self.geoList, self.micList)
+        self.setTabOrder(self.micList, self.camList)
+        self.setTabOrder(self.camList, self.micCamList)
+        self.setTabOrder(self.micCamList, self.removeButton)
+        self.setTabOrder(self.removeButton, self.removeAllButton)
+        
+        self.__permissionStrings = {
+            QWebEnginePage.PermissionGrantedByUser: self.tr("Allow"),
+            QWebEnginePage.PermissionDeniedByUser: self.tr("Deny"),
+        }
+        
+        self.__permissionsLists = {
+            # TODO: Qt 5.6
+##            QWebEnginePage.Notifications: self.notifList,
+            QWebEnginePage.Geolocation: self.geoList,
+            QWebEnginePage.MediaAudioCapture: self.micList,
+            QWebEnginePage.MediaVideoCapture: self.camList,
+            QWebEnginePage.MediaAudioVideoCapture: self.micCamList,
+        }
+        
+        for feature, permissionsList in self.__permissionsLists.items():
+            for permission in featurePermissions[feature]:
+                for host in featurePermissions[feature][permission]:
+                    itm = QTreeWidgetItem(
+                        permissionsList,
+                        [host, self.__permissionStrings[permission]])
+                    itm.setData(0, Qt.UserRole, permission)
+        
+        self.__previousCurrent = -1
+        self.tabWidget.currentChanged.connect(self.__currentTabChanged)
+        self.tabWidget.setCurrentIndex(0)
+    
+    @pyqtSlot(int)
+    def __currentTabChanged(self, index):
+        """
+        Private slot handling changes of the selected tab.
+        
+        @param index index of the current tab
+        @type int
+        """
+        if self.__previousCurrent >= 0:
+            previousList = self.tabWidget.widget(self.__previousCurrent)
+            previousList.itemSelectionChanged.disconnect(
+                self.__itemSelectionChanged)
+        
+        self.__updateButtons()
+        
+        currentList = self.tabWidget.currentWidget()
+        currentList.itemSelectionChanged.connect(self.__itemSelectionChanged)
+        self.__previousCurrent = index
+    
+    def __updateButtons(self):
+        """
+        Private method to update the buttons.
+        """
+        currentList = self.tabWidget.currentWidget()
+        self.removeAllButton.setEnabled(
+            currentList.topLevelItemCount() > 0)
+        self.removeButton.setEnabled(
+            len(currentList.selectedItems()) > 0)
+    
+    @pyqtSlot()
+    def __itemSelectionChanged(self):
+        """
+        Private slot handling changes in the current list of selected items.
+        """
+        self.__updateButtons()
+    
+    @pyqtSlot()
+    def on_removeButton_clicked(self):
+        """
+        Private slot to remove selected entries.
+        """
+        currentList = self.tabWidget.currentWidget()
+        for itm in currentList.selectedItems():
+            row = currentList.indexOfTopLevelItem(itm)
+            itm = currentList.takeTopLevelItem(row)
+            del itm
+        self.__updateButtons()
+    
+    @pyqtSlot()
+    def on_removeAllButton_clicked(self):
+        """
+        Private slot to remove all entries.
+        """
+        currentList = self.tabWidget.currentWidget()
+        while currentList.topLevelItemCount() > 0:
+            itm = currentList.takeTopLevelItem(0)      # __IGNORE_WARNING__
+            del itm
+        self.__updateGeoButtons()
+    
+    def getData(self):
+        """
+        Public method to retrieve the dialog contents.
+        
+        @return new feature permission settings
+        @rtype dict of dict of list
+        """
+        featurePermissions = {}
+        for feature, permissionsList in self.__permissionsLists.items():
+            featurePermissions[feature] = {
+                QWebEnginePage.PermissionGrantedByUser: [],
+                QWebEnginePage.PermissionDeniedByUser: [],
+            }
+            for row in range(permissionsList.topLevelItemCount()):
+                itm = permissionsList.topLevelItem(row)
+                host = itm.text(0)
+                permission = itm.data(0, Qt.UserRole)
+                featurePermissions[feature][permission].append(host)
+        
+        return featurePermissions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FeaturePermissions/FeaturePermissionsDialog.ui	Sun Feb 14 19:34:05 2016 +0100
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FeaturePermissionsDialog</class>
+ <widget class="QDialog" name="FeaturePermissionsDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>650</width>
+    <height>400</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>HTML5 Feature Permissions</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="1" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <layout class="QVBoxLayout" name="verticalLayout_3">
+     <item>
+      <spacer name="verticalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>40</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="removeButton">
+       <property name="text">
+        <string>&amp;Remove</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="removeAllButton">
+       <property name="text">
+        <string>Remove &amp;All</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="0" column="0">
+    <widget class="QTabWidget" name="tabWidget">
+     <property name="currentIndex">
+      <number>-1</number>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>tabWidget</tabstop>
+  <tabstop>removeButton</tabstop>
+  <tabstop>removeAllButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>FeaturePermissionsDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>227</x>
+     <y>381</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>FeaturePermissionsDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>295</x>
+     <y>387</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FeaturePermissions/__init__.py	Sun Feb 14 19:34:05 2016 +0100
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Package implementing feature permission related widgets for the eric6
+web browser.
+"""
--- a/WebBrowser/WebBrowserPage.py	Sun Feb 14 16:47:40 2016 +0100
+++ b/WebBrowser/WebBrowserPage.py	Sun Feb 14 19:34:05 2016 +0100
@@ -708,10 +708,9 @@
         @param feature requested feature
         @type QWebEnginePage.Feature
         """
-        # TODO: Feature Permission
-##        manager = WebBrowser.WebBrowserWindow.WebBrowserWindow\
-##            .featurePermissionManager()
-##        manager.requestFeaturePermission(self, frame, feature)
+        manager = WebBrowser.WebBrowserWindow.WebBrowserWindow\
+            .featurePermissionManager()
+        manager.requestFeaturePermission(self, url, feature)
     
     def execJavaScript(self, script):
         """
--- a/WebBrowser/WebBrowserWindow.py	Sun Feb 14 16:47:40 2016 +0100
+++ b/WebBrowser/WebBrowserWindow.py	Sun Feb 14 19:34:05 2016 +0100
@@ -95,7 +95,7 @@
 ##    _personalInformationManager = None
 ##    _greaseMonkeyManager = None
     _notification = None
-##    _featurePermissionManager = None
+    _featurePermissionManager = None
 ##    _flashCookieManager = None
     
     def __init__(self, home, path, parent, name, fromEric=False,
@@ -1367,23 +1367,22 @@
                 E5ErrorMessage.editMessageFilters)
         self.__actions.append(self.editMessageFilterAct)
         
-        # TODO: Feature Permission
-##        self.featurePermissionAct = E5Action(
-##            self.tr('Edit HTML5 Feature Permissions'),
-##            UI.PixmapCache.getIcon("featurePermission.png"),
-##            self.tr('Edit HTML5 Feature Permissions...'), 0, 0, self,
-##            'webbrowser_edit_feature_permissions')
-##        self.featurePermissionAct.setStatusTip(self.tr(
-##            'Edit the remembered HTML5 feature permissions'))
-##        self.featurePermissionAct.setWhatsThis(self.tr(
-##            """<b>Edit HTML5 Feature Permissions</b>"""
-##            """<p>Opens a dialog to edit the remembered HTML5"""
-##            """ feature permissions.</p>"""
-##        ))
-##        if not self.__initShortcutsOnly:
-##            self.featurePermissionAct.triggered.connect(
-##                self.__showFeaturePermissionDialog)
-##        self.__actions.append(self.featurePermissionAct)
+        self.featurePermissionAct = E5Action(
+            self.tr('Edit HTML5 Feature Permissions'),
+            UI.PixmapCache.getIcon("featurePermission.png"),
+            self.tr('Edit HTML5 Feature Permissions...'), 0, 0, self,
+            'webbrowser_edit_feature_permissions')
+        self.featurePermissionAct.setStatusTip(self.tr(
+            'Edit the remembered HTML5 feature permissions'))
+        self.featurePermissionAct.setWhatsThis(self.tr(
+            """<b>Edit HTML5 Feature Permissions</b>"""
+            """<p>Opens a dialog to edit the remembered HTML5"""
+            """ feature permissions.</p>"""
+        ))
+        if not self.__initShortcutsOnly:
+            self.featurePermissionAct.triggered.connect(
+                self.__showFeaturePermissionDialog)
+        self.__actions.append(self.featurePermissionAct)
         
         # TODO: re-enable once Qt 5.6 is available
 ##        if WebBrowserWindow.UseQtHelp or self.__initShortcutsOnly:
@@ -1858,7 +1857,7 @@
 ##        menu.addAction(self.offlineStorageAct)
 ##        menu.addAction(self.personalDataAct)
 ##        menu.addAction(self.greaseMonkeyAct)
-##        menu.addAction(self.featurePermissionAct)
+        menu.addAction(self.featurePermissionAct)
 ##        menu.addSeparator()
         menu.addAction(self.editMessageFilterAct)
         menu.addSeparator()
@@ -1998,7 +1997,7 @@
 ##        settingstb.addAction(self.offlineStorageAct)
 ##        settingstb.addAction(self.personalDataAct)
 ##        settingstb.addAction(self.greaseMonkeyAct)
-##        settingstb.addAction(self.featurePermissionAct)
+        settingstb.addAction(self.featurePermissionAct)
         
 ##        toolstb = self.addToolBar(self.tr("Tools"))
 ##        toolstb.setObjectName("ToolsToolBar")
@@ -3401,12 +3400,12 @@
 ##        """
 ##        self.greaseMonkeyManager().showConfigurationDialog()
 ##        
-##    def __showFeaturePermissionDialog(self):
-##        """
-##        Private slot to show the feature permission dialog.
-##        """
-##        self.featurePermissionManager().showFeaturePermissionsDialog()
-##        
+    def __showFeaturePermissionDialog(self):
+        """
+        Private slot to show the feature permission dialog.
+        """
+        self.featurePermissionManager().showFeaturePermissionsDialog()
+        
     def __showZoomValuesDialog(self):
         """
         Private slot to show the zoom values management dialog.
@@ -3588,21 +3587,21 @@
 ##        
 ##        return cls._greaseMonkeyManager
 ##        
-##    @classmethod
-##    def featurePermissionManager(cls):
-##        """
-##        Class method to get a reference to the feature permission manager.
-##        
-##        @return reference to the feature permission manager
-##        @rtype FeaturePermissionManager
-##        """
-##        if cls._featurePermissionManager is None:
-##            from .FeaturePermissions.FeaturePermissionManager import \
-##                FeaturePermissionManager
-##            cls._featurePermissionManager = FeaturePermissionManager()
-##        
-##        return cls._featurePermissionManager
-##        
+    @classmethod
+    def featurePermissionManager(cls):
+        """
+        Class method to get a reference to the feature permission manager.
+        
+        @return reference to the feature permission manager
+        @rtype FeaturePermissionManager
+        """
+        if cls._featurePermissionManager is None:
+            from .FeaturePermissions.FeaturePermissionManager import \
+                FeaturePermissionManager
+            cls._featurePermissionManager = FeaturePermissionManager()
+        
+        return cls._featurePermissionManager
+        
 ##    @classmethod
 ##    def flashCookieManager(cls):
 ##        """
--- a/eric6.e4p	Sun Feb 14 16:47:40 2016 +0100
+++ b/eric6.e4p	Sun Feb 14 19:34:05 2016 +0100
@@ -1289,6 +1289,10 @@
     <Source>WebBrowser/Bookmarks/XbelWriter.py</Source>
     <Source>WebBrowser/Bookmarks/__init__.py</Source>
     <Source>WebBrowser/ClosedTabsManager.py</Source>
+    <Source>WebBrowser/FeaturePermissions/FeaturePermissionBar.py</Source>
+    <Source>WebBrowser/FeaturePermissions/FeaturePermissionManager.py</Source>
+    <Source>WebBrowser/FeaturePermissions/FeaturePermissionsDialog.py</Source>
+    <Source>WebBrowser/FeaturePermissions/__init__.py</Source>
     <Source>WebBrowser/History/HistoryCompleter.py</Source>
     <Source>WebBrowser/History/HistoryDialog.py</Source>
     <Source>WebBrowser/History/HistoryFilterModel.py</Source>
@@ -1742,6 +1746,7 @@
     <Form>WebBrowser/Bookmarks/BookmarkPropertiesDialog.ui</Form>
     <Form>WebBrowser/Bookmarks/BookmarksDialog.ui</Form>
     <Form>WebBrowser/Bookmarks/BookmarksImportDialog.ui</Form>
+    <Form>WebBrowser/FeaturePermissions/FeaturePermissionsDialog.ui</Form>
     <Form>WebBrowser/History/HistoryDialog.ui</Form>
     <Form>WebBrowser/OpenSearch/OpenSearchDialog.ui</Form>
     <Form>WebBrowser/OpenSearch/OpenSearchEditDialog.ui</Form>

eric ide

mercurial