Continued porting the web browser. QtWebEngine

Wed, 17 Feb 2016 19:49:51 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 17 Feb 2016 19:49:51 +0100
branch
QtWebEngine
changeset 4744
ad3f6c1caf8d
parent 4743
f9e2e536d130
child 4745
285bfd224a1b

Continued porting the web browser.

- continued the passwords stuff

WebBrowser/JavaScript/AutoFillJsObject.py file | annotate | diff | comparison | revisions
WebBrowser/JavaScript/ExternalJsObject.py file | annotate | diff | comparison | revisions
WebBrowser/Passwords/LoginForm.py file | annotate | diff | comparison | revisions
WebBrowser/Passwords/PasswordManager.py file | annotate | diff | comparison | revisions
WebBrowser/Passwords/PasswordReader.py file | annotate | diff | comparison | revisions
WebBrowser/Passwords/PasswordWriter.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserPage.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserView.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
--- a/WebBrowser/JavaScript/AutoFillJsObject.py	Mon Feb 15 20:01:02 2016 +0100
+++ b/WebBrowser/JavaScript/AutoFillJsObject.py	Wed Feb 17 19:49:51 2016 +0100
@@ -46,14 +46,7 @@
         @param data data to be submitted
         @type QByteArray
         """
-        # TODO: AutoFill
-        pass
-##void AutoFillJsObject::formSubmitted(const QString &frameUrl, const QString &username, const QString &password, const QByteArray &data)
-##{
-##    PageFormData formData;
-##    formData.username = username;
-##    formData.password = password;
-##    formData.postData = data;
-##
-##    mApp->autoFill()->saveForm(m_jsObject->page(), QUrl(frameUrl), formData);
-##}
+        import WebBrowser.WebBrowserWindow
+        WebBrowser.WebBrowserWindow.WebBrowserWindow.passwordManager()\
+        .formSubmitted(urlStr, userName, password, data,
+                       self.__jsObject.page())
--- a/WebBrowser/JavaScript/ExternalJsObject.py	Mon Feb 15 20:01:02 2016 +0100
+++ b/WebBrowser/JavaScript/ExternalJsObject.py	Wed Feb 17 19:49:51 2016 +0100
@@ -68,6 +68,7 @@
         """
         return self.__autoFill
     
+    # TODO: OpenSearch
 ##void ExternalJsObject::AddSearchProvider(const QString &engineUrl)
 ##{ Slot
 ##    mApp->searchEnginesManager()->addEngine(QUrl(engineUrl));
--- a/WebBrowser/Passwords/LoginForm.py	Mon Feb 15 20:01:02 2016 +0100
+++ b/WebBrowser/Passwords/LoginForm.py	Wed Feb 17 19:49:51 2016 +0100
@@ -9,7 +9,7 @@
 
 from __future__ import unicode_literals
 
-from PyQt5.QtCore import QUrl
+from PyQt5.QtCore import QUrl, QByteArray
 
 
 class LoginForm(object):
@@ -22,11 +22,7 @@
         """
         self.url = QUrl()
         self.name = ""
-        self.hasAPassword = False
-        self.elements = []
-        # list of tuples of element name and value (string, string)
-        self.elementTypes = {}
-        # dict of element name as key and type as value
+        self.postData = QByteArray()
     
     def isValid(self):
         """
