1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2014 - 2017 Jan Bajer aka bajasoft <jbajer@gmail.com>
4 * Copyright (C) 2015 - 2019 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **************************************************************************/
20 
21 #include "ContentFiltersManager.h"
22 #include "AdblockContentFiltersProfile.h"
23 #include "Console.h"
24 #include "JsonSettings.h"
25 #include "SettingsManager.h"
26 #include "SessionsManager.h"
27 #include "Utils.h"
28 #include "../ui/ItemViewWidget.h"
29 
30 #include <QtCore/QDir>
31 #include <QtCore/QJsonArray>
32 #include <QtCore/QJsonObject>
33 #include <QtCore/QTimer>
34 #include <QtGui/QStandardItemModel>
35 
36 namespace Otter
37 {
38 
39 ContentFiltersManager* ContentFiltersManager::m_instance(nullptr);
40 QVector<ContentFiltersProfile*> ContentFiltersManager::m_contentBlockingProfiles;
41 QVector<ContentFiltersProfile*> ContentFiltersManager::m_fraudCheckingProfiles;
42 ContentFiltersManager::CosmeticFiltersMode ContentFiltersManager::m_cosmeticFiltersMode(AllFilters);
43 bool ContentFiltersManager::m_areWildcardsEnabled(true);
44 
ContentFiltersManager(QObject * parent)45 ContentFiltersManager::ContentFiltersManager(QObject *parent) : QObject(parent),
46 	m_saveTimer(0)
47 {
48 	m_areWildcardsEnabled = SettingsManager::getOption(SettingsManager::ContentBlocking_EnableWildcardsOption).toBool();
49 
50 	handleOptionChanged(SettingsManager::ContentBlocking_CosmeticFiltersModeOption, SettingsManager::getOption(SettingsManager::ContentBlocking_CosmeticFiltersModeOption).toString());
51 
52 	QTimer::singleShot(1000, this, [&]()
53 	{
54 		initialize();
55 	});
56 
57 	connect(SettingsManager::getInstance(), &SettingsManager::optionChanged, this, &ContentFiltersManager::handleOptionChanged);
58 }
59 
createInstance()60 void ContentFiltersManager::createInstance()
61 {
62 	if (!m_instance)
63 	{
64 		m_instance = new ContentFiltersManager(QCoreApplication::instance());
65 	}
66 }
67 
initialize()68 void ContentFiltersManager::initialize()
69 {
70 	if (!m_contentBlockingProfiles.isEmpty())
71 	{
72 		return;
73 	}
74 
75 	const QList<QFileInfo> existingProfiles(QDir(SessionsManager::getWritableDataPath(QLatin1String("contentBlocking"))).entryInfoList({QLatin1String("*.txt")}, QDir::Files));
76 	QJsonObject bundledMainObject(JsonSettings(SessionsManager::getReadableDataPath(QLatin1String("contentBlocking.json"), true)).object());
77 	QStringList profiles;
78 	profiles.reserve(existingProfiles.count());
79 
80 	for (int i = 0; i < existingProfiles.count(); ++i)
81 	{
82 		const QString name(existingProfiles.at(i).completeBaseName());
83 
84 		if (!profiles.contains(name))
85 		{
86 			profiles.append(name);
87 		}
88 	}
89 
90 	QJsonObject::const_iterator iterator;
91 
92 	for (iterator = bundledMainObject.constBegin(); iterator != bundledMainObject.constEnd(); ++iterator)
93 	{
94 		const QString name(iterator.key());
95 
96 		if (!profiles.contains(name))
97 		{
98 			profiles.append(name);
99 		}
100 	}
101 
102 	profiles.sort();
103 
104 	m_contentBlockingProfiles.reserve(profiles.count());
105 
106 	QJsonObject localMainObject(JsonSettings(SessionsManager::getWritableDataPath(QLatin1String("contentBlocking.json"))).object());
107 	const QHash<QString, ContentFiltersProfile::ProfileCategory> categoryTitles({{QLatin1String("advertisements"), ContentFiltersProfile::AdvertisementsCategory}, {QLatin1String("annoyance"), ContentFiltersProfile::AnnoyanceCategory}, {QLatin1String("privacy"), ContentFiltersProfile::PrivacyCategory}, {QLatin1String("social"), ContentFiltersProfile::SocialCategory}, {QLatin1String("regional"), ContentFiltersProfile::RegionalCategory}, {QLatin1String("other"), ContentFiltersProfile::OtherCategory}});
108 
109 	for (int i = 0; i < profiles.count(); ++i)
110 	{
111 		QJsonObject profileObject(localMainObject.value(profiles.at(i)).toObject());
112 		const QJsonObject bundledProfileObject(bundledMainObject.value(profiles.at(i)).toObject());
113 		QString title;
114 		QUrl updateUrl;
115 		ContentFiltersProfile::ProfileFlags flags(ContentFiltersProfile::NoFlags);
116 
117 		if (profiles.at(i) == QLatin1String("custom"))
118 		{
119 			title = tr("Custom Rules");
120 		}
121 		else if (profileObject.isEmpty())
122 		{
123 			profileObject = bundledProfileObject;
124 			updateUrl = QUrl(profileObject.value(QLatin1String("updateUrl")).toString());
125 			title = profileObject.value(QLatin1String("title")).toString();
126 		}
127 		else
128 		{
129 			if (profileObject.value(QLatin1String("isHidden")).toBool())
130 			{
131 				continue;
132 			}
133 
134 			updateUrl = QUrl(profileObject.value(QLatin1String("updateUrl")).toString());
135 			title = profileObject.value(QLatin1String("title")).toString();
136 
137 			if (updateUrl.isEmpty())
138 			{
139 				updateUrl = QUrl(bundledProfileObject.value(QLatin1String("updateUrl")).toString());
140 			}
141 			else
142 			{
143 				flags |= ContentFiltersProfile::HasCustomUpdateUrlFlag;
144 			}
145 
146 			if (title.isEmpty())
147 			{
148 				title = bundledProfileObject.value(QLatin1String("title")).toString();
149 			}
150 			else
151 			{
152 				flags |= ContentFiltersProfile::HasCustomTitleFlag;
153 			}
154 		}
155 
156 		QDateTime lastUpdate(QDateTime::fromString(profileObject.value(QLatin1String("lastUpdate")).toString(), Qt::ISODate));
157 		lastUpdate.setTimeSpec(Qt::UTC);
158 
159 		const QJsonArray languagesArray(profileObject.value(QLatin1String("languages")).toArray());
160 		QStringList languages;
161 		languages.reserve(languagesArray.count());
162 
163 		for (int j = 0; j < languagesArray.count(); ++j)
164 		{
165 			languages.append(languagesArray.at(j).toString());
166 		}
167 
168 		ContentFiltersProfile *profile(new AdblockContentFiltersProfile(profiles.at(i), title, updateUrl, lastUpdate, languages, profileObject.value(QLatin1String("updateInterval")).toInt(), categoryTitles.value(profileObject.value(QLatin1String("category")).toString()), flags, m_instance));
169 
170 		m_contentBlockingProfiles.append(profile);
171 
172 		connect(profile, &ContentFiltersProfile::profileModified, m_instance, &ContentFiltersManager::profileModified);
173 		connect(profile, &ContentFiltersProfile::profileModified, m_instance, &ContentFiltersManager::scheduleSave);
174 	}
175 
176 	m_contentBlockingProfiles.squeeze();
177 }
178 
timerEvent(QTimerEvent * event)179 void ContentFiltersManager::timerEvent(QTimerEvent *event)
180 {
181 	if (event->timerId() == m_saveTimer)
182 	{
183 		killTimer(m_saveTimer);
184 
185 		m_saveTimer = 0;
186 
187 		const QHash<ContentFiltersProfile::ProfileCategory, QString> categoryTitles({{ContentFiltersProfile::AdvertisementsCategory, QLatin1String("advertisements")}, {ContentFiltersProfile::AnnoyanceCategory, QLatin1String("annoyance")}, {ContentFiltersProfile::PrivacyCategory, QLatin1String("privacy")}, {ContentFiltersProfile::SocialCategory, QLatin1String("social")}, {ContentFiltersProfile::RegionalCategory, QLatin1String("regional")}, {ContentFiltersProfile::OtherCategory, QLatin1String("other")}});
188 		JsonSettings settings(SessionsManager::getWritableDataPath(QLatin1String("contentBlocking.json")));
189 		QJsonObject mainObject(settings.object());
190 		QJsonObject::iterator iterator(mainObject.begin());
191 
192 		while (iterator != mainObject.end())
193 		{
194 			const QJsonObject profileObject(mainObject.value(iterator.key()).toObject());
195 
196 			if (profileObject.value(QLatin1String("isHidden")).toBool())
197 			{
198 				++iterator;
199 			}
200 			else
201 			{
202 				iterator = mainObject.erase(iterator);
203 			}
204 		}
205 
206 		for (int i = 0; i < m_contentBlockingProfiles.count(); ++i)
207 		{
208 			const ContentFiltersProfile *profile(m_contentBlockingProfiles.at(i));
209 
210 			if (!profile || profile->getName() == QLatin1String("custom"))
211 			{
212 				continue;
213 			}
214 
215 			QJsonObject profileObject;
216 			const int updateInterval(profile->getUpdateInterval());
217 
218 			if (updateInterval > 0)
219 			{
220 				profileObject.insert(QLatin1String("updateInterval"), updateInterval);
221 			}
222 
223 			const QDateTime lastUpdate(profile->getLastUpdate());
224 
225 			if (lastUpdate.isValid())
226 			{
227 				profileObject.insert(QLatin1String("lastUpdate"), lastUpdate.toString(Qt::ISODate));
228 			}
229 
230 			if (profile->getFlags().testFlag(ContentFiltersProfile::HasCustomTitleFlag))
231 			{
232 				profileObject.insert(QLatin1String("title"), profile->getTitle());
233 			}
234 
235 			if (profile->getFlags().testFlag(ContentFiltersProfile::HasCustomUpdateUrlFlag))
236 			{
237 				profileObject.insert(QLatin1String("updateUrl"), profile->getUpdateUrl().url());
238 			}
239 
240 			profileObject.insert(QLatin1String("category"), categoryTitles.value(profile->getCategory()));
241 
242 			const QVector<QLocale::Language> languages(m_contentBlockingProfiles.at(i)->getLanguages());
243 
244 			if (!languages.contains(QLocale::AnyLanguage))
245 			{
246 				QJsonArray languagesArray;
247 
248 				for (int j = 0; j < languages.count(); ++j)
249 				{
250 					languagesArray.append(QLocale(languages.at(j)).name());
251 				}
252 
253 				profileObject.insert(QLatin1String("languages"), languagesArray);
254 			}
255 
256 			mainObject.insert(profile->getName(), profileObject);
257 		}
258 
259 		settings.setObject(mainObject);
260 		settings.save();
261 	}
262 }
263 
scheduleSave()264 void ContentFiltersManager::scheduleSave()
265 {
266 	if (m_saveTimer == 0)
267 	{
268 		m_saveTimer = startTimer(1000);
269 	}
270 }
271 
addProfile(ContentFiltersProfile * profile)272 void ContentFiltersManager::addProfile(ContentFiltersProfile *profile)
273 {
274 	if (profile)
275 	{
276 		m_contentBlockingProfiles.append(profile);
277 
278 		getInstance()->scheduleSave();
279 
280 		connect(profile, &ContentFiltersProfile::profileModified, m_instance, &ContentFiltersManager::scheduleSave);
281 	}
282 }
283 
handleOptionChanged(int identifier,const QVariant & value)284 void ContentFiltersManager::handleOptionChanged(int identifier, const QVariant &value)
285 {
286 	switch (identifier)
287 	{
288 		case SettingsManager::ContentBlocking_EnableWildcardsOption:
289 			m_areWildcardsEnabled = value.toBool();
290 
291 			break;
292 		case SettingsManager::ContentBlocking_CosmeticFiltersModeOption:
293 			{
294 				const QString cosmeticFiltersMode(value.toString());
295 
296 				if (cosmeticFiltersMode == QLatin1String("none"))
297 				{
298 					m_cosmeticFiltersMode = NoFilters;
299 				}
300 				else if (cosmeticFiltersMode == QLatin1String("domainOnly"))
301 				{
302 					m_cosmeticFiltersMode = DomainOnlyFilters;
303 				}
304 				else
305 				{
306 					m_cosmeticFiltersMode = AllFilters;
307 				}
308 			}
309 
310 			break;
311 		default:
312 			return;
313 	}
314 
315 	for (int i = 0; i < m_contentBlockingProfiles.count(); ++i)
316 	{
317 		m_contentBlockingProfiles.at(i)->clear();
318 	}
319 }
320 
removeProfile(ContentFiltersProfile * profile)321 void ContentFiltersManager::removeProfile(ContentFiltersProfile *profile)
322 {
323 	if (!profile || !profile->remove())
324 	{
325 		Console::addMessage(tr("Failed to remove content blocking profile file: %1").arg(profile ? profile->getName() : tr("Unknown")), Console::OtherCategory, Console::ErrorLevel);
326 
327 		return;
328 	}
329 
330 	JsonSettings localSettings(SessionsManager::getWritableDataPath(QLatin1String("contentBlocking.json")));
331 	QJsonObject localMainObject(localSettings.object());
332 	const QJsonObject bundledMainObject(JsonSettings(SessionsManager::getReadableDataPath(QLatin1String("contentBlocking.json"), true)).object());
333 
334 	if (bundledMainObject.keys().contains(profile->getName()))
335 	{
336 		QJsonObject profileObject(localMainObject.value(profile->getName()).toObject());
337 		profileObject.insert(QLatin1String("isHidden"), true);
338 
339 		localMainObject.insert(profile->getName(), profileObject);
340 	}
341 	else
342 	{
343 		localMainObject.remove(profile->getName());
344 	}
345 
346 	localSettings.setObject(localMainObject);
347 	localSettings.save();
348 
349 	m_contentBlockingProfiles.removeAll(profile);
350 
351 	profile->deleteLater();
352 }
353 
createModel(QObject * parent,const QStringList & profiles)354 QStandardItemModel* ContentFiltersManager::createModel(QObject *parent, const QStringList &profiles)
355 {
356 	initialize();
357 
358 	QHash<ContentFiltersProfile::ProfileCategory, QMultiMap<QString, QList<QStandardItem*> > > categoryEntries;
359 	QStandardItemModel *model(new QStandardItemModel(parent));
360 	model->setHorizontalHeaderLabels({tr("Title"), tr("Update Interval"), tr("Last Update")});
361 	model->setHeaderData(0, Qt::Horizontal, 250, HeaderViewWidget::WidthRole);
362 
363 	for (int i = 0; i < m_contentBlockingProfiles.count(); ++i)
364 	{
365 		const QString name(m_contentBlockingProfiles.at(i)->getName());
366 
367 		if (name == QLatin1String("custom"))
368 		{
369 			continue;
370 		}
371 
372 		const ContentFiltersProfile::ProfileCategory category(m_contentBlockingProfiles.at(i)->getCategory());
373 		QString title(m_contentBlockingProfiles.at(i)->getTitle());
374 
375 		if (category == ContentFiltersProfile::RegionalCategory)
376 		{
377 			const QVector<QLocale::Language> languages(m_contentBlockingProfiles.at(i)->getLanguages());
378 			QStringList languageNames;
379 			languageNames.reserve(languages.count());
380 
381 			for (int j = 0; j < languages.count(); ++j)
382 			{
383 				languageNames.append(QLocale::languageToString(languages.at(j)));
384 			}
385 
386 			title = QStringLiteral("%1 [%2]").arg(title).arg(languageNames.join(QLatin1String(", ")));
387 		}
388 
389 		QList<QStandardItem*> profileItems({new QStandardItem(title), new QStandardItem(QString::number(m_contentBlockingProfiles.at(i)->getUpdateInterval())), new QStandardItem(Utils::formatDateTime(m_contentBlockingProfiles.at(i)->getLastUpdate()))});
390 		profileItems[0]->setData(name, NameRole);
391 		profileItems[0]->setData(m_contentBlockingProfiles.at(i)->getUpdateUrl(), UpdateUrlRole);
392 		profileItems[0]->setFlags(Qt::ItemNeverHasChildren | Qt::ItemIsSelectable | Qt::ItemIsEnabled);
393 		profileItems[0]->setCheckable(true);
394 		profileItems[0]->setCheckState(profiles.contains(name) ? Qt::Checked : Qt::Unchecked);
395 		profileItems[1]->setFlags(Qt::ItemNeverHasChildren | Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
396 		profileItems[2]->setFlags(Qt::ItemNeverHasChildren | Qt::ItemIsSelectable | Qt::ItemIsEnabled);
397 
398 		if (!categoryEntries.contains(category))
399 		{
400 			categoryEntries[category] = QMultiMap<QString, QList<QStandardItem*> >();
401 		}
402 
403 		categoryEntries[category].insert(title, profileItems);
404 	}
405 
406 	const QVector<QPair<ContentFiltersProfile::ProfileCategory, QString> > categoryTitles({{ContentFiltersProfile::AdvertisementsCategory, tr("Advertisements")}, {ContentFiltersProfile::AnnoyanceCategory, tr("Annoyance")}, {ContentFiltersProfile::PrivacyCategory, tr("Privacy")}, {ContentFiltersProfile::SocialCategory, tr("Social")}, {ContentFiltersProfile::RegionalCategory, tr("Regional")}, {ContentFiltersProfile::OtherCategory, tr("Other")}});
407 
408 	for (int i = 0; i < categoryTitles.count(); ++i)
409 	{
410 		if (!categoryEntries.contains(categoryTitles.at(i).first))
411 		{
412 			continue;
413 		}
414 
415 		const QList<QList<QStandardItem*> > profileItems(categoryEntries[categoryTitles.at(i).first].values());
416 		QList<QStandardItem*> categoryItems({new QStandardItem(categoryTitles.at(i).second), new QStandardItem(), new QStandardItem()});
417 		categoryItems[0]->setData(categoryTitles.at(i).first, Qt::UserRole);
418 		categoryItems[0]->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
419 		categoryItems[1]->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
420 		categoryItems[2]->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
421 
422 		for (int j = 0; j < profileItems.count(); ++j)
423 		{
424 			categoryItems[0]->appendRow(profileItems.at(j));
425 		}
426 
427 		model->appendRow(categoryItems);
428 	}
429 
430 	return model;
431 }
432 
getInstance()433 ContentFiltersManager* ContentFiltersManager::getInstance()
434 {
435 	return m_instance;
436 }
437 
getProfile(const QString & profile)438 ContentFiltersProfile* ContentFiltersManager::getProfile(const QString &profile)
439 {
440 	for (int i = 0; i < m_contentBlockingProfiles.count(); ++i)
441 	{
442 		if (m_contentBlockingProfiles.at(i)->getName() == profile)
443 		{
444 			return m_contentBlockingProfiles.at(i);
445 		}
446 	}
447 
448 	return nullptr;
449 }
450 
getProfile(const QUrl & url)451 ContentFiltersProfile* ContentFiltersManager::getProfile(const QUrl &url)
452 {
453 	if (!url.isValid())
454 	{
455 		return nullptr;
456 	}
457 
458 	for (int i = 0; i < m_contentBlockingProfiles.count(); ++i)
459 	{
460 		if (m_contentBlockingProfiles.at(i)->getUpdateUrl() == url)
461 		{
462 			return m_contentBlockingProfiles.at(i);
463 		}
464 	}
465 
466 	return nullptr;
467 }
468 
getProfile(int identifier)469 ContentFiltersProfile* ContentFiltersManager::getProfile(int identifier)
470 {
471 	return m_contentBlockingProfiles.value(identifier, nullptr);
472 }
473 
checkUrl(const QVector<int> & profiles,const QUrl & baseUrl,const QUrl & requestUrl,NetworkManager::ResourceType resourceType)474 ContentFiltersManager::CheckResult ContentFiltersManager::checkUrl(const QVector<int> &profiles, const QUrl &baseUrl, const QUrl &requestUrl, NetworkManager::ResourceType resourceType)
475 {
476 	if (profiles.isEmpty())
477 	{
478 		return {};
479 	}
480 
481 	const QString scheme(requestUrl.scheme());
482 
483 	if (scheme != QLatin1String("http") && scheme != QLatin1String("https"))
484 	{
485 		return {};
486 	}
487 
488 	CheckResult result;
489 	result.isFraud = ((resourceType == NetworkManager::MainFrameType || resourceType == NetworkManager::SubFrameType) ? isFraud(requestUrl) : false);
490 
491 	for (int i = 0; i < profiles.count(); ++i)
492 	{
493 		if (profiles.at(i) >= 0 && profiles.at(i) < m_contentBlockingProfiles.count())
494 		{
495 			CheckResult currentResult(m_contentBlockingProfiles.at(profiles.at(i))->checkUrl(baseUrl, requestUrl, resourceType));
496 			currentResult.profile = profiles.at(i);
497 			currentResult.isFraud = result.isFraud;
498 
499 			if (currentResult.isBlocked)
500 			{
501 				result = currentResult;
502 			}
503 			else if (currentResult.isException)
504 			{
505 				return currentResult;
506 			}
507 		}
508 	}
509 
510 	return result;
511 }
512 
getCosmeticFilters(const QVector<int> & profiles,const QUrl & requestUrl)513 ContentFiltersManager::CosmeticFiltersResult ContentFiltersManager::getCosmeticFilters(const QVector<int> &profiles, const QUrl &requestUrl)
514 {
515 	if (profiles.isEmpty() || m_cosmeticFiltersMode == NoFilters)
516 	{
517 		return {};
518 	}
519 
520 	const CosmeticFiltersMode mode(checkUrl(profiles, requestUrl, requestUrl, NetworkManager::OtherType).comesticFiltersMode);
521 
522 	if (mode == ContentFiltersManager::NoFilters)
523 	{
524 		return {};
525 	}
526 
527 	CosmeticFiltersResult result;
528 	const QStringList domains(createSubdomainList(requestUrl.host()));
529 
530 	for (int i = 0; i < profiles.count(); ++i)
531 	{
532 		const int index(profiles.at(i));
533 
534 		if (index >= 0 && index < m_contentBlockingProfiles.count())
535 		{
536 			const CosmeticFiltersResult profileResult(m_contentBlockingProfiles.at(index)->getCosmeticFilters(domains, (mode == DomainOnlyFilters)));
537 
538 			result.rules.append(profileResult.rules);
539 			result.exceptions.append(profileResult.exceptions);
540 		}
541 	}
542 
543 	return result;
544 }
545 
createSubdomainList(const QString & domain)546 QStringList ContentFiltersManager::createSubdomainList(const QString &domain)
547 {
548 	QStringList subdomainList;
549 	int dotPosition(domain.lastIndexOf(QLatin1Char('.')));
550 	dotPosition = domain.lastIndexOf(QLatin1Char('.'), (dotPosition - 1));
551 
552 	while (dotPosition != -1)
553 	{
554 		subdomainList.append(domain.mid(dotPosition + 1));
555 
556 		dotPosition = domain.lastIndexOf(QLatin1Char('.'), (dotPosition - 1));
557 	}
558 
559 	subdomainList.append(domain);
560 
561 	return subdomainList;
562 }
563 
getProfileNames()564 QStringList ContentFiltersManager::getProfileNames()
565 {
566 	initialize();
567 
568 	QStringList names;
569 	names.reserve(m_contentBlockingProfiles.count());
570 
571 	for (int i = 0; i < m_contentBlockingProfiles.count(); ++i)
572 	{
573 		names.append(m_contentBlockingProfiles.at(i)->getName());
574 	}
575 
576 	return names;
577 }
578 
getContentBlockingProfiles()579 QVector<ContentFiltersProfile*> ContentFiltersManager::getContentBlockingProfiles()
580 {
581 	initialize();
582 
583 	return m_contentBlockingProfiles;
584 }
585 
getFraudCheckingProfiles()586 QVector<ContentFiltersProfile*> ContentFiltersManager::getFraudCheckingProfiles()
587 {
588 	initialize();
589 
590 	return m_fraudCheckingProfiles;
591 }
592 
getProfileIdentifiers(const QStringList & names)593 QVector<int> ContentFiltersManager::getProfileIdentifiers(const QStringList &names)
594 {
595 	initialize();
596 
597 	QVector<int> identifiers;
598 	identifiers.reserve(names.count());
599 
600 	for (int i = 0; i < m_contentBlockingProfiles.count(); ++i)
601 	{
602 		if (names.contains(m_contentBlockingProfiles.at(i)->getName()))
603 		{
604 			identifiers.append(i);
605 		}
606 	}
607 
608 	return identifiers;
609 }
610 
getCosmeticFiltersMode()611 ContentFiltersManager::CosmeticFiltersMode ContentFiltersManager::getCosmeticFiltersMode()
612 {
613 	return m_cosmeticFiltersMode;
614 }
615 
areWildcardsEnabled()616 bool ContentFiltersManager::areWildcardsEnabled()
617 {
618 	return m_areWildcardsEnabled;
619 }
620 
isFraud(const QUrl & url)621 bool ContentFiltersManager::isFraud(const QUrl &url)
622 {
623 	for (int i = 0; i < m_fraudCheckingProfiles.count(); ++i)
624 	{
625 		if (m_fraudCheckingProfiles.at(i)->isFraud(url))
626 		{
627 			return true;
628 		}
629 	}
630 
631 	return false;
632 }
633 
ContentFiltersProfile(QObject * parent)634 ContentFiltersProfile::ContentFiltersProfile(QObject *parent) : QObject(parent)
635 {
636 }
637 
checkUrl(const QUrl & baseUrl,const QUrl & requestUrl,NetworkManager::ResourceType resourceType)638 ContentFiltersManager::CheckResult ContentFiltersProfile::checkUrl(const QUrl &baseUrl, const QUrl &requestUrl, NetworkManager::ResourceType resourceType)
639 {
640 	Q_UNUSED(baseUrl)
641 	Q_UNUSED(requestUrl)
642 	Q_UNUSED(resourceType)
643 
644 	return {};
645 }
646 
getCosmeticFilters(const QStringList & domains,bool isDomainOnly)647 ContentFiltersManager::CosmeticFiltersResult ContentFiltersProfile::getCosmeticFilters(const QStringList &domains, bool isDomainOnly)
648 {
649 	Q_UNUSED(domains)
650 	Q_UNUSED(isDomainOnly)
651 
652 	return {};
653 }
654 
getCategory() const655 ContentFiltersProfile::ProfileCategory ContentFiltersProfile::getCategory() const
656 {
657 	return OtherCategory;
658 }
659 
getLanguages() const660 QVector<QLocale::Language> ContentFiltersProfile::getLanguages() const
661 {
662 	return {};
663 }
664 
isFraud(const QUrl & url)665 bool ContentFiltersProfile::isFraud(const QUrl &url)
666 {
667 	Q_UNUSED(url)
668 
669 	return false;
670 }
671 
672 }
673