Helpviewer/WebPlugins/ClickToFlash/ClickToFlash.py

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

eric ide

mercurial