| 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 | 
| deleted file mode 100644 | 
| index f5143695e6fb20d91b9d7878497873f4ca40e456..0000000000000000000000000000000000000000 | 
| --- a/libadblockplus-android/src/org/adblockplus/libadblockplus/android/AdblockEngine.java | 
| +++ /dev/null | 
| @@ -1,644 +0,0 @@ | 
| -/* | 
| - * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| - * Copyright (C) 2006-present 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.Arrays; | 
| -import java.util.Collection; | 
| -import java.util.HashSet; | 
| -import java.util.List; | 
| -import java.util.Locale; | 
| -import java.util.Map; | 
| -import java.util.Set; | 
| - | 
| -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.IsAllowedConnectionCallback; | 
| -import org.adblockplus.libadblockplus.JsValue; | 
| -import org.adblockplus.libadblockplus.LogSystem; | 
| -import org.adblockplus.libadblockplus.Platform; | 
| -import org.adblockplus.libadblockplus.ShowNotificationCallback; | 
| -import org.adblockplus.libadblockplus.Subscription; | 
| -import org.adblockplus.libadblockplus.UpdateAvailableCallback; | 
| -import org.adblockplus.libadblockplus.UpdateCheckDoneCallback; | 
| -import org.adblockplus.libadblockplus.WebRequest; | 
| - | 
| -import android.content.Context; | 
| -import android.content.pm.PackageInfo; | 
| -import android.content.pm.PackageManager; | 
| -import android.os.Build.VERSION; | 
| -import android.util.Log; | 
| - | 
| -public final class AdblockEngine | 
| -{ | 
| - // default base path to store subscription files in android app | 
| - public static final String BASE_PATH_DIRECTORY = "adblock"; | 
| - | 
| - private static final String TAG = Utils.getTag(AdblockEngine.class); | 
| - | 
| - /* | 
| - * 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 Platform platform; | 
| - private volatile FilterEngine filterEngine; | 
| - private volatile LogSystem logSystem; | 
| - private volatile WebRequest webRequest; | 
| - private volatile UpdateAvailableCallback updateAvailableCallback; | 
| - private volatile UpdateCheckDoneCallback updateCheckDoneCallback; | 
| - private volatile FilterChangeCallback filterChangeCallback; | 
| - private volatile ShowNotificationCallback showNotificationCallback; | 
| - private volatile boolean elemhideEnabled; | 
| - private volatile boolean enabled = true; | 
| - private volatile List<String> whitelistedDomains; | 
| - | 
| - public static AppInfo generateAppInfo(final Context context, boolean developmentBuild, | 
| - String application, String applicationVersion) | 
| - { | 
| - final String sdkVersion = String.valueOf(VERSION.SDK_INT); | 
| - final String locale = Locale.getDefault().toString().replace('_', '-'); | 
| - | 
| - AppInfo.Builder builder = | 
| - AppInfo | 
| - .builder() | 
| - .setApplicationVersion(sdkVersion) | 
| - .setLocale(locale) | 
| - .setDevelopmentBuild(developmentBuild); | 
| - | 
| - if (application != null) | 
| - { | 
| - builder.setApplication(application); | 
| - } | 
| - | 
| - if (applicationVersion != null) | 
| - { | 
| - builder.setApplicationVersion(applicationVersion); | 
| - } | 
| - | 
| - return builder.build(); | 
| - } | 
| - | 
| - public static AppInfo generateAppInfo(final Context context, boolean developmentBuild) | 
| - { | 
| - try | 
| - { | 
| - PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); | 
| - String application = context.getPackageName(); | 
| - String applicationVersion = packageInfo.versionName; | 
| - | 
| - return generateAppInfo(context, developmentBuild, application, applicationVersion); | 
| - } | 
| - catch (PackageManager.NameNotFoundException e) | 
| - { | 
| - throw new RuntimeException(e); | 
| - } | 
| - } | 
| - | 
| - /** | 
| - * Builds Adblock engine | 
| - */ | 
| - public static class Builder | 
| - { | 
| - private Context context; | 
| - private Map<String, Integer> urlToResourceIdMap; | 
| - private AndroidWebRequestResourceWrapper.Storage resourceStorage; | 
| - private AndroidWebRequest androidWebRequest; | 
| - private AppInfo appInfo; | 
| - private String basePath; | 
| - private IsAllowedConnectionCallback isAllowedConnectionCallback; | 
| - private Long v8IsolateProviderPtr; | 
| - | 
| - private AdblockEngine engine; | 
| - | 
| - protected Builder(final AppInfo appInfo, final String basePath) | 
| - { | 
| - engine = new AdblockEngine(); | 
| - engine.elemhideEnabled = true; | 
| - | 
| - // we can't create JsEngine and FilterEngine right now as it starts to download subscriptions | 
| - // and requests (AndroidWebRequest and probbaly wrappers) are not specified yet | 
| - this.appInfo = appInfo; | 
| - this.basePath = basePath; | 
| - } | 
| - | 
| - public Builder enableElementHiding(boolean enable) | 
| - { | 
| - engine.elemhideEnabled = enable; | 
| - return this; | 
| - } | 
| - | 
| - public Builder preloadSubscriptions(Context context, | 
| - Map<String, Integer> urlToResourceIdMap, | 
| - AndroidWebRequestResourceWrapper.Storage storage) | 
| - { | 
| - this.context = context; | 
| - this.urlToResourceIdMap = urlToResourceIdMap; | 
| - this.resourceStorage = storage; | 
| - return this; | 
| - } | 
| - | 
| - public Builder setIsAllowedConnectionCallback(IsAllowedConnectionCallback callback) | 
| - { | 
| - this.isAllowedConnectionCallback = callback; | 
| - return this; | 
| - } | 
| - | 
| - public Builder useV8IsolateProvider(long v8IsolateProviderPtr) | 
| - { | 
| - this.v8IsolateProviderPtr = v8IsolateProviderPtr; | 
| - return this; | 
| - } | 
| - | 
| - public Builder setUpdateAvailableCallback(UpdateAvailableCallback callback) | 
| - { | 
| - engine.updateAvailableCallback = callback; | 
| - return this; | 
| - } | 
| - | 
| - public Builder setUpdateCheckDoneCallback(UpdateCheckDoneCallback callback) | 
| - { | 
| - engine.updateCheckDoneCallback = callback; | 
| - return this; | 
| - } | 
| - | 
| - public Builder setShowNotificationCallback(ShowNotificationCallback callback) | 
| - { | 
| - engine.showNotificationCallback = callback; | 
| - return this; | 
| - } | 
| - | 
| - public Builder setFilterChangeCallback(FilterChangeCallback callback) | 
| - { | 
| - engine.filterChangeCallback = callback; | 
| - return this; | 
| - } | 
| - | 
| - private void initRequests() | 
| - { | 
| - androidWebRequest = new AndroidWebRequest(engine.elemhideEnabled, true); | 
| - engine.webRequest = androidWebRequest; | 
| - | 
| - if (urlToResourceIdMap != null) | 
| - { | 
| - AndroidWebRequestResourceWrapper wrapper = new AndroidWebRequestResourceWrapper( | 
| - context, engine.webRequest, urlToResourceIdMap, resourceStorage); | 
| - wrapper.setListener(new AndroidWebRequestResourceWrapper.Listener() | 
| - { | 
| - @Override | 
| - public void onIntercepted(String url, int resourceId) | 
| - { | 
| - Log.d(TAG, "Force subscription update for intercepted URL " + url); | 
| - if (engine.filterEngine != null) | 
| - { | 
| - engine.filterEngine.updateFiltersAsync(url); | 
| - } | 
| - } | 
| - }); | 
| - | 
| - engine.webRequest = wrapper; | 
| - } | 
| - } | 
| - | 
| - private void initCallbacks() | 
| - { | 
| - if (engine.updateAvailableCallback != null) | 
| - { | 
| - engine.filterEngine.setUpdateAvailableCallback(engine.updateAvailableCallback); | 
| - } | 
| - | 
| - if (engine.showNotificationCallback != null) | 
| - { | 
| - engine.filterEngine.setShowNotificationCallback(engine.showNotificationCallback); | 
| - } | 
| - | 
| - if (engine.filterChangeCallback != null) | 
| - { | 
| - engine.filterEngine.setFilterChangeCallback(engine.filterChangeCallback); | 
| - } | 
| - } | 
| - | 
| - public AdblockEngine build() | 
| - { | 
| - initRequests(); | 
| - | 
| - // webRequest should be ready to be used passed right after JsEngine is created | 
| - createEngines(); | 
| - | 
| - initCallbacks(); | 
| - | 
| - if (!engine.elemhideEnabled) | 
| - { | 
| - androidWebRequest.updateSubscriptionURLs(engine.filterEngine); | 
| - } | 
| - | 
| - return engine; | 
| - } | 
| - | 
| - private void createEngines() | 
| - { | 
| - engine.logSystem = new AndroidLogSystem(); | 
| - engine.platform = new Platform(engine.logSystem, engine.webRequest, basePath); | 
| - if (v8IsolateProviderPtr != null) | 
| - { | 
| - engine.platform.setUpJsEngine(appInfo, v8IsolateProviderPtr); | 
| - } | 
| - else | 
| - { | 
| - engine.platform.setUpJsEngine(appInfo); | 
| - } | 
| - engine.platform.setUpFilterEngine(isAllowedConnectionCallback); | 
| - engine.filterEngine = engine.platform.getFilterEngine(); | 
| - } | 
| - } | 
| - | 
| - public static Builder builder(AppInfo appInfo, String basePath) | 
| - { | 
| - return new Builder(appInfo, basePath); | 
| - } | 
| - | 
| - public void dispose() | 
| - { | 
| - Log.w(TAG, "Dispose"); | 
| - | 
| - // engines first | 
| - if (this.filterEngine != null) | 
| - { | 
| - if (this.updateAvailableCallback != null) | 
| - { | 
| - this.filterEngine.removeUpdateAvailableCallback(); | 
| - } | 
| - | 
| - if (this.filterChangeCallback != null) | 
| - { | 
| - this.filterEngine.removeFilterChangeCallback(); | 
| - } | 
| - | 
| - if (this.showNotificationCallback != null) | 
| - { | 
| - this.filterEngine.removeShowNotificationCallback(); | 
| - } | 
| - | 
| - this.platform.dispose(); | 
| - this.platform = null; | 
| - } | 
| - | 
| - // callbacks then | 
| - if (this.updateAvailableCallback != null) | 
| - { | 
| - this.updateAvailableCallback.dispose(); | 
| - this.updateAvailableCallback = 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; | 
| - } | 
| - | 
| - private static org.adblockplus.libadblockplus.android.Subscription convertJsSubscription(final Subscription jsSubscription) | 
| - { | 
| - final org.adblockplus.libadblockplus.android.Subscription subscription = | 
| - new org.adblockplus.libadblockplus.android.Subscription(); | 
| - | 
| - JsValue jsTitle = jsSubscription.getProperty("title"); | 
| - try | 
| - { | 
| - subscription.title = jsTitle.toString(); | 
| - } | 
| - finally | 
| - { | 
| - jsTitle.dispose(); | 
| - } | 
| - | 
| - JsValue jsUrl = jsSubscription.getProperty("url"); | 
| - try | 
| - { | 
| - subscription.url = jsUrl.toString(); | 
| - } | 
| - finally | 
| - { | 
| - jsUrl.dispose(); | 
| - } | 
| - | 
| - JsValue jsSpecialization = jsSubscription.getProperty("specialization"); | 
| - try | 
| - { | 
| - subscription.specialization = jsSpecialization.toString(); | 
| - } | 
| - finally | 
| - { | 
| - jsSpecialization.dispose(); | 
| - } | 
| - | 
| - return subscription; | 
| - } | 
| - | 
| - private static org.adblockplus.libadblockplus.android.Subscription[] convertJsSubscriptions( | 
| - final List<Subscription> jsSubscriptions) | 
| - { | 
| - final org.adblockplus.libadblockplus.android.Subscription[] subscriptions = | 
| - new org.adblockplus.libadblockplus.android.Subscription[jsSubscriptions.size()]; | 
| - | 
| - for (int i = 0; i < subscriptions.length; i++) | 
| - { | 
| - subscriptions[i] = convertJsSubscription(jsSubscriptions.get(i)); | 
| - } | 
| - | 
| - return subscriptions; | 
| - } | 
| - | 
| - public org.adblockplus.libadblockplus.android.Subscription[] getRecommendedSubscriptions() | 
| - { | 
| - List<Subscription> subscriptions = this.filterEngine.fetchAvailableSubscriptions(); | 
| - try | 
| - { | 
| - return convertJsSubscriptions(subscriptions); | 
| - } | 
| - finally | 
| - { | 
| - for (Subscription eachSubscription : subscriptions) | 
| - { | 
| - eachSubscription.dispose(); | 
| - } | 
| - } | 
| - } | 
| - | 
| - public org.adblockplus.libadblockplus.android.Subscription[] getListedSubscriptions() | 
| - { | 
| - List<Subscription> subscriptions = this.filterEngine.getListedSubscriptions(); | 
| - try | 
| - { | 
| - return convertJsSubscriptions(subscriptions); | 
| - } | 
| - finally | 
| - { | 
| - for (Subscription eachSubscription : subscriptions) | 
| - { | 
| - eachSubscription.dispose(); | 
| - } | 
| - } | 
| - } | 
| - | 
| - public void clearSubscriptions() | 
| - { | 
| - for (final Subscription s : this.filterEngine.getListedSubscriptions()) | 
| - { | 
| - try | 
| - { | 
| - s.removeFromList(); | 
| - } | 
| - finally | 
| - { | 
| - s.dispose(); | 
| - } | 
| - } | 
| - } | 
| - | 
| - public void setSubscription(final String url) | 
| - { | 
| - clearSubscriptions(); | 
| - | 
| - final Subscription sub = this.filterEngine.getSubscription(url); | 
| - if (sub != null) | 
| - { | 
| - try | 
| - { | 
| - sub.addToList(); | 
| - } | 
| - finally | 
| - { | 
| - sub.dispose(); | 
| - } | 
| - } | 
| - } | 
| - | 
| - public void setSubscriptions(Collection<String> urls) | 
| - { | 
| - clearSubscriptions(); | 
| - | 
| - for (String eachUrl : urls) | 
| - { | 
| - final Subscription sub = this.filterEngine.getSubscription(eachUrl); | 
| - if (sub != null) | 
| - { | 
| - try | 
| - { | 
| - sub.addToList(); | 
| - } | 
| - finally | 
| - { | 
| - sub.dispose(); | 
| - } | 
| - } | 
| - } | 
| - } | 
| - | 
| - public void setEnabled(final boolean enabled) | 
| - { | 
| - this.enabled = enabled; | 
| - } | 
| - | 
| - public boolean isEnabled() | 
| - { | 
| - return enabled; | 
| - } | 
| - | 
| - public String getAcceptableAdsSubscriptionURL() | 
| - { | 
| - return filterEngine.getAcceptableAdsSubscriptionURL(); | 
| - } | 
| - | 
| - public boolean isAcceptableAdsEnabled() | 
| - { | 
| - return filterEngine.isAcceptableAdsEnabled(); | 
| - } | 
| - | 
| - public void setAcceptableAdsEnabled(final boolean enabled) | 
| - { | 
| - filterEngine.setAcceptableAdsEnabled(enabled); | 
| - } | 
| - | 
| - public String getDocumentationLink() | 
| - { | 
| - JsValue jsPref = this.filterEngine.getPref("documentation_link"); | 
| - try | 
| - { | 
| - return jsPref.toString(); | 
| - } | 
| - finally | 
| - { | 
| - jsPref.dispose(); | 
| - } | 
| - } | 
| - | 
| - public boolean matches(final String fullUrl, final ContentType contentType, final String[] referrerChainArray) | 
| - { | 
| - if (!enabled) | 
| - { | 
| - return false; | 
| - } | 
| - | 
| - final Filter filter = this.filterEngine.matches(fullUrl, contentType, referrerChainArray); | 
| - | 
| - if (filter == null) | 
| - { | 
| - return false; | 
| - } | 
| - | 
| - try | 
| - { | 
| - // 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 | 
| - { | 
| - JsValue jsText = filter.getProperty("text"); | 
| - try | 
| - { | 
| - if (referrerChainArray.length == 0 && (jsText.toString()).contains("||")) | 
| - { | 
| - return false; | 
| - } | 
| - } | 
| - finally | 
| - { | 
| - jsText.dispose(); | 
| - } | 
| - } | 
| - catch (NullPointerException e) | 
| - { | 
| - } | 
| - | 
| - return filter.getType() != Filter.Type.EXCEPTION; | 
| - } | 
| - finally | 
| - { | 
| - filter.dispose(); | 
| - } | 
| - } | 
| - | 
| - public boolean isDocumentWhitelisted(final String url, final String[] referrerChainArray) | 
| - { | 
| - return this.filterEngine.isDocumentWhitelisted(url, referrerChainArray); | 
| - } | 
| - | 
| - public boolean isDomainWhitelisted(final String url, final String[] referrerChainArray) | 
| - { | 
| - if (whitelistedDomains == null) | 
| - { | 
| - return false; | 
| - } | 
| - | 
| - // using Set to remove duplicates | 
| - Set<String> referrersAndResourceUrls = new HashSet<String>(); | 
| - if (referrerChainArray != null) | 
| - { | 
| - referrersAndResourceUrls.addAll(Arrays.asList(referrerChainArray)); | 
| - } | 
| - referrersAndResourceUrls.add(url); | 
| - | 
| - for (String eachUrl : referrersAndResourceUrls) | 
| - { | 
| - if (whitelistedDomains.contains(filterEngine.getHostFromURL(eachUrl))) | 
| - { | 
| - return true; | 
| - } | 
| - } | 
| - | 
| - return false; | 
| - } | 
| - | 
| - 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.enabled | 
| - || !this.elemhideEnabled | 
| - || this.isDomainWhitelisted(url, referrerChainArray) | 
| - || 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; | 
| - } | 
| - | 
| - public void setWhitelistedDomains(List<String> domains) | 
| - { | 
| - this.whitelistedDomains = domains; | 
| - } | 
| - | 
| - public List<String> getWhitelistedDomains() | 
| - { | 
| - return whitelistedDomains; | 
| - } | 
| -} |