@@ -34,4 +30,5 @@
         
         @return flag indicating a valid form (boolean)
         """
-        return len(self.elements) > 0
+        return not self.url.isEmpty() and \
+            not self.postData.isEmpty()
--- a/WebBrowser/Passwords/PasswordManager.py	Mon Feb 15 20:01:02 2016 +0100
+++ b/WebBrowser/Passwords/PasswordManager.py	Wed Feb 17 19:49:51 2016 +0100
@@ -12,11 +12,9 @@
 import os
 
 from PyQt5.QtCore import pyqtSignal, QObject, QByteArray, QUrl, \
-    QCoreApplication, QXmlStreamReader, qVersion
+    QCoreApplication, QXmlStreamReader
 from PyQt5.QtWidgets import QApplication
-from PyQt5.QtNetwork import QNetworkRequest
-##from PyQt5.QtWebKit import QWebSettings
-##from PyQt5.QtWebKitWidgets import QWebPage
+from PyQt5.QtWebEngineWidgets import QWebEngineScript
 
 from E5Gui import E5MessageBox
 from E5Gui.E5ProgressDialog import E5ProgressDialog
@@ -26,6 +24,9 @@
 import Utilities.crypto
 import Preferences
 
+import WebBrowser.WebBrowserWindow
+from ..Tools import Scripts
+
 
 class PasswordManager(QObject):
     """
@@ -45,6 +46,16 @@
         """
         super(PasswordManager, self).__init__(parent)
         
+        # setup userscript to monitor forms
+        script = QWebEngineScript()
+        script.setName("_eric_passwordmonitor")
+        script.setInjectionPoint(QWebEngineScript.DocumentReady)
+        script.setWorldId(QWebEngineScript.MainWorld)
+        script.setRunsOnSubFrames(True)
+        script.setSourceCode(Scripts.setupFormObserver())
+        profile = WebBrowser.WebBrowserWindow.WebBrowserWindow.webProfile()
+        profile.scripts().insert(script)
+        
         self.__logins = {}
         self.__loginForms = {}
         self.__never = []
@@ -244,113 +255,69 @@
         return self.__logins[site][0], Utilities.crypto.pwConvert(
             self.__logins[site][1], encode=False)
     
-    # TODO: Password Manager: processing of form data
-    def post(self, request, data):
+    def formSubmitted(self, urlStr, userName, password, data, page):
         """
-        Public method to check, if the data to be sent contains login data.
+        Public method to record login data.
         
