| 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 package org.adblockplus.libadblockplus.android; | 
|   17  |   18  | 
|   18 package org.adblockplus.libadblockplus.android.settings; |   19 import org.adblockplus.libadblockplus.IsAllowedConnectionCallback; | 
|   19  |   20  | 
|   20 import android.content.Context; |   21 import android.content.Context; | 
|   21 import android.content.SharedPreferences; |   22 import android.content.SharedPreferences; | 
|   22 import android.net.ConnectivityManager; |   23 import android.net.ConnectivityManager; | 
|   23 import android.util.Log; |   24 import android.util.Log; | 
|   24  |   25  | 
|   25 import org.adblockplus.libadblockplus.IsAllowedConnectionCallback; |  | 
|   26 import org.adblockplus.libadblockplus.android.AdblockEngine; |  | 
|   27 import org.adblockplus.libadblockplus.android.AndroidWebRequestResourceWrapper; |  | 
|   28 import org.adblockplus.libadblockplus.android.Utils; |  | 
|   29  |  | 
|   30 import java.util.Map; |   26 import java.util.Map; | 
|   31 import java.util.concurrent.CountDownLatch; |   27 import java.util.concurrent.CountDownLatch; | 
|   32 import java.util.concurrent.atomic.AtomicInteger; |   28 import java.util.concurrent.atomic.AtomicInteger; | 
|   33  |   29  | 
|   34 /** |   30 /** | 
|   35  * AdblockHelper shared resources |   31  * Provides single instance of AdblockEngine shared between registered clients | 
|   36  * (singleton) |  | 
|   37  */ |   32  */ | 
|   38 public class AdblockHelper |   33 public class SingleInstanceEngineProvider implements AdblockEngineProvider | 
|   39 { |   34 { | 
|   40   private static final String TAG = Utils.getTag(AdblockHelper.class); |   35   private static final String TAG = Utils.getTag(SingleInstanceEngineProvider.cl
     ass); | 
|   41  |  | 
|   42   /** |  | 
|   43    * Suggested preference name to store settings |  | 
|   44    */ |  | 
|   45   public static final String PREFERENCE_NAME = "ADBLOCK"; |  | 
|   46  |  | 
|   47   /** |  | 
|   48    * Suggested preference name to store intercepted subscription requests |  | 
|   49    */ |  | 
|   50   public static final String PRELOAD_PREFERENCE_NAME = "ADBLOCK_PRELOAD"; |  | 
|   51   private static AdblockHelper _instance; |  | 
|   52  |   36  | 
|   53   private Context context; |   37   private Context context; | 
|   54   private String basePath; |   38   private String basePath; | 
|   55   private boolean developmentBuild; |   39   private boolean developmentBuild; | 
|   56   private String settingsPreferenceName; |  | 
|   57   private String preloadedPreferenceName; |   40   private String preloadedPreferenceName; | 
|   58   private Map<String, Integer> urlToResourceIdMap; |   41   private Map<String, Integer> urlToResourceIdMap; | 
|   59   private AdblockEngine engine; |   42   private AdblockEngine engine; | 
|   60   private AdblockSettingsStorage storage; |  | 
|   61   private CountDownLatch engineCreated; |   43   private CountDownLatch engineCreated; | 
|   62   private Long v8IsolateProviderPtr; |   44   private Long v8IsolateProviderPtr; | 
 |   45   private Runnable engineCreatedCallback; | 
 |   46   private Runnable engineDisposedCallback; | 
|   63  |   47  | 
|   64   /* |   48   /* | 
|   65     Simple ARC management for AdblockEngine |   49     Simple ARC management for AdblockEngine | 
|   66     Use `retain` and `release` |   50     Use `retain` and `release` | 
|   67    */ |   51    */ | 
|   68  |   52  | 
|   69   private AtomicInteger referenceCounter = new AtomicInteger(0); |   53   private AtomicInteger referenceCounter = new AtomicInteger(0); | 
|   70  |   54  | 
|   71   // singleton |  | 
|   72   protected AdblockHelper() |  | 
|   73   { |  | 
|   74     // prevents instantiation |  | 
|   75   } |  | 
|   76  |  | 
|   77   /** |  | 
|   78    * Use to get AdblockHelper instance |  | 
|   79    * @return adblock instance |  | 
|   80    */ |  | 
|   81   public static synchronized AdblockHelper get() |  | 
|   82   { |  | 
|   83     if (_instance == null) |  | 
|   84     { |  | 
|   85       _instance = new AdblockHelper(); |  | 
|   86     } |  | 
|   87  |  | 
|   88     return _instance; |  | 
|   89   } |  | 
|   90  |  | 
|   91   public AdblockEngine getEngine() |  | 
|   92   { |  | 
|   93     return engine; |  | 
|   94   } |  | 
|   95  |  | 
|   96   public AdblockSettingsStorage getStorage() |  | 
|   97   { |  | 
|   98     return storage; |  | 
|   99   } |  | 
|  100  |  | 
|  101   /** |   55   /** | 
|  102    * Init with context |   56    * Init with context | 
|  103    * @param context application context |   57    * @param context application context | 
|  104    * @param basePath file system root to store files |   58    * @param basePath file system root to store files | 
|  105    * |   59    * | 
|  106    *                 Adblock Plus library will download subscription files and s
     tore them on |   60    *                 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 |   61    *                 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 |   62    *                 cleared out occasionally. Using `context.getCacheDir().getA
     bsolutePath()` is not | 
|  109    *                 recommended because it can be cleared by the system. |   63    *                 recommended because it can be cleared by the system. | 
|  110    * @param developmentBuild debug or release? |   64    * @param developmentBuild debug or release? | 
|  111    * @param preferenceName Shared Preferences name to store adblock settings |  | 
|  112    */ |   65    */ | 
|  113   public AdblockHelper init(Context context, String basePath, |   66   public SingleInstanceEngineProvider(Context context, String basePath, boolean 
     developmentBuild) | 
|  114                             boolean developmentBuild, String preferenceName) |  | 
|  115   { |   67   { | 
|  116     this.context = context.getApplicationContext(); |   68     this.context = context.getApplicationContext(); | 
|  117     this.basePath = basePath; |   69     this.basePath = basePath; | 
|  118     this.developmentBuild = developmentBuild; |   70     this.developmentBuild = developmentBuild; | 
|  119     this.settingsPreferenceName = preferenceName; |  | 
|  120     return this; |  | 
|  121   } |   71   } | 
|  122  |   72  | 
|  123   /** |   73   /** | 
|  124    * Use preloaded subscriptions |   74    * Use preloaded subscriptions | 
|  125    * @param preferenceName Shared Preferences name to store intercepted requests
      stats |   75    * @param preferenceName Shared Preferences name to store intercepted requests
      stats | 
|  126    * @param urlToResourceIdMap |   76    * @param urlToResourceIdMap | 
|  127    */ |   77    */ | 
|  128   public AdblockHelper preloadSubscriptions(String preferenceName, Map<String, I
     nteger> urlToResourceIdMap) |   78   public SingleInstanceEngineProvider preloadSubscriptions(String preferenceName
     , | 
 |   79                                                            Map<String, Integer> 
     urlToResourceIdMap) | 
|  129   { |   80   { | 
|  130     this.preloadedPreferenceName = preferenceName; |   81     this.preloadedPreferenceName = preferenceName; | 
|  131     this.urlToResourceIdMap = urlToResourceIdMap; |   82     this.urlToResourceIdMap = urlToResourceIdMap; | 
|  132     return this; |   83     return this; | 
|  133   } |   84   } | 
|  134  |   85  | 
|  135   public AdblockHelper useV8IsolateProvider(long ptr) |   86   public SingleInstanceEngineProvider useV8IsolateProvider(long ptr) | 
|  136   { |   87   { | 
|  137     this.v8IsolateProviderPtr = ptr; |   88     this.v8IsolateProviderPtr = ptr; | 
|  138     return this; |   89     return this; | 
|  139   } |   90   } | 
|  140  |   91  | 
 |   92   public SingleInstanceEngineProvider setEngineCreatedCallback(Runnable callback
     ) | 
 |   93   { | 
 |   94     this.engineCreatedCallback = callback; | 
 |   95     return this; | 
 |   96   } | 
 |   97  | 
 |   98   public SingleInstanceEngineProvider setEngineDisposedCallback(Runnable callbac
     k) | 
 |   99   { | 
 |  100     this.engineDisposedCallback = callback; | 
 |  101     return this; | 
 |  102   } | 
 |  103  | 
|  141   private void createAdblock() |  104   private void createAdblock() | 
|  142   { |  105   { | 
|  143     ConnectivityManager connectivityManager = |  106     ConnectivityManager connectivityManager = | 
|  144       (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVIC
     E); |  107       (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVIC
     E); | 
|  145     IsAllowedConnectionCallback isAllowedConnectionCallback = new IsAllowedConne
     ctionCallbackImpl(connectivityManager); |  108     IsAllowedConnectionCallback isAllowedConnectionCallback = | 
 |  109       new IsAllowedConnectionCallbackImpl(connectivityManager); | 
|  146  |  110  | 
|  147     Log.d(TAG, "Creating adblock engine ..."); |  111     Log.d(TAG, "Creating adblock engine ..."); | 
|  148  |  112  | 
|  149     // read and apply current settings |  | 
|  150     SharedPreferences settingsPrefs = context.getSharedPreferences( |  | 
|  151       settingsPreferenceName, |  | 
|  152       Context.MODE_PRIVATE); |  | 
|  153     storage = new SharedPrefsStorage(settingsPrefs); |  | 
|  154  |  | 
|  155     AdblockEngine.Builder builder = AdblockEngine |  113     AdblockEngine.Builder builder = AdblockEngine | 
|  156       .builder( |  114       .builder( | 
|  157         AdblockEngine.generateAppInfo(context, developmentBuild), |  115         AdblockEngine.generateAppInfo(context, developmentBuild), | 
|  158         basePath) |  116         basePath) | 
|  159       .setIsAllowedConnectionCallback(isAllowedConnectionCallback) |  117       .setIsAllowedConnectionCallback(isAllowedConnectionCallback) | 
|  160       .enableElementHiding(true); |  118       .enableElementHiding(true); | 
|  161  |  119  | 
|  162     if (v8IsolateProviderPtr != null) |  120     if (v8IsolateProviderPtr != null) | 
|  163     { |  121     { | 
|  164       builder.useV8IsolateProvider(v8IsolateProviderPtr); |  122       builder.useV8IsolateProvider(v8IsolateProviderPtr); | 
|  165     } |  123     } | 
|  166  |  124  | 
|  167     // if preloaded subscriptions provided |  125     // if preloaded subscriptions provided | 
|  168     if (preloadedPreferenceName != null) |  126     if (preloadedPreferenceName != null) | 
|  169     { |  127     { | 
|  170       SharedPreferences preloadedSubscriptionsPrefs = context.getSharedPreferenc
     es( |  128       SharedPreferences preloadedSubscriptionsPrefs = context.getSharedPreferenc
     es( | 
|  171         preloadedPreferenceName, |  129         preloadedPreferenceName, | 
|  172         Context.MODE_PRIVATE); |  130         Context.MODE_PRIVATE); | 
|  173       builder.preloadSubscriptions( |  131       builder.preloadSubscriptions( | 
|  174         context, |  132         context, | 
|  175         urlToResourceIdMap, |  133         urlToResourceIdMap, | 
|  176         new AndroidWebRequestResourceWrapper.SharedPrefsStorage(preloadedSubscri
     ptionsPrefs)); |  134         new AndroidWebRequestResourceWrapper.SharedPrefsStorage(preloadedSubscri
     ptionsPrefs)); | 
|  177     } |  135     } | 
|  178  |  136  | 
|  179     engine = builder.build(); |  137     engine = builder.build(); | 
|  180  |  138  | 
|  181     Log.d(TAG, "AdblockHelper engine created"); |  139     Log.d(TAG, "AdblockHelper engine created"); | 
|  182  |  140  | 
|  183     AdblockSettings settings = storage.load(); |  141     // sometimes we need to init AdblockEngine instance, eg. set user settings | 
|  184     if (settings != null) |  142     if (engineCreatedCallback != null) | 
|  185     { |  143     { | 
|  186       Log.d(TAG, "Applying saved adblock settings to adblock engine"); |  144       engineCreatedCallback.run(); | 
|  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     } |  145     } | 
|  205   } |  146   } | 
|  206  |  147  | 
|  207   /** |  148   @Override | 
|  208    * Wait until everything is ready (used for `retain(true)`) |  | 
|  209    * Warning: locks current thread |  | 
|  210    */ |  | 
|  211   public void waitForReady() |  | 
|  212   { |  | 
|  213     if (engineCreated == null) |  | 
|  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   } |  | 
|  239  |  | 
|  240   /** |  | 
|  241    * Get registered clients count |  | 
|  242    * @return registered clients count |  | 
|  243    */ |  | 
|  244   public int getCounter() |  | 
|  245   { |  | 
|  246     return referenceCounter.get(); |  | 
|  247   } |  | 
|  248  |  | 
|  249   /** |  | 
|  250    * Register AdblockHelper engine client |  | 
|  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    */ |  | 
|  256   public synchronized boolean retain(boolean asynchronous) |  149   public synchronized boolean retain(boolean asynchronous) | 
|  257   { |  150   { | 
|  258     boolean firstInstance = false; |  151     boolean firstInstance = false; | 
|  259  |  152  | 
|  260     if (referenceCounter.getAndIncrement() == 0) |  153     if (referenceCounter.getAndIncrement() == 0) | 
|  261     { |  154     { | 
|  262       firstInstance = true; |  155       firstInstance = true; | 
|  263  |  156  | 
|  264       if (!asynchronous) |  157       if (!asynchronous) | 
|  265       { |  158       { | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|  279  |  172  | 
|  280             // unlock waiting client thread |  173             // unlock waiting client thread | 
|  281             engineCreated.countDown(); |  174             engineCreated.countDown(); | 
|  282           } |  175           } | 
|  283         }).start(); |  176         }).start(); | 
|  284       } |  177       } | 
|  285     } |  178     } | 
|  286     return firstInstance; |  179     return firstInstance; | 
|  287   } |  180   } | 
|  288  |  181  | 
|  289   /** |  182   @Override | 
|  290    * Unregister AdblockHelper engine client |  183   public void waitForReady() | 
|  291    * @return `true` if the last instance is destroyed |  184   { | 
|  292    */ |  185     if (engineCreated == null) | 
 |  186     { | 
 |  187       throw new IllegalStateException("Usage exception: call retain(true) first"
     ); | 
 |  188     } | 
 |  189  | 
 |  190     try | 
 |  191     { | 
 |  192       Log.d(TAG, "Waiting for ready ..."); | 
 |  193       engineCreated.await(); | 
 |  194       Log.d(TAG, "Ready"); | 
 |  195     } | 
 |  196     catch (InterruptedException e) | 
 |  197     { | 
 |  198       Log.w(TAG, "Interrupted", e); | 
 |  199     } | 
 |  200   } | 
 |  201  | 
 |  202   @Override | 
 |  203   public AdblockEngine getEngine() | 
 |  204   { | 
 |  205     return engine; | 
 |  206   } | 
 |  207  | 
 |  208   @Override | 
