 Issue 29389555:
  Issue 5010 - Allow to preload subscription files  (Closed)
    
  
    Issue 29389555:
  Issue 5010 - Allow to preload subscription files  (Closed) 
  | 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..3b790799b428e6638231c321a43dc2da4653caa7 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,171 @@ 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 AndroidWebRequestResourceWrapper.Listener resourceWrapperListener = | 
| + new AndroidWebRequestResourceWrapper.Listener() | 
| 
diegocarloslima
2017/03/30 09:42:07
Since this member variable never changes, you shou
 
anton
2017/03/30 10:27:16
Acknowledged.
 | 
| + { | 
| + private static final int UPDATE_DELAY_MS = 1 * 1000; | 
| + | 
| + private Handler handler = new Handler(Looper.getMainLooper()); | 
| 
diegocarloslima
2017/03/30 09:42:07
Since this member variable never changes, you shou
 
anton
2017/03/30 10:27:16
Acknowledged.
 | 
| + | 
| + private Runnable forceUpdateRunnable = new Runnable() | 
| 
diegocarloslima
2017/03/30 09:42:07
Since this member variable never changes, you shou
 | 
| + { | 
| + public void run() { | 
| + // Filter Engine can be already disposed | 
| + if (filterEngine != null) | 
| + { | 
| + Log.d(TAG, "Force update subscriptions"); | 
| + filterEngine.forceUpdateCheck(updateCheckDoneCallback); | 
| + } | 
| + } | 
| + }; | 
| + | 
| + @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"); |