-        @param request reference to the network request (QNetworkRequest)
-        @param data data to be sent (QByteArray)
+        @param urlStr form submission URL
+        @type str
+        @param userName name of the user
+        @type str
+        @param password user password
+        @type str
+        @param data data to be submitted
+        @type QByteArray
+        @param page reference to the calling page
+        @type QWrbEnginePage
         """
-##        # shall passwords be saved?
-##        if not Preferences.getUser("SavePasswords"):
-##            return
-##        
-##        # observe privacy
-##        # TODO: Privacy, i.e. isPrivate()
-####        if QWebSettings.globalSettings().testAttribute(
-####                QWebSettings.PrivateBrowsingEnabled):
-####            return
-##        
-##        if not self.__loaded:
-##            self.__load()
-##        
-##        # determine the url
-##        refererHeader = request.rawHeader(b"Referer")
-##        if refererHeader.isEmpty():
-##            return
-##        url = QUrl.fromEncoded(refererHeader)
-##        url = self.__stripUrl(url)
-##        
-##        # check that url isn't in __never
-##        if url.toString() in self.__never:
-##            return
-##        
-##        # check the request type
-##        navType = request.attribute(QNetworkRequest.User + 101)
-##        if navType is None:
-##            return
-##        if navType != QWebPage.NavigationTypeFormSubmitted:
-##            return
-##        
-##        # determine the QWebPage
-##        webPage = request.attribute(QNetworkRequest.User + 100)
-##        if webPage is None:
-##            return
-##        
-##        # determine the requests content type
-##        contentTypeHeader = request.rawHeader(b"Content-Type")
-##        if contentTypeHeader.isEmpty():
-##            return
-##        multipart = contentTypeHeader.startsWith(b"multipart/form-data")
-##        if multipart:
-##            boundary = contentTypeHeader.split(" ")[1].split("=")[1]
-##        else:
-##            boundary = None
-##        
-##        # find the matching form on the web page
-##        form = self.__findForm(webPage, data, boundary=boundary)
-##        if not form.isValid():
-##            return
-##        form.url = QUrl(url)
-##        
-##        # check, if the form has a password
-##        if not form.hasAPassword:
-##            return
-##        
-##        # prompt, if the form has never be seen
-##        key = self.__createKey(url, "")
-##        if key not in self.__loginForms:
-##            mb = E5MessageBox.E5MessageBox(
-##                E5MessageBox.Question,
-##                self.tr("Save password"),
-##                self.tr(
-##                    """<b>Would you like to save this password?</b><br/>"""
-##                    """To review passwords you have saved and remove them, """
-##                    """use the password management dialog of the Settings"""
-##                    """ menu."""),
-##                modal=True)
-##            neverButton = mb.addButton(
-##                self.tr("Never for this site"),
-##                E5MessageBox.DestructiveRole)
-##            noButton = mb.addButton(
-##                self.tr("Not now"), E5MessageBox.RejectRole)
-##            mb.addButton(E5MessageBox.Yes)
-##            mb.exec_()
-##            if mb.clickedButton() == neverButton:
-##                self.__never.append(url.toString())
-##                return
-##            elif mb.clickedButton() == noButton:
-##                return
-##        
-##        # extract user name and password
-##        user = ""
-##        password = ""
-##        for index in range(len(form.elements)):
-##            element = form.elements[index]
-##            type_ = form.elementTypes[element[0]]
-##            if user == "" and \
-##               type_ == "text":
-##                user = element[1]
-##            elif password == "" and \
-##                    type_ == "password":
-##                password = element[1]
-##                form.elements[index] = (element[0], "--PASSWORD--")
-##        if user and password:
-##            self.__logins[key] = \
-##                (user, Utilities.crypto.pwConvert(password, encode=True))
-##            self.__loginForms[key] = form
-##            self.changed.emit()
+        # shall passwords be saved?
+        if not Preferences.getUser("SavePasswords"):
+            return
+        
+        if WebBrowser.WebBrowserWindow.WebBrowserWindow.mainWindow()\
+                .isPrivate():
+            return
+        
+        if urlStr in self.__never:
+            return
+        
+        if userName and password:
+            url = QUrl(urlStr)
+            url = self.__stripUrl(url)
+            key = self.__createKey(url, "")
+            if key not in self.__loginForms:
+                mb = E5MessageBox.E5MessageBox(
+                    E5MessageBox.Question,
+                    self.tr("Save password"),
+                    self.tr(
+                        """<b>Would you like to save this password?</b><br/>"""
+                        """To review passwords you have saved and remove"""
+                        """ them, use the password management dialog of the"""
+                        """ Settings menu."""),
+                    modal=True, parent=page.view())
+                neverButton = mb.addButton(
+                    self.tr("Never for this site"),
+                    E5MessageBox.DestructiveRole)
+                noButton = mb.addButton(
+                    self.tr("Not now"), E5MessageBox.RejectRole)
+                mb.addButton(E5MessageBox.Yes)
+                mb.exec_()
+                if mb.clickedButton() == neverButton:
+                    self.__never.append(url.toString())
+                    return
+                elif mb.clickedButton() == noButton:
+                    return
+        
+            self.__logins[key] = \
+                (userName,
+                 Utilities.crypto.pwConvert(password, encode=True))
+            from .LoginForm import LoginForm
+            form = LoginForm()
+            form.url = url
+            form.name = userName
+            form.postData = QByteArray(data)
+            self.__loginForms[key] = form
+            self.changed.emit()
     
     def __stripUrl(self, url):
         """
@@ -371,171 +338,31 @@
         cleanUrl.setFragment("")
         return cleanUrl
     
