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 |
index 2b6138245dddd39e780ee5c851f7b584956c9681..56e403c81eb9e2e90e3701a4158581ebd82ca93e 100644 |
--- a/libadblockplus-android/src/org/adblockplus/libadblockplus/android/AdblockEngine.java |
+++ b/libadblockplus-android/src/org/adblockplus/libadblockplus/android/AdblockEngine.java |
@@ -23,6 +23,7 @@ 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; |
@@ -36,15 +37,21 @@ 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.NameNotFoundException; |
import android.os.Build.VERSION; |
+import android.os.Handler; |
+import android.os.Looper; |
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); |
/* |
@@ -61,19 +68,14 @@ public final class AdblockEngine |
private volatile JsEngine jsEngine; |
private volatile FilterEngine filterEngine; |
private volatile LogSystem logSystem; |
- private volatile AndroidWebRequest webRequest; |
+ private volatile WebRequest webRequest; |
private volatile UpdateAvailableCallback updateAvailableCallback; |
private volatile UpdateCheckDoneCallback updateCheckDoneCallback; |
private volatile FilterChangeCallback filterChangeCallback; |
private volatile ShowNotificationCallback showNotificationCallback; |
- private final boolean elemhideEnabled; |
+ private volatile boolean elemhideEnabled; |
private volatile boolean enabled = true; |
- private List<String> whitelistedDomains; |
- |
- private AdblockEngine(final boolean enableElemhide) |
- { |
- this.elemhideEnabled = enableElemhide; |
- } |
+ private volatile List<String> whitelistedDomains; |
public static AppInfo generateAppInfo(final Context context, boolean developmentBuild) |
{ |
@@ -100,59 +102,182 @@ public final class AdblockEngine |
.build(); |
} |
- public static AdblockEngine create(final AppInfo appInfo, |
- final String basePath, boolean enableElemhide, |
- UpdateAvailableCallback updateAvailableCallback, |
- UpdateCheckDoneCallback updateCheckDoneCallback, |
- ShowNotificationCallback showNotificationCallback, |
- FilterChangeCallback filterChangeCallback) |
+ /** |
+ * Builds Adblock engine |
+ */ |
+ public static class Builder |
{ |
- Log.w(TAG, "Create"); |
+ private Context context; |
+ private Map<String, Integer> URLtoResourceIdMap; |
+ private AndroidWebRequestResourceWrapper.Storage resourceStorage; |
+ private AndroidWebRequest androidWebRequest; |
+ private AppInfo appInfo; |
+ private String basePath; |
- final AdblockEngine engine = new AdblockEngine(enableElemhide); |
+ private AdblockEngine engine; |
- engine.jsEngine = new JsEngine(appInfo); |
- engine.jsEngine.setDefaultFileSystem(basePath); |
+ protected Builder(final AppInfo appInfo, final String basePath) |
+ { |
+ engine = new AdblockEngine(); |
+ engine.elemhideEnabled = true; |
- engine.logSystem = new AndroidLogSystem(); |
- engine.jsEngine.setLogSystem(engine.logSystem); |
+ // 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; |
+ } |
- engine.webRequest = new AndroidWebRequest(enableElemhide); |
- engine.jsEngine.setWebRequest(engine.webRequest); |
+ public Builder enableElementHiding(boolean enable) |
+ { |
+ engine.elemhideEnabled = enable; |
+ return this; |
+ } |
- engine.filterEngine = new FilterEngine(engine.jsEngine); |
+ public Builder preloadSubscriptions(Context context, |
+ Map<String, Integer> URLtoResourceIdMap, |
+ AndroidWebRequestResourceWrapper.Storage storage) |
+ { |
+ this.context = context; |
+ this.URLtoResourceIdMap = URLtoResourceIdMap; |
+ this.resourceStorage = storage; |
+ return this; |
+ } |
- engine.updateAvailableCallback = updateAvailableCallback; |
- if (engine.updateAvailableCallback != null) |
+ public Builder setUpdateAvailableCallback(UpdateAvailableCallback callback) |
{ |
- engine.filterEngine.setUpdateAvailableCallback(updateAvailableCallback); |
+ engine.updateAvailableCallback = callback; |
+ return this; |
} |
- engine.updateCheckDoneCallback = updateCheckDoneCallback; |
+ public Builder setUpdateCheckDoneCallback(UpdateCheckDoneCallback callback) |
+ { |
+ engine.updateCheckDoneCallback = callback; |
+ return this; |
+ } |
- engine.showNotificationCallback = showNotificationCallback; |
- if (engine.showNotificationCallback != null) |
+ public Builder setShowNotificationCallback(ShowNotificationCallback callback) |
{ |
- engine.filterEngine.setShowNotificationCallback(showNotificationCallback); |
+ engine.showNotificationCallback = callback; |
+ return this; |
} |
- engine.filterChangeCallback = filterChangeCallback; |
- if (engine.filterChangeCallback != null) |
+ public Builder setFilterChangeCallback(FilterChangeCallback callback) |
{ |
- engine.filterEngine.setFilterChangeCallback(filterChangeCallback); |
+ engine.filterChangeCallback = callback; |
+ return this; |
} |
- engine.webRequest.updateSubscriptionURLs(engine.filterEngine); |
+ private void initRequests() |
+ { |
+ androidWebRequest = new AndroidWebRequest(engine.elemhideEnabled); |
+ engine.webRequest = androidWebRequest; |
- return engine; |
+ if (URLtoResourceIdMap != null) |
+ { |
+ AndroidWebRequestResourceWrapper wrapper = new AndroidWebRequestResourceWrapper( |
+ context, engine.webRequest, URLtoResourceIdMap, resourceStorage); |
+ wrapper.setListener(engine.resourceWrapperListener); |
+ |
+ 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(); |
+ |
+ androidWebRequest.updateSubscriptionURLs(engine.filterEngine); |
+ |
+ return engine; |
+ } |
+ |
+ private void createEngines() |
+ { |
+ engine.jsEngine = new JsEngine(appInfo); |
+ engine.jsEngine.setDefaultFileSystem(basePath); |
+ |
+ engine.jsEngine.setWebRequest(engine.webRequest); |
+ |
+ engine.logSystem = new AndroidLogSystem(); |
+ engine.jsEngine.setLogSystem(engine.logSystem); |
+ |
+ engine.filterEngine = new FilterEngine(engine.jsEngine); |
+ } |
} |
- public static AdblockEngine create(final AppInfo appInfo, |
- final String basePath, boolean elemhideEnabled) |
+ public static Builder builder(AppInfo appInfo, String basePath) |
{ |
- return create(appInfo, basePath, elemhideEnabled, null, null, null, null); |
+ return new Builder(appInfo, basePath); |
} |
+ private final AndroidWebRequestResourceWrapper.Listener resourceWrapperListener = |
+ new AndroidWebRequestResourceWrapper.Listener() |
+ { |
+ private static final int UPDATE_DELAY_MS = 1 * 1000; |
+ |
+ private final Handler handler = new Handler(Looper.getMainLooper()); |
+ |
+ private final Runnable forceUpdateRunnable = new Runnable() |
+ { |
+ public void run() { |
+ // Filter Engine can be already disposed |
+ if (filterEngine != null) |
+ { |
+ Log.d(TAG, "Force update subscriptions"); |
+ List<Subscription> subscriptions = filterEngine.getListedSubscriptions(); |
+ for (Subscription eachSubscription : subscriptions) |
sergei
2017/03/30 22:14:37
Nit: I would remove "each".
|
+ { |
+ try |
+ { |
+ eachSubscription.updateFilters(); |
+ } |
+ finally |
+ { |
+ eachSubscription.dispose(); |
+ } |
+ } |
+ } |
+ } |
+ }; |
+ |
+ @Override |
+ public void onIntercepted(String url, int resourceId) |
+ { |
+ // we need to force update subscriptions ASAP after preloaded one is returned |
+ // but we should note that multiple interceptions (for main easylist and AA) and force update once only |
+ |
+ // adding into main thread queue to avoid concurrency issues (start update while updating) |
+ // as usually onIntercepted() is invoked in background thread |
+ handler.removeCallbacks(forceUpdateRunnable); |
+ handler.postDelayed(forceUpdateRunnable, UPDATE_DELAY_MS); |
+ |
+ Log.d(TAG, "Scheduled force update in " + UPDATE_DELAY_MS); |
+ } |
+ }; |
+ |
public void dispose() |
{ |
Log.w(TAG, "Dispose"); |