Continued porting the web browser. QtWebEngine

Fri, 19 Feb 2016 19:55:56 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 19 Feb 2016 19:55:56 +0100
branch
QtWebEngine
changeset 4751
f745a556fd6f
parent 4750
9fc5d2625d61
child 4752
a3bcc42a82a9

Continued porting the web browser.

- added the Flash Cookies manager

Preferences/__init__.py file | annotate | diff | comparison | revisions
WebBrowser/FlashCookieManager/FlashCookie.py file | annotate | diff | comparison | revisions
WebBrowser/FlashCookieManager/FlashCookieManager.py file | annotate | diff | comparison | revisions
WebBrowser/FlashCookieManager/FlashCookieManagerDialog.py file | annotate | diff | comparison | revisions
WebBrowser/FlashCookieManager/FlashCookieManagerDialog.ui file | annotate | diff | comparison | revisions
WebBrowser/FlashCookieManager/FlashCookieNotification.py file | annotate | diff | comparison | revisions
WebBrowser/FlashCookieManager/FlashCookieReader.py file | annotate | diff | comparison | revisions
WebBrowser/FlashCookieManager/FlashCookieUtilities.py file | annotate | diff | comparison | revisions
WebBrowser/FlashCookieManager/__init__.py file | annotate | diff | comparison | revisions
WebBrowser/Passwords/PasswordManager.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
--- a/Preferences/__init__.py	Fri Feb 19 19:55:27 2016 +0100
+++ b/Preferences/__init__.py	Fri Feb 19 19:55:56 2016 +0100
@@ -55,9 +55,12 @@
     ResourcesBrowserFlag, TranslationsBrowserFlag, InterfacesBrowserFlag, \
     OthersBrowserFlag, AllBrowsersFlag
 