-    # TODO: Password Manager: processing of form data
-##    def __findForm(self, webPage, data, boundary=None):
-##        """
-##        Private method to find the form used for logging in.
-##        
-##        @param webPage reference to the web page (QWebPage)
-##        @param data data to be sent (QByteArray)
-##        @keyparam boundary boundary string (QByteArray) for multipart
-##            encoded data, None for urlencoded data
-##        @return parsed form (LoginForm)
-##        """
-##        from .LoginForm import LoginForm
-##        form = LoginForm()
-##        if boundary is not None:
-##            args = self.__extractMultipartQueryItems(data, boundary)
-##        else:
-##            if qVersion() >= "5.0.0":
-##                from PyQt5.QtCore import QUrlQuery
-##                argsUrl = QUrl.fromEncoded(
-##                    QByteArray(b"foo://bar.com/?" + QUrl.fromPercentEncoding(
-##                        data.replace(b"+", b"%20")).encode("utf-8")))
-##                encodedArgs = QUrlQuery(argsUrl).queryItems()
-##            else:
-##                argsUrl = QUrl.fromEncoded(
-##                    QByteArray(b"foo://bar.com/?" + data.replace(b"+", b"%20"))
-##                )
-##                encodedArgs = argsUrl.queryItems()
-##            args = set()
-##            for arg in encodedArgs:
-##                key = arg[0]
-##                value = arg[1]
-##                args.add((key, value))
-##        
-##        # extract the forms
-##        from Helpviewer.JavaScriptResources import parseForms_js
-##        lst = webPage.mainFrame().evaluateJavaScript(parseForms_js)
-##        for map in lst:
-##            formHasPasswords = False
-##            formName = map["name"]
-##            formIndex = map["index"]
-##            if isinstance(formIndex, float) and formIndex.is_integer():
-##                formIndex = int(formIndex)
-##            elements = map["elements"]
-##            formElements = set()
-##            formElementTypes = {}
-##            deadElements = set()
-##            for elementMap in elements:
-##                try:
-##                    name = elementMap["name"]
-##                    value = elementMap["value"]
-##                    type_ = elementMap["type"]
-##                except KeyError:
-##                    continue
-##                if type_ == "password":
-##                    formHasPasswords = True
-##                t = (name, value)
-##                try:
-##                    if elementMap["autocomplete"] == "off":
-##                        deadElements.add(t)
-##                except KeyError:
-##                    pass
-##                if name:
-##                    formElements.add(t)
-##                    formElementTypes[name] = type_
-##            if formElements.intersection(args) == args:
-##                form.hasAPassword = formHasPasswords
-##                if not formName:
-##                    form.name = formIndex
-##                else:
-##                    form.name = formName
-##                args.difference_update(deadElements)
-##                for elt in deadElements:
-##                    if elt[0] in formElementTypes:
-##                        del formElementTypes[elt[0]]
-##                form.elements = list(args)
-##                form.elementTypes = formElementTypes
-##                break
-##        
-##        return form
-##    
-##    def __extractMultipartQueryItems(self, data, boundary):
-##        """
-##        Private method to extract the query items for a post operation.
-##        
-##        @param data data to be sent (QByteArray)
-##        @param boundary boundary string (QByteArray)
-##        @return set of name, value pairs (set of tuple of string, string)
-##        """
-##        args = set()
-##        
-##        dataStr = bytes(data).decode()
-##        boundaryStr = bytes(boundary).decode()
-##        
-##        parts = dataStr.split(boundaryStr + "\r\n")
-##        for part in parts:
-##            if part.startswith("Content-Disposition"):
-##                lines = part.split("\r\n")
-##                name = lines[0].split("=")[1][1:-1]
-##                value = lines[2]
-##                args.add((name, value))
-##        
-##        return args
-##    
-##    def fill(self, page):
-##        """
-##        Public slot to fill login forms with saved data.
-##        
-##        @param page reference to the web page (QWebPage)
-##        """
-##        if page is None or page.mainFrame() is None:
-##            return
-##        
-##        if not self.__loaded:
-##            self.__load()
-##        
-##        url = page.mainFrame().url()
-##        url = self.__stripUrl(url)
-##        key = self.__createKey(url, "")
-##        if key not in self.__loginForms or \
-##           key not in self.__logins:
-##            return
-##        
-##        form = self.__loginForms[key]
-##        if form.url != url:
-##            return
-##        
-##        if form.name == "":
-##            formName = "0"
-##        else:
-##            try:
-##                formName = "{0:d}".format(int(form.name))
-##            except ValueError:
-##                formName = '"{0}"'.format(form.name)
-##        for element in form.elements:
-##            name = element[0]
-##            value = element[1]
-##            
-##            disabled = page.mainFrame().evaluateJavaScript(
-##                'document.forms[{0}].elements["{1}"].disabled'.format(
-##                    formName, name))
-##            if disabled:
-##                continue
-##            
-##            readOnly = page.mainFrame().evaluateJavaScript(
-##                'document.forms[{0}].elements["{1}"].readOnly'.format(
-##                    formName, name))
-##            if readOnly:
-##                continue
-##            
-##            type_ = page.mainFrame().evaluateJavaScript(
-##                'document.forms[{0}].elements["{1}"].type'.format(
-##                    formName, name))
-##            if type_ == "" or \
-##               type_ in ["hidden", "reset", "submit"]:
-##                continue
-##            if type_ == "password":
-##                value = Utilities.crypto.pwConvert(
-##                    self.__logins[key][1], encode=False)
-##            setType = type_ == "checkbox" and "checked" or "value"
-##            value = value.replace("\\", "\\\\")
-##            value = value.replace('"', '\\"')
-##            javascript = \
-##                'document.forms[{0}].elements["{1}"].{2}="{3}";'.format(
-##                    formName, name, setType, value)
-##            page.mainFrame().evaluateJavaScript(javascript)
+    def completePage(self, page):
+        """
+        Public slot to complete login forms with saved data.
+        
+        @param page reference to the web page (WebBrowserPage)
+        """
+        if page is None:
+            return
+        
+        if not self.__loaded:
+            self.__load()
+        
+        url = page.url()
+        url = self.__stripUrl(url)
+        key = self.__createKey(url, "")
+        if key not in self.__loginForms or \
+           key not in self.__logins:
+            return
+        
+        form = self.__loginForms[key]
+        if form.url != url:
+            return
+        
+        script = Scripts.completeFormData(form.postData)
+        page.runJavaScript(script)
     
     def masterPasswordChanged(self, oldPassword, newPassword):
         """
--- a/WebBrowser/Passwords/PasswordReader.py	Mon Feb 15 20:01:02 2016 +0100
+++ b/WebBrowser/Passwords/PasswordReader.py	Wed Feb 17 19:49:51 2016 +0100
@@ -10,7 +10,7 @@
 from __future__ import unicode_literals
 
 from PyQt5.QtCore import QXmlStreamReader, QIODevice, QFile, \
-    QCoreApplication, QUrl
+    QCoreApplication, QUrl, QByteArray
 
 
 class PasswordReader(QXmlStreamReader):
@@ -49,12 +49,12 @@
             if self.isStartElement():
                 version = self.attributes().value("version")
                 if self.name() == "Password" and \
-                   (not version or version == "1.0"):
+                   (not version or version == "2.0"):
                     self.__readPasswords()
                 else:
                     self.raiseError(QCoreApplication.translate(
                         "PasswordReader",
-                        "The file is not a Passwords version 1.0 file."))
+                        "The file is not a Passwords version 2.0 file."))
         
         return self.__logins, self.__loginForms, self.__never
     
@@ -112,6 +112,7 @@
         if not self.isStartElement() and self.name() != "Forms":
             return
         
+        # TODO: Passwords: adjust reader to new login form
         while not self.atEnd():
             self.readNext()
             if self.isStartElement():
@@ -122,14 +123,10 @@
                     form = LoginForm()
                     form.url = QUrl(attributes.value("url"))
                     form.name = attributes.value("name")
-                    form.hasAPassword = attributes.value("password") == "yes"
-                elif self.name() == "Elements":
-                    continue
-                elif self.name() == "Element":
-                    attributes = self.attributes()
-                    name = attributes.value("name")
-                    value = attributes.value("value")
-                    form.elements.append((name, value))
+                    
+                elif self.name() == "PostData":
+                    form.postData = QByteArray(
+                        self.readElementText().encode("utf-8"))
                 else:
                     self.__skipUnknownElement()
             
--- a/WebBrowser/Passwords/PasswordWriter.py	Mon Feb 15 20:01:02 2016 +0100
+++ b/WebBrowser/Passwords/PasswordWriter.py	Wed Feb 17 19:49:51 2016 +0100
@@ -57,7 +57,7 @@
         self.writeStartDocument()
         self.writeDTD("<!DOCTYPE passwords>")
         self.writeStartElement("Password")
-        self.writeAttribute("version", "1.0")
+        self.writeAttribute("version", "2.0")
         
         if logins:
             self.__writeLogins(logins)
@@ -95,15 +95,8 @@
             self.writeAttribute("key", key)
             self.writeAttribute("url", form.url.toString())
             self.writeAttribute("name", str(form.name))
-            self.writeAttribute(
-                "password", "yes" if form.hasAPassword else "no")
-            if form.elements:
-                self.writeStartElement("Elements")
-                for element in form.elements:
-                    self.writeEmptyElement("Element")
-                    self.writeAttribute("name", element[0])
-                    self.writeAttribute("value", element[1])
-                self.writeEndElement()
+            self.writeTextElement(
+                "PostData", bytes(form.postData).decode("utf-8"))
             self.writeEndElement()
         self.writeEndElement()
     
--- a/WebBrowser/WebBrowserPage.py	Mon Feb 15 20:01:02 2016 +0100
+++ b/WebBrowser/WebBrowserPage.py	Wed Feb 17 19:49:51 2016 +0100
@@ -769,7 +769,7 @@
         Public method to setup a web channel to our external object.
         """
         oldChannel = self.webChannel()
