WebBrowser/GreaseMonkey/GreaseMonkeyScript.py

branch
QtWebEngine
changeset 4763
8ad353f31184
parent 4631
5c1a96925da4
child 4766
5f8d08aa2217
equal deleted inserted replaced
4762:ea40955a0937 4763:8ad353f31184
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the GreaseMonkey script.
8 """
9
10 from __future__ import unicode_literals
11
12 from PyQt5.QtCore import QUrl, QRegExp
13
14 from .GreaseMonkeyUrlMatcher import GreaseMonkeyUrlMatcher
15
16
17 class GreaseMonkeyScript(object):
18 """
19 Class implementing the GreaseMonkey script.
20 """
21 DocumentStart = 0
22 DocumentEnd = 1
23
24 def __init__(self, manager, path):
25 """
26 Constructor
27
28 @param manager reference to the manager object (GreaseMonkeyManager)
29 @param path path of the Javascript file (string)
30 """
31 self.__manager = manager
32
33 self.__name = ""
34 self.__namespace = "GreaseMonkeyNS"
35 self.__description = ""
36 self.__version = ""
37
38 self.__include = []
39 self.__exclude = []
40
41 self.__downloadUrl = QUrl()
42 self.__startAt = GreaseMonkeyScript.DocumentEnd
43
44 self.__script = ""
45 self.__fileName = path
46 self.__enabled = True
47 self.__valid = False
48 self.__metaData = ""
49
50 self.__parseScript(path)
51 ## , m_fileWatcher(new DelayedFileWatcher(this))
52 ## connect(m_fileWatcher, SIGNAL(delayedFileChanged(QString)), this, SLOT(watchedFileChanged(QString)));
53
54 def isValid(self):
55 """
56 Public method to check the validity of the script.
57
58 @return flag indicating a valid script (boolean)
59 """
60 return self.__valid
61
62 def name(self):
63 """
64 Public method to get the name of the script.
65
66 @return name of the script (string)
67 """
68 return self.__name
69
70 def nameSpace(self):
71 """
72 Public method to get the name space of the script.
73
74 @return name space of the script (string)
75 """
76 return self.__namespace
77
78 def fullName(self):
79 """
80 Public method to get the full name of the script.
81
82 @return full name of the script (string)
83 """
84 return "{0}/{1}".format(self.__namespace, self.__name)
85
86 def description(self):
87 """
88 Public method to get the description of the script.
89
90 @return description of the script (string)
91 """
92 return self.__description
93
94 def version(self):
95 """
96 Public method to get the version of the script.
97
98 @return version of the script (string)
99 """
100 return self.__version
101
102 def downloadUrl(self):
103 """
104 Public method to get the download URL of the script.
105
106 @return download URL of the script (QUrl)
107 """
108 return QUrl(self.__downloadUrl)
109
110 def startAt(self):
111 """
112 Public method to get the start point of the script.
113
114 @return start point of the script (DocumentStart or DocumentEnd)
115 """
116 return self.__startAt
117
118 def isEnabled(self):
119 """
120 Public method to check, if the script is enabled.
121
122 @return flag indicating an enabled state (boolean)
123 """
124 return self.__enabled
125
126 def setEnabled(self, enable):
127 """
128 Public method to enable a script.
129
130 @param enable flag indicating the new enabled state (boolean)
131 """
132 self.__enabled = enable
133
134 def include(self):
135 """
136 Public method to get the list of included URLs.
137
138 @return list of included URLs (list of strings)
139 """
140 list = []
141 for matcher in self.__include:
142 list.append(matcher.pattern())
143 return list
144
145 def exclude(self):
146 """
147 Public method to get the list of excluded URLs.
148
149 @return list of excluded URLs (list of strings)
150 """
151 list = []
152 for matcher in self.__exclude:
153 list.append(matcher.pattern())
154 return list
155
156 def script(self):
157 """
158 Public method to get the Javascript source.
159
160 @return Javascript source (string)
161 """
162 return self.__script
163
164 ##QString GM_Script::metaData() const
165 ##{
166 ## return m_metadata;
167 ##}
168
169 def fileName(self):
170 """
171 Public method to get the path of the Javascript file.
172
173 @return path path of the Javascript file (string)
174 """
175 return self.__fileName
176
177 def match(self, urlString):
178 """
179 Public method to check, if the script matches the given URL.
180
181 @param urlString URL (string)
182 @return flag indicating a match (boolean)
183 """
184 if not self.__enabled:
185 return False
186
187 for matcher in self.__exclude:
188 if matcher.match(urlString):
189 return False
190
191 for matcher in self.__include:
192 if matcher.match(urlString):
193 return True
194
195 return False
196
197 def __parseScript(self, path):
198 """
199 Private method to parse the given script and populate the data
200 structure.
201
202 @param path path of the Javascript file (string)
203 """
204 try:
205 f = open(path, "r", encoding="utf-8")
206 fileData = f.read()
207 f.close()
208 except (IOError, OSError):
209 # silently ignore because it shouldn't happen
210 return
211
212 rx = QRegExp("// ==UserScript==(.*)// ==/UserScript==")
213 rx.indexIn(fileData)
214 metaDataBlock = rx.cap(1).strip()
215
216 if metaDataBlock == "":
217 # invalid script file
218 return
219
220 requireList = []
221 for line in metaDataBlock.splitlines():
222 if not line.startswith("// @"):
223 continue
224
225 line = line[3:].replace("\t", " ")
226 index = line.find(" ")
227 if index < 0:
228 continue
229
230 key = line[:index].strip()
231 value = line[index + 1:].strip()
232
233 # Ignored values: @resource, @unwrap
234
235 if not key or not value:
236 continue
237
238 if key == "@name":
239 self.__name = value
240
241 elif key == "@namespace":
242 self.__namespace = value
243
244 elif key == "@description":
245 self.__description = value
246
247 elif key == "@version":
248 self.__version = value
249
250 elif key == "@updateURL":
251 self.__downloadUrl = QUrl(value)
252
253 elif key in ["@include", "@match"]:
254 self.__include.append(GreaseMonkeyUrlMatcher(value))
255
256 elif key in ["@exclude", "@exclude_match"]:
257 self.__exclude.append(GreaseMonkeyUrlMatcher(value))
258
259 elif key == "@require":
260 requireList.append(value)
261
262 elif key == "@run-at":
263 if value == "document-end":
264 self.__startAt = GreaseMonkeyScript.DocumentEnd
265 elif value == "document-start":
266 self.__startAt = GreaseMonkeyScript.DocumentStart
267
268 elif key == "@downloadURL" and self.__downloadUrl.isEmpty():
269 self.__downloadUrl = QUrl(value)
270
271 if not self.__include:
272 self.__include.append(GreaseMonkeyUrlMatcher("*"))
273
274 marker = "// ==/UserScript=="
275 index = fileData.find(marker) + len(marker)
276 self.__metaData = fileData[:index]
277 script = fileData[index:].strip()
278 script = "{0}{1}".format(
279 self.__manager.requireScripts(requireList),
280 script)
281 self.__script = "(function(){{{0}}})();".format(script)
282 self.__valid = len(script) > 0
283 ## const QString nspace = QCryptographicHash::hash(fullName().toUtf8(), QCryptographicHash::Md4).toHex();
284 ## const QString gmValues = m_manager->valuesScript().arg(nspace);
285 ##
286 ## m_script = QSL("(function(){%1\n%2\n%3\n})();").arg(gmValues, m_manager->requireScripts(requireList), script);
287 ## m_valid = true;
288
289 def webScript(self):
290 """
291 Public method to create a script object
292
293 @return prepared script object
294 @rtype QWebEngineScript
295 """
296 ##QWebEngineScript GM_Script::webScript() const
297 ##{
298 ## QWebEngineScript script;
299 ## script.setName(fullName());
300 ## script.setInjectionPoint(startAt() == DocumentStart ? QWebEngineScript::DocumentCreation : QWebEngineScript::DocumentReady);
301 ## script.setWorldId(QWebEngineScript::MainWorld);
302 ## script.setRunsOnSubFrames(!m_noframes);
303 ## script.setSourceCode(QSL("%1\n%2\n%3").arg(m_metadata, m_manager->bootstrapScript(), m_script));
304 ## return script;
305 ##}

eric ide

mercurial