eric6/Helpviewer/GreaseMonkey/GreaseMonkeyManager.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 manager for GreaseMonkey scripts.
8 """
9
10 from __future__ import unicode_literals
11
12 import os
13
14 from PyQt5.QtCore import pyqtSignal, QObject, QTimer, QFile, QDir, QSettings, \
15 QUrl, QByteArray
16 from PyQt5.QtNetwork import QNetworkAccessManager
17 from PyQt5.QtWebKitWidgets import QWebFrame
18
19 import Utilities
20 import Preferences
21
22
23 class GreaseMonkeyManager(QObject):
24 """
25 Class implementing the manager for GreaseMonkey scripts.
26
27 @signal scriptsChanged() emitted to indicate a change of scripts
28 """
29 scriptsChanged = pyqtSignal()
30
31 def __init__(self, parent=None):
32 """
33 Constructor
34
35 @param parent reference to the parent object (QObject)
36 """
37 super(GreaseMonkeyManager, self).__init__(parent)
38
39 self.__disabledScripts = []
40 self.__endScripts = []
41 self.__startScripts = []
42 self.__downloaders = []
43
44 QTimer.singleShot(0, self.__load)
45
46 def showConfigurationDialog(self, parent=None):
47 """
48 Public method to show the configuration dialog.
49
50 @param parent reference to the parent widget (QWidget)
51 """
52 from .GreaseMonkeyConfiguration.GreaseMonkeyConfigurationDialog \
53 import GreaseMonkeyConfigurationDialog
54 self.__configDiaolg = GreaseMonkeyConfigurationDialog(self, parent)
55 self.__configDiaolg.show()
56
57 def downloadScript(self, request):
58 """
59 Public method to download a GreaseMonkey script.
60
61 @param request reference to the request (QNetworkRequest)
62 """
63 from .GreaseMonkeyDownloader import GreaseMonkeyDownloader
64 downloader = GreaseMonkeyDownloader(request, self)
65 downloader.finished.connect(
66 lambda: self.__downloaderFinished(downloader))
67 self.__downloaders.append(downloader)
68
69 def __downloaderFinished(self, downloader):
70 """
71 Private slot to handle the completion of a script download.
72
73 @param downloader reference to the downloader object
74 @type GreaseMonkeyDownloader
75 """
76 if downloader in self.__downloaders:
77 self.__downloaders.remove(downloader)
78
79 def scriptsDirectory(self):
80 """
81 Public method to get the path of the scripts directory.
82
83 @return path of the scripts directory (string)
84 """
85 return os.path.join(
86 Utilities.getConfigDir(), "browser", "greasemonkey")
87
88 def requireScriptsDirectory(self):
89 """
90 Public method to get the path of the scripts directory.
91
92 @return path of the scripts directory (string)
93 """
94 return os.path.join(self.scriptsDirectory(), "requires")
95
96 def requireScripts(self, urlList):
97 """
98 Public method to get the sources of all required scripts.
99
100 @param urlList list of URLs (list of string)
101 @return sources of all required scripts (string)
102 """
103 requiresDir = QDir(self.requireScriptsDirectory())
104 if not requiresDir.exists() or len(urlList) == 0:
105 return ""
106
107 script = ""
108
109 settings = QSettings(
110 os.path.join(self.requireScriptsDirectory(), "requires.ini"),
111 QSettings.IniFormat)
112 settings.beginGroup("Files")
113 for url in urlList:
114 if settings.contains(url):
115 fileName = settings.value(url)
116 try:
117 f = open(fileName, "r", encoding="utf-8")
118 source = f.read()
119 f.close()
120 except (IOError, OSError):
121 source = ""
122 script += source.strip() + "\n"
123
124 return script
125
126 def saveConfiguration(self):
127 """
128 Public method to save the configuration.
129 """
130 Preferences.setHelp("GreaseMonkeyDisabledScripts",
131 self.__disabledScripts)
132
133 def allScripts(self):
134 """
135 Public method to get a list of all scripts.
136
137 @return list of all scripts (list of GreaseMonkeyScript)
138 """
139 return self.__startScripts[:] + self.__endScripts[:]
140
141 def containsScript(self, fullName):
142 """
143 Public method to check, if the given script exists.
144
145 @param fullName full name of the script (string)
146 @return flag indicating the existence (boolean)
147 """
148 for script in self.__startScripts:
149 if script.fullName() == fullName:
150 return True
151 for script in self.__endScripts:
152 if script.fullName() == fullName:
153 return True
154 return False
155
156 def enableScript(self, script):
157 """
158 Public method to enable the given script.
159
160 @param script script to be enabled (GreaseMonkeyScript)
161 """
162 script.setEnabled(True)
163 fullName = script.fullName()
164 if fullName in self.__disabledScripts:
165 self.__disabledScripts.remove(fullName)
166
167 def disableScript(self, script):
168 """
169 Public method to disable the given script.
170
171 @param script script to be disabled (GreaseMonkeyScript)
172 """
173 script.setEnabled(False)
174 fullName = script.fullName()
175 if fullName not in self.__disabledScripts:
176 self.__disabledScripts.append(fullName)
177
178 def addScript(self, script):
179 """
180 Public method to add a script.
181
182 @param script script to be added (GreaseMonkeyScript)
183 @return flag indicating success (boolean)
184 """
185 if not script:
186 return False
187
188 from .GreaseMonkeyScript import GreaseMonkeyScript
189 if script.startAt() == GreaseMonkeyScript.DocumentStart:
190 self.__startScripts.append(script)
191 else:
192 self.__endScripts.append(script)
193
194 self.scriptsChanged.emit()
195 return True
196
197 def removeScript(self, script):
198 """
199 Public method to remove a script.
200
201 @param script script to be removed (GreaseMonkeyScript)
202 @return flag indicating success (boolean)
203 """
204 if not script:
205 return False
206
207 from .GreaseMonkeyScript import GreaseMonkeyScript
208 if script.startAt() == GreaseMonkeyScript.DocumentStart:
209 try:
210 self.__startScripts.remove(script)
211 except ValueError:
212 pass
213 else:
214 try:
215 self.__endScripts.remove(script)
216 except ValueError:
217 pass
218
219 fullName = script.fullName()
220 if fullName in self.__disabledScripts:
221 self.__disabledScripts.remove(fullName)
222 QFile.remove(script.fileName())
223
224 self.scriptsChanged.emit()
225 return True
226
227 def canRunOnScheme(self, scheme):
228 """
229 Public method to check, if scripts can be run on a scheme.
230
231 @param scheme scheme to check (string)
232 @return flag indicating, that scripts can be run (boolean)
233 """
234 return scheme in ["http", "https", "data", "ftp"]
235
236 def pageLoadStarted(self):
237 """
238 Public slot to handle the start of loading a page.
239 """
240 frame = self.sender()
241 if frame is None or not isinstance(frame, QWebFrame):
242 return
243
244 urlScheme = frame.url().scheme()
245 urlString = bytes(frame.url().toEncoded()).decode()
246
247 if not self.canRunOnScheme(urlScheme):
248 return
249
250 from .GreaseMonkeyJavaScript import bootstrap_js
251 for script in self.__startScripts:
252 if script.match(urlString):
253 frame.evaluateJavaScript(bootstrap_js + script.script())
254
255 for script in self.__endScripts:
256 if script.match(urlString):
257 javascript = 'window.addEventListener("DOMContentLoaded",' \
258 'function(e) {{ {0} }}, false);'.format(
259 bootstrap_js + script.script())
260 frame.evaluateJavaScript(javascript)
261
262 def __load(self):
263 """
264 Private slot to load the available scripts into the manager.
265 """
266 scriptsDir = QDir(self.scriptsDirectory())
267 if not scriptsDir.exists():
268 scriptsDir.mkpath(self.scriptsDirectory())
269
270 if not scriptsDir.exists("requires"):
271 scriptsDir.mkdir("requires")
272
273 self.__disabledScripts = \
274 Preferences.getHelp("GreaseMonkeyDisabledScripts")
275
276 from .GreaseMonkeyScript import GreaseMonkeyScript
277 for fileName in scriptsDir.entryList(["*.js"], QDir.Files):
278 absolutePath = scriptsDir.absoluteFilePath(fileName)
279 script = GreaseMonkeyScript(self, absolutePath)
280
281 if script.fullName() in self.__disabledScripts:
282 script.setEnabled(False)
283
284 if script.startAt() == GreaseMonkeyScript.DocumentStart:
285 self.__startScripts.append(script)
286 else:
287 self.__endScripts.append(script)
288
289 def connectPage(self, page):
290 """
291 Public method to allow the GreaseMonkey manager to connect to the page.
292
293 @param page reference to the web page (HelpWebPage)
294 """
295 page.mainFrame().javaScriptWindowObjectCleared.connect(
296 self.pageLoadStarted)
297
298 def createRequest(self, op, request, outgoingData=None):
299 """
300 Public method to create a request.
301
302 @param op the operation to be performed
303 (QNetworkAccessManager.Operation)
304 @param request reference to the request object (QNetworkRequest)
305 @param outgoingData reference to an IODevice containing data to be sent
306 (QIODevice)
307 @return reference to the created reply object (QNetworkReply)
308 """
309 if op == QNetworkAccessManager.GetOperation and \
310 request.rawHeader(b"X-Eric6-UserLoadAction") == QByteArray(b"1"):
311 urlString = request.url().toString(
312 QUrl.RemoveFragment | QUrl.RemoveQuery)
313 if urlString.endswith(".user.js"):
314 self.downloadScript(request)
315 from Helpviewer.Network.EmptyNetworkReply import \
316 EmptyNetworkReply
317 return EmptyNetworkReply(self)
318
319 return None

eric ide

mercurial