-from Helpviewer.FlashCookieManager.FlashCookieUtilities import \
-    flashDataPathForOS
-
+try:
+    from Helpviewer.FlashCookieManager.FlashCookieUtilities import \
+        flashDataPathForOS
+except ImportError:
+    from WebBrowser.FlashCookieManager.FlashCookieUtilities import \
+        flashDataPathForOS
 
 class Prefs(object):
     """
@@ -1022,6 +1025,13 @@
         "WebSearchKeywords": [],    # array of two tuples (keyword,
                                     # search engine name)
         "SearchLanguage": QLocale().language(),
+        # Flash Cookie Manager
+        "FlashCookiesDeleteOnStartExit": False,
+        "FlashCookieAutoRefresh": False,
+        "FlashCookieNotify": False,
+        "FlashCookiesWhitelist": [],
+        "FlashCookiesBlacklist": [],
+        "FlashCookiesDataPath": flashDataPathForOS(),
     }
     
     @classmethod
@@ -2672,7 +2682,7 @@
 ##    elif key in ["DownloadManagerDownloads"]:
 ##        # return a list of tuples of (URL, save location, done flag, page url)
 ##        downloads = []
-##        length = prefClass.settings.beginReadArray("Help/" + key)
+##        length = prefClass.settings.beginReadArray("WebBrowser/" + key)
 ##        for index in range(length):
 ##            prefClass.settings.setArrayIndex(index)
 ##            url = prefClass.settings.value("URL")
@@ -2687,7 +2697,7 @@
 ##    elif key == "RssFeeds":
 ##        # return a list of tuples of (URL, title, icon)
 ##        feeds = []
-##        length = prefClass.settings.beginReadArray("Help/" + key)
+##        length = prefClass.settings.beginReadArray("WebBrowser/" + key)
 ##        for index in range(length):
 ##            prefClass.settings.setArrayIndex(index)
 ##            url = prefClass.settings.value("URL")
@@ -2699,11 +2709,11 @@
 ##    elif key in ["SyncFtpPassword", "SyncEncryptionKey"]:
 ##        from Utilities.crypto import pwConvert
 ##        return pwConvert(prefClass.settings.value(
-##            "Help/" + key, prefClass.helpDefaults[key]), encode=False)
+##            "WebBrowser/" + key, prefClass.helpDefaults[key]), encode=False)
 ##    elif key == "HelpViewerType":
 ##        # special treatment to adjust for missing QtWebKit
 ##        value = int(prefClass.settings.value(
-##            "Help/" + key, prefClass.helpDefaults[key]))
+##            "WebBrowser/" + key, prefClass.helpDefaults[key]))
 ##        if QWebSettings is None:
 ##            value = prefClass.helpDefaults[key]
 ##        return value
@@ -2748,6 +2758,8 @@
                  "LocalContentCanAccessFileUrls", "XSSAuditingEnabled",
                  "ScrollAnimatorEnabled", "ErrorPageEnabled",
                  "WarnOnMultipleClose", "WebSearchSuggestions",
+                 "FlashCookiesDeleteOnStartExit", "FlashCookieAutoRefresh",
+                 "FlashCookieNotify",
                  ]:
         return toBool(prefClass.settings.value(
             "WebBrowser/" + key, prefClass.webBrowserDefaults[key]))
@@ -2756,8 +2768,10 @@
 ##                 "GreaseMonkeyDisabledScripts", "NoCacheHosts",
 ##                 "FlashCookiesWhitelist", "FlashCookiesBlacklist",
 ##                 ]:
-##        return toList(prefClass.settings.value(
-##            "Help/" + key, prefClass.helpDefaults[key]))
+    elif key in ["FlashCookiesWhitelist", "FlashCookiesBlacklist",
+                 ]:
+        return toList(prefClass.settings.value(
+            "WebBrowser/" + key, prefClass.helpDefaults[key]))
     else:
         return prefClass.settings.value("WebBrowser/" + key,
                                         prefClass.webBrowserDefaults[key])
@@ -2789,7 +2803,7 @@
 ##    elif key == "DownloadManagerDownloads":
 ##        # value is list of tuples of (URL, save location, done flag, page url)
 ##        prefClass.settings.remove("Help/" + key)
-##        prefClass.settings.beginWriteArray("Help/" + key, len(value))
+##        prefClass.settings.beginWriteArray("WebBrowser/" + key, len(value))
 ##        index = 0
 ##        for v in value:
 ##            prefClass.settings.setArrayIndex(index)
@@ -2801,7 +2815,7 @@
 ##        prefClass.settings.endArray()
 ##    elif key == "RssFeeds":
 ##        # value is list of tuples of (URL, title, icon)
-##        prefClass.settings.remove("Help/" + key)
+##        prefClass.settings.remove("WebBrowser/" + key)
 ##        prefClass.settings.beginWriteArray("Help/" + key, len(value))
 ##        index = 0
 ##        for v in value:
@@ -2814,7 +2828,7 @@
 ##    elif key in ["SyncFtpPassword", "SyncEncryptionKey"]:
 ##        from Utilities.crypto import pwConvert
 ##        prefClass.settings.setValue(
-##            "Help/" + key, pwConvert(value, encode=True))
+##            "WebBrowser/" + key, pwConvert(value, encode=True))
     else:
         prefClass.settings.setValue("WebBrowser/" + key, value)
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FlashCookieManager/FlashCookie.py	Fri Feb 19 19:55:56 2016 +0100
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the Flash cookie class.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import QDateTime
+
+
+class FlashCookie(object):
+    """
+    Class implementing the Flash cookie.
+    """
+    def __init__(self):
+        """
+        Constructor
+        """
+        self.name = ""
+        self.origin = ""
+        self.size = 0
+        self.path = ""
+        self.contents = ""
+        self.lastModified = QDateTime()
+    
+    def __eq__(self, other):
+        """
+        Special method to compare to another Flash cookie.
+        
+        @param other reference to the other Flash cookie
+        @type FlashCookie
+        @return flag indicating equality of the two cookies
+        @rtype bool
+        """
+        return (self.name == other.name and
+                self.path == other.path)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FlashCookieManager/FlashCookieManager.py	Fri Feb 19 19:55:56 2016 +0100
@@ -0,0 +1,363 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the Flash cookie manager.
+"""
+
+from __future__ import unicode_literals
+
+try:
+    str = unicode       # __IGNORE_EXCEPTION__
+except NameError:
+    pass
+
+import shutil
+
+from PyQt5.QtCore import QObject, QTimer, QDir, QFileInfo, QFile
+
+from .FlashCookie import FlashCookie
+from .FlashCookieReader import FlashCookieReader, FlashCookieReaderError
+
+import WebBrowser.WebBrowserWindow
+
+import Preferences
+
+
+class FlashCookieManager(QObject):
+    """
+    Class implementing the Flash cookie manager object.
+    """
+    RefreshInterval = 60 * 1000
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent object
+        @type QObject
+        """
+        super(FlashCookieManager, self).__init__(parent)
+        
+        self.__flashCookieManagerDialog = None
+        self.__flashCookies = []    # list of FlashCookie
+        self.__newCookiesList = []  # list of str
+##        self.__whitelist = []       # list of str
+##        self.__blacklist = []       # list of str
+        
+        self.__timer = QTimer(self)
+        self.__timer.setInterval(FlashCookieManager.RefreshInterval)
+        self.__timer.timeout.connect(self.__autoRefresh)
+        
+        # start the timer if needed
+        self.__startStopTimer()
+        
+        if Preferences.getHelp("FlashCookiesDeleteOnStartExit"):
+            self.__loadFlashCookies()
+            self.__removeAllButWhitelisted()
+    
+    def shutdown(self):
+        """
+        Public method to perform shutdown actions.
+        """
+        if self.__flashCookieManagerDialog is not None:
+            self.__flashCookieManagerDialog.close()
+        
+        if Preferences.getHelp("FlashCookiesDeleteOnStartExit"):
+            self.__removeAllButWhitelisted()
+    
+    def setFlashCookies(self, cookies):
+        """
+        Public method to set the list of cached Flash cookies.
+        
+        @param cookies list of Flash cookies to store
+        @type list of FlashCookie
+        """
+        self.__flashCookies = cookies[:]
+    
+    def flashCookies(self):
+        """
+        Public method to get the list of cached Flash cookies.
+        
+        @return list of Flash cookies
+        @rtype list of FlashCookie
+        """
+        if not self.__flashCookies:
+            self.__loadFlashCookies()
+        
+        return self.__flashCookies[:]
+    
+    def newCookiesList(self):
+        """
+        Public method to get the list of newly detected Flash cookies.
+        
+        @return list of newly detected Flash cookies
+        @rtype list of str
+        """
+        return self.__newCookiesList[:]
+    
+    def clearNewOrigins(self):
+        """
+        Public method to clear the list of newly detected Flash cookies.
+        """
+        self.__newCookiesList = []
+    
+    def clearCache(self):
+        """
+        Public method to clear the list of cached Flash cookies.
+        """
+        self.__flashCookies = []
+    
+    def __isBlacklisted(self, cookie):
+        """
+        Private method to check for a blacklisted cookie.
+        
+        @param cookie Flash cookie to be tested
+        @type FlashCookie
+        @return flag indicating a blacklisted cookie
+        @rtype bool
+        """
+        return cookie.origin in Preferences.getHelp("FlashCookiesBlacklist")
+    
+    def __isWhitelisted(self, cookie):
+        """
+        Private method to check for a whitelisted cookie.
+        
+        @param cookie Flash cookie to be tested
+        @type FlashCookie
+        @return flag indicating a whitelisted cookie
+        @rtype bool
+        """
+        return cookie.origin in Preferences.getHelp("FlashCookiesWhitelist")
+    
+    def __removeAllButWhitelisted(self):
+        """
+        Private method to remove all non-whitelisted cookies.
+        """
+        for cookie in self.__flashCookies[:]:
+            if not self.__isWhitelisted(cookie):
+                self.removeCookie(cookie)
+    
+    def removeAllCookies(self):
+        """
+        Public method to remove all flash cookies.
+        """
+        for cookie in self.__flashCookies[:]:
+            self.removeCookie(cookie)
+        self.clearNewOrigins()
+        self.clearCache()
+    
+    def __sharedObjectDirName(self):
+        """
+        Private slot to determine the path of the shared data objects.
+        
+        @return path of the shared data objects
+        @rtype str
+        """
+        if "macromedia" in self.flashPlayerDataPath().lower() or \
+                "/.gnash" not in self.flashPlayerDataPath().lower():
+            return "/#SharedObjects/"
+        else:
+            return "/SharedObjects/"
+    
+    def flashPlayerDataPath(self):
+        """
+        Public method to get the Flash Player data path.
+        
+        @return Flash Player data path
+        @rtype str
+        """
+        return Preferences.getHelp("FlashCookiesDataPath")
+    
+    def preferencesChanged(self):
+        """
+        Public slot to handle a change of preferences.
+        """
+        self.__startStopTimer()
+    
+    def removeCookie(self, cookie):
+        """
+        Public method to remove a cookie of the list of cached cookies.
+        
+        @param cookie Flash cookie to be removed
+        @type FlashCookie
+        """
+        if cookie in self.__flashCookies:
+            self.__flashCookies.remove(cookie)
+            shutil.rmtree(cookie.path, True)
+    
+    def __autoRefresh(self):
+        """
+        Private slot to refresh the list of cookies.
+        """
+        if self.__flashCookieManagerDialog and \
+                self.__flashCookieManagerDialog.isVisible():
+            return
+        
+        oldFlashCookies = self.__flashCookies[:]
+        self.__loadFlashCookies()
+        newCookieList = []
+        
+        for cookie in self.__flashCookies[:]:
+            if self.__isBlacklisted(cookie):
+                self.removeCookie(cookie)
+                continue
+            
+            if self.__isWhitelisted(cookie):
+                continue
+            
+            newCookie = True
+            for oldCookie in oldFlashCookies:
+                if (oldCookie.path + oldCookie.name ==
+                        cookie.path + cookie.name):
+                    newCookie = False
+                    break
+            
+            if newCookie:
+                newCookieList.append(cookie.path + "/" + cookie.name)
+        
+        if newCookieList and Preferences.getHelp("FlashCookieNotify"):
+            self.__newCookiesList.extend(newCookieList)
+            win = WebBrowser.WebBrowserWindow.WebBrowserWindow.mainWindow()
+            if win is None:
+                return
+            
+            view = win.currentBrowser()
+            if view is None:
+                return
+            
+            from .FlashCookieNotification import FlashCookieNotification
+            notification = FlashCookieNotification(
+                view, self, len(newCookieList))
+            notification.show()
+    
+    def showFlashCookieManagerDialog(self):
+        """
+        Public method to show the Flash cookies management dialog.
+        """
+        if self.__flashCookieManagerDialog is None:
+            from .FlashCookieManagerDialog import FlashCookieManagerDialog
+            self.__flashCookieManagerDialog = FlashCookieManagerDialog(self)
+        
+        self.__flashCookieManagerDialog.refreshView()
+        self.__flashCookieManagerDialog.showPage(0)
+        self.__flashCookieManagerDialog.show()
+        self.__flashCookieManagerDialog.raise_()
+    
+    def __startStopTimer(self):
+        """
+        Private slot to start or stop the auto refresh timer.
+        """
+        if Preferences.getHelp("FlashCookieAutoRefresh"):
+            if not self.__timer.isActive():
+                if not bool(self.__flashCookies):
+                    self.__loadFlashCookies()
+                
+                self.__timer.start()
+        else:
+            self.__timer.stop()
+    
+    def __loadFlashCookies(self):
+        """
+        Private slot to load the Flash cookies to be cached.
+        """
+        self.__flashCookies = []
+        self.__loadFlashCookiesFromPath(self.flashPlayerDataPath())
+    
+    def __loadFlashCookiesFromPath(self, path):
+        """
+        Private slot to load the Flash cookies from a path.
+        
+        @param path Flash cookies path
+        @type str
+        """
+        if path.endswith("#AppContainer"):
+            # specific to IE and Windows
+            return
+        
+        path = path.replace("\\", "/")
+        solDir = QDir(path)
+        entryList = solDir.entryList()
+        for entry in entryList:
+            if entry == "." or entry == "..":
+                continue
+            entryInfo = QFileInfo(path + "/" + entry)
+            if entryInfo.isDir():
+                self.__loadFlashCookiesFromPath(entryInfo.filePath())
+            else:
+                self.__insertFlashCookie(entryInfo.filePath())
+    
+    def __insertFlashCookie(self, path):
+        """
+        Private method to insert a Flash cookie into the cache.
+        
+        @param path Flash cookies path
+        @type str
+        """
+        solFile = QFile(path)
+        if not solFile.open(QFile.ReadOnly):
+            return
+        
+        dataStr = ""
+        data = bytes(solFile.readAll())
+        if data:
+            try:
+                reader = FlashCookieReader()
+                reader.setBytes(data)
+                reader.parse()
+                dataStr = reader.toString()
+            except FlashCookieReaderError as err:
+                dataStr = err.msg
+        
+        solFileInfo = QFileInfo(solFile)
+        
+        cookie = FlashCookie()
+        cookie.contents = dataStr
+        cookie.name = solFileInfo.fileName()
+        cookie.path = solFileInfo.canonicalPath()
+        cookie.size = int(solFile.size())
+        cookie.lastModified = solFileInfo.lastModified()
+        cookie.origin = self.__extractOriginFrom(path)
+        
+        self.__flashCookies.append(cookie)
+    
+    def __extractOriginFrom(self, path):
+        """
+        Private method to extract the cookie origin given its file name.
+        
+        @param path file name of the cookie file
+        @type str
+        @return cookie origin
+        @rtype str
+        """
+        origin = path
+        if path.startswith(
+                self.flashPlayerDataPath() + self.__sharedObjectDirName()):
+            origin = origin.replace(
+                self.flashPlayerDataPath() + self.__sharedObjectDirName(), "")
+            if "/" in origin:
+                origin = origin.split("/", 1)[1]
+        elif path.startswith(
+            self.flashPlayerDataPath() +
+                "/macromedia.com/support/flashplayer/sys/"):
+            origin = origin.replace(
+                self.flashPlayerDataPath() +
+                "/macromedia.com/support/flashplayer/sys/", "")
+            if origin == "settings.sol":
+                return self.tr("!default")
+            elif origin.startswith("#"):
+                origin = origin[1:]
+        else:
+            origin = ""
+        
+        index = origin.find("/")
+        if index == -1:
+            return self.tr("!other")
+        
+        origin = origin[:index]
+        if origin in ["localhost", "local"]:
+            origin = "!localhost"
+        
+        return origin
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FlashCookieManager/FlashCookieManagerDialog.py	Fri Feb 19 19:55:56 2016 +0100
@@ -0,0 +1,423 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to manage the flash cookies.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSlot, Qt, QPoint, QTimer
+from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QApplication, QMenu, \
+    QInputDialog, QLineEdit
+
+from E5Gui import E5MessageBox
+
+from .Ui_FlashCookieManagerDialog import Ui_FlashCookieManagerDialog
+
+import Preferences
+import UI.PixmapCache
+
+
+class FlashCookieManagerDialog(QDialog, Ui_FlashCookieManagerDialog):
+    """
+    Class implementing a dialog to manage the flash cookies.
+    """
+    def __init__(self, manager, parent=None):
+        """
+        Constructor
+        
+        @param manager reference to the Flash cookie manager object
+        @type FlashCookieManager
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(FlashCookieManagerDialog, self).__init__(parent)
+        self.setupUi(self)
+        self.setWindowFlags(Qt.Window)
+        
+        self.cookiesList.setContextMenuPolicy(Qt.CustomContextMenu)
+        self.cookiesList.customContextMenuRequested.connect(
+            self.__cookiesListContextMenuRequested)
+        
+        self.__manager = manager
+    
+    @pyqtSlot()
+    def on_whiteList_itemSelectionChanged(self):
+        """
+        Private slot handling the selection of items in the whitelist.
+        """
+        enable = len(self.whiteList.selectedItems()) > 0
+        self.removeWhiteButton.setEnabled(enable)
+    
+    @pyqtSlot()
+    def on_blackList_itemSelectionChanged(self):
+        """
+        Private slot handling the selection of items in the blacklist.
+        """
+        enable = len(self.blackList.selectedItems()) > 0
+        self.removeBlackButton.setEnabled(enable)
+    
+    @pyqtSlot()
+    def on_removeWhiteButton_clicked(self):
+        """
+        Private slot to remove a server from the whitelist.
+        """
+        for itm in self.whiteList.selectedItems():
+            row = self.whiteList.row(itm)
+            self.whiteList.takeItem(row)
+            del itm
+    
+    @pyqtSlot()
+    def on_addWhiteButton_clicked(self):
+        """
+        Private slot to add a server to the whitelist.
+        """
+        origin, ok = QInputDialog.getText(
+            self,
+            self.tr("Add to whitelist"),
+            self.tr("Origin:"),
+            QLineEdit.Normal)
+        if ok and bool(origin):
+            self.__addWhitelist(origin)
+    
+    def __addWhitelist(self, origin):
+        """
+        Private method to add a cookie origin to the whitelist.
+        
+        @param origin origin to be added to the list
+        @type str
+        """
+        if not origin:
+            return
+        
+        if len(self.blackList.findItems(origin, Qt.MatchFixedString)) > 0:
+            E5MessageBox.information(
+                self,
+                self.tr("Add to whitelist"),
+                self.tr("""The server '{0}' is already in the blacklist."""
+                        """ Please remove it first.""").format(origin))
+            return
+        
+        if len(self.whiteList.findItems(origin, Qt.MatchFixedString)) == 0:
+            self.whiteList.addItem(origin)
+    
+    @pyqtSlot()
+    def on_removeBlackButton_clicked(self):
+        """
+        Private slot to remove a server from the blacklist.
+        """
+        for itm in self.blackList.selectedItems():
+            row = self.blackList.row(itm)
+            self.blackList.takeItem(row)
+            del itm
+    
+    @pyqtSlot()
+    def on_addBlackButton_clicked(self):
+        """
+        Private slot to add a server to the blacklist.
+        """
+        origin, ok = QInputDialog.getText(
+            self,
+            self.tr("Add to blacklist"),
+            self.tr("Origin:"),
+            QLineEdit.Normal)
+        if ok and bool(origin):
+            self.__addBlacklist(origin)
+    
+    def __addBlacklist(self, origin):
+        """
+        Private method to add a cookie origin to the blacklist.
+        
+        @param origin origin to be added to the list
+        @type str
+        """
+        if not origin:
+            return
+        
+        if len(self.whiteList.findItems(origin, Qt.MatchFixedString)) > 0:
+            E5MessageBox.information(
+                self,
+                self.tr("Add to blacklist"),
+                self.tr("""The server '{0}' is already in the whitelist."""
+                        """ Please remove it first.""").format(origin))
+            return
+        
+        if len(self.blackList.findItems(origin, Qt.MatchFixedString)) == 0:
+            self.blackList.addItem(origin)
+    
+    @pyqtSlot(str)
+    def on_filterEdit_textChanged(self, filter):
+        """
+        Private slot to filter the cookies list.
+        
+        @param filter filter text
+        @type str
+        """
+        if not filter:
+            # show all in collapsed state
+            for index in range(self.cookiesList.topLevelItemCount()):
+                self.cookiesList.topLevelItem(index).setHidden(False)
+                self.cookiesList.topLevelItem(index).setExpanded(False)
+        else:
+            # show matching in expanded state
+            filter = filter.lower()
+            for index in range(self.cookiesList.topLevelItemCount()):
+                txt = "." + self.cookiesList.topLevelItem(index)\
+                    .text(0).lower()
+                self.cookiesList.topLevelItem(index).setHidden(
+                    filter not in txt)
+                self.cookiesList.topLevelItem(index).setExpanded(True)
+    
+    @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
+    def on_cookiesList_currentItemChanged(self, current, previous):
+        """
+        Private slot handling a change of the current cookie item.
+        
+        @param current reference to the current item
+        @type QTreeWidgetItem
+        @param previous reference to the previous item
+        @type QTreeWidgetItem
+        """
+        if current is None:
+            self.removeButton.setEnabled(False)
+            return
+        
+        cookie = current.data(0, Qt.UserRole)
+        if cookie is None:
+            self.nameLabel.setText(self.tr("<no flash cookie selected>"))
+            self.sizeLabel.setText(self.tr("<no flash cookie selected>"))
+            self.originLabel.setText(self.tr("<no flash cookie selected>"))
+            self.modifiedLabel.setText(self.tr("<no flash cookie selected>"))
+            self.contentsEdit.clear()
+            self.pathEdit.clear()
+            self.removeButton.setText(self.tr("Remove Cookie Group"))
+        else:
+            suffix = ""
+            if cookie.path.startswith(
+                self.__manager.flashPlayerDataPath() +
+                    "/macromedia.com/support/flashplayer/sys"):
+                suffix = self.tr(" (settings)")
+            self.nameLabel.setText(
+                self.tr("{0}{1}", "name and suffix")
+                .format(cookie.name, suffix))
+            self.sizeLabel.setText(self.tr("{0} Byte").format(cookie.size))
+            self.originLabel.setText(cookie.origin)
+            self.modifiedLabel.setText(
+                cookie.lastModified.toString("yyyy-MM-dd hh:mm:ss"))
+            self.contentsEdit.setPlainText(cookie.contents)
+            self.pathEdit.setText(cookie.path)
+            self.removeButton.setText(self.tr("Remove Cookie"))
+        self.removeButton.setEnabled(True)
+    
+    @pyqtSlot(QPoint)
+    def __cookiesListContextMenuRequested(self, pos):
+        """
+        Private slot handling the cookies list context menu.
+        
+        @param pos position to show the menu at
+        @type QPoint
+        """
+        itm = self.cookiesList.itemAt(pos)
+        if itm is None:
+            return
+        
+        menu = QMenu()
+        addBlacklistAct = menu.addAction(self.tr("Add to blacklist"))
+        addWhitelistAct = menu.addAction(self.tr("Add to whitelist"))
+        
+        self.cookiesList.setCurrentItem(itm)
+        
+        activatedAction = menu.exec_(
+            self.cookiesList.viewport().mapToGlobal(pos))
+        if itm.childCount() == 0:
+            origin = itm.data(0, Qt.UserRole).origin
+        else:
+            origin = itm.text(0)
+        
+        if activatedAction == addBlacklistAct:
+            self.__addBlacklist(origin)
+        elif activatedAction == addWhitelistAct:
+            self.__addWhitelist(origin)
+    
+    @pyqtSlot()
+    def on_reloadButton_clicked(self):
+        """
+        Private slot handling a press of the reload button.
+        """
+        self.refreshView(True)
+    
+    @pyqtSlot()
+    def on_removeAllButton_clicked(self):
+        """
+        Private slot to remove all cookies.
+        """
+        ok = E5MessageBox.yesNo(
+            self,
+            self.tr("Remove All"),
+            self.tr("""Do you really want to delete all flash cookies on"""
+                    """ your computer?"""))
+        if ok:
+            cookies = self.__manager.flashCookies()
+            for cookie in cookies:
+                self.__manager.removeCookie(cookie)
+            
+            self.cookiesList.clear()
+            self.__manager.clearNewOrigins()
+            self.__manager.clearCache()
+    
+    @pyqtSlot()
+    def on_removeButton_clicked(self):
+        """
+        Private slot to remove one cookie or a cookie group.
+        """
+        itm = self.cookiesList.currentItem()
+        if itm is None:
+            return
+        
+        cookie = itm.data(0, Qt.UserRole)
+        if cookie is None:
+            # remove a whole cookie group
+            origin = itm.text(0)
+            cookieList = self.__manager.flashCookies()
+            for fcookie in cookieList:
+                if fcookie.origin == origin:
+                    self.__manager.removeCookie(fcookie)
+            
+            index = self.cookiesList.indexOfTopLevelItem(itm)
+            self.cookiesList.takeTopLevelItem(index)
+        else:
+            self.__manager.removeCookie(cookie)
+            parent = itm.parent()
+            index = parent.indexOfChild(itm)
+            parent.takeChild(index)
+            
+            if parent.childCount() == 0:
+                # remove origin item as well
+                index = self.cookiesList.indexOfTopLevelItem(parent)
+                self.cookiesList.takeTopLevelItem(index)
+                del parent
+        del itm
+    
+    def refreshView(self, forceReload=False):
+        """
+        Public method to refresh the dialog view.
+        
+        @param forceReload flag indicating to reload the cookies
+        @type bool
+        """
+        blocked = self.filterEdit.blockSignals(True)
+        self.filterEdit.clear()
+        self.contentsEdit.clear()
+        self.filterEdit.blockSignals(blocked)
+        
+        if forceReload:
+            self.__manager.clearCache()
+            self.__manager.clearNewOrigins()
+        
+        QTimer.singleShot(0, self.__refreshCookiesList)
+        QTimer.singleShot(0, self.__refreshFilterLists)
+    
+    def showPage(self, index):
+        """
+        Public method to display a given page.
+        
+        @param index index of the page to be shown
+        @type int
+        """
+        self.cookiesTabWidget.setCurrentIndex(index)
+    
+    @pyqtSlot()
+    def __refreshCookiesList(self):
+        """
+        Private slot to refresh the cookies list.
+        """
+        QApplication.setOverrideCursor(Qt.WaitCursor)
+        
+        cookies = self.__manager.flashCookies()
+        self.cookiesList.clear()
+        
+        counter = 0
+        originDict = {}
+        for cookie in cookies:
+            cookieOrigin = cookie.origin
+            if cookieOrigin.startswith("."):
+                cookieOrigin = cookieOrigin[1:]
+            
+            if cookieOrigin in originDict:
+                itm = QTreeWidgetItem(originDict[cookieOrigin])
+            else:
+                newParent = QTreeWidgetItem(self.cookiesList)
+                newParent.setText(0, cookieOrigin)
+                newParent.setIcon(0, UI.PixmapCache.getIcon("dirOpen.png"))
+                self.cookiesList.addTopLevelItem(newParent)
+                originDict[cookieOrigin] = newParent
+                
+                itm = QTreeWidgetItem(newParent)
+            
+            suffix = ""
+            if cookie.path.startswith(
+                self.__manager.flashPlayerDataPath() +
+                    "/macromedia.com/support/flashplayer/sys"):
+                suffix = self.tr(" (settings)")
+            
+            if cookie.path + "/" + cookie.name in \
+                    self.__manager.newCookiesList():
+                suffix += self.tr(" [new]")
+                font = itm.font(0)
+                font.setBold(True)
+                itm.setFont(font)
+                itm.parent().setExpanded(True)
+            
+            itm.setText(0, self.tr("{0}{1}", "name and suffix").format(
+                cookie.name, suffix))
+            itm.setData(0, Qt.UserRole, cookie)
+            
+            counter += 1
+            if counter > 100:
+                QApplication.processEvents()
+                counter = 0
+        
+        self.removeAllButton.setEnabled(
+            self.cookiesList.topLevelItemCount() > 0)
+        self.removeButton.setEnabled(False)
+        
+        QApplication.restoreOverrideCursor()
+    
+    @pyqtSlot()
+    def __refreshFilterLists(self):
+        """
+        Private slot to refresh the white and black lists.
+        """
+        self.whiteList.clear()
+        self.blackList.clear()
+        
+        self.whiteList.addItems(Preferences.getHelp("FlashCookiesWhitelist"))
+        self.blackList.addItems(Preferences.getHelp("FlashCookiesBlacklist"))
+        
+        self.on_whiteList_itemSelectionChanged()
+        self.on_blackList_itemSelectionChanged()
+    
+    def closeEvent(self, evt):
+        """
+        Protected method to handle the close event.
+        
+        @param evt reference to the close event
+        @type QCloseEvent
+        """
+        self.__manager.clearNewOrigins()
+        
+        whiteList = []
+        for row in range(self.whiteList.count()):
+            whiteList.append(self.whiteList.item(row).text())
+        
+        blackList = []
+        for row in range(self.blackList.count()):
+            blackList.append(self.blackList.item(row).text())
+        
+        Preferences.setHelp("FlashCookiesWhitelist", whiteList)
+        Preferences.setHelp("FlashCookiesBlacklist", blackList)
+        
+        evt.accept()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FlashCookieManager/FlashCookieManagerDialog.ui	Fri Feb 19 19:55:56 2016 +0100
@@ -0,0 +1,478 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FlashCookieManagerDialog</class>
+ <widget class="QDialog" name="FlashCookieManagerDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>550</width>
+    <height>500</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Flash Cookie Management</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTabWidget" name="cookiesTabWidget">
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tab">
+      <attribute name="title">
+       <string>Stored Flash Cookies</string>
+      </attribute>
+      <layout class="QGridLayout" name="gridLayout_4">
+       <item row="0" column="0">
+        <layout class="QGridLayout" name="gridLayout">
+         <item row="0" column="0">
+          <widget class="QLabel" name="label_4">
+           <property name="text">
+            <string>Filter:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1">
+          <widget class="QLineEdit" name="filterEdit">
+           <property name="toolTip">
+            <string>Enter cookie filter string</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0" colspan="2">
+          <widget class="QLabel" name="label_24">
+           <property name="text">
+            <string>Stored Flash Cookies:</string>
+           </property>
+           <property name="wordWrap">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="0" colspan="2">
+          <widget class="QTreeWidget" name="cookiesList">
+           <property name="alternatingRowColors">
+            <bool>true</bool>
+           </property>
+           <column>
+            <property name="text">
+             <string>Origin</string>
+            </property>
+           </column>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="0" column="1">
+        <layout class="QGridLayout" name="gridLayout_3">
+         <item row="0" column="0">
+          <spacer name="horizontalSpacer">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>158</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item row="0" column="1">
+          <widget class="QPushButton" name="reloadButton">
+           <property name="toolTip">
+            <string>Press to reload Flash cookies from disk</string>
+           </property>
+           <property name="text">
+            <string>Reload</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0" colspan="2">
+          <layout class="QGridLayout" name="gridLayout_2">
+           <item row="0" column="0">
+            <widget class="QLabel" name="label_6">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="text">
+              <string>Name:</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+             </property>
+            </widget>
+           </item>
+           <item row="0" column="1">
+            <widget class="QLabel" name="nameLabel">
+             <property name="text">
+              <string>&lt;no flash cookie selected&gt;</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="0">
+            <widget class="QLabel" name="labelSize_2">
+             <property name="text">
+              <string>Size:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="1">
+            <widget class="QLabel" name="sizeLabel">
+             <property name="text">
+              <string>&lt;no flash cookie selected&gt;</string>
+             </property>
+            </widget>
+           </item>
+           <item row="2" column="0">
+            <widget class="QLabel" name="label_7">
+             <property name="text">
+              <string>Origin:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="2" column="1">
+            <widget class="QLabel" name="originLabel">
+             <property name="text">
+              <string>&lt;no flash cookie selected&gt;</string>
+             </property>
+            </widget>
+           </item>
+           <item row="3" column="0">
+            <widget class="QLabel" name="label_22">
+             <property name="text">
+              <string>Last Modified:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="3" column="1">
+            <widget class="QLabel" name="modifiedLabel">
+             <property name="text">
+              <string>&lt;no flash cookie selected&gt;</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item row="2" column="0" colspan="2">
+          <widget class="QLabel" name="label">
+           <property name="text">
+            <string>Contents:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="3" column="0" colspan="2">
+          <widget class="QPlainTextEdit" name="contentsEdit">
+           <property name="tabChangesFocus">
+            <bool>true</bool>
+           </property>
+           <property name="lineWrapMode">
+            <enum>QPlainTextEdit::NoWrap</enum>
+           </property>
+           <property name="readOnly">
+            <bool>true</bool>
+           </property>
+           <property name="textInteractionFlags">
+            <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="1" column="0" colspan="2">
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <widget class="QLabel" name="label_2">
+           <property name="text">
+            <string>Path:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="pathEdit">
+           <property name="readOnly">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="2" column="0" colspan="2">
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <widget class="QPushButton" name="removeAllButton">
+           <property name="toolTip">
+            <string>Press to remove all flash cookies</string>
+           </property>
+           <property name="text">
+            <string>Remove All Cookies</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="removeButton">
+           <property name="toolTip">
+            <string>Press to remove selected flash cookies</string>
+           </property>
+           <property name="text">
+            <string>Remove Cookie</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_2">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tab_2">
+      <attribute name="title">
+       <string>Flash Cookies Lists</string>
+      </attribute>
+      <layout class="QGridLayout" name="gridLayout_5">
+       <item row="0" column="0">
+        <widget class="QLabel" name="label_3">
+         <property name="text">
+          <string>&lt;b&gt;Flash cookie whitelist&lt;/b&gt;</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1">
+        <widget class="QLabel" name="label_5">
+         <property name="text">
+          <string>&lt;b&gt;Flash cookie blacklist&lt;/b&gt;</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <widget class="QLabel" name="label_17">
+         <property name="text">
+          <string>Flash cookies from these origins will not be deleted automatically. (Also detection of them will not be notified to user.)</string>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="1">
+        <widget class="QLabel" name="label_18">
+         <property name="text">
+          <string>Flash cookies from these origins will be deleted without any notification.</string>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="0">
+        <widget class="QListWidget" name="whiteList">
+         <property name="alternatingRowColors">
+          <bool>true</bool>
+         </property>
+         <property name="selectionMode">
+          <enum>QAbstractItemView::ExtendedSelection</enum>
+         </property>
+         <property name="sortingEnabled">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="1">
+        <widget class="QListWidget" name="blackList">
+         <property name="alternatingRowColors">
+          <bool>true</bool>
+         </property>
+         <property name="selectionMode">
+          <enum>QAbstractItemView::ExtendedSelection</enum>
+         </property>
+         <property name="sortingEnabled">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="0">
+        <layout class="QHBoxLayout" name="horizontalLayout_3">
+         <item>
+          <spacer name="horizontalSpacer_3">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QPushButton" name="removeWhiteButton">
+           <property name="toolTip">
+            <string>Press to remove selected origins from the whitelist</string>
+           </property>
+           <property name="text">
+            <string>Remove</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="addWhiteButton">
+           <property name="toolTip">
+            <string>Press to add an origin to the whitelist</string>
+           </property>
+           <property name="text">
+            <string>Add...</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_4">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+       <item row="3" column="1">
+        <layout class="QHBoxLayout" name="horizontalLayout_4">
+         <item>
+          <spacer name="horizontalSpacer_5">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QPushButton" name="removeBlackButton">
+           <property name="toolTip">
+            <string>Press to remove selected origins from the blacklist</string>
+           </property>
+           <property name="text">
+            <string>Remove</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="addBlackButton">
+           <property name="toolTip">
+            <string>Press to add an origin to the blacklist</string>
+           </property>
+           <property name="text">
+            <string>Add...</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_6">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Close</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>cookiesTabWidget</tabstop>
+  <tabstop>filterEdit</tabstop>
+  <tabstop>cookiesList</tabstop>
+  <tabstop>reloadButton</tabstop>
+  <tabstop>contentsEdit</tabstop>
+  <tabstop>pathEdit</tabstop>
+  <tabstop>removeAllButton</tabstop>
+  <tabstop>removeButton</tabstop>
+  <tabstop>whiteList</tabstop>
+  <tabstop>removeWhiteButton</tabstop>
+  <tabstop>addWhiteButton</tabstop>
+  <tabstop>blackList</tabstop>
+  <tabstop>removeBlackButton</tabstop>
+  <tabstop>addBlackButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>FlashCookieManagerDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>FlashCookieManagerDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</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/FlashCookieManager/FlashCookieNotification.py	Fri Feb 19 19:55:56 2016 +0100
@@ -0,0 +1,66 @@
+# -*- 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.QtWidgets import QLabel, QHBoxLayout, QPushButton
+
+from E5Gui.E5AnimatedWidget import E5AnimatedWidget
+
+import UI.PixmapCache
+
+
+class FlashCookieNotification(E5AnimatedWidget):
+    """
+    Class implementing the feature permission bar widget.
+    """
+    DefaultHeight = 30
+    
+    def __init__(self, view, manager, noCookies):
+        """
+        Constructor
+        
+        @param view reference to the web view
+        @type WebBrowserView
+        @param manager reference to the Flash cookie manager object
+        @type FlashCookieManager
+        @param noCookies number of newly detected Flash cookies
+        @type int
+        """
+        super(FlashCookieNotification, self).__init__(parent=view)
+        
+        self.__manager = manager
+        
+        if noCookies == 1:
+            msg = self.tr("A new flash cookie was detected.")
+        else:
+            msg = self.tr("{0} new flash cookies were detected.")\
+                .format(noCookies)
+        self.setAutoFillBackground(True)
+        self.__layout = QHBoxLayout()
+        self.setLayout(self.__layout)
+        self.__layout.setContentsMargins(9, 0, 0, 0)
+        self.__iconLabel = QLabel(self)
+        self.__iconLabel.setPixmap(UI.PixmapCache.getPixmap("flashCookie.png"))
+        self.__layout.addWidget(self.__iconLabel)
+        self.__messageLabel = QLabel(msg, self)
+        self.__layout.addWidget(self.__messageLabel)
+        self.__viewButton = QPushButton(self.tr("View"), self)
+        self.__layout.addWidget(self.__viewButton)
+        self.__layout.addStretch()
+        self.__discardButton = QPushButton(UI.PixmapCache.getIcon("close.png"),
+                                           "", self)
+        self.__layout.addWidget(self.__discardButton)
+        
+        self.__viewButton.clicked.connect(manager.showFlashCookieManagerDialog)
+        self.__viewButton.clicked.connect(self.hide)
+        self.__discardButton.clicked.connect(self.hide)
+        
+        self.resize(view.width(), self.height())
+        self.startAnimation()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FlashCookieManager/FlashCookieReader.py	Fri Feb 19 19:55:56 2016 +0100
@@ -0,0 +1,474 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a class to read flash cookies.
+"""
+
+#
+# Note: The code is based on s2x.py
+#
+
+from __future__ import unicode_literals
+
+import struct
+import io
+
+from PyQt5.QtCore import QDateTime
+
+
+class FlashCookieReaderError(Exception):
+    """
+    Class containing data of a reader error.
+    """
+    def __init__(self, msg):
+        """
+        Constructor
+        
+        @param msg error message
+        @type str
+        """
+        self.msg = msg
+
+
+class FlashCookieReader(object):
+    """
+    Class implementing a reader for flash cookies (*.sol files).
+    """
+    Number = b'\x00'
+    Boolean = b'\x01'
+    String = b'\x02'
+    ObjObj = b'\x03'
+    Null = b'\x05'
+    Undef = b'\x06'
+    ObjArr = b'\x08'
+    ObjDate = b'\x0B'
+    ObjM = b'\x0D'
+    ObjXml = b'\x0F'
+    ObjCc = b'\x10'
+    
+    EpochCorrectionMsecs = 31 * 24 * 60 * 60 * 1000
+    # Flash Epoch starts at 1969-12-01
+    
+    def __init__(self):
+        """
+        Constructor
+        """
+        self.__result = {}
+        # dictionary with element name as key and tuple of
+        # type and value as value
+        self.__data = None
+        self.__parsed = False
+    
+    def setBytes(self, solData):
+        """
+        Public method to set the contents of a sol file to be parsed.
+        
+        @param solData contents of the file
+        @type bytes
+        """
+        self.__data = io.BytesIO(solData)
+    
+    def setFileName(self, solFilename):
+        """
+        Public method to set the name of a sol file to be parsed.
+        
+        @param solFilename name of the sol file
+        @type str
+        """
+        self.__data = open(solFilename, "rb")
+    
+    def setFile(self, solFile):
+        """
+        Public method to set an open sol file to be parsed.
+        
+        @param solFile sol file to be parsed
+        @type io.FileIO
+        """
+        self.__data = solFile
+    
+    def parse(self):
+        """
+        Public method to parse the sol file.
+        
+        @exception FlashCookieReaderError raised when encountering a parse
+            issue
+        """
+        if self.__data is None:
+            return
+        
+        self.__data.seek(0, 2)
+        lenSolData = self.__data.tell()
+        self.__data.seek(0)
+        self.__data.read(2)
+        sLenData = self.__data.read(4)
+        lenData, = struct.unpack(">L", sLenData)    # unsigned long, big-endian
+        if lenSolData != lenData + 6:
+            raise FlashCookieReaderError(
+                "Flash cookie data lengths don't match\n"
+                "  file length: {0}\n"
+                "  data length: {1}"
+                .format(lenSolData - 6, lenData))
+        sDataType = self.__data.read(4).decode("utf-8")             # 'TCSO'
+        if sDataType != "TCSO":
+            raise FlashCookieReaderError(
+                "Flash cookie type is not 'TCSO'; found '{0}'."
+                .format(sDataType))
+        self.__data.read(6)
+        lenSolName, = struct.unpack(">H", self.__data.read(2))
+        # unsigned short,  big-endian
+        solName = self.__data.read(lenSolName)
+        solName = solName.decode("utf-8", "replace")
+        self.__result["SolName"] = ("string", solName)
+        self.__data.read(4)
+        while self.__data.tell() < lenSolData:
+            lenVariableName, = struct.unpack(">H", self.__data.read(2))
+            # unsigned short,  big-endian
+            variableName = self.__data.read(lenVariableName)
+            variableName = variableName.decode("utf-8", "replace")
+            variableType = self.__data.read(1)
+            if len(variableType):
+                if variableType == self.Number:
+                    self.__parseNumber(variableName, self.__result)
+                elif variableType == self.Boolean:
+                    self.__parseBoolean(variableName, self.__result)
+                elif variableType == self.String:
+                    self.__parseString(variableName, self.__result)
+                elif variableType == self.ObjObj:
+                    self.__parseObject(variableName, self.__result)
+                elif variableType == self.ObjArr:
+                    self.__parseArray(variableName, self.__result)
+                elif variableType == self.ObjDate:
+                    self.__parseDate(variableName, self.__result)
+                elif variableType == self.ObjXml:
+                    self.__parseXml(variableName, self.__result)
+                elif variableType == self.ObjCc:
+                    self.__parseOcc(variableName, self.__result)
+                elif variableType == self.ObjM:
+                    self.__parseOjm(variableName, self.__result)
+                elif variableType == self.Null:
+                    self.__parseNull(variableName, self.__result)
+                elif variableType == self.Undef:
+                    self.__parseUndefined(variableName, self.__result)
+                else:
+                    raise FlashCookieReaderError(
+                        "Unexpected Data Type: " + hex(ord(variableType)))
+            self.__data.read(1)       # '\x00'
+        self.__data.close()
+        self.__parsed = True
+        
+    def __parseNumber(self, variableName, parent):
+        """
+        Private method to parse a number.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        """
+        b = self.__data.read(8)
+        if b == b"\x7F\xF0\x00\x00\x00\x00\x00\x00":
+            value = "Infinity"
+        elif b == b"\xFF\xF0\x00\x00\x00\x00\x00\x00":
+            value = "-Infinity"
+        elif b == b"\x7F\xF8\x00\x00\x00\x00\x00\x00":
+            value = "NaN"
+        else:
+            value, = struct.unpack(">d", b)    # double, big-endian
+            value = str(value)
+        parent[variableName] = ("number", value)
+    
+    def __parseBoolean(self, variableName, parent):
+        """
+        Private method to parse a boolean.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        """
+        b = self.__data.read(1)
+        if b == b"\x00":
+            value = "False"
+        elif b == b"\x01":
+            value = "True"
+        else:
+            # boolean value error; default to True
+            value = "True"
+        parent[variableName] = ("boolean", value)
+    
+    def __parseString(self, variableName, parent):
+        """
+        Private method to parse a string.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        """
+        lenStr, = struct.unpack(">H", self.__data.read(2))
+        # unsigned short, big-endian
+        b = self.__data.read(lenStr)
+        value = b.decode("utf-8", "replace")
+        parent[variableName] = ("string", value)
+    
+    def __parseDate(self, variableName, parent):
+        """
+        Private method to parse a date.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        """
+        msec, = struct.unpack(">d", self.__data.read(8))
+        # double, big-endian
+        # DateObject: Milliseconds Count From Dec. 1, 1969
+        msec -= self.EpochCorrectionMsecs   # correct for Unix epoch
+        minOffset, = struct.unpack(">h", self.__data.read(2))
+        # short, big-endian
+        offset = minOffset // 60    # offset in hours
+        # Timezone: UTC + Offset
+        value = QDateTime()
+        value.setMSecsSinceEpoch(msec)
+        value.setOffsetFromUtc(offset * 3600)
+        parent[variableName] = ("date",
+                                value.toString("yyyy-MM-dd HH:mm:ss t"))
+    
+    def __parseXml(self, variableName, parent):
+        """
+        Private method to parse XML.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        """
+        lenCData, = struct.unpack(">L", self.__data.read(4))
+        # unsigned long, big-endian
+        cData = self.__data.read(lenCData)
+        value = cData.decode("utf-8", "replace")
+        parent[variableName] = ("xml", value)
+    
+    def __parseOjm(self, variableName, parent):
+        """
+        Private method to parse an m_object.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        """
+        parent[variableName] = ("m_object", "")
+    
+    def __parseNull(self, variableName, parent):
+        """
+        Private method to parse a null object.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        """
+        parent[variableName] = ("null", "")
+    
+    def __parseUndefined(self, variableName, parent):
+        """
+        Private method to parse an undefined object.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        """
+        parent[variableName] = ("undefined", "")
+    
+    def __parseObject(self, variableName, parent):
+        """
+        Private method to parse an object.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        @exception FlashCookieReaderError raised when an issue with the cookie
+            file is found
+        """
+        value = {}
+        parent[variableName] = ("object", value)
+        
+        lenVariableName, = struct.unpack(">H", self.__data.read(2))
+        # unsigned short,  big-endian
+        while lenVariableName != 0:
+            variableName = self.__data.read(lenVariableName)
+            variableName = variableName.decode("utf-8", "replace")
+            variableType = self.__data.read(1)
+            if variableType == self.Number:
+                self.__parseNumber(variableName, value)
+            elif variableType == self.Boolean:
+                self.__parseBoolean(variableName, value)
+            elif variableType == self.String:
+                self.__parseString(variableName, value)
+            elif variableType == self.ObjObj:
+                self.__parseObject(variableName, value)
+            elif variableType == self.ObjArr:
+                self.__parseArray(variableName, value)
+            elif variableType == self.ObjDate:
+                self.__parseDate(variableName, value)
+            elif variableType == self.ObjXml:
+                self.__parseXml(variableName, value)
+            elif variableType == self.ObjCc:
+                self.__parseOcc(variableName, value)
+            elif variableType == self.ObjM:
+                self.__parseOjm(variableName, value)
+            elif variableType == self.Null:
+                self.__parseNull(variableName, value)
+            elif variableType == self.Undef:
+                self.__parseUndefined(variableName, value)
+            else:
+                raise FlashCookieReaderError(
+                    "Unexpected Data Type: " + hex(ord(variableType)))
+            lenVariableName, = struct.unpack(">H", self.__data.read(2))
+        self.__data.read(1)       # '\x09'
+    
+    def __parseArray(self, variableName, parent):
+        """
+        Private method to parse an array.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        @exception FlashCookieReaderError raised when an issue with the cookie
+            file is found
+        """
+        arrayLength, = struct.unpack(">L", self.__data.read(4))
+        # unsigned long, big-endian
+        
+        value = {}
+        parent[variableName] = ("array; length={0}".format(arrayLength), value)
+        
+        lenVariableName, = struct.unpack(">H", self.__data.read(2))
+        # unsigned short,  big-endian
+        while lenVariableName != 0:
+            variableName = self.__data.read(lenVariableName)
+            variableName = variableName.decode("utf-8", "replace")
+            variableType = self.__data.read(1)
+            if variableType == self.Number:
+                self.__parseNumber(variableName, value)
+            elif variableType == self.Boolean:
+                self.__parseBoolean(variableName, value)
+            elif variableType == self.String:
+                self.__parseString(variableName, value)
+            elif variableType == self.ObjObj:
+                self.__parseObject(variableName, value)
+            elif variableType == self.ObjArr:
+                self.__parseArray(variableName, value)
+            elif variableType == self.ObjDate:
+                self.__parseDate(variableName, value)
+            elif variableType == self.ObjXml:
+                self.__parseXml(variableName, value)
+            elif variableType == self.ObjCc:
+                self.__parseOcc(variableName, value)
+            elif variableType == self.ObjM:
+                self.__parseOjm(variableName, value)
+            elif variableType == self.Null:
+                self.__parseNull(variableName, value)
+            elif variableType == self.Undef:
+                self.__parseUndefined(variableName, value)
+            else:
+                raise FlashCookieReaderError(
+                    "Unexpected Data Type: " + hex(ord(variableType)))
+            lenVariableName, = struct.unpack(">H", self.__data.read(2))
+        self.__data.read(1)       # '\x09'
+    
+    def __parseOcc(self, variableName, parent):
+        """
+        Private method to parse a c_object.
+        
+        @param variableName name of the variable to be parsed
+        @type str
+        @param parent reference to the dictionary to insert the result into
+        @type dict
+        @exception FlashCookieReaderError raised when an issue with the cookie
+            file is found
+        """
+        lenCname = struct.unpack(">H", self.__data.read(2))
+        # unsigned short,  big-endian
+        cname = self.__data.read(lenCname)
+        cname = cname.decode("utf-8", "replace")
+        
+        value = {}
+        parent[variableName] = ("c_object; cname={0}".format(cname), value)
+        
+        lenVariableName, = struct.unpack(">H", self.__data.read(2))
+        # unsigned short,  big-endian
+        while lenVariableName != 0:
+            variableName = self.__data.read(lenVariableName)
+            variableName = variableName.decode("utf-8", "replace")
+            variableType = self.__data.read(1)
+            if variableType == self.Number:
+                self.__parseNumber(variableName, value)
+            elif variableType == self.Boolean:
+                self.__parseBoolean(variableName, value)
+            elif variableType == self.String:
+                self.__parseString(variableName, value)
+            elif variableType == self.ObjObj:
+                self.__parseObject(variableName, value)
+            elif variableType == self.ObjArr:
+                self.__parseArray(variableName, value)
+            elif variableType == self.ObjDate:
+                self.__parseDate(variableName, value)
+            elif variableType == self.ObjXml:
+                self.__parseXml(variableName, value)
+            elif variableType == self.ObjCc:
+                self.__parseOcc(variableName, value)
+            elif variableType == self.ObjM:
+                self.__parseOjm(variableName, value)
+            elif variableType == self.Null:
+                self.__parseNull(variableName, value)
+            elif variableType == self.Undef:
+                self.__parseUndefined(variableName, value)
+            else:
+                raise FlashCookieReaderError(
+                    "Unexpected Data Type: " + hex(ord(variableType)))
+            lenVariableName, = struct.unpack(">H", self.__data.read(2))
+        self.__data.read(1)       # '\x09'
+    
+    def toString(self, indent=0, parent=None):
+        """
+        Public method to convert the parsed cookie to a string representation.
+        
+        @param indent indentation level
+        @type int
+        @param parent reference to the dictionary to be converted
+        @type dict
+        @return string representation of the cookie
+        @rtype str
+        """
+        indentStr = "  " * indent
+        strArr = []
+        
+        if parent is None:
+            parent = self.__result
+        
+        if not parent:
+            return ""
+        
+        for variableName in sorted(parent.keys()):
+            variableType, value = parent[variableName]
+            if isinstance(value, dict):
+                resultStr = self.toString(indent + 1, value)
+                if resultStr:
+                    strArr.append("{0}{1}:\n{2}"
+                                  .format(indentStr, variableName, resultStr))
+                else:
+                    strArr.append("{0}{1}:"
+                                  .format(indentStr, variableName))
+            else:
+                strArr.append("{0}{1}: {2}"
+                              .format(indentStr, variableName, value))
+        
+        return "\n".join(strArr)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FlashCookieManager/FlashCookieUtilities.py	Fri Feb 19 19:55:56 2016 +0100
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing some utility functions.
+"""
+
+from __future__ import unicode_literals
+
+import os
+
+from PyQt5.QtCore import QProcessEnvironment
+
+import Globals
+
+
+def flashDataPathForOS():
+    """
+    Function to determine the OS dependent path where Flash cookies
+    are stored.
+    
+    @return Flash data path
+    @rtype str
+    """
+    # On Microsoft Windows NT 5.x and 6.x, they are stored in:
+    # %APPDATA%\Macromedia\Flash Player\#SharedObjects\
+    # %APPDATA%\Macromedia\Flash Player\macromedia.com\support\flashplayer\sys\
+    # On Mac OS X, they are stored in:
+    # ~/Library/Preferences/Macromedia/Flash Player/#SharedObjects/
+    # ~/Library/Preferences/Macromedia/Flash Player/macromedia.com/support/⏎
+    #   flashplayer/sys/
+    # On Linux or Unix, they are stored in:
+    # ~/.macromedia/Flash_Player/#SharedObjects/
+    # ~/.macromedia/Flash_Player/macromedia.com/support/flashplayer/sys/
+    # For Linux and Unix systems, if the open-source Gnash plugin is being used
+    #  instead of the official Adobe Flash, they will instead be found at:
+    # ~/.gnash/SharedObjects/
+    
+    flashPath = ""
+    
+    if Globals.isWindowsPlatform():
+        appData = QProcessEnvironment.systemEnvironment().value("APPDATA")
+        appData = appData.replace("\\", "/")
+        flashPath = appData + "/Macromedia/Flash Player"
+    elif Globals.isMacPlatform():
+        flashPath = os.path.expanduser(
+            "~/Library/Preferences/Macromedia/Flash Player")
+    else:
+        if os.path.exists(os.path.expanduser("~/.macromedia")):
+            flashPath = os.path.expanduser("~/.macromedia/Flash_Player")
+        elif os.path.exists(os.path.expanduser("~/.gnash")):
+            flashPath = os.path.expanduser("~/.gnash")
+    
+    return flashPath
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/FlashCookieManager/__init__.py	Fri Feb 19 19:55:56 2016 +0100
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Package implementing the Flash cookie manager and associated objects.
+"""
--- a/WebBrowser/Passwords/PasswordManager.py	Fri Feb 19 19:55:27 2016 +0100
+++ b/WebBrowser/Passwords/PasswordManager.py	Fri Feb 19 19:55:56 2016 +0100
@@ -381,7 +381,6 @@
         if not self.__loaded:
             self.__load()
         
-        # TODO: change this to include postData
         progress = E5ProgressDialog(
             self.tr("Re-encoding saved passwords..."),
             None, 0, len(self.__logins) + len(self.__loginForms),
--- a/WebBrowser/WebBrowserWindow.py	Fri Feb 19 19:55:27 2016 +0100
+++ b/WebBrowser/WebBrowserWindow.py	Fri Feb 19 19:55:56 2016 +0100
@@ -97,7 +97,7 @@
 ##    _greaseMonkeyManager = None
     _notification = None
     _featurePermissionManager = None
-##    _flashCookieManager = None
+    _flashCookieManager = None
     
     def __init__(self, home, path, parent, name, fromEric=False,
                  initShortcutsOnly=False, searchWord=None,
@@ -1282,21 +1282,20 @@
 ##                self.__showCookiesConfiguration)
 ##        self.__actions.append(self.cookiesAct)
         
-        # TODO: Flash Cookies
-##        self.flashCookiesAct = E5Action(
-##            self.tr('Flash Cookies'),
-##            UI.PixmapCache.getIcon("flashCookie.png"),
-##            self.tr('&Flash Cookies...'), 0, 0, self, 'webbrowser_flash_cookies')
-##        self.flashCookiesAct.setStatusTip(self.tr(
-##            'Manage flash cookies'))
-##        self.flashCookiesAct.setWhatsThis(self.tr(
-##            """<b>Flash Cookies</b>"""
-##            """<p>Show a dialog to manage the flash cookies.</p>"""
-##        ))
-##        if not self.__initShortcutsOnly:
-##            self.flashCookiesAct.triggered.connect(
-##                self.__showFlashCookiesManagement)
-##        self.__actions.append(self.flashCookiesAct)
+        self.flashCookiesAct = E5Action(
+            self.tr('Flash Cookies'),
+            UI.PixmapCache.getIcon("flashCookie.png"),
+            self.tr('&Flash Cookies...'), 0, 0, self, 'webbrowser_flash_cookies')
+        self.flashCookiesAct.setStatusTip(self.tr(
+            'Manage flash cookies'))
+        self.flashCookiesAct.setWhatsThis(self.tr(
+            """<b>Flash Cookies</b>"""
+            """<p>Show a dialog to manage the flash cookies.</p>"""
+        ))
+        if not self.__initShortcutsOnly:
+            self.flashCookiesAct.triggered.connect(
+                self.__showFlashCookiesManagement)
+        self.__actions.append(self.flashCookiesAct)
         
         # TODO: Offline Storage
 ##        self.offlineStorageAct = E5Action(
@@ -1856,7 +1855,7 @@
         menu.addAction(self.prefAct)
 ##        menu.addAction(self.acceptedLanguagesAct)
 ##        menu.addAction(self.cookiesAct)
-##        menu.addAction(self.flashCookiesAct)
+        menu.addAction(self.flashCookiesAct)
 ##        menu.addAction(self.offlineStorageAct)
 ##        menu.addAction(self.personalDataAct)
 ##        menu.addAction(self.greaseMonkeyAct)
@@ -1996,7 +1995,7 @@
         settingstb.addAction(self.prefAct)
 ##        settingstb.addAction(self.acceptedLanguagesAct)
 ##        settingstb.addAction(self.cookiesAct)
-##        settingstb.addAction(self.flashCookiesAct)
+        settingstb.addAction(self.flashCookiesAct)
 ##        settingstb.addAction(self.offlineStorageAct)
 ##        settingstb.addAction(self.personalDataAct)
 ##        settingstb.addAction(self.greaseMonkeyAct)
@@ -2849,11 +2848,11 @@
 ##        dlg = CookiesConfigurationDialog(self)
 ##        dlg.exec_()
     
-##    def __showFlashCookiesManagement(self):
-##        """
-##        Private slot to show the flash cookies management dialog.
-##        """
-##        self.flashCookieManager().showFlashCookieManagerDialog()
+    def __showFlashCookiesManagement(self):
+        """
+        Private slot to show the flash cookies management dialog.
+        """
+        self.flashCookieManager().showFlashCookieManagerDialog()
     
 ##    def __showOfflineStorageConfiguration(self):
 ##        """
