|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2008 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 |
|
7 """ |
|
8 Module implementing the helpbrowser using QWebView. |
|
9 """ |
|
10 |
|
11 from PyQt6.QtCore import ( |
|
12 pyqtSlot, pyqtSignal, QUrl, QUrlQuery, QTimer, QEventLoop, QPoint |
|
13 ) |
|
14 from PyQt6.QtGui import QDesktopServices |
|
15 from PyQt6.QtWebEngineCore import ( |
|
16 QWebEnginePage, QWebEngineSettings, QWebEngineScript |
|
17 ) |
|
18 from PyQt6.QtWebChannel import QWebChannel |
|
19 |
|
20 try: |
|
21 from PyQt6.QtNetwork import QSslConfiguration, QSslCertificate |
|
22 SSL_AVAILABLE = True |
|
23 except ImportError: |
|
24 SSL_AVAILABLE = False |
|
25 |
|
26 from EricWidgets import EricMessageBox |
|
27 |
|
28 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
29 |
|
30 from .JavaScript.ExternalJsObject import ExternalJsObject |
|
31 |
|
32 from .Tools.WebHitTestResult import WebHitTestResult |
|
33 from .Tools import Scripts |
|
34 |
|
35 import Preferences |
|
36 import Globals |
|
37 |
|
38 |
|
39 class WebBrowserPage(QWebEnginePage): |
|
40 """ |
|
41 Class implementing an enhanced web page. |
|
42 |
|
43 @signal safeBrowsingAbort() emitted to indicate an abort due to a safe |
|
44 browsing event |
|
45 @signal safeBrowsingBad(threatType, threatMessages) emitted to indicate a |
|
46 malicious web site as determined by safe browsing |
|
47 @signal printPageRequested() emitted to indicate a print request of the |
|
48 shown web page |
|
49 @signal navigationRequestAccepted(url, navigation type, main frame) emitted |
|
50 to signal an accepted navigation request |
|
51 @signal sslConfigurationChanged() emitted to indicate a change of the |
|
52 stored SSL configuration data |
|
53 """ |
|
54 SafeJsWorld = QWebEngineScript.ScriptWorldId.ApplicationWorld |
|
55 UnsafeJsWorld = QWebEngineScript.ScriptWorldId.MainWorld |
|
56 |
|
57 safeBrowsingAbort = pyqtSignal() |
|
58 safeBrowsingBad = pyqtSignal(str, str) |
|
59 |
|
60 printPageRequested = pyqtSignal() |
|
61 navigationRequestAccepted = pyqtSignal(QUrl, QWebEnginePage.NavigationType, |
|
62 bool) |
|
63 |
|
64 sslConfigurationChanged = pyqtSignal() |
|
65 |
|
66 def __init__(self, view, parent=None): |
|
67 """ |
|
68 Constructor |
|
69 |
|
70 @param view reference to the WebBrowserView associated with the page |
|
71 @type WebBrowserView |
|
72 @param parent reference to the parent widget (defaults to None) |
|
73 @type QWidget (optional) |
|
74 """ |
|
75 super().__init__( |
|
76 WebBrowserWindow.webProfile(), parent) |
|
77 |
|
78 self.__printer = None |
|
79 self.__badSite = False |
|
80 self.__registerProtocolHandlerRequest = None |
|
81 |
|
82 self.__view = view |
|
83 |
|
84 self.featurePermissionRequested.connect( |
|
85 self.__featurePermissionRequested) |
|
86 self.authenticationRequired.connect( |
|
87 lambda url, auth: WebBrowserWindow.networkManager().authentication( |
|
88 url, auth, self)) |
|
89 self.proxyAuthenticationRequired.connect( |
|
90 WebBrowserWindow.networkManager().proxyAuthentication) |
|
91 self.fullScreenRequested.connect(self.__fullScreenRequested) |
|
92 self.urlChanged.connect(self.__urlChanged) |
|
93 self.contentsSizeChanged.connect(self.__contentsSizeChanged) |
|
94 self.registerProtocolHandlerRequested.connect( |
|
95 self.__registerProtocolHandlerRequested) |
|
96 |
|
97 self.__sslConfiguration = None |
|
98 |
|
99 # Workaround for changing webchannel world inside |
|
100 # acceptNavigationRequest not working |
|
101 self.__channelUrl = QUrl() |
|
102 self.__channelWorldId = -1 |
|
103 self.__setupChannelTimer = QTimer(self) |
|
104 self.__setupChannelTimer.setSingleShot(True) |
|
105 self.__setupChannelTimer.setInterval(100) |
|
106 self.__setupChannelTimer.timeout.connect(self.__setupChannelTimeout) |
|
107 |
|
108 def view(self): |
|
109 """ |
|
110 Public method to get a reference to the WebBrowserView associated with |
|
111 the page. |
|
112 |
|
113 @return reference to the WebBrowserView associated with the page |
|
114 r@type WebBrowserView |
|
115 """ |
|
116 return self.__view |
|
117 |
|
118 @pyqtSlot() |
|
119 def __setupChannelTimeout(self): |
|
120 """ |
|
121 Private slot to initiate the setup of the web channel. |
|
122 """ |
|
123 self.__setupWebChannelForUrl(self.__channelUrl) |
|
124 |
|
125 def acceptNavigationRequest(self, url, type_, isMainFrame): |
|
126 """ |
|
127 Public method to determine, if a request may be accepted. |
|
128 |
|
129 @param url URL to navigate to |
|
130 @type QUrl |
|
131 @param type_ type of the navigation request |
|
132 @type QWebEnginePage.NavigationType |
|
133 @param isMainFrame flag indicating, that the request originated from |
|
134 the main frame |
|
135 @type bool |
|
136 @return flag indicating acceptance |
|
137 @rtype bool |
|
138 """ |
|
139 scheme = url.scheme() |
|
140 if scheme == "mailto": |
|
141 QDesktopServices.openUrl(url) |
|
142 return False |
|
143 |
|
144 # AdBlock |
|
145 if ( |
|
146 url.scheme() == "abp" and |
|
147 WebBrowserWindow.adBlockManager().addSubscriptionFromUrl(url) |
|
148 ): |
|
149 return False |
|
150 |
|
151 # GreaseMonkey |
|
152 navigationType = type_ in ( |
|
153 QWebEnginePage.NavigationType.NavigationTypeLinkClicked, |
|
154 QWebEnginePage.NavigationType.NavigationTypeRedirect |
|
155 ) |
|
156 if navigationType and url.toString().endswith(".user.js"): |
|
157 WebBrowserWindow.greaseMonkeyManager().downloadScript(url) |
|
158 return False |
|
159 |
|
160 if url.scheme() == "eric": |
|
161 if url.path() == "AddSearchProvider": |
|
162 query = QUrlQuery(url) |
|
163 self.__view.mainWindow().openSearchManager().addEngine( |
|
164 QUrl(query.queryItemValue("url"))) |
|
165 return False |
|
166 elif url.path() == "PrintPage": |
|
167 self.printPageRequested.emit() |
|
168 return False |
|
169 |
|
170 # Safe Browsing |
|
171 self.__badSite = False |
|
172 from WebBrowser.SafeBrowsing.SafeBrowsingManager import ( |
|
173 SafeBrowsingManager |
|
174 ) |
|
175 if ( |
|
176 SafeBrowsingManager.isEnabled() and |
|
177 url.scheme() not in SafeBrowsingManager.getIgnoreSchemes() |
|
178 ): |
|
179 threatLists = ( |
|
180 WebBrowserWindow.safeBrowsingManager().lookupUrl(url)[0] |
|
181 ) |
|
182 if threatLists: |
|
183 threatMessages = ( |
|
184 WebBrowserWindow.safeBrowsingManager() |
|
185 .getThreatMessages(threatLists) |
|
186 ) |
|
187 res = EricMessageBox.warning( |
|
188 WebBrowserWindow.getWindow(), |
|
189 self.tr("Suspicuous URL detected"), |
|
190 self.tr("<p>The URL <b>{0}</b> was found in the Safe" |
|
191 " Browsing database.</p>{1}").format( |
|
192 url.toString(), "".join(threatMessages)), |
|
193 EricMessageBox.Abort | EricMessageBox.Ignore, |
|
194 EricMessageBox.Abort) |
|
195 if res == EricMessageBox.Abort: |
|
196 self.safeBrowsingAbort.emit() |
|
197 return False |
|
198 |
|
199 self.__badSite = True |
|
200 threatType = ( |
|
201 WebBrowserWindow.safeBrowsingManager() |
|
202 .getThreatType(threatLists[0]) |
|
203 ) |
|
204 self.safeBrowsingBad.emit(threatType, "".join(threatMessages)) |
|
205 |
|
206 result = QWebEnginePage.acceptNavigationRequest( |
|
207 self, url, type_, isMainFrame) |
|
208 |
|
209 if result: |
|
210 if isMainFrame: |
|
211 isWeb = url.scheme() in ("http", "https", "ftp", "ftps", |
|
212 "file") |
|
213 globalJsEnabled = WebBrowserWindow.webSettings().testAttribute( |
|
214 QWebEngineSettings.WebAttribute.JavascriptEnabled) |
|
215 if isWeb: |
|
216 enable = globalJsEnabled |
|
217 else: |
|
218 enable = True |
|
219 self.settings().setAttribute( |
|
220 QWebEngineSettings.WebAttribute.JavascriptEnabled, enable) |
|
221 |
|
222 self.__channelUrl = url |
|
223 self.__setupChannelTimer.start() |
|
224 self.navigationRequestAccepted.emit(url, type_, isMainFrame) |
|
225 |
|
226 return result |
|
227 |
|
228 @pyqtSlot(QUrl) |
|
229 def __urlChanged(self, url): |
|
230 """ |
|
231 Private slot to handle changes of the URL. |
|
232 |
|
233 @param url new URL |
|
234 @type QUrl |
|
235 """ |
|
236 if ( |
|
237 not url.isEmpty() and |
|
238 url.scheme() == "eric" and |
|
239 not self.isJavaScriptEnabled() |
|
240 ): |
|
241 self.settings().setAttribute( |
|
242 QWebEngineSettings.WebAttribute.JavascriptEnabled, True) |
|
243 self.triggerAction(QWebEnginePage.WebAction.Reload) |
|
244 |
|
245 @classmethod |
|
246 def userAgent(cls, resolveEmpty=False): |
|
247 """ |
|
248 Class method to get the global user agent setting. |
|
249 |
|
250 @param resolveEmpty flag indicating to resolve an empty |
|
251 user agent (boolean) |
|
252 @return user agent string (string) |
|
253 """ |
|
254 agent = Preferences.getWebBrowser("UserAgent") |
|
255 if agent == "" and resolveEmpty: |
|
256 agent = cls.userAgentForUrl(QUrl()) |
|
257 return agent |
|
258 |
|
259 @classmethod |
|
260 def setUserAgent(cls, agent): |
|
261 """ |
|
262 Class method to set the global user agent string. |
|
263 |
|
264 @param agent new current user agent string (string) |
|
265 """ |
|
266 Preferences.setWebBrowser("UserAgent", agent) |
|
267 |
|
268 @classmethod |
|
269 def userAgentForUrl(cls, url): |
|
270 """ |
|
271 Class method to determine the user agent for the given URL. |
|
272 |
|
273 @param url URL to determine user agent for (QUrl) |
|
274 @return user agent string (string) |
|
275 """ |
|
276 agent = WebBrowserWindow.userAgentsManager().userAgentForUrl(url) |
|
277 if agent == "": |
|
278 # no agent string specified for the given host -> use global one |
|
279 agent = Preferences.getWebBrowser("UserAgent") |
|
280 if agent == "": |
|
281 # no global agent string specified -> use default one |
|
282 agent = WebBrowserWindow.webProfile().httpUserAgent() |
|
283 return agent |
|
284 |
|
285 def __featurePermissionRequested(self, url, feature): |
|
286 """ |
|
287 Private slot handling a feature permission request. |
|
288 |
|
289 @param url url requesting the feature |
|
290 @type QUrl |
|
291 @param feature requested feature |
|
292 @type QWebEnginePage.Feature |
|
293 """ |
|
294 manager = WebBrowserWindow.featurePermissionManager() |
|
295 manager.requestFeaturePermission(self, url, feature) |
|
296 |
|
297 def execJavaScript(self, script, |
|
298 worldId=QWebEngineScript.ScriptWorldId.MainWorld, |
|
299 timeout=500): |
|
300 """ |
|
301 Public method to execute a JavaScript function synchroneously. |
|
302 |
|
303 @param script JavaScript script source to be executed |
|
304 @type str |
|
305 @param worldId ID to run the script under |
|
306 @type QWebEngineScript.ScriptWorldId |
|
307 @param timeout max. time the script is given to execute |
|
308 @type int |
|
309 @return result of the script |
|
310 @rtype depending upon script result |
|
311 """ |
|
312 loop = QEventLoop() |
|
313 resultDict = {"res": None} |
|
314 QTimer.singleShot(timeout, loop.quit) |
|
315 |
|
316 def resultCallback(res, resDict=resultDict): |
|
317 if loop and loop.isRunning(): |
|
318 resDict["res"] = res |
|
319 loop.quit() |
|
320 |
|
321 self.runJavaScript(script, worldId, resultCallback) |
|
322 |
|
323 loop.exec() |
|
324 return resultDict["res"] |
|
325 |
|
326 def runJavaScript(self, script, worldId=-1, callback=None): |
|
327 """ |
|
328 Public method to run a script in the context of the page. |
|
329 |
|
330 @param script JavaScript script source to be executed |
|
331 @type str |
|
332 @param worldId ID to run the script under |
|
333 @type int |
|
334 @param callback callback function to be executed when the script has |
|
335 ended |
|
336 @type function |
|
337 """ |
|
338 if worldId > -1: |
|
339 if callback is None: |
|
340 QWebEnginePage.runJavaScript(self, script, worldId) |
|
341 else: |
|
342 QWebEnginePage.runJavaScript(self, script, worldId, callback) |
|
343 else: |
|
344 if callback is None: |
|
345 QWebEnginePage.runJavaScript(self, script) |
|
346 else: |
|
347 QWebEnginePage.runJavaScript(self, script, callback) |
|
348 |
|
349 def isJavaScriptEnabled(self): |
|
350 """ |
|
351 Public method to test, if JavaScript is enabled. |
|
352 |
|
353 @return flag indicating the state of the JavaScript support |
|
354 @rtype bool |
|
355 """ |
|
356 return self.settings().testAttribute( |
|
357 QWebEngineSettings.WebAttribute.JavascriptEnabled) |
|
358 |
|
359 def scroll(self, x, y): |
|
360 """ |
|
361 Public method to scroll by the given amount of pixels. |
|
362 |
|
363 @param x horizontal scroll value |
|
364 @type int |
|
365 @param y vertical scroll value |
|
366 @type int |
|
367 """ |
|
368 self.runJavaScript( |
|
369 "window.scrollTo(window.scrollX + {0}, window.scrollY + {1})" |
|
370 .format(x, y), |
|
371 WebBrowserPage.SafeJsWorld |
|
372 ) |
|
373 |
|
374 def scrollTo(self, pos): |
|
375 """ |
|
376 Public method to scroll to the given position. |
|
377 |
|
378 @param pos position to scroll to |
|
379 @type QPointF |
|
380 """ |
|
381 self.runJavaScript( |
|
382 "window.scrollTo({0}, {1});".format(pos.x(), pos.y()), |
|
383 WebBrowserPage.SafeJsWorld |
|
384 ) |
|
385 |
|
386 def mapToViewport(self, pos): |
|
387 """ |
|
388 Public method to map a position to the viewport. |
|
389 |
|
390 @param pos position to be mapped |
|
391 @type QPoint |
|
392 @return viewport position |
|
393 @rtype QPoint |
|
394 """ |
|
395 return QPoint(int(pos.x() // self.zoomFactor()), |
|
396 int(pos.y() // self.zoomFactor())) |
|
397 |
|
398 def hitTestContent(self, pos): |
|
399 """ |
|
400 Public method to test the content at a specified position. |
|
401 |
|
402 @param pos position to execute the test at |
|
403 @type QPoint |
|
404 @return test result object |
|
405 @rtype WebHitTestResult |
|
406 """ |
|
407 return WebHitTestResult(self, pos) |
|
408 |
|
409 def __setupWebChannelForUrl(self, url): |
|
410 """ |
|
411 Private method to setup a web channel to our external object. |
|
412 |
|
413 @param url URL for which to setup the web channel |
|
414 @type QUrl |
|
415 """ |
|
416 channel = self.webChannel() |
|
417 if channel is None: |
|
418 channel = QWebChannel(self) |
|
419 ExternalJsObject.setupWebChannel(channel, self) |
|
420 |
|
421 worldId = -1 |
|
422 worldId = ( |
|
423 self.UnsafeJsWorld |
|
424 if url.scheme() in ("eric", "qthelp") else |
|
425 self.SafeJsWorld |
|
426 ) |
|
427 if worldId != self.__channelWorldId: |
|
428 self.__channelWorldId = worldId |
|
429 self.setWebChannel(channel, self.__channelWorldId) |
|
430 |
|
431 def certificateError(self, error): |
|
432 """ |
|
433 Public method to handle SSL certificate errors. |
|
434 |
|
435 @param error object containing the certificate error information |
|
436 @type QWebEngineCertificateError |
|
437 @return flag indicating to ignore this error |
|
438 @rtype bool |
|
439 """ |
|
440 return WebBrowserWindow.networkManager().certificateError( |
|
441 error, self.__view) |
|
442 |
|
443 def __fullScreenRequested(self, request): |
|
444 """ |
|
445 Private slot handling a full screen request. |
|
446 |
|
447 @param request reference to the full screen request |
|
448 @type QWebEngineFullScreenRequest |
|
449 """ |
|
450 self.__view.requestFullScreen(request.toggleOn()) |
|
451 |
|
452 accepted = request.toggleOn() == self.__view.isFullScreen() |
|
453 |
|
454 if accepted: |
|
455 request.accept() |
|
456 else: |
|
457 request.reject() |
|
458 |
|
459 def execPrintPage(self, printer, timeout=1000): |
|
460 """ |
|
461 Public method to execute a synchronous print. |
|
462 |
|
463 @param printer reference to the printer object |
|
464 @type QPrinter |
|
465 @param timeout timeout value in milliseconds |
|
466 @type int |
|
467 @return flag indicating a successful print job |
|
468 @rtype bool |
|
469 """ |
|
470 loop = QEventLoop() |
|
471 resultDict = {"res": None} |
|
472 QTimer.singleShot(timeout, loop.quit) |
|
473 |
|
474 def printCallback(res, resDict=resultDict): |
|
475 if loop and loop.isRunning(): |
|
476 resDict["res"] = res |
|
477 loop.quit() |
|
478 |
|
479 self.print(printer, printCallback) |
|
480 |
|
481 loop.exec() |
|
482 return resultDict["res"] |
|
483 |
|
484 def __contentsSizeChanged(self, size): |
|
485 """ |
|
486 Private slot to work around QWebEnginePage not scrolling to anchors |
|
487 when opened in a background tab. |
|
488 |
|
489 @param size changed contents size (unused) |
|
490 @type QSize |
|
491 """ |
|
492 fragment = self.url().fragment() |
|
493 self.runJavaScript(Scripts.scrollToAnchor(fragment)) |
|
494 |
|
495 ############################################## |
|
496 ## Methods below deal with JavaScript messages |
|
497 ############################################## |
|
498 |
|
499 def javaScriptConsoleMessage(self, level, message, lineNumber, sourceId): |
|
500 """ |
|
501 Public method to show a console message. |
|
502 |
|
503 @param level severity |
|
504 @type QWebEnginePage.JavaScriptConsoleMessageLevel |
|
505 @param message message to be shown |
|
506 @type str |
|
507 @param lineNumber line number of an error |
|
508 @type int |
|
509 @param sourceId source URL causing the error |
|
510 @type str |
|
511 """ |
|
512 self.__view.mainWindow().javascriptConsole().javaScriptConsoleMessage( |
|
513 level, message, lineNumber, sourceId) |
|
514 |
|
515 ########################################################################### |
|
516 ## Methods below implement safe browsing related functions |
|
517 ########################################################################### |
|
518 |
|
519 def getSafeBrowsingStatus(self): |
|
520 """ |
|
521 Public method to get the safe browsing status of the current page. |
|
522 |
|
523 @return flag indicating a safe site |
|
524 @rtype bool |
|
525 """ |
|
526 return not self.__badSite |
|
527 |
|
528 ############################################################# |
|
529 ## Methods below implement protocol handler related functions |
|
530 ############################################################# |
|
531 |
|
532 @pyqtSlot("QWebEngineRegisterProtocolHandlerRequest") |
|
533 def __registerProtocolHandlerRequested(self, request): |
|
534 """ |
|
535 Private slot to handle the registration of a custom protocol |
|
536 handler. |
|
537 |
|
538 @param request reference to the registration request |
|
539 @type QWebEngineRegisterProtocolHandlerRequest |
|
540 """ |
|
541 from PyQt6.QtWebEngineCore import ( |
|
542 QWebEngineRegisterProtocolHandlerRequest |
|
543 ) |
|
544 |
|
545 if self.__registerProtocolHandlerRequest: |
|
546 del self.__registerProtocolHandlerRequest |
|
547 self.__registerProtocolHandlerRequest = None |
|
548 self.__registerProtocolHandlerRequest = ( |
|
549 QWebEngineRegisterProtocolHandlerRequest(request) |
|
550 ) |
|
551 |
|
552 def registerProtocolHandlerRequestUrl(self): |
|
553 """ |
|
554 Public method to get the registered protocol handler request URL. |
|
555 |
|
556 @return registered protocol handler request URL |
|
557 @rtype QUrl |
|
558 """ |
|
559 if ( |
|
560 self.__registerProtocolHandlerRequest and |
|
561 (self.url().host() == |
|
562 self.__registerProtocolHandlerRequest.origin().host()) |
|
563 ): |
|
564 return self.__registerProtocolHandlerRequest.origin() |
|
565 else: |
|
566 return QUrl() |
|
567 |
|
568 def registerProtocolHandlerRequestScheme(self): |
|
569 """ |
|
570 Public method to get the registered protocol handler request scheme. |
|
571 |
|
572 @return registered protocol handler request scheme |
|
573 @rtype str |
|
574 """ |
|
575 if ( |
|
576 self.__registerProtocolHandlerRequest and |
|
577 (self.url().host() == |
|
578 self.__registerProtocolHandlerRequest.origin().host()) |
|
579 ): |
|
580 return self.__registerProtocolHandlerRequest.scheme() |
|
581 else: |
|
582 return "" |
|
583 |
|
584 ############################################################# |
|
585 ## SSL configuration handling below |
|
586 ############################################################# |
|
587 |
|
588 def setSslConfiguration(self, sslConfiguration): |
|
589 """ |
|
590 Public slot to set the SSL configuration data of the page. |
|
591 |
|
592 @param sslConfiguration SSL configuration to be set |
|
593 @type QSslConfiguration |
|
594 """ |
|
595 self.__sslConfiguration = QSslConfiguration(sslConfiguration) |
|
596 self.__sslConfiguration.url = self.url() |
|
597 self.sslConfigurationChanged.emit() |
|
598 |
|
599 def getSslConfiguration(self): |
|
600 """ |
|
601 Public method to return a reference to the current SSL configuration. |
|
602 |
|
603 @return reference to the SSL configuration in use |
|
604 @rtype QSslConfiguration |
|
605 """ |
|
606 return self.__sslConfiguration |
|
607 |
|
608 def clearSslConfiguration(self): |
|
609 """ |
|
610 Public slot to clear the stored SSL configuration data. |
|
611 """ |
|
612 self.__sslConfiguration = None |
|
613 self.sslConfigurationChanged.emit() |
|
614 |
|
615 def getSslCertificate(self): |
|
616 """ |
|
617 Public method to get a reference to the SSL certificate. |
|
618 |
|
619 @return amended SSL certificate |
|
620 @rtype QSslCertificate |
|
621 """ |
|
622 if self.__sslConfiguration is None: |
|
623 return None |
|
624 |
|
625 sslCertificate = self.__sslConfiguration.peerCertificate() |
|
626 sslCertificate.url = QUrl(self.__sslConfiguration.url) |
|
627 return sslCertificate |
|
628 |
|
629 def getSslCertificateChain(self): |
|
630 """ |
|
631 Public method to get a reference to the SSL certificate chain. |
|
632 |
|
633 @return SSL certificate chain |
|
634 @rtype list of QSslCertificate |
|
635 """ |
|
636 if self.__sslConfiguration is None: |
|
637 return [] |
|
638 |
|
639 chain = self.__sslConfiguration.peerCertificateChain() |
|
640 return chain |
|
641 |
|
642 def showSslInfo(self, pos): |
|
643 """ |
|
644 Public slot to show some SSL information for the loaded page. |
|
645 |
|
646 @param pos position to show the info at |
|
647 @type QPoint |
|
648 """ |
|
649 if SSL_AVAILABLE and self.__sslConfiguration is not None: |
|
650 from EricNetwork.EricSslInfoWidget import EricSslInfoWidget |
|
651 widget = EricSslInfoWidget(self.url(), self.__sslConfiguration, |
|
652 self.__view) |
|
653 widget.showAt(pos) |
|
654 else: |
|
655 EricMessageBox.warning( |
|
656 self.__view, |
|
657 self.tr("SSL Info"), |
|
658 self.tr("""This site does not contain SSL information.""")) |
|
659 |
|
660 def hasValidSslInfo(self): |
|
661 """ |
|
662 Public method to check, if the page has a valid SSL certificate. |
|
663 |
|
664 @return flag indicating a valid SSL certificate |
|
665 @rtype bool |
|
666 """ |
|
667 if self.__sslConfiguration is None: |
|
668 return False |
|
669 |
|
670 certList = self.__sslConfiguration.peerCertificateChain() |
|
671 if not certList: |
|
672 return False |
|
673 |
|
674 certificateDict = Globals.toDict( |
|
675 Preferences.getSettings().value("Ssl/CaCertificatesDict")) |
|
676 for server in certificateDict: |
|
677 localCAList = QSslCertificate.fromData(certificateDict[server]) |
|
678 if any(cert in localCAList for cert in certList): |
|
679 return True |
|
680 |
|
681 return all(not cert.isBlacklisted() for cert in certList) |