| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| 3  * Copyright (C) 2006-present eyeo GmbH | 3  * Copyright (C) 2006-present eyeo GmbH | 
| 4  * | 4  * | 
| 5  * Adblock Plus is free software: you can redistribute it and/or modify | 5  * Adblock Plus is free software: you can redistribute it and/or modify | 
| 6  * it under the terms of the GNU General Public License version 3 as | 6  * it under the terms of the GNU General Public License version 3 as | 
| 7  * published by the Free Software Foundation. | 7  * published by the Free Software Foundation. | 
| 8  * | 8  * | 
| 9  * Adblock Plus is distributed in the hope that it will be useful, | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
| 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 12  * GNU General Public License for more details. | 12  * GNU General Public License for more details. | 
| 13  * | 13  * | 
| 14  * You should have received a copy of the GNU General Public License | 14  * You should have received a copy of the GNU General Public License | 
| 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 16  */ | 16  */ | 
| 17 | 17 | 
| 18 package org.adblockplus.libadblockplus.android.settings; | 18 package org.adblockplus.libadblockplus.android.settings; | 
| 19 | 19 | 
| 20 import android.content.Context; | 20 import android.content.Context; | 
| 21 import android.content.SharedPreferences; | 21 import android.content.SharedPreferences; | 
| 22 import android.net.ConnectivityManager; |  | 
| 23 import android.util.Log; | 22 import android.util.Log; | 
| 24 | 23 | 
| 25 import org.adblockplus.libadblockplus.IsAllowedConnectionCallback; |  | 
| 26 import org.adblockplus.libadblockplus.android.AdblockEngine; | 24 import org.adblockplus.libadblockplus.android.AdblockEngine; | 
| 27 import org.adblockplus.libadblockplus.android.AndroidWebRequestResourceWrapper; | 25 import org.adblockplus.libadblockplus.android.AdblockEngineProvider; | 
|  | 26 import org.adblockplus.libadblockplus.android.SingleInstanceEngineProvider; | 
| 28 import org.adblockplus.libadblockplus.android.Utils; | 27 import org.adblockplus.libadblockplus.android.Utils; | 
| 29 | 28 | 
| 30 import java.util.Map; |  | 
| 31 import java.util.concurrent.CountDownLatch; |  | 
| 32 import java.util.concurrent.atomic.AtomicInteger; |  | 
| 33 |  | 
| 34 /** | 29 /** | 
| 35  * AdblockHelper shared resources | 30  * AdblockHelper shared resources | 
| 36  * (singleton) | 31  * (singleton) | 
| 37  */ | 32  */ | 
| 38 public class AdblockHelper | 33 public class AdblockHelper | 
| 39 { | 34 { | 
| 40   private static final String TAG = Utils.getTag(AdblockHelper.class); | 35   private static final String TAG = Utils.getTag(AdblockHelper.class); | 
| 41 | 36 | 
| 42   /** | 37   /** | 
| 43    * Suggested preference name to store settings | 38    * Suggested preference name to store settings | 
| 44    */ | 39    */ | 
| 45   public static final String PREFERENCE_NAME = "ADBLOCK"; | 40   public static final String PREFERENCE_NAME = "ADBLOCK"; | 
| 46 | 41 | 
| 47   /** | 42   /** | 
| 48    * Suggested preference name to store intercepted subscription requests | 43    * Suggested preference name to store intercepted subscription requests | 
| 49    */ | 44    */ | 
| 50   public static final String PRELOAD_PREFERENCE_NAME = "ADBLOCK_PRELOAD"; | 45   public static final String PRELOAD_PREFERENCE_NAME = "ADBLOCK_PRELOAD"; | 
| 51   private static AdblockHelper _instance; | 46   private static AdblockHelper _instance; | 
| 52 | 47 | 
| 53   private Context context; | 48   private SingleInstanceEngineProvider provider; | 
| 54   private String basePath; |  | 
| 55   private boolean developmentBuild; |  | 
| 56   private String settingsPreferenceName; |  | 
| 57   private String preloadedPreferenceName; |  | 
| 58   private Map<String, Integer> urlToResourceIdMap; |  | 
| 59   private AdblockEngine engine; |  | 
| 60   private AdblockSettingsStorage storage; | 49   private AdblockSettingsStorage storage; | 
| 61   private CountDownLatch engineCreated; |  | 
| 62   private Long v8IsolateProviderPtr; |  | 
| 63 | 50 | 
| 64   /* | 51   private final Runnable engineCreatedCallback = new Runnable() | 
| 65     Simple ARC management for AdblockEngine | 52   { | 
| 66     Use `retain` and `release` | 53     @Override | 
| 67    */ | 54     public void run() | 
|  | 55     { | 
|  | 56       AdblockSettings settings = storage.load(); | 
|  | 57       if (settings != null) | 
|  | 58       { | 
|  | 59         Log.d(TAG, "Applying saved adblock settings to adblock engine"); | 
|  | 60         // apply last saved settings to adblock engine. | 
|  | 61         // all the settings except `enabled` and whitelisted domains list | 
|  | 62         // are saved by adblock engine itself | 
|  | 63         provider.getEngine().setEnabled(settings.isAdblockEnabled()); | 
|  | 64         provider.getEngine().setWhitelistedDomains(settings.getWhitelistedDomain
     s()); | 
| 68 | 65 | 
| 69   private AtomicInteger referenceCounter = new AtomicInteger(0); | 66         // allowed connection type is saved by filter engine but we need to over
     ride it | 
|  | 67         // as filter engine can be not created when changing | 
|  | 68         String connectionType = (settings.getAllowedConnectionType() != null | 
|  | 69           ? settings.getAllowedConnectionType().getValue() | 
|  | 70           : null); | 
|  | 71         provider.getEngine().getFilterEngine().setAllowedConnectionType(connecti
     onType); | 
|  | 72       } | 
|  | 73       else | 
|  | 74       { | 
|  | 75         Log.w(TAG, "No saved adblock settings"); | 
|  | 76       } | 
|  | 77     } | 
|  | 78   }; | 
|  | 79 | 
|  | 80   private final Runnable engineDisposedCallback = new Runnable() | 
|  | 81   { | 
|  | 82     @Override | 
|  | 83     public void run() | 
|  | 84     { | 
|  | 85       Log.d(TAG, "Releasing adblock settings storage"); | 
|  | 86       storage = null; | 
|  | 87     } | 
|  | 88   }; | 
| 70 | 89 | 
| 71   // singleton | 90   // singleton | 
| 72   protected AdblockHelper() | 91   protected AdblockHelper() | 
| 73   { | 92   { | 
| 74     // prevents instantiation | 93     // prevents instantiation | 
| 75   } | 94   } | 
| 76 | 95 | 
| 77   /** | 96   /** | 
| 78    * Use to get AdblockHelper instance | 97    * Use to get AdblockHelper instance | 
| 79    * @return adblock instance | 98    * @return adblock instance | 
| 80    */ | 99    */ | 
| 81   public static synchronized AdblockHelper get() | 100   public static synchronized AdblockHelper get() | 
| 82   { | 101   { | 
| 83     if (_instance == null) | 102     if (_instance == null) | 
| 84     { | 103     { | 
| 85       _instance = new AdblockHelper(); | 104       _instance = new AdblockHelper(); | 
| 86     } | 105     } | 
| 87 | 106 | 
| 88     return _instance; | 107     return _instance; | 
| 89   } | 108   } | 
| 90 | 109 | 
| 91   public AdblockEngine getEngine() | 110   public AdblockEngineProvider getProvider() | 
| 92   { | 111   { | 
| 93     return engine; | 112     if (provider == null) | 
|  | 113     { | 
|  | 114       throw new IllegalStateException("Usage exception: call init(...) first"); | 
|  | 115     } | 
|  | 116     return provider; | 
| 94   } | 117   } | 
| 95 | 118 | 
| 96   public AdblockSettingsStorage getStorage() | 119   public AdblockSettingsStorage getStorage() | 
| 97   { | 120   { | 
|  | 121     if (storage == null) | 
|  | 122     { | 
|  | 123       throw new IllegalStateException("Usage exception: call init(...) first"); | 
|  | 124     } | 
| 98     return storage; | 125     return storage; | 
| 99   } | 126   } | 
| 100 | 127 | 
| 101   /** | 128   /** | 
| 102    * Init with context | 129    * Init with context | 
| 103    * @param context application context | 130    * @param context application context | 
| 104    * @param basePath file system root to store files | 131    * @param basePath file system root to store files | 
| 105    * | 132    * | 
| 106    *                 Adblock Plus library will download subscription files and s
     tore them on | 133    *                 Adblock Plus library will download subscription files and s
     tore them on | 
| 107    *                 the path passed. The path should exist and the directory co
     ntent should not be | 134    *                 the path passed. The path should exist and the directory co
     ntent should not be | 
| 108    *                 cleared out occasionally. Using `context.getCacheDir().getA
     bsolutePath()` is not | 135    *                 cleared out occasionally. Using `context.getCacheDir().getA
     bsolutePath()` is not | 
| 109    *                 recommended because it can be cleared by the system. | 136    *                 recommended because it can be cleared by the system. | 
| 110    * @param developmentBuild debug or release? | 137    * @param developmentBuild debug or release? | 
| 111    * @param preferenceName Shared Preferences name to store adblock settings | 138    * @param preferenceName Shared Preferences name to store adblock settings | 
| 112    */ | 139    */ | 
| 113   public AdblockHelper init(Context context, String basePath, | 140   public SingleInstanceEngineProvider init(Context context, String basePath, | 
| 114                             boolean developmentBuild, String preferenceName) | 141                                            boolean developmentBuild, String pref
     erenceName) | 
| 115   { | 142   { | 
| 116     this.context = context.getApplicationContext(); | 143     initProvider(context, basePath, developmentBuild); | 
| 117     this.basePath = basePath; | 144     initStorage(context, preferenceName); | 
| 118     this.developmentBuild = developmentBuild; | 145     return provider; | 
| 119     this.settingsPreferenceName = preferenceName; |  | 
| 120     return this; |  | 
| 121   } | 146   } | 
| 122 | 147 | 
| 123   /** | 148   private void initProvider(Context context, String basePath, boolean developmen
     tBuild) | 
| 124    * Use preloaded subscriptions |  | 
| 125    * @param preferenceName Shared Preferences name to store intercepted requests
      stats |  | 
| 126    * @param urlToResourceIdMap |  | 
| 127    */ |  | 
| 128   public AdblockHelper preloadSubscriptions(String preferenceName, Map<String, I
     nteger> urlToResourceIdMap) |  | 
| 129   { | 149   { | 
| 130     this.preloadedPreferenceName = preferenceName; | 150     provider = new SingleInstanceEngineProvider(context, basePath, developmentBu
     ild); | 
| 131     this.urlToResourceIdMap = urlToResourceIdMap; | 151     provider.setEngineCreatedCallback(engineCreatedCallback); | 
| 132     return this; | 152     provider.setEngineDisposedCallback(engineDisposedCallback); | 
| 133   } | 153   } | 
| 134 | 154 | 
| 135   public AdblockHelper useV8IsolateProvider(long ptr) | 155   private void initStorage(Context context, String settingsPreferenceName) | 
| 136   { | 156   { | 
| 137     this.v8IsolateProviderPtr = ptr; |  | 
| 138     return this; |  | 
| 139   } |  | 
| 140 |  | 
| 141   private void createAdblock() |  | 
| 142   { |  | 
| 143     ConnectivityManager connectivityManager = |  | 
| 144       (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVIC
     E); |  | 
| 145     IsAllowedConnectionCallback isAllowedConnectionCallback = new IsAllowedConne
     ctionCallbackImpl(connectivityManager); |  | 
| 146 |  | 
| 147     Log.d(TAG, "Creating adblock engine ..."); |  | 
| 148 |  | 
| 149     // read and apply current settings | 157     // read and apply current settings | 
| 150     SharedPreferences settingsPrefs = context.getSharedPreferences( | 158     SharedPreferences settingsPrefs = context.getSharedPreferences( | 
| 151       settingsPreferenceName, | 159       settingsPreferenceName, | 
| 152       Context.MODE_PRIVATE); | 160       Context.MODE_PRIVATE); | 
|  | 161 | 
| 153     storage = new SharedPrefsStorage(settingsPrefs); | 162     storage = new SharedPrefsStorage(settingsPrefs); | 
| 154 |  | 
| 155     AdblockEngine.Builder builder = AdblockEngine |  | 
| 156       .builder( |  | 
| 157         AdblockEngine.generateAppInfo(context, developmentBuild), |  | 
| 158         basePath) |  | 
| 159       .setIsAllowedConnectionCallback(isAllowedConnectionCallback) |  | 
| 160       .enableElementHiding(true); |  | 
| 161 |  | 
| 162     if (v8IsolateProviderPtr != null) |  | 
| 163     { |  | 
| 164       builder.useV8IsolateProvider(v8IsolateProviderPtr); |  | 
| 165     } |  | 
| 166 |  | 
| 167     // if preloaded subscriptions provided |  | 
| 168     if (preloadedPreferenceName != null) |  | 
| 169     { |  | 
| 170       SharedPreferences preloadedSubscriptionsPrefs = context.getSharedPreferenc
     es( |  | 
| 171         preloadedPreferenceName, |  | 
| 172         Context.MODE_PRIVATE); |  | 
| 173       builder.preloadSubscriptions( |  | 
| 174         context, |  | 
| 175         urlToResourceIdMap, |  | 
| 176         new AndroidWebRequestResourceWrapper.SharedPrefsStorage(preloadedSubscri
     ptionsPrefs)); |  | 
| 177     } |  | 
| 178 |  | 
| 179     engine = builder.build(); |  | 
| 180 |  | 
| 181     Log.d(TAG, "AdblockHelper engine created"); |  | 
| 182 |  | 
| 183     AdblockSettings settings = storage.load(); |  | 
| 184     if (settings != null) |  | 
| 185     { |  | 
| 186       Log.d(TAG, "Applying saved adblock settings to adblock engine"); |  | 
| 187       // apply last saved settings to adblock engine |  | 
| 188 |  | 
| 189       // all the settings except `enabled` and whitelisted domains list |  | 
| 190       // are saved by adblock engine itself |  | 
| 191       engine.setEnabled(settings.isAdblockEnabled()); |  | 
| 192       engine.setWhitelistedDomains(settings.getWhitelistedDomains()); |  | 
| 193 |  | 
| 194       // allowed connection type is saved by filter engine but we need to overri
     de it |  | 
| 195       // as filter engine can be not created when changing |  | 
| 196       String connectionType = (settings.getAllowedConnectionType() != null |  | 
| 197        ? settings.getAllowedConnectionType().getValue() |  | 
| 198        : null); |  | 
| 199       engine.getFilterEngine().setAllowedConnectionType(connectionType); |  | 
| 200     } |  | 
| 201     else |  | 
| 202     { |  | 
| 203       Log.w(TAG, "No saved adblock settings"); |  | 
| 204     } |  | 
| 205   } | 163   } | 
| 206 | 164 | 
| 207   /** | 165   /** | 
| 208    * Wait until everything is ready (used for `retain(true)`) | 166    * @deprecated The method is deprecated: use .getProvider().retain() instead | 
| 209    * Warning: locks current thread |  | 
| 210    */ | 167    */ | 
| 211   public void waitForReady() | 168   @Deprecated | 
|  | 169   public boolean retain(boolean asynchronous) | 
| 212   { | 170   { | 
| 213     if (engineCreated == null) | 171     return provider.retain(asynchronous); | 
| 214     { |  | 
| 215       throw new RuntimeException("AdblockHelper Plus usage exception: call retai
     n(true) first"); |  | 
| 216     } |  | 
| 217 |  | 
| 218     try |  | 
| 219     { |  | 
| 220       Log.d(TAG, "Waiting for ready ..."); |  | 
| 221       engineCreated.await(); |  | 
| 222       Log.d(TAG, "Ready"); |  | 
| 223     } |  | 
| 224     catch (InterruptedException e) |  | 
| 225     { |  | 
| 226       Log.w(TAG, "Interrupted", e); |  | 
| 227     } |  | 
| 228   } |  | 
| 229 |  | 
| 230   private void disposeAdblock() |  | 
| 231   { |  | 
| 232     Log.w(TAG, "Disposing adblock engine"); |  | 
| 233 |  | 
| 234     engine.dispose(); |  | 
| 235     engine = null; |  | 
| 236 |  | 
| 237     storage = null; |  | 
| 238   } | 172   } | 
| 239 | 173 | 
| 240   /** | 174   /** | 
| 241    * Get registered clients count | 175    * @deprecated The method is deprecated: use .getProvider().waitForReady() ins
     tead | 
| 242    * @return registered clients count |  | 
| 243    */ | 176    */ | 
| 244   public int getCounter() | 177   @Deprecated | 
|  | 178   public void waitForReady() | 
| 245   { | 179   { | 
| 246     return referenceCounter.get(); | 180     provider.waitForReady(); | 
| 247   } | 181   } | 
| 248 | 182 | 
| 249   /** | 183   /** | 
| 250    * Register AdblockHelper engine client | 184    * @deprecated The method is deprecated: use .getProvider().getEngine() instea
     d | 
| 251    * @param asynchronous If `true` engines will be created in background thread 
     without locking of |  | 
| 252    *                     current thread. Use waitForReady() before getEngine() l
     ater. |  | 
| 253    *                     If `false` locks current thread. |  | 
| 254    * @return if a new instance is allocated |  | 
| 255    */ | 185    */ | 
| 256   public synchronized boolean retain(boolean asynchronous) | 186   @Deprecated | 
|  | 187   public AdblockEngine getEngine() | 
| 257   { | 188   { | 
| 258     boolean firstInstance = false; | 189     return provider.getEngine(); | 
| 259 |  | 
| 260     if (referenceCounter.getAndIncrement() == 0) |  | 
| 261     { |  | 
| 262       firstInstance = true; |  | 
| 263 |  | 
| 264       if (!asynchronous) |  | 
| 265       { |  | 
| 266         createAdblock(); |  | 
| 267       } |  | 
| 268       else |  | 
| 269       { |  | 
| 270         // latch is required for async (see `waitForReady()`) |  | 
| 271         engineCreated = new CountDownLatch(1); |  | 
| 272 |  | 
| 273         new Thread(new Runnable() |  | 
| 274         { |  | 
| 275           @Override |  | 
| 276           public void run() |  | 
| 277           { |  | 
| 278             createAdblock(); |  | 
| 279 |  | 
| 280             // unlock waiting client thread |  | 
| 281             engineCreated.countDown(); |  | 
| 282           } |  | 
| 283         }).start(); |  | 
| 284       } |  | 
| 285     } |  | 
| 286     return firstInstance; |  | 
| 287   } | 190   } | 
| 288 | 191 | 
| 289   /** | 192   /** | 
| 290    * Unregister AdblockHelper engine client | 193    * @deprecated The method is deprecated: use .getProvider().release() instead | 
| 291    * @return `true` if the last instance is destroyed |  | 
| 292    */ | 194    */ | 
| 293   public synchronized boolean release() | 195   @Deprecated | 
|  | 196   public boolean release() | 
| 294   { | 197   { | 
| 295     boolean lastInstance = false; | 198     return provider.release(); | 
|  | 199   } | 
| 296 | 200 | 
| 297     if (referenceCounter.decrementAndGet() == 0) | 201   /** | 
| 298     { | 202    * @deprecated The method is deprecated: use .getProvider().getCounter() inste
     ad | 
| 299       lastInstance = true; | 203    */ | 
| 300 | 204   @Deprecated | 
| 301       if (engineCreated != null) | 205   public int getCounter() | 
| 302       { | 206   { | 
| 303         // retained asynchronously | 207     return provider.getCounter(); | 
| 304         waitForReady(); |  | 
| 305         disposeAdblock(); |  | 
| 306 |  | 
| 307         // to unlock waiting client in waitForReady() |  | 
| 308         engineCreated.countDown(); |  | 
| 309         engineCreated = null; |  | 
| 310       } |  | 
| 311       else |  | 
| 312       { |  | 
| 313         disposeAdblock(); |  | 
| 314       } |  | 
| 315     } |  | 
| 316     return lastInstance; |  | 
| 317   } | 208   } | 
| 318 } | 209 } | 
| OLD | NEW | 
|---|