eric6/Helpviewer/WebPlugins/ClickToFlash/ClickToFlash.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2012 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the Flash blocker.
8 """
9
10
11 from __future__ import unicode_literals
12
13 from PyQt5.QtCore import pyqtSlot, QUrl, Qt, QByteArray, QTimer
14 from PyQt5.QtGui import QCursor
15 from PyQt5.QtWidgets import QWidget, QMenu, QDialog, QLabel, QFormLayout
16 from PyQt5.QtNetwork import QNetworkRequest
17 from PyQt5.QtWebKit import QWebElement, QWebElementCollection
18 from PyQt5.QtWebKitWidgets import QWebHitTestResult, QWebView
19
20 from .Ui_ClickToFlash import Ui_ClickToFlash
21
22 import UI.PixmapCache
23
24
25 class ClickToFlash(QWidget, Ui_ClickToFlash):
26 """
27 Class implementing the Flash blocker.
28 """
29 _acceptedUrl = QUrl()
30 _acceptedArgNames = []
31 _acceptedArgValues = []
32
33 def __init__(self, plugin, mimeType, url, argumentNames, argumentValues,
34 parent=None):
35 """
36 Constructor
37
38 @param plugin reference to the plug-in (ClickToFlashPlugin)
39 @param mimeType MIME type for the plug-in (string)
40 @param url requested URL (QUrl)
41 @param argumentNames list of argument names (list of strings)
42 @param argumentValues list of argument values (list of strings)
43 @param parent reference to the parent widget (QWidget)
44 """
45 super(ClickToFlash, self).__init__(parent)
46
47 # Check AdBlock first
48 import Helpviewer.HelpWindow
49 manager = Helpviewer.HelpWindow.HelpWindow.adBlockManager()
50 if manager.isEnabled():
51 urlString = bytes(url.toEncoded()).decode()
52 urlDomain = url.host()
53 for subscription in manager.subscriptions():
54 blockedRule = subscription.match(
55 QNetworkRequest(url), urlDomain, urlString)
56 if blockedRule:
57 QTimer.singleShot(200, self.__hideAdBlocked)
58 return
59
60 self.setupUi(self)
61
62 self.__swapping = False
63 self.__element = QWebElement()
64
65 self.__plugin = plugin
66 self.__url = QUrl(url)
67 self.__argumentNames = argumentNames[:]
68 self.__argumentValues = argumentValues[:]
69 self.__mimeType = mimeType
70
71 self.setContextMenuPolicy(Qt.CustomContextMenu)
72 self.customContextMenuRequested.connect(self.__showContextMenu)
73 self.setToolTip(self.__url.toString())
74
75 iconName = plugin.getIconName(mimeType)
76 if iconName:
77 self.loadFlashButton.setIcon(UI.PixmapCache.getIcon(iconName))
78 else:
79 self.loadFlashButton.setText(self.tr("Load"))
80
81 @pyqtSlot()
82 def on_loadFlashButton_clicked(self):
83 """
84 Private slot handling the flash activation.
85 """
86 self.__load()
87
88 def __showContextMenu(self):
89 """
90 Private slot to show the context menu.
91 """
92 menu = QMenu()
93 act = menu.addAction(self.tr("Object blocked by ClickToFlash"))
94 font = act.font()
95 font.setBold(True)
96 act.setFont(font)
97 menu.addAction(
98 self.tr("Show information about object"), self.__showInfo)
99 menu.addSeparator()
100 menu.addAction(self.tr("Load"), self.__load)
101 menu.addAction(self.tr("Delete object"), self.__hideAdBlocked)
102 menu.addSeparator()
103 host = self.__url.host()
104 add = menu.addAction(
105 self.tr("Add '{0}' to Whitelist").format(host),
106 self.__addToWhitelist)
107 remove = menu.addAction(
108 self.tr("Remove '{0}' from Whitelist").format(host),
109 self.__removeFromWhitelist)
110 onWhitelist = self.__plugin.onWhitelist(host)
111 add.setEnabled(not onWhitelist)
112 remove.setEnabled(onWhitelist)
113 menu.addSeparator()
114 menu.addAction(self.tr("Configure Whitelist"), self.__configure)
115 menu.actions()[0].setEnabled(False)
116
117 menu.exec_(QCursor.pos())
118
119 def swapping(self):
120 """
121 Public method to check, if the plug-in is swapping.
122
123 @return flag indicating the swapping status (boolean)
124 """
125 return self.__swapping
126
127 def __configure(self):
128 """
129 Private slot to configure the whitelist.
130 """
131 self.__plugin.configure()
132
133 def __addToWhitelist(self):
134 """
135 Private slot to add the host to the whitelist.
136 """
137 self.__plugin.addToWhitelist(self.__url.host())
138
139 def __removeFromWhitelist(self):
140 """
141 Private slot to remove the host from the whitelist.
142 """
143 self.__plugin.removeFromWhitelist(self.__url.host())
144
145 def __load(self, allPlayers=False):
146 """
147 Private slot to load the flash content.
148
149 @param allPlayers flag indicating to load all flash players (boolean)
150 """
151 self.__findElement()
152 if not self.__element.isNull():
153 substitute = self.__element.clone()
154 substitute.setAttribute("type", self.__mimeType)
155 self.__element.replace(substitute)
156
157 ClickToFlash._acceptedUrl = self.__url
158 ClickToFlash._acceptedArgNames = self.__argumentNames
159 ClickToFlash._acceptedArgValues = self.__argumentValues
160
161 def __findElement(self):
162 """
163 Private method to find the element belonging to this ClickToFlash
164 instance.
165 """
166 parent = self.parentWidget()
167 view = None
168 while parent is not None:
169 if isinstance(parent, QWebView):
170 view = parent
171 break
172 parent = parent.parentWidget()
173 if view is None:
174 return
175
176 objectPos = view.mapFromGlobal(self.loadFlashButton.mapToGlobal(
177 self.loadFlashButton.pos()))
178 objectFrame = view.page().frameAt(objectPos)
179 hitResult = QWebHitTestResult()
180 hitElement = QWebElement()
181
182 if objectFrame is not None:
183 hitResult = objectFrame.hitTestContent(objectPos)
184 hitElement = hitResult.element()
185
186 if not hitElement.isNull() and \
187 hitElement.tagName().lower() in ["embed", "object"]:
188 self.__element = hitElement
189 return
190
191 # hit test failed, trying to find element by src
192 # attribute in elements of all frames on page (although less accurate
193 frames = []
194 frames.append(view.page().mainFrame())
195 while frames:
196 frame = frames.pop(0)
197 if not frame:
198 continue
199 docElement = frame.documentElement()
200 elements = QWebElementCollection()
201 elements.append(docElement.findAll("embed"))
202 elements.append(docElement.findAll("object"))
203
204 for element in elements:
205 if not self.__checkElement(element) and \
206 not self.__checkUrlOnElement(element, view):
207 continue
208 self.__element = element
209 return
210 frames.extend(frame.childFrames())
211
212 def __checkUrlOnElement(self, element, view):
213 """
214 Private slot to check the URL of an element.
215
216 @param element reference to the element to check (QWebElement)
217 @param view reference to the view object (QWebView)
218 @return flag indicating a positive result (boolean)
219 """
220 checkString = element.attribute("src")
221 if checkString == "":
222 checkString = element.attribute("data")
223 if checkString == "":
224 checkString = element.attribute("value")
225
226 checkString = view.url().resolved(QUrl(checkString)).toString(
227 QUrl.RemoveQuery)
228 return self.__url.toEncoded().contains(
229 QByteArray(checkString.encode("utf-8")))
230
231 def __checkElement(self, element):
232 """
233 Private slot to check an element against the saved arguments.
234
235 @param element reference to the element to check (QWebElement)
236 @return flag indicating a positive result (boolean)
237 """
238 if self.__argumentNames == element.attributeNames():
239 for name in self.__argumentNames:
240 if element.attribute(name) not in self.__argumentValues:
241 return False
242
243 return True
244
245 return False
246
247 def __hideAdBlocked(self):
248 """
249 Private slot to hide the object.
250 """
251 self.__findElement()
252 if not self.__element.isNull():
253 self.__element.setStyleProperty("display", "none")
254 else:
255 self.hide()
256
257 def __showInfo(self):
258 """
259 Private slot to show information about the blocked object.
260 """
261 dlg = QDialog()
262 dlg.setWindowTitle(self.tr("Flash Object"))
263 dlg.setSizeGripEnabled(True)
264 layout = QFormLayout(dlg)
265 layout.addRow(QLabel(self.tr("<b>Attribute Name</b>")),
266 QLabel(self.tr("<b>Value</b>")))
267
268 index = 0
269 for name in self.__argumentNames:
270 nameLabel = QLabel(self.__elide(name, length=30))
271 value = self.__argumentValues[index]
272 valueLabel = QLabel(self.__elide(value, length=60))
273 valueLabel.setTextInteractionFlags(
274 Qt.TextSelectableByMouse | Qt.LinksAccessibleByMouse)
275 layout.addRow(nameLabel, valueLabel)
276
277 index += 1
278
279 if index == 0:
280 layout.addRow(QLabel(self.tr("No information available.")))
281
282 dlg.setMaximumHeight(500)
283 dlg.setMaximumWidth(500)
284 dlg.exec_()
285
286 def __elide(self, txt, mode=Qt.ElideMiddle, length=40):
287 """
288 Private method to elide some text.
289
290 @param txt text to be elided (string)
291 @keyparam mode elide mode (Qt.TextElideMode)
292 @keyparam length amount of characters to be used (integer)
293 @return the elided text (string)
294 """
295 if mode == Qt.ElideNone or len(txt) < length:
296 return txt
297 elif mode == Qt.ElideLeft:
298 return "...{0}".format(txt[-length:])
299 elif mode == Qt.ElideMiddle:
300 return "{0}...{1}".format(txt[:length // 2], txt[-(length // 2):])
301 elif mode == Qt.ElideRight:
302 return "{0}...".format(txt[:length])
303 else:
304 # just in case
305 return txt
306
307 @classmethod
308 def isAlreadyAccepted(cls, url, argumentNames, argumentValues):
309 """
310 Class method to check, if the given parameter combination is being
311 accepted.
312
313 @param url URL to be checked for (QUrl)
314 @param argumentNames argument names to be checked for (list of strings)
315 @param argumentValues argument values to be checked for (list of
316 strings)
317 @return flag indicating that this was already accepted (boolean)
318 """
319 return url == cls._acceptedUrl and \
320 argumentNames == cls._acceptedArgNames and \
321 argumentValues == cls._acceptedArgValues

eric ide

mercurial