-        newChannel = QWebChannel()
+        newChannel = QWebChannel(self)
         newChannel.registerObject("eric_object", ExternalJsObject(self))
         self.setWebChannel(newChannel)
         
--- a/WebBrowser/WebBrowserView.py	Mon Feb 15 20:01:02 2016 +0100
+++ b/WebBrowser/WebBrowserView.py	Wed Feb 17 19:49:51 2016 +0100
@@ -1524,8 +1524,7 @@
             self.__mw.historyManager().addHistoryEntry(self)
             # TODO: AdBlock
 ##            self.__mw.adBlockManager().page().hideBlockedPageEntries(self.page())
-            # TODO: Password Manager
-##            self.__mw.passwordManager().fill(self.page())
+            self.__mw.passwordManager().completePage(self.page())
     
     def isLoading(self):
         """
--- a/WebBrowser/WebBrowserWindow.py	Mon Feb 15 20:01:02 2016 +0100
+++ b/WebBrowser/WebBrowserWindow.py	Wed Feb 17 19:49:51 2016 +0100
@@ -80,6 +80,7 @@
     _fromEric = False
     UseQtHelp = QTHELP_AVAILABLE
     
+    _webProfile = None
     _networkManager = None
 ##    _cookieJar = None
 ##    _helpEngine = None
@@ -135,21 +136,22 @@
         if self.__initShortcutsOnly:
             self.__initActions()
         else:
-            if self.isPrivate():
-                self.__webProfile = QWebEngineProfile(self)
-            else:
-                self.__webProfile = QWebEngineProfile.defaultProfile()
-            self.__webProfile.downloadRequested.connect(
-                self.__downloadRequested)
-            
-            # Setup QWebChannel user script
-            script = QWebEngineScript()
-            script.setName("_eric_webchannel")
-            script.setInjectionPoint(QWebEngineScript.DocumentCreation)
-            script.setWorldId(QWebEngineScript.MainWorld)
-            script.setRunsOnSubFrames(True)
-            script.setSourceCode(Scripts.setupWebChannel())
-            self.__webProfile.scripts().insert(script)
+            self.webProfile(private)
+##            if self.isPrivate():
+##                self.__webProfile = QWebEngineProfile(self)
+##            else:
+##                self.__webProfile = QWebEngineProfile.defaultProfile()
+##            self.__webProfile.downloadRequested.connect(
+##                self.__downloadRequested)
+##            
+##            # Setup QWebChannel user script
+##            script = QWebEngineScript()
+##            script.setName("_eric_webchannel")
+##            script.setInjectionPoint(QWebEngineScript.DocumentCreation)
+##            script.setWorldId(QWebEngineScript.MainWorld)
+##            script.setRunsOnSubFrames(True)
+##            script.setSourceCode(Scripts.setupWebChannel())
+##            self.__webProfile.scripts().insert(script)
             
             from .SearchWidget import SearchWidget
             # TODO: QtHelp
@@ -260,6 +262,8 @@
             self.__setIconDatabasePath()
             self.__initWebEngineSettings()
             
+            self.passwordManager()
+            
             self.__initActions()
             self.__initMenus()
             self.__initToolbars()
@@ -4029,9 +4033,9 @@
             .replace("\n", "")
         name = "_eric_userstylesheet"
         
-        oldScript = self.__webProfile.scripts().findScript(name)
+        oldScript = self.webProfile().scripts().findScript(name)
         if not oldScript.isNull():
-            self.__webProfile.scripts().remove(oldScript)
+            self.webProfile().scripts().remove(oldScript)
         
         if userStyle:
             script = QWebEngineScript()
@@ -4040,7 +4044,7 @@
             script.setWorldId(QWebEngineScript.ApplicationWorld)
             script.setRunsOnSubFrames(True)
             script.setSourceCode(Scripts.setStyleSheet(userStyle))
-            self.__webProfile.scripts().insert(script)
+            self.webProfile().scripts().insert(script)
     
     ##########################################
     ## Support for desktop notifications below
@@ -4088,9 +4092,10 @@
     ## Support for download files below
     ###################################
     
-    def __downloadRequested(self, download):
+    @classmethod
+    def downloadRequested(self, download):
         """