|  293   public synchronized boolean release() |  209   public synchronized boolean release() | 
|  294   { |  210   { | 
|  295     boolean lastInstance = false; |  211     boolean lastInstance = false; | 
|  296  |  212  | 
|  297     if (referenceCounter.decrementAndGet() == 0) |  213     if (referenceCounter.decrementAndGet() == 0) | 
|  298     { |  214     { | 
|  299       lastInstance = true; |  215       lastInstance = true; | 
|  300  |  216  | 
|  301       if (engineCreated != null) |  217       if (engineCreated != null) | 
|  302       { |  218       { | 
|  303         // retained asynchronously |  219         // retained asynchronously | 
|  304         waitForReady(); |  220         waitForReady(); | 
|  305         disposeAdblock(); |  221         disposeAdblock(); | 
|  306  |  222  | 
|  307         // to unlock waiting client in waitForReady() |  223         // to unlock waiting client in waitForReady() | 
|  308         engineCreated.countDown(); |  224         engineCreated.countDown(); | 
|  309         engineCreated = null; |  225         engineCreated = null; | 
|  310       } |  226       } | 
|  311       else |  227       else | 
|  312       { |  228       { | 
|  313         disposeAdblock(); |  229         disposeAdblock(); | 
|  314       } |  230       } | 
|  315     } |  231     } | 
|  316     return lastInstance; |  232     return lastInstance; | 
|  317   } |  233   } | 
 |  234  | 
 |  235   private void disposeAdblock() | 
 |  236   { | 
 |  237     Log.w(TAG, "Disposing adblock engine"); | 
 |  238  | 
 |  239     engine.dispose(); | 
 |  240     engine = null; | 
 |  241  | 
 |  242     // sometimes we need to deinit something after AdblockEngine instance dispos
     ed | 
 |  243     // eg. release user settings | 
 |  244     if (engineDisposedCallback != null) | 
 |  245     { | 
 |  246       engineDisposedCallback.run(); | 
 |  247     } | 
 |  248   } | 
 |  249  | 
 |  250   @Override | 
 |  251   public int getCounter() | 
 |  252   { | 
 |  253     return referenceCounter.get(); | 
 |  254   } | 
|  318 } |  255 } | 
| OLD | NEW |