@@ -3323,20 +3322,8 @@
 ##                    for securityOrigin in QWebSecurityOrigin.allOrigins():
 ##                        for database in securityOrigin.databases():
 ##                            QWebDatabase.removeDatabase(database)
-            # TODO: Flash Cookie Manager
-##            if flashCookies:
-##                from .HelpLanguagesDialog import HelpLanguagesDialog
-##                languages = Preferences.toList(
-##                    Preferences.Prefs.settings.value(
-##                        "Help/AcceptLanguages",
-##                        HelpLanguagesDialog.defaultAcceptLanguages()))
-##                if languages:
-##                    language = languages[0]
-##                    langCode = language.split("[")[1][:2]
-##                self.newTab(
-##                    "http://www.macromedia.com/support/documentation/"
-##                    "{0}/flashplayer/help/settings_manager07.html".format(
-##                        langCode))
+            if flashCookies:
+                self.flashCookieManager().removeAllCookies()
             if zoomValues:
                 ZoomManager.instance().clear()
         
@@ -3603,21 +3590,21 @@
         
         return cls._featurePermissionManager
         
-##    @classmethod
-##    def flashCookieManager(cls):
-##        """
-##        Class method to get a reference to the flash cookies manager.
-##        
-##        @return reference to the flash cookies manager
-##        @rtype FlashCookieManager
-##        """
-##        if cls._flashCookieManager is None:
-##            from .FlashCookieManager.FlashCookieManager import \
-##                FlashCookieManager
-##            cls._flashCookieManager = FlashCookieManager()
-##        
-##        return cls._flashCookieManager
-##        
+    @classmethod
+    def flashCookieManager(cls):
+        """
+        Class method to get a reference to the flash cookies manager.
+        
+        @return reference to the flash cookies manager
+        @rtype FlashCookieManager
+        """
+        if cls._flashCookieManager is None:
+            from .FlashCookieManager.FlashCookieManager import \
+                FlashCookieManager
+            cls._flashCookieManager = FlashCookieManager()
+        
+        return cls._flashCookieManager
+        
     @classmethod
     def mainWindow(cls):
         """
--- a/eric6.e4p	Fri Feb 19 19:55:27 2016 +0100
+++ b/eric6.e4p	Fri Feb 19 19:55:56 2016 +0100
@@ -1293,6 +1293,13 @@
     <Source>WebBrowser/FeaturePermissions/FeaturePermissionManager.py</Source>
     <Source>WebBrowser/FeaturePermissions/FeaturePermissionsDialog.py</Source>
     <Source>WebBrowser/FeaturePermissions/__init__.py</Source>
+    <Source>WebBrowser/FlashCookieManager/FlashCookie.py</Source>
+    <Source>WebBrowser/FlashCookieManager/FlashCookieManager.py</Source>
+    <Source>WebBrowser/FlashCookieManager/FlashCookieManagerDialog.py</Source>
+    <Source>WebBrowser/FlashCookieManager/FlashCookieNotification.py</Source>
+    <Source>WebBrowser/FlashCookieManager/FlashCookieReader.py</Source>
+    <Source>WebBrowser/FlashCookieManager/FlashCookieUtilities.py</Source>
+    <Source>WebBrowser/FlashCookieManager/__init__.py</Source>
     <Source>WebBrowser/History/HistoryCompleter.py</Source>
     <Source>WebBrowser/History/HistoryDialog.py</Source>
     <Source>WebBrowser/History/HistoryFilterModel.py</Source>
@@ -1753,6 +1760,7 @@
     <Form>WebBrowser/Bookmarks/BookmarksDialog.ui</Form>
     <Form>WebBrowser/Bookmarks/BookmarksImportDialog.ui</Form>
     <Form>WebBrowser/FeaturePermissions/FeaturePermissionsDialog.ui</Form>
+    <Form>WebBrowser/FlashCookieManager/FlashCookieManagerDialog.ui</Form>
     <Form>WebBrowser/History/HistoryDialog.ui</Form>
     <Form>WebBrowser/OpenSearch/OpenSearchDialog.ui</Form>
     <Form>WebBrowser/OpenSearch/OpenSearchEditDialog.ui</Form>

eric ide

mercurial