-        Private slot to handle a download request.
+        Class method to handle a download request.
         
         @param download reference to the download data
         @type QWebEngineDownloadItem
@@ -4098,3 +4103,36 @@
         pass
         # TODO: DownloadManager
 ##        self.downloadManager().download(download, mainWindow=self)
+    
+    ########################################
+    ## Support for web engine profiles below
+    ########################################
+    
+    @classmethod
+    def webProfile(cls, private=False):
+        """
+        Class method handling the web engine profile.
+        
+        @param private flag indicating the privacy mode
+        @type bool
+        @return reference to the web profile object
+        @rtype QWebEngineProfile
+        """
+        if cls._webProfile is None:
+            if private:
+                cls._webProfile = QWebEngineProfile()
+            else:
+                cls._webProfile = QWebEngineProfile.defaultProfile()
+            cls._webProfile.downloadRequested.connect(
+                cls.downloadRequested)
+            
+            # Setup QWebChannel user script
+            script = QWebEngineScript()
+            script.setName("_eric_webchannel")
+            script.setInjectionPoint(QWebEngineScript.DocumentCreation)
+            script.setWorldId(QWebEngineScript.MainWorld)
+            script.setRunsOnSubFrames(True)
+            script.setSourceCode(Scripts.setupWebChannel())
+            cls._webProfile.scripts().insert(script)
+        
+        return cls._webProfile

eric ide

mercurial