29 |
27 |
30 |
28 |
31 class AdBlockManager(QObject): |
29 class AdBlockManager(QObject): |
32 """ |
30 """ |
33 Class implementing the AdBlock manager. |
31 Class implementing the AdBlock manager. |
34 |
32 |
35 @signal rulesChanged() emitted after some rule has changed |
33 @signal rulesChanged() emitted after some rule has changed |
36 @signal requiredSubscriptionLoaded(subscription) emitted to indicate |
34 @signal requiredSubscriptionLoaded(subscription) emitted to indicate |
37 loading of a required subscription is finished (AdBlockSubscription) |
35 loading of a required subscription is finished (AdBlockSubscription) |
38 @signal enabledChanged(enabled) emitted to indicate a change of the |
36 @signal enabledChanged(enabled) emitted to indicate a change of the |
39 enabled state |
37 enabled state |
40 """ |
38 """ |
|
39 |
41 rulesChanged = pyqtSignal() |
40 rulesChanged = pyqtSignal() |
42 requiredSubscriptionLoaded = pyqtSignal(AdBlockSubscription) |
41 requiredSubscriptionLoaded = pyqtSignal(AdBlockSubscription) |
43 enabledChanged = pyqtSignal(bool) |
42 enabledChanged = pyqtSignal(bool) |
44 |
43 |
45 def __init__(self, parent=None): |
44 def __init__(self, parent=None): |
46 """ |
45 """ |
47 Constructor |
46 Constructor |
48 |
47 |
49 @param parent reference to the parent object |
48 @param parent reference to the parent object |
50 @type QObject |
49 @type QObject |
51 """ |
50 """ |
52 super().__init__(parent) |
51 super().__init__(parent) |
53 |
52 |
54 self.__loaded = False |
53 self.__loaded = False |
55 self.__subscriptionsLoaded = False |
54 self.__subscriptionsLoaded = False |
56 self.__enabled = False |
55 self.__enabled = False |
57 self.__adBlockDialog = None |
56 self.__adBlockDialog = None |
58 self.__adBlockExceptionsDialog = None |
57 self.__adBlockExceptionsDialog = None |
59 self.__adBlockNetwork = None |
58 self.__adBlockNetwork = None |
60 self.__adBlockPage = None |
59 self.__adBlockPage = None |
61 self.__subscriptions = [] |
60 self.__subscriptions = [] |
62 self.__exceptedHosts = Preferences.getWebBrowser("AdBlockExceptions") |
61 self.__exceptedHosts = Preferences.getWebBrowser("AdBlockExceptions") |
63 self.__saveTimer = AutoSaver(self, self.save) |
62 self.__saveTimer = AutoSaver(self, self.save) |
64 self.__limitedEasyList = Preferences.getWebBrowser( |
63 self.__limitedEasyList = Preferences.getWebBrowser("AdBlockUseLimitedEasyList") |
65 "AdBlockUseLimitedEasyList") |
64 |
66 |
|
67 self.__defaultSubscriptionUrlString = ( |
65 self.__defaultSubscriptionUrlString = ( |
68 "abp:subscribe?location=" |
66 "abp:subscribe?location=" |
69 "https://easylist-downloads.adblockplus.org/easylist.txt&" |
67 "https://easylist-downloads.adblockplus.org/easylist.txt&" |
70 "title=EasyList" |
68 "title=EasyList" |
71 ) |
69 ) |
72 self.__additionalDefaultSubscriptionUrlStrings = ( |
70 self.__additionalDefaultSubscriptionUrlStrings = ( |
73 "abp:subscribe?location=https://raw.githubusercontent.com/" |
71 "abp:subscribe?location=https://raw.githubusercontent.com/" |
74 "hoshsadiq/adblock-nocoin-list/master/nocoin.txt&" |
72 "hoshsadiq/adblock-nocoin-list/master/nocoin.txt&" |
75 "title=NoCoin", |
73 "title=NoCoin", |
76 ) |
74 ) |
77 self.__customSubscriptionUrlString = ( |
75 self.__customSubscriptionUrlString = bytes( |
78 bytes(self.__customSubscriptionUrl().toEncoded()).decode() |
76 self.__customSubscriptionUrl().toEncoded() |
79 ) |
77 ).decode() |
80 |
78 |
81 self.__mutex = QMutex() |
79 self.__mutex = QMutex() |
82 self.__matcher = AdBlockMatcher(self) |
80 self.__matcher = AdBlockMatcher(self) |
83 |
81 |
84 self.rulesChanged.connect(self.__saveTimer.changeOccurred) |
82 self.rulesChanged.connect(self.__saveTimer.changeOccurred) |
85 self.rulesChanged.connect(self.__rulesChanged) |
83 self.rulesChanged.connect(self.__rulesChanged) |
86 |
84 |
87 self.__interceptor = AdBlockUrlInterceptor(self) |
85 self.__interceptor = AdBlockUrlInterceptor(self) |
88 |
86 |
89 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
87 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
90 WebBrowserWindow.networkManager().installUrlInterceptor( |
88 |
91 self.__interceptor) |
89 WebBrowserWindow.networkManager().installUrlInterceptor(self.__interceptor) |
92 |
90 |
93 def __rulesChanged(self): |
91 def __rulesChanged(self): |
94 """ |
92 """ |
95 Private slot handling a change of the AdBlock rules. |
93 Private slot handling a change of the AdBlock rules. |
96 """ |
94 """ |
97 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
95 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
96 |
98 WebBrowserWindow.mainWindow().reloadUserStyleSheet() |
97 WebBrowserWindow.mainWindow().reloadUserStyleSheet() |
99 self.__updateMatcher() |
98 self.__updateMatcher() |
100 |
99 |
101 def close(self): |
100 def close(self): |
102 """ |
101 """ |
103 Public method to close the open search engines manager. |
102 Public method to close the open search engines manager. |
104 """ |
103 """ |
105 self.__adBlockDialog and self.__adBlockDialog.close() |
104 self.__adBlockDialog and self.__adBlockDialog.close() |
106 (self.__adBlockExceptionsDialog and |
105 (self.__adBlockExceptionsDialog and self.__adBlockExceptionsDialog.close()) |
107 self.__adBlockExceptionsDialog.close()) |
106 |
108 |
|
109 self.__saveTimer.saveIfNeccessary() |
107 self.__saveTimer.saveIfNeccessary() |
110 |
108 |
111 def isEnabled(self): |
109 def isEnabled(self): |
112 """ |
110 """ |
113 Public method to check, if blocking ads is enabled. |
111 Public method to check, if blocking ads is enabled. |
114 |
112 |
115 @return flag indicating the enabled state |
113 @return flag indicating the enabled state |
116 @rtype bool |
114 @rtype bool |
117 """ |
115 """ |
118 if not self.__loaded: |
116 if not self.__loaded: |
119 self.load() |
117 self.load() |
120 |
118 |
121 return self.__enabled |
119 return self.__enabled |
122 |
120 |
123 def setEnabled(self, enabled): |
121 def setEnabled(self, enabled): |
124 """ |
122 """ |
125 Public slot to set the enabled state. |
123 Public slot to set the enabled state. |
126 |
124 |
127 @param enabled flag indicating the enabled state |
125 @param enabled flag indicating the enabled state |
128 @type bool |
126 @type bool |
129 """ |
127 """ |
130 if self.isEnabled() == enabled: |
128 if self.isEnabled() == enabled: |
131 return |
129 return |
132 |
130 |
133 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
131 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
132 |
134 self.__enabled = enabled |
133 self.__enabled = enabled |
135 for mainWindow in WebBrowserWindow.mainWindows(): |
134 for mainWindow in WebBrowserWindow.mainWindows(): |
136 mainWindow.adBlockIcon().setEnabled(enabled) |
135 mainWindow.adBlockIcon().setEnabled(enabled) |
137 if enabled: |
136 if enabled: |
138 self.__loadSubscriptions() |
137 self.__loadSubscriptions() |
139 |
138 |
140 self.rulesChanged.emit() |
139 self.rulesChanged.emit() |
141 self.enabledChanged.emit(enabled) |
140 self.enabledChanged.emit(enabled) |
142 |
141 |
143 def block(self, info): |
142 def block(self, info): |
144 """ |
143 """ |
145 Public method to check, if a request should be blocked. |
144 Public method to check, if a request should be blocked. |
146 |
145 |
147 @param info request info object |
146 @param info request info object |
148 @type QWebEngineUrlRequestInfo |
147 @type QWebEngineUrlRequestInfo |
149 @return flag indicating to block the request |
148 @return flag indicating to block the request |
150 @rtype bool |
149 @rtype bool |
151 """ |
150 """ |
152 with EricMutexLocker(self.__mutex): |
151 with EricMutexLocker(self.__mutex): |
153 if not self.isEnabled(): |
152 if not self.isEnabled(): |
154 return False |
153 return False |
155 |
154 |
156 urlString = bytes(info.requestUrl().toEncoded()).decode().lower() |
155 urlString = bytes(info.requestUrl().toEncoded()).decode().lower() |
157 urlDomain = info.requestUrl().host().lower() |
156 urlDomain = info.requestUrl().host().lower() |
158 urlScheme = info.requestUrl().scheme().lower() |
157 urlScheme = info.requestUrl().scheme().lower() |
159 |
158 |
160 if ( |
159 if not self.canRunOnScheme(urlScheme) or not self.__canBeBlocked( |
161 not self.canRunOnScheme(urlScheme) or |
160 info.firstPartyUrl() |
162 not self.__canBeBlocked(info.firstPartyUrl()) |
|
163 ): |
161 ): |
164 return False |
162 return False |
165 |
163 |
166 res = False |
164 res = False |
167 blockedRule = self.__matcher.match(info, urlDomain, urlString) |
165 blockedRule = self.__matcher.match(info, urlDomain, urlString) |
168 |
166 |
169 if blockedRule: |
167 if blockedRule: |
170 res = True |
168 res = True |
171 if ( |
169 if ( |
172 info.resourceType() == |
170 info.resourceType() |
173 QWebEngineUrlRequestInfo.ResourceType |
171 == QWebEngineUrlRequestInfo.ResourceType.ResourceTypeMainFrame |
174 .ResourceTypeMainFrame |
|
175 ): |
172 ): |
176 url = QUrl("eric:adblock") |
173 url = QUrl("eric:adblock") |
177 query = QUrlQuery() |
174 query = QUrlQuery() |
178 query.addQueryItem("rule", blockedRule.filter()) |
175 query.addQueryItem("rule", blockedRule.filter()) |
179 query.addQueryItem( |
176 query.addQueryItem( |
180 "subscription", blockedRule.subscription().title()) |
177 "subscription", blockedRule.subscription().title() |
|
178 ) |
181 url.setQuery(query) |
179 url.setQuery(query) |
182 info.redirect(url) |
180 info.redirect(url) |
183 else: |
181 else: |
184 info.block(True) |
182 info.block(True) |
185 |
183 |
186 return res |
184 return res |
187 |
185 |
188 def canRunOnScheme(self, scheme): |
186 def canRunOnScheme(self, scheme): |
189 """ |
187 """ |
190 Public method to check, if AdBlock can be performed on the scheme. |
188 Public method to check, if AdBlock can be performed on the scheme. |
191 |
189 |
192 @param scheme scheme to check |
190 @param scheme scheme to check |
193 @type str |
191 @type str |
194 @return flag indicating, that AdBlock can be performed |
192 @return flag indicating, that AdBlock can be performed |
195 @rtype bool |
193 @rtype bool |
196 """ |
194 """ |
197 return scheme not in ["data", "eric", "qthelp", "qrc", "file", "abp"] |
195 return scheme not in ["data", "eric", "qthelp", "qrc", "file", "abp"] |
198 |
196 |
199 def page(self): |
197 def page(self): |
200 """ |
198 """ |
201 Public method to get a reference to the page block object. |
199 Public method to get a reference to the page block object. |
202 |
200 |
203 @return reference to the page block object |
201 @return reference to the page block object |
204 @rtype AdBlockPage |
202 @rtype AdBlockPage |
205 """ |
203 """ |
206 if self.__adBlockPage is None: |
204 if self.__adBlockPage is None: |
207 from .AdBlockPage import AdBlockPage |
205 from .AdBlockPage import AdBlockPage |
|
206 |
208 self.__adBlockPage = AdBlockPage(self) |
207 self.__adBlockPage = AdBlockPage(self) |
209 return self.__adBlockPage |
208 return self.__adBlockPage |
210 |
209 |
211 def __customSubscriptionLocation(self): |
210 def __customSubscriptionLocation(self): |
212 """ |
211 """ |
213 Private method to generate the path for custom subscriptions. |
212 Private method to generate the path for custom subscriptions. |
214 |
213 |
215 @return URL for custom subscriptions |
214 @return URL for custom subscriptions |
216 @rtype QUrl |
215 @rtype QUrl |
217 """ |
216 """ |
218 dataDir = os.path.join(Utilities.getConfigDir(), "web_browser", |
217 dataDir = os.path.join(Utilities.getConfigDir(), "web_browser", "subscriptions") |
219 "subscriptions") |
|
220 if not os.path.exists(dataDir): |
218 if not os.path.exists(dataDir): |
221 os.makedirs(dataDir) |
219 os.makedirs(dataDir) |
222 fileName = os.path.join(dataDir, "adblock_subscription_custom") |
220 fileName = os.path.join(dataDir, "adblock_subscription_custom") |
223 return QUrl.fromLocalFile(fileName) |
221 return QUrl.fromLocalFile(fileName) |
224 |
222 |
225 def __customSubscriptionUrl(self): |
223 def __customSubscriptionUrl(self): |
226 """ |
224 """ |
227 Private method to generate the URL for custom subscriptions. |
225 Private method to generate the URL for custom subscriptions. |
228 |
226 |
229 @return URL for custom subscriptions |
227 @return URL for custom subscriptions |
230 @rtype QUrl |
228 @rtype QUrl |
231 """ |
229 """ |
232 location = self.__customSubscriptionLocation() |
230 location = self.__customSubscriptionLocation() |
233 encodedUrl = bytes(location.toEncoded()).decode() |
231 encodedUrl = bytes(location.toEncoded()).decode() |
234 url = QUrl("abp:subscribe?location={0}&title={1}".format( |
232 url = QUrl( |
235 encodedUrl, self.tr("Custom Rules"))) |
233 "abp:subscribe?location={0}&title={1}".format( |
|
234 encodedUrl, self.tr("Custom Rules") |
|
235 ) |
|
236 ) |
236 return url |
237 return url |
237 |
238 |
238 def customRules(self): |
239 def customRules(self): |
239 """ |
240 """ |
240 Public method to get a subscription for custom rules. |
241 Public method to get a subscription for custom rules. |
241 |
242 |
242 @return subscription object for custom rules |
243 @return subscription object for custom rules |
243 @rtype AdBlockSubscription |
244 @rtype AdBlockSubscription |
244 """ |
245 """ |
245 location = self.__customSubscriptionLocation() |
246 location = self.__customSubscriptionLocation() |
246 for subscription in self.__subscriptions: |
247 for subscription in self.__subscriptions: |
247 if subscription.location() == location: |
248 if subscription.location() == location: |
248 return subscription |
249 return subscription |
249 |
250 |
250 url = self.__customSubscriptionUrl() |
251 url = self.__customSubscriptionUrl() |
251 customAdBlockSubscription = AdBlockSubscription(url, True, self) |
252 customAdBlockSubscription = AdBlockSubscription(url, True, self) |
252 self.addSubscription(customAdBlockSubscription) |
253 self.addSubscription(customAdBlockSubscription) |
253 return customAdBlockSubscription |
254 return customAdBlockSubscription |
254 |
255 |
255 def subscriptions(self): |
256 def subscriptions(self): |
256 """ |
257 """ |
257 Public method to get all subscriptions. |
258 Public method to get all subscriptions. |
258 |
259 |
259 @return list of subscriptions |
260 @return list of subscriptions |
260 @rtype list of AdBlockSubscription |
261 @rtype list of AdBlockSubscription |
261 """ |
262 """ |
262 if not self.__loaded: |
263 if not self.__loaded: |
263 self.load() |
264 self.load() |
264 |
265 |
265 return self.__subscriptions[:] |
266 return self.__subscriptions[:] |
266 |
267 |
267 def subscription(self, location): |
268 def subscription(self, location): |
268 """ |
269 """ |
269 Public method to get a subscription based on its location. |
270 Public method to get a subscription based on its location. |
270 |
271 |
271 @param location location of the subscription to search for |
272 @param location location of the subscription to search for |
272 @type str |
273 @type str |
273 @return subscription or None |
274 @return subscription or None |
274 @rtype AdBlockSubscription |
275 @rtype AdBlockSubscription |
275 """ |
276 """ |
276 if location != "": |
277 if location != "": |
277 for subscription in self.__subscriptions: |
278 for subscription in self.__subscriptions: |
278 if subscription.location().toString() == location: |
279 if subscription.location().toString() == location: |
279 return subscription |
280 return subscription |
280 |
281 |
281 return None |
282 return None |
282 |
283 |
283 def updateAllSubscriptions(self): |
284 def updateAllSubscriptions(self): |
284 """ |
285 """ |
285 Public method to update all subscriptions. |
286 Public method to update all subscriptions. |
286 """ |
287 """ |
287 for subscription in self.__subscriptions: |
288 for subscription in self.__subscriptions: |
288 subscription.updateNow() |
289 subscription.updateNow() |
289 |
290 |
290 def removeSubscription(self, subscription, emitSignal=True): |
291 def removeSubscription(self, subscription, emitSignal=True): |
291 """ |
292 """ |
292 Public method to remove an AdBlock subscription. |
293 Public method to remove an AdBlock subscription. |
293 |
294 |
294 @param subscription AdBlock subscription to be removed |
295 @param subscription AdBlock subscription to be removed |
295 @type AdBlockSubscription |
296 @type AdBlockSubscription |
296 @param emitSignal flag indicating to send a signal |
297 @param emitSignal flag indicating to send a signal |
297 @type bool |
298 @type bool |
298 """ |
299 """ |
299 if subscription is None: |
300 if subscription is None: |
300 return |
301 return |
301 |
302 |
302 if subscription.url().toString().startswith( |
303 if ( |
303 (self.__defaultSubscriptionUrlString, |
304 subscription.url() |
304 self.__customSubscriptionUrlString)): |
305 .toString() |
|
306 .startswith( |
|
307 ( |
|
308 self.__defaultSubscriptionUrlString, |
|
309 self.__customSubscriptionUrlString, |
|
310 ) |
|
311 ) |
|
312 ): |
305 return |
313 return |
306 |
314 |
307 with contextlib.suppress(ValueError): |
315 with contextlib.suppress(ValueError): |
308 self.__subscriptions.remove(subscription) |
316 self.__subscriptions.remove(subscription) |
309 rulesFileName = subscription.rulesFileName() |
317 rulesFileName = subscription.rulesFileName() |
310 os.unlink(rulesFileName) |
318 os.unlink(rulesFileName) |
311 requiresSubscriptions = self.getRequiresSubscriptions(subscription) |
319 requiresSubscriptions = self.getRequiresSubscriptions(subscription) |
312 for requiresSubscription in requiresSubscriptions: |
320 for requiresSubscription in requiresSubscriptions: |
313 self.removeSubscription(requiresSubscription, False) |
321 self.removeSubscription(requiresSubscription, False) |
314 if emitSignal: |
322 if emitSignal: |
315 self.rulesChanged.emit() |
323 self.rulesChanged.emit() |
316 |
324 |
317 def addSubscriptionFromUrl(self, url): |
325 def addSubscriptionFromUrl(self, url): |
318 """ |
326 """ |
319 Public method to ad an AdBlock subscription given the abp URL. |
327 Public method to ad an AdBlock subscription given the abp URL. |
320 |
328 |
321 @param url URL to subscribe an AdBlock subscription |
329 @param url URL to subscribe an AdBlock subscription |
322 @type QUrl |
330 @type QUrl |
323 @return flag indicating success |
331 @return flag indicating success |
324 @rtype bool |
332 @rtype bool |
325 """ |
333 """ |
326 if url.path() != "subscribe": |
334 if url.path() != "subscribe": |
327 return False |
335 return False |
328 |
336 |
329 title = QUrl.fromPercentEncoding( |
337 title = QUrl.fromPercentEncoding( |
330 QByteArray(QUrlQuery(url).queryItemValue("title").encode())) |
338 QByteArray(QUrlQuery(url).queryItemValue("title").encode()) |
|
339 ) |
331 if not title: |
340 if not title: |
332 return False |
341 return False |
333 |
342 |
334 res = EricMessageBox.yesNo( |
343 res = EricMessageBox.yesNo( |
335 None, |
344 None, |
336 self.tr("Subscribe?"), |
345 self.tr("Subscribe?"), |
337 self.tr( |
346 self.tr( |
338 """<p>Subscribe to this AdBlock subscription?</p>""" |
347 """<p>Subscribe to this AdBlock subscription?</p>""" """<p>{0}</p>""" |
339 """<p>{0}</p>""").format(title)) |
348 ).format(title), |
|
349 ) |
340 if res: |
350 if res: |
341 from .AdBlockSubscription import AdBlockSubscription |
351 from .AdBlockSubscription import AdBlockSubscription |
342 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
352 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
343 |
353 |
344 dlg = WebBrowserWindow.adBlockManager().showDialog() |
354 dlg = WebBrowserWindow.adBlockManager().showDialog() |
345 subscription = AdBlockSubscription( |
355 subscription = AdBlockSubscription( |
346 url, False, |
356 url, False, WebBrowserWindow.adBlockManager() |
347 WebBrowserWindow.adBlockManager()) |
357 ) |
348 WebBrowserWindow.adBlockManager().addSubscription(subscription) |
358 WebBrowserWindow.adBlockManager().addSubscription(subscription) |
349 dlg.addSubscription(subscription, False) |
359 dlg.addSubscription(subscription, False) |
350 dlg.setFocus() |
360 dlg.setFocus() |
351 dlg.raise_() |
361 dlg.raise_() |
352 |
362 |
353 return res |
363 return res |
354 |
364 |
355 def addSubscription(self, subscription): |
365 def addSubscription(self, subscription): |
356 """ |
366 """ |
357 Public method to add an AdBlock subscription. |
367 Public method to add an AdBlock subscription. |
358 |
368 |
359 @param subscription AdBlock subscription to be added |
369 @param subscription AdBlock subscription to be added |
360 @type AdBlockSubscription |
370 @type AdBlockSubscription |
361 """ |
371 """ |
362 if subscription is None: |
372 if subscription is None: |
363 return |
373 return |
364 |
374 |
365 self.__subscriptions.insert(-1, subscription) |
375 self.__subscriptions.insert(-1, subscription) |
366 |
376 |
367 subscription.rulesChanged.connect(self.rulesChanged) |
377 subscription.rulesChanged.connect(self.rulesChanged) |
368 subscription.changed.connect(self.rulesChanged) |
378 subscription.changed.connect(self.rulesChanged) |
369 subscription.enabledChanged.connect(self.rulesChanged) |
379 subscription.enabledChanged.connect(self.rulesChanged) |
370 |
380 |
371 self.rulesChanged.emit() |
381 self.rulesChanged.emit() |
372 |
382 |
373 def save(self): |
383 def save(self): |
374 """ |
384 """ |
375 Public method to save the AdBlock subscriptions. |
385 Public method to save the AdBlock subscriptions. |
376 """ |
386 """ |
377 if not self.__loaded: |
387 if not self.__loaded: |
378 return |
388 return |
379 |
389 |
380 Preferences.setWebBrowser("AdBlockEnabled", self.__enabled) |
390 Preferences.setWebBrowser("AdBlockEnabled", self.__enabled) |
381 if self.__subscriptionsLoaded: |
391 if self.__subscriptionsLoaded: |
382 subscriptions = [] |
392 subscriptions = [] |
383 requiresSubscriptions = [] |
393 requiresSubscriptions = [] |
384 # intermediate store for subscription requiring others |
394 # intermediate store for subscription requiring others |
392 subscriptions.append(urlString) |
402 subscriptions.append(urlString) |
393 subscription.saveRules() |
403 subscription.saveRules() |
394 for subscription in requiresSubscriptions: |
404 for subscription in requiresSubscriptions: |
395 subscriptions.insert(-1, subscription) # custom should be last |
405 subscriptions.insert(-1, subscription) # custom should be last |
396 Preferences.setWebBrowser("AdBlockSubscriptions", subscriptions) |
406 Preferences.setWebBrowser("AdBlockSubscriptions", subscriptions) |
397 |
407 |
398 def load(self): |
408 def load(self): |
399 """ |
409 """ |
400 Public method to load the AdBlock subscriptions. |
410 Public method to load the AdBlock subscriptions. |
401 """ |
411 """ |
402 if self.__loaded: |
412 if self.__loaded: |
403 return |
413 return |
404 |
414 |
405 self.__loaded = True |
415 self.__loaded = True |
406 |
416 |
407 self.__enabled = Preferences.getWebBrowser("AdBlockEnabled") |
417 self.__enabled = Preferences.getWebBrowser("AdBlockEnabled") |
408 if self.__enabled: |
418 if self.__enabled: |
409 self.__loadSubscriptions() |
419 self.__loadSubscriptions() |
410 |
420 |
411 def __loadSubscriptions(self): |
421 def __loadSubscriptions(self): |
412 """ |
422 """ |
413 Private method to load the set of subscriptions. |
423 Private method to load the set of subscriptions. |
414 """ |
424 """ |
415 if self.__subscriptionsLoaded: |
425 if self.__subscriptionsLoaded: |
416 return |
426 return |
417 |
427 |
418 subscriptions = Preferences.getWebBrowser("AdBlockSubscriptions") |
428 subscriptions = Preferences.getWebBrowser("AdBlockSubscriptions") |
419 if subscriptions: |
429 if subscriptions: |
420 for subscription in subscriptions: |
430 for subscription in subscriptions: |
421 if subscription.startswith(self.__customSubscriptionUrlString): |
431 if subscription.startswith(self.__customSubscriptionUrlString): |
422 break |
432 break |
423 else: |
433 else: |
424 subscriptions.append(self.__customSubscriptionUrlString) |
434 subscriptions.append(self.__customSubscriptionUrlString) |
425 else: |
435 else: |
426 subscriptions = ( |
436 subscriptions = ( |
427 [self.__defaultSubscriptionUrlString] + |
437 [self.__defaultSubscriptionUrlString] |
428 list(self.__additionalDefaultSubscriptionUrlStrings) + |
438 + list(self.__additionalDefaultSubscriptionUrlStrings) |
429 [self.__customSubscriptionUrlString] |
439 + [self.__customSubscriptionUrlString] |
430 ) |
440 ) |
431 for subscription in subscriptions: |
441 for subscription in subscriptions: |
432 url = QUrl.fromEncoded(subscription.encode("utf-8")) |
442 url = QUrl.fromEncoded(subscription.encode("utf-8")) |
433 adBlockSubscription = AdBlockSubscription( |
443 adBlockSubscription = AdBlockSubscription( |
434 url, |
444 url, |
435 subscription.startswith(self.__customSubscriptionUrlString), |
445 subscription.startswith(self.__customSubscriptionUrlString), |
436 self, |
446 self, |
437 subscription.startswith(self.__defaultSubscriptionUrlString)) |
447 subscription.startswith(self.__defaultSubscriptionUrlString), |
|
448 ) |
438 adBlockSubscription.rulesChanged.connect(self.rulesChanged) |
449 adBlockSubscription.rulesChanged.connect(self.rulesChanged) |
439 adBlockSubscription.changed.connect(self.rulesChanged) |
450 adBlockSubscription.changed.connect(self.rulesChanged) |
440 adBlockSubscription.enabledChanged.connect(self.rulesChanged) |
451 adBlockSubscription.enabledChanged.connect(self.rulesChanged) |
|
452 adBlockSubscription.rulesEnabledChanged.connect(self.__updateMatcher) |
441 adBlockSubscription.rulesEnabledChanged.connect( |
453 adBlockSubscription.rulesEnabledChanged.connect( |
442 self.__updateMatcher) |
454 self.__saveTimer.changeOccurred |
443 adBlockSubscription.rulesEnabledChanged.connect( |
455 ) |
444 self.__saveTimer.changeOccurred) |
|
445 self.__subscriptions.append(adBlockSubscription) |
456 self.__subscriptions.append(adBlockSubscription) |
446 |
457 |
447 self.__subscriptionsLoaded = True |
458 self.__subscriptionsLoaded = True |
448 |
459 |
449 self.__updateMatcher() |
460 self.__updateMatcher() |
450 |
461 |
451 def loadRequiredSubscription(self, location, title): |
462 def loadRequiredSubscription(self, location, title): |
452 """ |
463 """ |
453 Public method to load a subscription required by another one. |
464 Public method to load a subscription required by another one. |
454 |
465 |
455 @param location location of the required subscription |
466 @param location location of the required subscription |
456 @type str |
467 @type str |
457 @param title title of the required subscription |
468 @param title title of the required subscription |
458 @type str |
469 @type str |
459 """ |
470 """ |
460 # Step 1: check, if the subscription is in the list of subscriptions |
471 # Step 1: check, if the subscription is in the list of subscriptions |
461 urlString = "abp:subscribe?location={0}&title={1}".format( |
472 urlString = "abp:subscribe?location={0}&title={1}".format(location, title) |
462 location, title) |
|
463 for subscription in self.__subscriptions: |
473 for subscription in self.__subscriptions: |
464 if subscription.url().toString().startswith(urlString): |
474 if subscription.url().toString().startswith(urlString): |
465 # We found it! |
475 # We found it! |
466 return |
476 return |
467 |
477 |
468 # Step 2: if it is not, get it |
478 # Step 2: if it is not, get it |
469 url = QUrl.fromEncoded(urlString.encode("utf-8")) |
479 url = QUrl.fromEncoded(urlString.encode("utf-8")) |
470 adBlockSubscription = AdBlockSubscription(url, False, self) |
480 adBlockSubscription = AdBlockSubscription(url, False, self) |
471 self.addSubscription(adBlockSubscription) |
481 self.addSubscription(adBlockSubscription) |
472 self.requiredSubscriptionLoaded.emit(adBlockSubscription) |
482 self.requiredSubscriptionLoaded.emit(adBlockSubscription) |
473 |
483 |
474 def getRequiresSubscriptions(self, subscription): |
484 def getRequiresSubscriptions(self, subscription): |
475 """ |
485 """ |
476 Public method to get a list of subscriptions, that require the given |
486 Public method to get a list of subscriptions, that require the given |
477 one. |
487 one. |
478 |
488 |
479 @param subscription subscription to check for |
489 @param subscription subscription to check for |
480 @type AdBlockSubscription |
490 @type AdBlockSubscription |
481 @return list of subscription requiring the given one |
491 @return list of subscription requiring the given one |
482 @rtype list of AdBlockSubscription |
492 @rtype list of AdBlockSubscription |
483 """ |
493 """ |
484 subscriptions = [] |
494 subscriptions = [] |
485 location = subscription.location().toString() |
495 location = subscription.location().toString() |
486 for subscription in self.__subscriptions: |
496 for subscription in self.__subscriptions: |
487 if subscription.requiresLocation() == location: |
497 if subscription.requiresLocation() == location: |
488 subscriptions.append(subscription) |
498 subscriptions.append(subscription) |
489 |
499 |
490 return subscriptions |
500 return subscriptions |
491 |
501 |
492 def showDialog(self): |
502 def showDialog(self): |
493 """ |
503 """ |
494 Public slot to show the AdBlock subscription management dialog. |
504 Public slot to show the AdBlock subscription management dialog. |
495 |
505 |
496 @return reference to the dialog |
506 @return reference to the dialog |
497 @rtype AdBlockDialog |
507 @rtype AdBlockDialog |
498 """ |
508 """ |
499 if self.__adBlockDialog is None: |
509 if self.__adBlockDialog is None: |
500 from .AdBlockDialog import AdBlockDialog |
510 from .AdBlockDialog import AdBlockDialog |
|
511 |
501 self.__adBlockDialog = AdBlockDialog(self) |
512 self.__adBlockDialog = AdBlockDialog(self) |
502 |
513 |
503 self.__adBlockDialog.show() |
514 self.__adBlockDialog.show() |
504 return self.__adBlockDialog |
515 return self.__adBlockDialog |
505 |
516 |
506 def elementHidingRules(self, url): |
517 def elementHidingRules(self, url): |
507 """ |
518 """ |
508 Public method to get the element hiding rules. |
519 Public method to get the element hiding rules. |
509 |
520 |
510 |
521 |
511 @param url URL to get hiding rules for |
522 @param url URL to get hiding rules for |
512 @type QUrl |
523 @type QUrl |
513 @return element hiding rules |
524 @return element hiding rules |
514 @rtype str |
525 @rtype str |
515 """ |
526 """ |
516 if ( |
527 if ( |
517 not self.isEnabled() or |
528 not self.isEnabled() |
518 not self.canRunOnScheme(url.scheme()) or |
529 or not self.canRunOnScheme(url.scheme()) |
519 not self.__canBeBlocked(url) |
530 or not self.__canBeBlocked(url) |
520 ): |
531 ): |
521 return "" |
532 return "" |
522 |
533 |
523 return self.__matcher.elementHidingRules() |
534 return self.__matcher.elementHidingRules() |
524 |
535 |
525 def elementHidingRulesForDomain(self, url): |
536 def elementHidingRulesForDomain(self, url): |
526 """ |
537 """ |
527 Public method to get the element hiding rules for a domain. |
538 Public method to get the element hiding rules for a domain. |
528 |
539 |
529 @param url URL to get hiding rules for |
540 @param url URL to get hiding rules for |
530 @type QUrl |
541 @type QUrl |
531 @return element hiding rules |
542 @return element hiding rules |
532 @rtype str |
543 @rtype str |
533 """ |
544 """ |
534 if ( |
545 if ( |
535 not self.isEnabled() or |
546 not self.isEnabled() |
536 not self.canRunOnScheme(url.scheme()) or |
547 or not self.canRunOnScheme(url.scheme()) |
537 not self.__canBeBlocked(url) |
548 or not self.__canBeBlocked(url) |
538 ): |
549 ): |
539 return "" |
550 return "" |
540 |
551 |
541 return self.__matcher.elementHidingRulesForDomain(url.host()) |
552 return self.__matcher.elementHidingRulesForDomain(url.host()) |
542 |
553 |
543 def exceptions(self): |
554 def exceptions(self): |
544 """ |
555 """ |
545 Public method to get a list of excepted hosts. |
556 Public method to get a list of excepted hosts. |
546 |
557 |
547 @return list of excepted hosts |
558 @return list of excepted hosts |
548 @rtype list of str |
559 @rtype list of str |
549 """ |
560 """ |
550 return self.__exceptedHosts |
561 return self.__exceptedHosts |
551 |
562 |
552 def setExceptions(self, hosts): |
563 def setExceptions(self, hosts): |
553 """ |
564 """ |
554 Public method to set the list of excepted hosts. |
565 Public method to set the list of excepted hosts. |
555 |
566 |
556 @param hosts list of excepted hosts |
567 @param hosts list of excepted hosts |
557 @type list of str |
568 @type list of str |
558 """ |
569 """ |
559 self.__exceptedHosts = [host.lower() for host in hosts] |
570 self.__exceptedHosts = [host.lower() for host in hosts] |
560 Preferences.setWebBrowser("AdBlockExceptions", self.__exceptedHosts) |
571 Preferences.setWebBrowser("AdBlockExceptions", self.__exceptedHosts) |
561 |
572 |
562 def addException(self, host): |
573 def addException(self, host): |
563 """ |
574 """ |
564 Public method to add an exception. |
575 Public method to add an exception. |
565 |
576 |
566 @param host to be excepted |
577 @param host to be excepted |
567 @type str |
578 @type str |
568 """ |
579 """ |
569 host = host.lower() |
580 host = host.lower() |
570 if host and host not in self.__exceptedHosts: |
581 if host and host not in self.__exceptedHosts: |
571 self.__exceptedHosts.append(host) |
582 self.__exceptedHosts.append(host) |
572 Preferences.setWebBrowser( |
583 Preferences.setWebBrowser("AdBlockExceptions", self.__exceptedHosts) |
573 "AdBlockExceptions", self.__exceptedHosts) |
584 |
574 |
|
575 def removeException(self, host): |
585 def removeException(self, host): |
576 """ |
586 """ |
577 Public method to remove an exception. |
587 Public method to remove an exception. |
578 |
588 |
579 @param host to be removed from the list of exceptions |
589 @param host to be removed from the list of exceptions |
580 @type str |
590 @type str |
581 """ |
591 """ |
582 host = host.lower() |
592 host = host.lower() |
583 if host in self.__exceptedHosts: |
593 if host in self.__exceptedHosts: |
584 self.__exceptedHosts.remove(host) |
594 self.__exceptedHosts.remove(host) |
585 Preferences.setWebBrowser( |
595 Preferences.setWebBrowser("AdBlockExceptions", self.__exceptedHosts) |
586 "AdBlockExceptions", self.__exceptedHosts) |
596 |
587 |
|
588 def isHostExcepted(self, host): |
597 def isHostExcepted(self, host): |
589 """ |
598 """ |
590 Public slot to check, if a host is excepted. |
599 Public slot to check, if a host is excepted. |
591 |
600 |
592 @param host host to check |
601 @param host host to check |
593 @type str |
602 @type str |
594 @return flag indicating an exception |
603 @return flag indicating an exception |
595 @rtype bool |
604 @rtype bool |
596 """ |
605 """ |
597 host = host.lower() |
606 host = host.lower() |
598 return host in self.__exceptedHosts |
607 return host in self.__exceptedHosts |
599 |
608 |
600 def showExceptionsDialog(self): |
609 def showExceptionsDialog(self): |
601 """ |
610 """ |
602 Public method to show the AdBlock Exceptions dialog. |
611 Public method to show the AdBlock Exceptions dialog. |
603 |
612 |
604 @return reference to the exceptions dialog |
613 @return reference to the exceptions dialog |
605 @rtype AdBlockExceptionsDialog |
614 @rtype AdBlockExceptionsDialog |
606 """ |
615 """ |
607 if self.__adBlockExceptionsDialog is None: |
616 if self.__adBlockExceptionsDialog is None: |
608 from .AdBlockExceptionsDialog import AdBlockExceptionsDialog |
617 from .AdBlockExceptionsDialog import AdBlockExceptionsDialog |
|
618 |
609 self.__adBlockExceptionsDialog = AdBlockExceptionsDialog() |
619 self.__adBlockExceptionsDialog = AdBlockExceptionsDialog() |
610 |
620 |
611 self.__adBlockExceptionsDialog.load(self.__exceptedHosts) |
621 self.__adBlockExceptionsDialog.load(self.__exceptedHosts) |
612 self.__adBlockExceptionsDialog.show() |
622 self.__adBlockExceptionsDialog.show() |
613 return self.__adBlockExceptionsDialog |
623 return self.__adBlockExceptionsDialog |
614 |
624 |
615 def useLimitedEasyList(self): |
625 def useLimitedEasyList(self): |
616 """ |
626 """ |
617 Public method to test, if limited EasyList rules shall be used. |
627 Public method to test, if limited EasyList rules shall be used. |
618 |
628 |
619 @return flag indicating limited EasyList rules |
629 @return flag indicating limited EasyList rules |
620 @rtype bool |
630 @rtype bool |
621 """ |
631 """ |
622 return self.__limitedEasyList |
632 return self.__limitedEasyList |
623 |
633 |
624 def setUseLimitedEasyList(self, limited): |
634 def setUseLimitedEasyList(self, limited): |
625 """ |
635 """ |
626 Public method to set the limited EasyList flag. |
636 Public method to set the limited EasyList flag. |
627 |
637 |
628 @param limited flag indicating to use limited EasyList |
638 @param limited flag indicating to use limited EasyList |
629 @type bool |
639 @type bool |
630 """ |
640 """ |
631 self.__limitedEasyList = limited |
641 self.__limitedEasyList = limited |
632 |
642 |
633 for subscription in self.__subscriptions: |
643 for subscription in self.__subscriptions: |
634 if subscription.url().toString().startswith( |
644 if ( |
635 self.__defaultSubscriptionUrlString): |
645 subscription.url() |
|
646 .toString() |
|
647 .startswith(self.__defaultSubscriptionUrlString) |
|
648 ): |
636 subscription.updateNow() |
649 subscription.updateNow() |
637 |
650 |
638 Preferences.setWebBrowser("AdBlockUseLimitedEasyList", limited) |
651 Preferences.setWebBrowser("AdBlockUseLimitedEasyList", limited) |
639 |
652 |
640 def getDefaultSubscriptionUrl(self): |
653 def getDefaultSubscriptionUrl(self): |
641 """ |
654 """ |
642 Public method to get the default subscription URL. |
655 Public method to get the default subscription URL. |
643 |
656 |
644 @return default subscription URL |
657 @return default subscription URL |
645 @rtype str |
658 @rtype str |
646 """ |
659 """ |
647 return self.__defaultSubscriptionUrlString |
660 return self.__defaultSubscriptionUrlString |
648 |
661 |
649 def __updateMatcher(self): |
662 def __updateMatcher(self): |
650 """ |
663 """ |
651 Private slot to update the adblock matcher. |
664 Private slot to update the adblock matcher. |
652 """ |
665 """ |
653 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
666 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
654 WebBrowserWindow.networkManager().removeUrlInterceptor( |
667 |
655 self.__interceptor) |
668 WebBrowserWindow.networkManager().removeUrlInterceptor(self.__interceptor) |
656 |
669 |
657 if self.__enabled: |
670 if self.__enabled: |
658 self.__matcher.update() |
671 self.__matcher.update() |
659 else: |
672 else: |
660 self.__matcher.clear() |
673 self.__matcher.clear() |
661 |
674 |
662 WebBrowserWindow.networkManager().installUrlInterceptor( |
675 WebBrowserWindow.networkManager().installUrlInterceptor(self.__interceptor) |
663 self.__interceptor) |
676 |
664 |
|
665 def __canBeBlocked(self, url): |
677 def __canBeBlocked(self, url): |
666 """ |
678 """ |
667 Private method to check, if the given URL could be blocked (i.e. is |
679 Private method to check, if the given URL could be blocked (i.e. is |
668 not whitelisted). |
680 not whitelisted). |
669 |
681 |
670 @param url URL to be checked |
682 @param url URL to be checked |
671 @type QUrl |
683 @type QUrl |
672 @return flag indicating that the given URL can be blocked |
684 @return flag indicating that the given URL can be blocked |
673 @rtype bool |
685 @rtype bool |
674 """ |
686 """ |