|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2008 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 |
|
7 """ |
|
8 Module implementing the helpbrowser using QWebView. |
|
9 """ |
|
10 |
|
11 from __future__ import unicode_literals |
|
12 try: |
|
13 str = unicode |
|
14 except NameError: |
|
15 pass |
|
16 |
|
17 from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QT_TRANSLATE_NOOP, \ |
|
18 QUrl, QBuffer, QIODevice, QFileInfo, Qt, QTimer, QEvent, \ |
|
19 QRect, QFile, QPoint, QByteArray, qVersion |
|
20 from PyQt5.QtGui import QDesktopServices, QClipboard, QMouseEvent, QColor, \ |
|
21 QPalette |
|
22 from PyQt5.QtWidgets import qApp, QStyle, QMenu, QApplication, QInputDialog, \ |
|
23 QLineEdit, QLabel, QToolTip, QFrame, QDialog |
|
24 from PyQt5.QtPrintSupport import QPrinter, QPrintDialog |
|
25 ##from PyQt5.QtWebKit import QWebSettings |
|
26 ##from PyQt5.QtWebKitWidgets import QWebView, QWebPage |
|
27 from PyQt5.QtWebEngineWidgets import QWebEnginePage |
|
28 try: |
|
29 from PyQt5.QtWebKit import QWebElement |
|
30 except ImportError: |
|
31 pass |
|
32 from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest |
|
33 import sip |
|
34 |
|
35 from E5Gui import E5MessageBox, E5FileDialog |
|
36 |
|
37 import WebBrowser |
|
38 import WebBrowser.WebBrowserWindow |
|
39 |
|
40 import Preferences |
|
41 import UI.PixmapCache |
|
42 import Globals |
|
43 |
|
44 try: |
|
45 from PyQt5.QtNetwork import QSslCertificate |
|
46 SSL_AVAILABLE = True |
|
47 except ImportError: |
|
48 SSL_AVAILABLE = False |
|
49 |
|
50 ############################################################################### |
|
51 ## |
|
52 ## |
|
53 ##class JavaScriptExternalObject(QObject): |
|
54 ## """ |
|
55 ## Class implementing an external javascript object to add search providers. |
|
56 ## """ |
|
57 ## def __init__(self, mw, parent=None): |
|
58 ## """ |
|
59 ## Constructor |
|
60 ## |
|
61 ## @param mw reference to the main window 8HelpWindow) |
|
62 ## @param parent reference to the parent object (QObject) |
|
63 ## """ |
|
64 ## super(JavaScriptExternalObject, self).__init__(parent) |
|
65 ## |
|
66 ## self.__mw = mw |
|
67 ## |
|
68 ## @pyqtSlot(str) |
|
69 ## def AddSearchProvider(self, url): |
|
70 ## """ |
|
71 ## Public slot to add a search provider. |
|
72 ## |
|
73 ## @param url url of the XML file defining the search provider (string) |
|
74 ## """ |
|
75 ## self.__mw.openSearchManager().addEngine(QUrl(url)) |
|
76 ## |
|
77 ## |
|
78 ##class LinkedResource(object): |
|
79 ## """ |
|
80 ## Class defining a data structure for linked resources. |
|
81 ## """ |
|
82 ## def __init__(self): |
|
83 ## """ |
|
84 ## Constructor |
|
85 ## """ |
|
86 ## self.rel = "" |
|
87 ## self.type_ = "" |
|
88 ## self.href = "" |
|
89 ## self.title = "" |
|
90 ## |
|
91 ############################################################################### |
|
92 ## |
|
93 ## |
|
94 ##class JavaScriptEricObject(QObject): |
|
95 ## """ |
|
96 ## Class implementing an external javascript object to search via the |
|
97 ## startpage. |
|
98 ## """ |
|
99 ## # these must be in line with the strings used by the javascript part of |
|
100 ## # the start page |
|
101 ## translations = [ |
|
102 ## QT_TRANSLATE_NOOP("JavaScriptEricObject", |
|
103 ## "Welcome to eric6 Web Browser!"), |
|
104 ## QT_TRANSLATE_NOOP("JavaScriptEricObject", "eric6 Web Browser"), |
|
105 ## QT_TRANSLATE_NOOP("JavaScriptEricObject", "Search!"), |
|
106 ## QT_TRANSLATE_NOOP("JavaScriptEricObject", "About eric6"), |
|
107 ## ] |
|
108 ## |
|
109 ## def __init__(self, mw, parent=None): |
|
110 ## """ |
|
111 ## Constructor |
|
112 ## |
|
113 ## @param mw reference to the main window 8HelpWindow) |
|
114 ## @param parent reference to the parent object (QObject) |
|
115 ## """ |
|
116 ## super(JavaScriptEricObject, self).__init__(parent) |
|
117 ## |
|
118 ## self.__mw = mw |
|
119 ## |
|
120 ## @pyqtSlot(str, result=str) |
|
121 ## def translate(self, trans): |
|
122 ## """ |
|
123 ## Public method to translate the given string. |
|
124 ## |
|
125 ## @param trans string to be translated (string) |
|
126 ## @return translation (string) |
|
127 ## """ |
|
128 ## if trans == "QT_LAYOUT_DIRECTION": |
|
129 ## # special handling to detect layout direction |
|
130 ## if qApp.isLeftToRight(): |
|
131 ## return "LTR" |
|
132 ## else: |
|
133 ## return "RTL" |
|
134 ## |
|
135 ## return self.tr(trans) |
|
136 ## |
|
137 ## @pyqtSlot(result=str) |
|
138 ## def providerString(self): |
|
139 ## """ |
|
140 ## Public method to get a string for the search provider. |
|
141 ## |
|
142 ## @return string for the search provider (string) |
|
143 ## """ |
|
144 ## return self.tr("Search results provided by {0}")\ |
|
145 ## .format(self.__mw.openSearchManager().currentEngineName()) |
|
146 ## |
|
147 ## @pyqtSlot(str, result=str) |
|
148 ## def searchUrl(self, searchStr): |
|
149 ## """ |
|
150 ## Public method to get the search URL for the given search term. |
|
151 ## |
|
152 ## @param searchStr search term (string) |
|
153 ## @return search URL (string) |
|
154 ## """ |
|
155 ## return bytes( |
|
156 ## self.__mw.openSearchManager().currentEngine() |
|
157 ## .searchUrl(searchStr).toEncoded()).decode() |
|
158 ## |
|
159 ############################################################################### |
|
160 |
|
161 |
|
162 class WebBrowserPage(QWebEnginePage): |
|
163 """ |
|
164 Class implementing an enhanced web page. |
|
165 """ |
|
166 ## _webPluginFactory = None |
|
167 ## |
|
168 def __init__(self, parent=None): |
|
169 """ |
|
170 Constructor |
|
171 |
|
172 @param parent parent widget of this window (QWidget) |
|
173 """ |
|
174 super(WebBrowserPage, self).__init__(parent) |
|
175 |
|
176 ## self.setPluginFactory(self.webPluginFactory()) |
|
177 ## |
|
178 ## self.__lastRequest = None |
|
179 ## self.__lastRequestType = QWebPage.NavigationTypeOther |
|
180 ## |
|
181 ## import Helpviewer.HelpWindow |
|
182 ## from .Network.NetworkAccessManagerProxy import \ |
|
183 ## NetworkAccessManagerProxy |
|
184 ## self.__proxy = NetworkAccessManagerProxy(self) |
|
185 ## self.__proxy.setWebPage(self) |
|
186 ## self.__proxy.setPrimaryNetworkAccessManager( |
|
187 ## Helpviewer.HelpWindow.HelpWindow.networkAccessManager()) |
|
188 ## self.setNetworkAccessManager(self.__proxy) |
|
189 ## |
|
190 ## self.__sslConfiguration = None |
|
191 ## self.__proxy.finished.connect(self.__managerFinished) |
|
192 ## |
|
193 self.__adBlockedEntries = [] |
|
194 self.loadStarted.connect(self.__loadStarted) |
|
195 ## |
|
196 ## self.saveFrameStateRequested.connect( |
|
197 ## self.__saveFrameStateRequested) |
|
198 ## self.restoreFrameStateRequested.connect( |
|
199 ## self.__restoreFrameStateRequested) |
|
200 self.featurePermissionRequested.connect( |
|
201 self.__featurePermissionRequested) |
|
202 |
|
203 def acceptNavigationRequest(self, url, type_, isMainFrame): |
|
204 """ |
|
205 Protected method to determine, if a request may be accepted. |
|
206 |
|
207 @param url URL to navigate to |
|
208 @type QUrl |
|
209 @param type_ type of the navigation request |
|
210 @type QWebEnginePage.NavigationType |
|
211 @param isMainFrame flag indicating, that the request originated from |
|
212 the main frame |
|
213 @type bool |
|
214 @return flag indicating acceptance |
|
215 @rtype bool |
|
216 """ |
|
217 ## self.__lastRequest = request |
|
218 ## if self.__lastRequest.url() != request.url() or \ |
|
219 ## type_ != QWebPage.NavigationTypeOther: |
|
220 ## self.__lastRequestType = type_ |
|
221 |
|
222 # TODO: Qt 5.6: move to handleUnknownProtocol |
|
223 scheme = url.scheme() |
|
224 if scheme == "mailto": |
|
225 QDesktopServices.openUrl(url) |
|
226 return False |
|
227 |
|
228 # AdBlock |
|
229 if url.scheme() == "abp": |
|
230 if WebBrowser.WebBrowserWindow.WebBrowserWindow.adBlockManager()\ |
|
231 .addSubscriptionFromUrl(url): |
|
232 return False |
|
233 ## |
|
234 ## if type_ == QWebPage.NavigationTypeFormResubmitted: |
|
235 ## res = E5MessageBox.yesNo( |
|
236 ## self.view(), |
|
237 ## self.tr("Resending POST request"), |
|
238 ## self.tr( |
|
239 ## """In order to display the site, the request along with""" |
|
240 ## """ all the data must be sent once again, which may lead""" |
|
241 ## """ to some unexpected behaviour of the site e.g. the""" |
|
242 ## """ same action might be performed once again. Do you""" |
|
243 ## """ want to continue anyway?"""), |
|
244 ## icon=E5MessageBox.Warning) |
|
245 ## if not res: |
|
246 ## return False |
|
247 |
|
248 return QWebEnginePage.acceptNavigationRequest(self, url, type_, |
|
249 isMainFrame) |
|
250 ## |
|
251 ## def populateNetworkRequest(self, request): |
|
252 ## """ |
|
253 ## Public method to add data to a network request. |
|
254 ## |
|
255 ## @param request reference to the network request object |
|
256 ## (QNetworkRequest) |
|
257 ## """ |
|
258 ## try: |
|
259 ## request.setAttribute(QNetworkRequest.User + 100, self) |
|
260 ## if self.__lastRequest.url() == request.url(): |
|
261 ## request.setAttribute(QNetworkRequest.User + 101, |
|
262 ## self.__lastRequestType) |
|
263 ## if self.__lastRequestType == \ |
|
264 ## QWebPage.NavigationTypeLinkClicked: |
|
265 ## request.setRawHeader(b"X-Eric6-UserLoadAction", |
|
266 ## QByteArray(b"1")) |
|
267 ## except TypeError: |
|
268 ## pass |
|
269 ## |
|
270 ## def pageAttributeId(self): |
|
271 ## """ |
|
272 ## Public method to get the attribute id of the page attribute. |
|
273 ## |
|
274 ## @return attribute id of the page attribute (integer) |
|
275 ## """ |
|
276 ## return QNetworkRequest.User + 100 |
|
277 ## |
|
278 ## def supportsExtension(self, extension): |
|
279 ## """ |
|
280 ## Public method to check the support for an extension. |
|
281 ## |
|
282 ## @param extension extension to test for (QWebPage.Extension) |
|
283 ## @return flag indicating the support of extension (boolean) |
|
284 ## """ |
|
285 ## try: |
|
286 ## if extension in [QWebPage.ErrorPageExtension, |
|
287 ## QWebPage.ChooseMultipleFilesExtension]: |
|
288 ## return True |
|
289 ## except AttributeError: |
|
290 ## pass |
|
291 ## |
|
292 ## return QWebPage.supportsExtension(self, extension) |
|
293 ## |
|
294 ## def extension(self, extension, option, output): |
|
295 ## """ |
|
296 ## Public method to implement a specific extension. |
|
297 ## |
|
298 ## @param extension extension to be executed (QWebPage.Extension) |
|
299 ## @param option provides input to the extension |
|
300 ## (QWebPage.ExtensionOption) |
|
301 ## @param output stores the output results (QWebPage.ExtensionReturn) |
|
302 ## @return flag indicating a successful call of the extension (boolean) |
|
303 ## """ |
|
304 ## if extension == QWebPage.ChooseMultipleFilesExtension: |
|
305 ## info = sip.cast(option, |
|
306 ## QWebPage.ChooseMultipleFilesExtensionOption) |
|
307 ## files = sip.cast(output, |
|
308 ## QWebPage.ChooseMultipleFilesExtensionReturn) |
|
309 ## if info is None or files is None: |
|
310 ## return super(HelpWebPage, self).extension( |
|
311 ## extension, option, output) |
|
312 ## |
|
313 ## suggestedFileName = "" |
|
314 ## if info.suggestedFileNames: |
|
315 ## suggestedFileName = info.suggestedFileNames[0] |
|
316 ## |
|
317 ## files.fileNames = E5FileDialog.getOpenFileNames( |
|
318 ## None, |
|
319 ## self.tr("Select files to upload..."), |
|
320 ## suggestedFileName) |
|
321 ## return True |
|
322 ## |
|
323 ## if extension == QWebPage.ErrorPageExtension: |
|
324 ## info = sip.cast(option, QWebPage.ErrorPageExtensionOption) |
|
325 ## |
|
326 ## errorPage = sip.cast(output, QWebPage.ErrorPageExtensionReturn) |
|
327 ## urlString = bytes(info.url.toEncoded()).decode() |
|
328 ## errorPage.baseUrl = info.url |
|
329 ## if info.domain == QWebPage.QtNetwork and \ |
|
330 ## info.error == QNetworkReply.ProtocolUnknownError: |
|
331 ## url = QUrl(info.url) |
|
332 ## res = E5MessageBox.yesNo( |
|
333 ## None, |
|
334 ## self.tr("Protocol Error"), |
|
335 ## self.tr("""Open external application for {0}-link?\n""" |
|
336 ## """URL: {1}""").format( |
|
337 ## url.scheme(), url.toString( |
|
338 ## QUrl.PrettyDecoded | QUrl.RemovePassword)), |
|
339 ## yesDefault=True) |
|
340 ## |
|
341 ## if res: |
|
342 ## QDesktopServices.openUrl(url) |
|
343 ## return True |
|
344 ## elif info.domain == QWebPage.QtNetwork and \ |
|
345 ## info.error == QNetworkReply.ContentAccessDenied and \ |
|
346 ## info.errorString.startswith("AdBlockRule:"): |
|
347 ## if info.frame != info.frame.page().mainFrame(): |
|
348 ## # content in <iframe> |
|
349 ## docElement = info.frame.page().mainFrame()\ |
|
350 ## .documentElement() |
|
351 ## for element in docElement.findAll("iframe"): |
|
352 ## src = element.attribute("src") |
|
353 ## if src in info.url.toString(): |
|
354 ## element.setAttribute("style", "display:none;") |
|
355 ## return False |
|
356 ## else: |
|
357 ## # the whole page is blocked |
|
358 ## rule = info.errorString.replace("AdBlockRule:", "") |
|
359 ## title = self.tr("Content blocked by AdBlock Plus") |
|
360 ## message = self.tr( |
|
361 ## "Blocked by rule: <i>{0}</i>").format(rule) |
|
362 ## |
|
363 ## htmlFile = QFile(":/html/adblockPage.html") |
|
364 ## htmlFile.open(QFile.ReadOnly) |
|
365 ## html = htmlFile.readAll() |
|
366 ## html = html.replace( |
|
367 ## "@FAVICON@", "qrc:icons/adBlockPlus16.png") |
|
368 ## html = html.replace( |
|
369 ## "@IMAGE@", "qrc:icons/adBlockPlus64.png") |
|
370 ## html = html.replace("@TITLE@", title.encode("utf8")) |
|
371 ## html = html.replace("@MESSAGE@", message.encode("utf8")) |
|
372 ## errorPage.content = html |
|
373 ## return True |
|
374 ## |
|
375 ## if info.domain == QWebPage.QtNetwork and \ |
|
376 ## info.error == QNetworkReply.OperationCanceledError and \ |
|
377 ## info.errorString == "eric6:No Error": |
|
378 ## return False |
|
379 ## |
|
380 ## if info.domain == QWebPage.WebKit and info.error == 203: |
|
381 ## # "Loading is handled by the media engine" |
|
382 ## return False |
|
383 ## |
|
384 ## title = self.tr("Error loading page: {0}").format(urlString) |
|
385 ## htmlFile = QFile(":/html/notFoundPage.html") |
|
386 ## htmlFile.open(QFile.ReadOnly) |
|
387 ## html = htmlFile.readAll() |
|
388 ## pixmap = qApp.style()\ |
|
389 ## .standardIcon(QStyle.SP_MessageBoxWarning).pixmap(48, 48) |
|
390 ## imageBuffer = QBuffer() |
|
391 ## imageBuffer.open(QIODevice.ReadWrite) |
|
392 ## if pixmap.save(imageBuffer, "PNG"): |
|
393 ## html = html.replace("@IMAGE@", imageBuffer.buffer().toBase64()) |
|
394 ## pixmap = qApp.style()\ |
|
395 ## .standardIcon(QStyle.SP_MessageBoxWarning).pixmap(16, 16) |
|
396 ## imageBuffer = QBuffer() |
|
397 ## imageBuffer.open(QIODevice.ReadWrite) |
|
398 ## if pixmap.save(imageBuffer, "PNG"): |
|
399 ## html = html.replace( |
|
400 ## "@FAVICON@", imageBuffer.buffer().toBase64()) |
|
401 ## html = html.replace("@TITLE@", title.encode("utf8")) |
|
402 ## html = html.replace("@H1@", info.errorString.encode("utf8")) |
|
403 ## html = html.replace( |
|
404 ## "@H2@", self.tr("When connecting to: {0}.") |
|
405 ## .format(urlString).encode("utf8")) |
|
406 ## html = html.replace( |
|
407 ## "@LI-1@", |
|
408 ## self.tr("Check the address for errors such as " |
|
409 ## "<b>ww</b>.example.org instead of " |
|
410 ## "<b>www</b>.example.org").encode("utf8")) |
|
411 ## html = html.replace( |
|
412 ## "@LI-2@", |
|
413 ## self.tr( |
|
414 ## "If the address is correct, try checking the network " |
|
415 ## "connection.").encode("utf8")) |
|
416 ## html = html.replace( |
|
417 ## "@LI-3@", |
|
418 ## self.tr( |
|
419 ## "If your computer or network is protected by a firewall " |
|
420 ## "or proxy, make sure that the browser is permitted to " |
|
421 ## "access the network.").encode("utf8")) |
|
422 ## html = html.replace( |
|
423 ## "@LI-4@", |
|
424 ## self.tr("If your cache policy is set to offline browsing," |
|
425 ## "only pages in the local cache are available.") |
|
426 ## .encode("utf8")) |
|
427 ## html = html.replace( |
|
428 ## "@BUTTON@", self.tr("Try Again").encode("utf8")) |
|
429 ## errorPage.content = html |
|
430 ## return True |
|
431 ## |
|
432 ## return QWebPage.extension(self, extension, option, output) |
|
433 |
|
434 def __loadStarted(self): |
|
435 """ |
|
436 Private method to handle the loadStarted signal. |
|
437 """ |
|
438 self.__adBlockedEntries = [] |
|
439 ## |
|
440 ## def addAdBlockRule(self, rule, url): |
|
441 ## """ |
|
442 ## Public slot to add an AdBlock rule to the page. |
|
443 ## |
|
444 ## @param rule AdBlock rule to add (AdBlockRule) |
|
445 ## @param url URL that matched the rule (QUrl) |
|
446 ## """ |
|
447 ## from .AdBlock.AdBlockPage import AdBlockedPageEntry |
|
448 ## entry = AdBlockedPageEntry(rule, url) |
|
449 ## if entry not in self.__adBlockedEntries: |
|
450 ## self.__adBlockedEntries.append(entry) |
|
451 ## |
|
452 ## def getAdBlockedPageEntries(self): |
|
453 ## """ |
|
454 ## Public method to get the list of AdBlock page entries. |
|
455 ## |
|
456 ## @return list of AdBlock page entries (list of AdBlockedPageEntry) |
|
457 ## """ |
|
458 ## return self.__adBlockedEntries |
|
459 |
|
460 # TODO: re-enable once User Agent Manager is done |
|
461 ## def userAgent(self, resolveEmpty=False): |
|
462 ## """ |
|
463 ## Public method to get the global user agent setting. |
|
464 ## |
|
465 ## @param resolveEmpty flag indicating to resolve an empty |
|
466 ## user agent (boolean) |
|
467 ## @return user agent string (string) |
|
468 ## """ |
|
469 ## agent = Preferences.getWebBrowser("UserAgent") |
|
470 ## if agent == "" and resolveEmpty: |
|
471 ## agent = self.userAgentForUrl(QUrl()) |
|
472 ## return agent |
|
473 ## |
|
474 ## def setUserAgent(self, agent): |
|
475 ## """ |
|
476 ## Public method to set the global user agent string. |
|
477 ## |
|
478 ## @param agent new current user agent string (string) |
|
479 ## """ |
|
480 ## Preferences.setHelp("UserAgent", agent) |
|
481 ## |
|
482 ## def userAgentForUrl(self, url): |
|
483 ## """ |
|
484 ## Public method to determine the user agent for the given URL. |
|
485 ## |
|
486 ## @param url URL to determine user agent for (QUrl) |
|
487 ## @return user agent string (string) |
|
488 ## """ |
|
489 ## import Helpviewer.HelpWindow |
|
490 ## agent = Helpviewer.HelpWindow.HelpWindow.userAgentsManager()\ |
|
491 ## .userAgentForUrl(url) |
|
492 ## if agent == "": |
|
493 ## # no agent string specified for the given host -> use global one |
|
494 ## agent = Preferences.getHelp("UserAgent") |
|
495 ## if agent == "": |
|
496 ## # no global agent string specified -> use default one |
|
497 ## agent = QWebPage.userAgentForUrl(self, url) |
|
498 ## return agent |
|
499 ## |
|
500 ## def __managerFinished(self, reply): |
|
501 ## """ |
|
502 ## Private slot to handle a finished reply. |
|
503 ## |
|
504 ## This slot is used to get SSL related information for a reply. |
|
505 ## |
|
506 ## @param reply reference to the finished reply (QNetworkReply) |
|
507 ## """ |
|
508 ## try: |
|
509 ## frame = reply.request().originatingObject() |
|
510 ## except AttributeError: |
|
511 ## frame = None |
|
512 ## |
|
513 ## mainFrameRequest = frame == self.mainFrame() |
|
514 ## |
|
515 ## if mainFrameRequest and \ |
|
516 ## self.__sslConfiguration is not None and \ |
|
517 ## reply.url() == self.mainFrame().url(): |
|
518 ## self.__sslConfiguration = None |
|
519 ## |
|
520 ## if reply.error() == QNetworkReply.NoError and \ |
|
521 ## mainFrameRequest and \ |
|
522 ## self.__sslConfiguration is None and \ |
|
523 ## reply.url().scheme().lower() == "https" and \ |
|
524 ## reply.url() == self.mainFrame().url(): |
|
525 ## self.__sslConfiguration = reply.sslConfiguration() |
|
526 ## self.__sslConfiguration.url = QUrl(reply.url()) |
|
527 ## |
|
528 ## if reply.error() == QNetworkReply.NoError and \ |
|
529 ## mainFrameRequest and \ |
|
530 ## reply.url() == self.mainFrame().url(): |
|
531 ## modified = reply.header(QNetworkRequest.LastModifiedHeader) |
|
532 ## if modified and modified.isValid(): |
|
533 ## import Helpviewer.HelpWindow |
|
534 ## manager = Helpviewer.HelpWindow.HelpWindow.bookmarksManager() |
|
535 ## from .Bookmarks.BookmarkNode import BookmarkNode |
|
536 ## for bookmark in manager.bookmarksForUrl(reply.url()): |
|
537 ## manager.setTimestamp(bookmark, BookmarkNode.TsModified, |
|
538 ## modified) |
|
539 |
|
540 ## def getSslCertificate(self): |
|
541 ## """ |
|
542 ## Public method to get a reference to the SSL certificate. |
|
543 ## |
|
544 ## @return amended SSL certificate (QSslCertificate) |
|
545 ## """ |
|
546 ## if self.__sslConfiguration is None: |
|
547 ## return None |
|
548 ## |
|
549 ## sslInfo = self.__sslConfiguration.peerCertificate() |
|
550 ## sslInfo.url = QUrl(self.__sslConfiguration.url) |
|
551 ## return sslInfo |
|
552 ## |
|
553 ## def getSslCertificateChain(self): |
|
554 ## """ |
|
555 ## Public method to get a reference to the SSL certificate chain. |
|
556 ## |
|
557 ## @return SSL certificate chain (list of QSslCertificate) |
|
558 ## """ |
|
559 ## if self.__sslConfiguration is None: |
|
560 ## return [] |
|
561 ## |
|
562 ## chain = self.__sslConfiguration.peerCertificateChain() |
|
563 ## return chain |
|
564 ## |
|
565 ## def getSslConfiguration(self): |
|
566 ## """ |
|
567 ## Public method to return a reference to the current SSL configuration. |
|
568 ## |
|
569 ## @return reference to the SSL configuration in use (QSslConfiguration) |
|
570 ## """ |
|
571 ## return self.__sslConfiguration |
|
572 ## |
|
573 ## def showSslInfo(self, pos): |
|
574 ## """ |
|
575 ## Public slot to show some SSL information for the loaded page. |
|
576 ## |
|
577 ## @param pos position to show the info at (QPoint) |
|
578 ## """ |
|
579 ## if SSL_AVAILABLE and self.__sslConfiguration is not None: |
|
580 ## from E5Network.E5SslInfoWidget import E5SslInfoWidget |
|
581 ## widget = E5SslInfoWidget( |
|
582 ## self.mainFrame().url(), self.__sslConfiguration, self.view()) |
|
583 ## widget.showAt(pos) |
|
584 ## else: |
|
585 ## E5MessageBox.warning( |
|
586 ## self.view(), |
|
587 ## self.tr("SSL Info"), |
|
588 ## self.tr("""This site does not contain SSL information.""")) |
|
589 ## |
|
590 ## def hasValidSslInfo(self): |
|
591 ## """ |
|
592 ## Public method to check, if the page has a valid SSL certificate. |
|
593 ## |
|
594 ## @return flag indicating a valid SSL certificate (boolean) |
|
595 ## """ |
|
596 ## if self.__sslConfiguration is None: |
|
597 ## return False |
|
598 ## |
|
599 ## certList = self.__sslConfiguration.peerCertificateChain() |
|
600 ## if not certList: |
|
601 ## return False |
|
602 ## |
|
603 ## certificateDict = Globals.toDict( |
|
604 ## Preferences.Prefs.settings.value("Ssl/CaCertificatesDict")) |
|
605 ## for server in certificateDict: |
|
606 ## localCAList = QSslCertificate.fromData(certificateDict[server]) |
|
607 ## for cert in certList: |
|
608 ## if cert in localCAList: |
|
609 ## return True |
|
610 ## |
|
611 ## if qVersion() >= "5.0.0": |
|
612 ## for cert in certList: |
|
613 ## if cert.isBlacklisted(): |
|
614 ## return False |
|
615 ## else: |
|
616 ## for cert in certList: |
|
617 ## if not cert.isValid(): |
|
618 ## return False |
|
619 ## |
|
620 ## return True |
|
621 |
|
622 ## @classmethod |
|
623 ## def webPluginFactory(cls): |
|
624 ## """ |
|
625 ## Class method to get a reference to the web plug-in factory |
|
626 ## instance. |
|
627 ## |
|
628 ## @return reference to the web plug-in factory instance (WebPluginFactory |
|
629 ## """ |
|
630 ## if cls._webPluginFactory is None: |
|
631 ## from .WebPlugins.WebPluginFactory import WebPluginFactory |
|
632 ## cls._webPluginFactory = WebPluginFactory() |
|
633 ## |
|
634 ## return cls._webPluginFactory |
|
635 ## |
|
636 ## def event(self, evt): |
|
637 ## """ |
|
638 ## Public method implementing the event handler. |
|
639 ## |
|
640 ## @param evt reference to the event (QEvent) |
|
641 ## @return flag indicating that the event was handled (boolean) |
|
642 ## """ |
|
643 ## if evt.type() == QEvent.Leave: |
|
644 ## # Fake a mouse move event just outside of the widget to trigger |
|
645 ## # the WebKit event handler's mouseMoved function. This implements |
|
646 ## # the interesting mouse-out behavior like invalidating scrollbars. |
|
647 ## fakeEvent = QMouseEvent(QEvent.MouseMove, QPoint(0, -1), |
|
648 ## Qt.NoButton, Qt.NoButton, Qt.NoModifier) |
|
649 ## return super(HelpWebPage, self).event(fakeEvent) |
|
650 ## |
|
651 ## return super(HelpWebPage, self).event(evt) |
|
652 ## |
|
653 ## def __saveFrameStateRequested(self, frame, itm): |
|
654 ## """ |
|
655 ## Private slot to save the page state (i.e. zoom level and scroll |
|
656 ## position). |
|
657 ## |
|
658 ## Note: Code is based on qutebrowser. |
|
659 ## |
|
660 ## @param frame frame to be saved |
|
661 ## @type QWebFrame |
|
662 ## @param itm web history item to be saved |
|
663 ## @type QWebHistoryItem |
|
664 ## """ |
|
665 ## try: |
|
666 ## if frame != self.mainFrame(): |
|
667 ## return |
|
668 ## except RuntimeError: |
|
669 ## # With Qt 5.2.1 (Ubuntu Trusty) we get this when closing a tab: |
|
670 ## # RuntimeError: wrapped C/C++ object of type BrowserPage has |
|
671 ## # been deleted |
|
672 ## # Since the information here isn't that important for closing web |
|
673 ## # views anyways, we ignore this error. |
|
674 ## return |
|
675 ## data = { |
|
676 ## 'zoom': frame.zoomFactor(), |
|
677 ## 'scrollPos': frame.scrollPosition(), |
|
678 ## } |
|
679 ## itm.setUserData(data) |
|
680 ## |
|
681 ## def __restoreFrameStateRequested(self, frame): |
|
682 ## """ |
|
683 ## Private slot to restore scroll position and zoom level from |
|
684 ## history. |
|
685 ## |
|
686 ## Note: Code is based on qutebrowser. |
|
687 ## |
|
688 ## @param frame frame to be restored |
|
689 ## @type QWebFrame |
|
690 ## """ |
|
691 ## if frame != self.mainFrame(): |
|
692 ## return |
|
693 ## |
|
694 ## data = self.history().currentItem().userData() |
|
695 ## if data is None: |
|
696 ## return |
|
697 ## |
|
698 ## if 'zoom' in data: |
|
699 ## frame.page().view().setZoomValue(int(data['zoom'] * 100), |
|
700 ## saveValue=False) |
|
701 ## |
|
702 ## if 'scrollPos' in data and frame.scrollPosition() == QPoint(0, 0): |
|
703 ## frame.setScrollPosition(data['scrollPos']) |
|
704 |
|
705 def __featurePermissionRequested(self, url, feature): |
|
706 """ |
|
707 Private slot handling a feature permission request. |
|
708 |
|
709 @param url url requesting the feature |
|
710 @type QUrl |
|
711 @param feature requested feature |
|
712 @type QWebEnginePage.Feature |
|
713 """ |
|
714 manager = WebBrowser.WebBrowserWindow.WebBrowserWindow\ |
|
715 .featurePermissionManager() |
|
716 manager.requestFeaturePermission(self, frame, feature) |