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 |