Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: libadblockplus-android/src/org/adblockplus/libadblockplus/android/AdblockEngine.java

Issue 29389555: Issue 5010 - Allow to preload subscription files (Closed)
Patch Set: force downloading actually Created March 30, 2017, 10:12 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
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-2016 Eyeo GmbH 3 * Copyright (C) 2006-2016 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; 18 package org.adblockplus.libadblockplus.android;
19 19
20 import java.util.ArrayList; 20 import java.util.ArrayList;
21 import java.util.Arrays; 21 import java.util.Arrays;
22 import java.util.Collection; 22 import java.util.Collection;
23 import java.util.HashSet; 23 import java.util.HashSet;
24 import java.util.List; 24 import java.util.List;
25 import java.util.Locale; 25 import java.util.Locale;
26 import java.util.Map;
26 import java.util.Set; 27 import java.util.Set;
27 28
28 import org.adblockplus.libadblockplus.AppInfo; 29 import org.adblockplus.libadblockplus.AppInfo;
29 import org.adblockplus.libadblockplus.Filter; 30 import org.adblockplus.libadblockplus.Filter;
30 import org.adblockplus.libadblockplus.FilterChangeCallback; 31 import org.adblockplus.libadblockplus.FilterChangeCallback;
31 import org.adblockplus.libadblockplus.FilterEngine; 32 import org.adblockplus.libadblockplus.FilterEngine;
32 import org.adblockplus.libadblockplus.FilterEngine.ContentType; 33 import org.adblockplus.libadblockplus.FilterEngine.ContentType;
33 import org.adblockplus.libadblockplus.JsEngine; 34 import org.adblockplus.libadblockplus.JsEngine;
34 import org.adblockplus.libadblockplus.LogSystem; 35 import org.adblockplus.libadblockplus.LogSystem;
35 import org.adblockplus.libadblockplus.ShowNotificationCallback; 36 import org.adblockplus.libadblockplus.ShowNotificationCallback;
36 import org.adblockplus.libadblockplus.Subscription; 37 import org.adblockplus.libadblockplus.Subscription;
37 import org.adblockplus.libadblockplus.UpdateAvailableCallback; 38 import org.adblockplus.libadblockplus.UpdateAvailableCallback;
38 import org.adblockplus.libadblockplus.UpdateCheckDoneCallback; 39 import org.adblockplus.libadblockplus.UpdateCheckDoneCallback;
40 import org.adblockplus.libadblockplus.WebRequest;
39 41
40 import android.content.Context; 42 import android.content.Context;
41 import android.content.pm.PackageInfo; 43 import android.content.pm.PackageInfo;
42 import android.content.pm.PackageManager.NameNotFoundException; 44 import android.content.pm.PackageManager.NameNotFoundException;
43 import android.os.Build.VERSION; 45 import android.os.Build.VERSION;
46 import android.os.Handler;
47 import android.os.Looper;
44 import android.util.Log; 48 import android.util.Log;
45 49
46 public final class AdblockEngine 50 public final class AdblockEngine
47 { 51 {
52 // default base path to store subscription files in android app
53 public static final String BASE_PATH_DIRECTORY = "adblock";
54
48 private static final String TAG = Utils.getTag(AdblockEngine.class); 55 private static final String TAG = Utils.getTag(AdblockEngine.class);
49 56
50 /* 57 /*
51 * The fields below are volatile because: 58 * The fields below are volatile because:
52 * 59 *
53 * I encountered JNI related bugs/crashes caused by JNI backed Java objects. I t seemed that under 60 * I encountered JNI related bugs/crashes caused by JNI backed Java objects. I t seemed that under
54 * certain conditions the objects were optimized away which resulted in crashe s when trying to 61 * certain conditions the objects were optimized away which resulted in crashe s when trying to
55 * release the object, sometimes even on access. 62 * release the object, sometimes even on access.
56 * 63 *
57 * The only solution that really worked was to declare the variables holding t he references 64 * The only solution that really worked was to declare the variables holding t he references
58 * volatile, this seems to prevent the JNI from 'optimizing away' those object s (as a volatile 65 * volatile, this seems to prevent the JNI from 'optimizing away' those object s (as a volatile
59 * variable might be changed at any time from any thread). 66 * variable might be changed at any time from any thread).
60 */ 67 */
61 private volatile JsEngine jsEngine; 68 private volatile JsEngine jsEngine;
62 private volatile FilterEngine filterEngine; 69 private volatile FilterEngine filterEngine;
63 private volatile LogSystem logSystem; 70 private volatile LogSystem logSystem;
64 private volatile AndroidWebRequest webRequest; 71 private volatile WebRequest webRequest;
65 private volatile UpdateAvailableCallback updateAvailableCallback; 72 private volatile UpdateAvailableCallback updateAvailableCallback;
66 private volatile UpdateCheckDoneCallback updateCheckDoneCallback; 73 private volatile UpdateCheckDoneCallback updateCheckDoneCallback;
67 private volatile FilterChangeCallback filterChangeCallback; 74 private volatile FilterChangeCallback filterChangeCallback;
68 private volatile ShowNotificationCallback showNotificationCallback; 75 private volatile ShowNotificationCallback showNotificationCallback;
69 private final boolean elemhideEnabled; 76 private volatile boolean elemhideEnabled;
70 private volatile boolean enabled = true; 77 private volatile boolean enabled = true;
71 private List<String> whitelistedDomains; 78 private volatile List<String> whitelistedDomains;
72
73 private AdblockEngine(final boolean enableElemhide)
74 {
75 this.elemhideEnabled = enableElemhide;
76 }
77 79
78 public static AppInfo generateAppInfo(final Context context, boolean developme ntBuild) 80 public static AppInfo generateAppInfo(final Context context, boolean developme ntBuild)
79 { 81 {
80 String version = "0"; 82 String version = "0";
81 try 83 try
82 { 84 {
83 final PackageInfo info = context.getPackageManager().getPackageInfo(contex t.getPackageName(), 0); 85 final PackageInfo info = context.getPackageManager().getPackageInfo(contex t.getPackageName(), 0);
84 version = info.versionName; 86 version = info.versionName;
85 if (developmentBuild) 87 if (developmentBuild)
86 version += "." + info.versionCode; 88 version += "." + info.versionCode;
87 } 89 }
88 catch (final NameNotFoundException e) 90 catch (final NameNotFoundException e)
89 { 91 {
90 Log.e(TAG, "Failed to get the application version number", e); 92 Log.e(TAG, "Failed to get the application version number", e);
91 } 93 }
92 final String sdkVersion = String.valueOf(VERSION.SDK_INT); 94 final String sdkVersion = String.valueOf(VERSION.SDK_INT);
93 final String locale = Locale.getDefault().toString().replace('_', '-'); 95 final String locale = Locale.getDefault().toString().replace('_', '-');
94 96
95 return AppInfo.builder() 97 return AppInfo.builder()
96 .setVersion(version) 98 .setVersion(version)
97 .setApplicationVersion(sdkVersion) 99 .setApplicationVersion(sdkVersion)
98 .setLocale(locale) 100 .setLocale(locale)
99 .setDevelopmentBuild(developmentBuild) 101 .setDevelopmentBuild(developmentBuild)
100 .build(); 102 .build();
101 } 103 }
102 104
103 public static AdblockEngine create(final AppInfo appInfo, 105 /**
104 final String basePath, boolean enableElemhi de, 106 * Builds Adblock engine
105 UpdateAvailableCallback updateAvailableCall back, 107 */
106 UpdateCheckDoneCallback updateCheckDoneCall back, 108 public static class Builder
107 ShowNotificationCallback showNotificationCa llback,
108 FilterChangeCallback filterChangeCallback)
109 { 109 {
110 Log.w(TAG, "Create"); 110 private Context context;
111 private Map<String, Integer> URLtoResourceIdMap;
112 private AndroidWebRequestResourceWrapper.Storage resourceStorage;
113 private AndroidWebRequest androidWebRequest;
114 private AppInfo appInfo;
115 private String basePath;
111 116
112 final AdblockEngine engine = new AdblockEngine(enableElemhide); 117 private AdblockEngine engine;
113 118
114 engine.jsEngine = new JsEngine(appInfo); 119 protected Builder(final AppInfo appInfo, final String basePath)
115 engine.jsEngine.setDefaultFileSystem(basePath); 120 {
121 engine = new AdblockEngine();
122 engine.elemhideEnabled = true;
116 123
117 engine.logSystem = new AndroidLogSystem(); 124 // we can't create JsEngine and FilterEngine right now as it starts to dow nload subscriptions
118 engine.jsEngine.setLogSystem(engine.logSystem); 125 // and requests (AndroidWebRequest and probbaly wrappers) are not specifie d yet
119 126 this.appInfo = appInfo;
120 engine.webRequest = new AndroidWebRequest(enableElemhide); 127 this.basePath = basePath;
121 engine.jsEngine.setWebRequest(engine.webRequest);
122
123 engine.filterEngine = new FilterEngine(engine.jsEngine);
124
125 engine.updateAvailableCallback = updateAvailableCallback;
126 if (engine.updateAvailableCallback != null)
127 {
128 engine.filterEngine.setUpdateAvailableCallback(updateAvailableCallback);
129 } 128 }
130 129
131 engine.updateCheckDoneCallback = updateCheckDoneCallback; 130 public Builder enableElementHiding(boolean enable)
132
133 engine.showNotificationCallback = showNotificationCallback;
134 if (engine.showNotificationCallback != null)
135 { 131 {
136 engine.filterEngine.setShowNotificationCallback(showNotificationCallback); 132 engine.elemhideEnabled = enable;
133 return this;
137 } 134 }
138 135
139 engine.filterChangeCallback = filterChangeCallback; 136 public Builder preloadSubscriptions(Context context,
140 if (engine.filterChangeCallback != null) 137 Map<String, Integer> URLtoResourceIdMap,
138 AndroidWebRequestResourceWrapper.Storage storage)
141 { 139 {
142 engine.filterEngine.setFilterChangeCallback(filterChangeCallback); 140 this.context = context;
141 this.URLtoResourceIdMap = URLtoResourceIdMap;
142 this.resourceStorage = storage;
143 return this;
143 } 144 }
144 145
145 engine.webRequest.updateSubscriptionURLs(engine.filterEngine); 146 public Builder setUpdateAvailableCallback(UpdateAvailableCallback callback)
147 {
148 engine.updateAvailableCallback = callback;
149 return this;
150 }
146 151
147 return engine; 152 public Builder setUpdateCheckDoneCallback(UpdateCheckDoneCallback callback)
153 {
154 engine.updateCheckDoneCallback = callback;
155 return this;
156 }
157
158 public Builder setShowNotificationCallback(ShowNotificationCallback callback )
159 {
160 engine.showNotificationCallback = callback;
161 return this;
162 }
163
164 public Builder setFilterChangeCallback(FilterChangeCallback callback)
165 {
166 engine.filterChangeCallback = callback;
167 return this;
168 }
169
170 private void initRequests()
171 {
172 androidWebRequest = new AndroidWebRequest(engine.elemhideEnabled);
173 engine.webRequest = androidWebRequest;
174
175 if (URLtoResourceIdMap != null)
176 {
177 AndroidWebRequestResourceWrapper wrapper = new AndroidWebRequestResource Wrapper(
178 context, engine.webRequest, URLtoResourceIdMap, resourceStorage);
179 wrapper.setListener(engine.resourceWrapperListener);
180
181 engine.webRequest = wrapper;
182 }
183 }
184
185 private void initCallbacks()
186 {
187 if (engine.updateAvailableCallback != null)
188 {
189 engine.filterEngine.setUpdateAvailableCallback(engine.updateAvailableCal lback);
190 }
191
192 if (engine.showNotificationCallback != null)
193 {
194 engine.filterEngine.setShowNotificationCallback(engine.showNotificationC allback);
195 }
196
197 if (engine.filterChangeCallback != null)
198 {
199 engine.filterEngine.setFilterChangeCallback(engine.filterChangeCallback) ;
200 }
201 }
202
203 public AdblockEngine build()
204 {
205 initRequests();
206
207 // webRequest should be ready to be used passed right after JsEngine is cr eated
208 createEngines();
209
210 initCallbacks();
211
212 androidWebRequest.updateSubscriptionURLs(engine.filterEngine);
213
214 return engine;
215 }
216
217 private void createEngines()
218 {
219 engine.jsEngine = new JsEngine(appInfo);
220 engine.jsEngine.setDefaultFileSystem(basePath);
221
222 engine.jsEngine.setWebRequest(engine.webRequest);
223
224 engine.logSystem = new AndroidLogSystem();
225 engine.jsEngine.setLogSystem(engine.logSystem);
226
227 engine.filterEngine = new FilterEngine(engine.jsEngine);
228 }
148 } 229 }
149 230
150 public static AdblockEngine create(final AppInfo appInfo, 231 public static Builder builder(AppInfo appInfo, String basePath)
151 final String basePath, boolean elemhideEnab led)
152 { 232 {
153 return create(appInfo, basePath, elemhideEnabled, null, null, null, null); 233 return new Builder(appInfo, basePath);
154 } 234 }
155 235
236 private final AndroidWebRequestResourceWrapper.Listener resourceWrapperListene r =
237 new AndroidWebRequestResourceWrapper.Listener()
238 {
239 private static final int UPDATE_DELAY_MS = 1 * 1000;
240
241 private final Handler handler = new Handler(Looper.getMainLooper());
242
243 private final Runnable forceUpdateRunnable = new Runnable()
244 {
245 public void run() {
246 // Filter Engine can be already disposed
247 if (filterEngine != null)
248 {
249 Log.d(TAG, "Force update subscriptions");
250 List<Subscription> subscriptions = filterEngine.getListedSubscriptions ();
251 for (Subscription eachSubscription : subscriptions)
sergei 2017/03/30 22:14:37 Nit: I would remove "each".
252 {
253 try
254 {
255 eachSubscription.updateFilters();
256 }
257 finally
258 {
259 eachSubscription.dispose();
260 }
261 }
262 }
263 }
264 };
265
266 @Override
267 public void onIntercepted(String url, int resourceId)
268 {
269 // we need to force update subscriptions ASAP after preloaded one is retur ned
270 // but we should note that multiple interceptions (for main easylist and A A) and force update once only
271
272 // adding into main thread queue to avoid concurrency issues (start update while updating)
273 // as usually onIntercepted() is invoked in background thread
274 handler.removeCallbacks(forceUpdateRunnable);
275 handler.postDelayed(forceUpdateRunnable, UPDATE_DELAY_MS);
276
277 Log.d(TAG, "Scheduled force update in " + UPDATE_DELAY_MS);
278 }
279 };
280
156 public void dispose() 281 public void dispose()
157 { 282 {
158 Log.w(TAG, "Dispose"); 283 Log.w(TAG, "Dispose");
159 284
160 if (this.logSystem != null) 285 if (this.logSystem != null)
161 { 286 {
162 this.logSystem.dispose(); 287 this.logSystem.dispose();
163 this.logSystem = null; 288 this.logSystem = null;
164 } 289 }
165 290
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 public void setWhitelistedDomains(List<String> domains) 589 public void setWhitelistedDomains(List<String> domains)
465 { 590 {
466 this.whitelistedDomains = domains; 591 this.whitelistedDomains = domains;
467 } 592 }
468 593
469 public List<String> getWhitelistedDomains() 594 public List<String> getWhitelistedDomains()
470 { 595 {
471 return whitelistedDomains; 596 return whitelistedDomains;
472 } 597 }
473 } 598 }
OLDNEW

Powered by Google App Engine
This is Rietveld