Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: libadblockplus-android/src/org/adblockplus/libadblockplus/android/AdblockEngine.java

Issue 29351744: Issue 4399 - Add WebView inheritor with ad blocking (Closed)
Patch Set: changed packages, now using AdblockEngine (original ABPEngine), improved demo app Created Oct. 25, 2016, 11:20 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: libadblockplus-android/src/org/adblockplus/libadblockplus/android/AdblockEngine.java
diff --git a/libadblockplus-android/src/org/adblockplus/libadblockplus/android/AdblockEngine.java b/libadblockplus-android/src/org/adblockplus/libadblockplus/android/AdblockEngine.java
new file mode 100644
index 0000000000000000000000000000000000000000..b12740e6f1f358ef9723b7bbcbd0cee0e82a426f
--- /dev/null
+++ b/libadblockplus-android/src/org/adblockplus/libadblockplus/android/AdblockEngine.java
@@ -0,0 +1,313 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2016 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.adblockplus.libadblockplus.android;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.adblockplus.libadblockplus.AppInfo;
+import org.adblockplus.libadblockplus.Filter;
+import org.adblockplus.libadblockplus.FilterChangeCallback;
+import org.adblockplus.libadblockplus.FilterEngine;
+import org.adblockplus.libadblockplus.FilterEngine.ContentType;
+import org.adblockplus.libadblockplus.JsEngine;
+import org.adblockplus.libadblockplus.LogSystem;
+import org.adblockplus.libadblockplus.ShowNotificationCallback;
+import org.adblockplus.libadblockplus.Subscription;
+import org.adblockplus.libadblockplus.UpdateAvailableCallback;
+import org.adblockplus.libadblockplus.UpdateCheckDoneCallback;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Build.VERSION;
+import android.util.Log;
+
+public final class AdblockEngine
+{
+ private static final String TAG = Utils.getTag(AdblockEngine.class);
+
+ private final Context context;
+
+ /*
+ * The fields below are volatile because:
+ *
+ * I encountered JNI related bugs/crashes caused by JNI backed Java objects. It seemed that under
+ * certain conditions the objects were optimized away which resulted in crashes when trying to
+ * release the object, sometimes even on access.
+ *
+ * The only solution that really worked was to declare the variables holding the references
+ * volatile, this seems to prevent the JNI from 'optimizing away' those objects (as a volatile
+ * variable might be changed at any time from any thread).
+ */
+ private volatile JsEngine jsEngine;
+ private volatile FilterEngine filterEngine;
+ private volatile LogSystem logSystem;
+ private volatile AndroidWebRequest webRequest;
+ private volatile UpdateAvailableCallback updateAvailableCallback;
+ private volatile UpdateCheckDoneCallback updateCheckDoneCallback;
+ private volatile FilterChangeCallback filterChangeCallback;
+ private volatile ShowNotificationCallback showNotificationCallback;
+ private final boolean elemhideEnabled;
+
+ private AdblockEngine(final Context context, final boolean enableElemhide)
+ {
+ this.context = context;
+ this.elemhideEnabled = enableElemhide;
+ }
+
+ public static AppInfo generateAppInfo(final Context context, boolean developmentBuild)
+ {
+ String version = "0";
+ try
+ {
+ final PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+ version = info.versionName;
+ if (developmentBuild)
+ version += "." + info.versionCode;
+ }
+ catch (final NameNotFoundException e)
+ {
+ Log.e(TAG, "Failed to get the application version number", e);
+ }
+ final String sdkVersion = String.valueOf(VERSION.SDK_INT);
+ final String locale = Locale.getDefault().toString().replace('_', '-');
+
+ return AppInfo.builder()
+ .setVersion(version)
+ .setApplicationVersion(sdkVersion)
+ .setLocale(locale)
+ .setDevelopmentBuild(developmentBuild)
+ .build();
+ }
+
+ public static AdblockEngine create(final Context context, final AppInfo appInfo, final String basePath)
+ {
+ return create(context, appInfo, basePath, false);
+ }
+
+ public static AdblockEngine create(final Context context, final AppInfo appInfo, final String basePath, boolean enableElemhide)
+ {
+ final AdblockEngine engine = new AdblockEngine(context, enableElemhide);
+
+ engine.jsEngine = new JsEngine(appInfo);
+ engine.jsEngine.setDefaultFileSystem(basePath);
+
+ engine.logSystem = new AndroidLogSystem();
+ engine.jsEngine.setLogSystem(engine.logSystem);
+
+ engine.webRequest = new AndroidWebRequest(enableElemhide);
+ engine.jsEngine.setWebRequest(engine.webRequest);
+
+ engine.filterEngine = new FilterEngine(engine.jsEngine);
+
+ engine.webRequest.updateSubscriptionURLs(engine.filterEngine);
+
+ return engine;
+ }
+
+ public void dispose()
+ {
+ // Safe disposing (just in case)
+ if (this.filterEngine != null)
+ {
+ this.filterEngine.dispose();
+ this.filterEngine = null;
+ }
+
+ if (this.jsEngine != null)
+ {
+ this.jsEngine.dispose();
+ this.jsEngine = null;
+ }
+
+ if (this.logSystem != null)
+ {
+ this.logSystem.dispose();
+ this.logSystem = null;
+ }
+
+ if (this.webRequest != null)
+ {
+ this.webRequest.dispose();
+ this.webRequest = null;
+ }
+
+ if (this.updateAvailableCallback != null)
+ {
+ this.updateAvailableCallback.dispose();
+ this.updateAvailableCallback = null;
+ }
+
+ if (this.updateCheckDoneCallback != null)
+ {
+ this.updateCheckDoneCallback.dispose();
+ this.updateCheckDoneCallback = null;
+ }
+
+ if (this.filterChangeCallback != null)
+ {
+ this.filterChangeCallback.dispose();
+ this.filterChangeCallback = null;
+ }
+
+ if (this.showNotificationCallback != null)
+ {
+ this.showNotificationCallback.dispose();
+ this.showNotificationCallback = null;
+ }
+ }
+
+ public boolean isFirstRun()
+ {
+ return this.filterEngine.isFirstRun();
+ }
+
+ public boolean isElemhideEnabled()
+ {
+ return this.elemhideEnabled;
+ }
+
+ public void setSubscription(final String url)
+ {
+ for (final Subscription s : this.filterEngine.getListedSubscriptions())
+ {
+ s.removeFromList();
+ }
+
+ final Subscription sub = this.filterEngine.getSubscription(url);
+ if (sub != null)
+ {
+ sub.addToList();
+ }
+ }
+
+ public void refreshSubscriptions()
+ {
+ for (final Subscription s : this.filterEngine.getListedSubscriptions())
+ {
+ s.updateFilters();
+ }
+ }
+
+ public boolean isAcceptableAdsEnabled()
+ {
+ final String url = this.filterEngine.getPref("subscriptions_exceptionsurl").toString();
+ List<Subscription> subscriptions = this.filterEngine.getListedSubscriptions();
+ for (Subscription eachSubscription : subscriptions)
+ {
+ if (eachSubscription.getProperty("url").toString().equals(url))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setAcceptableAdsEnabled(final boolean enabled)
+ {
+ final String url = this.filterEngine.getPref("subscriptions_exceptionsurl").toString();
+ final Subscription sub = this.filterEngine.getSubscription(url);
+ if (sub != null)
+ {
+ if (enabled)
+ {
+ sub.addToList();
+ }
+ else
+ {
+ sub.removeFromList();
+ }
+ }
+ }
+
+ public String getDocumentationLink()
+ {
+ return this.filterEngine.getPref("documentation_link").toString();
+ }
+
+ public boolean matches(final String fullUrl, final ContentType contentType, final String[] referrerChainArray)
+ {
+ final Filter filter = this.filterEngine.matches(fullUrl, contentType, referrerChainArray);
+
+ if (filter == null)
+ {
+ return false;
+ }
+
+ // hack: if there is no referrer, block only if filter is domain-specific
+ // (to re-enable in-app ads blocking, proposed on 12.11.2012 Monday meeting)
+ // (documentUrls contains the referrers on Android)
+ try
+ {
+ if (referrerChainArray.length == 0 && (filter.getProperty("text").toString()).contains("||"))
+ {
+ return false;
+ }
+ } catch (NullPointerException e) {
+ }
+
+ return filter.getType() != Filter.Type.EXCEPTION;
+ }
+
+ public boolean isDocumentWhitelisted(final String url, final String[] referrerChainArray)
+ {
+ return this.filterEngine.isDocumentWhitelisted(url, referrerChainArray);
+ }
+
+ public boolean isElemhideWhitelisted(final String url, final String[] referrerChainArray)
+ {
+ return this.filterEngine.isElemhideWhitelisted(url, referrerChainArray);
+ }
+
+ public List<String> getElementHidingSelectors(final String url, final String domain, final String[] referrerChainArray)
+ {
+ /*
+ * Issue 3364 (https://issues.adblockplus.org/ticket/3364) introduced the
+ * feature to re-enabled element hiding.
+ *
+ * Nothing changes for Adblock Plus for Android, as `this.elemhideEnabled`
+ * is `false`, which results in an empty list being returned and converted
+ * into a `(String[])null` in AdblockPlus.java, which is the only place
+ * this function here is called from Adblock Plus for Android.
+ *
+ * If element hiding is enabled, then this function now first checks for
+ * possible whitelisting of either the document or element hiding for
+ * the given URL and returns an empty list if so. This is needed to
+ * ensure correct functioning of e.g. acceptable ads.
+ */
+ if (!this.elemhideEnabled
+ || this.isDocumentWhitelisted(url, referrerChainArray)
+ || this.isElemhideWhitelisted(url, referrerChainArray))
+ {
+ return new ArrayList<String>();
+ }
+ return this.filterEngine.getElementHidingSelectors(domain);
+ }
+
+ public void checkForUpdates()
+ {
+ this.filterEngine.forceUpdateCheck(this.updateCheckDoneCallback);
+ }
+
+ public FilterEngine getFilterEngine()
+ {
+ return this.filterEngine;
+ }
+}

Powered by Google App Engine
This is Rietveld