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: Created March 20, 2017, 8:11 a.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 {
48 private static final String TAG = Utils.getTag(AdblockEngine.class); 52 private static final String TAG = Utils.getTag(AdblockEngine.class);
49 53
50 /* 54 /*
51 * The fields below are volatile because: 55 * The fields below are volatile because:
52 * 56 *
53 * I encountered JNI related bugs/crashes caused by JNI backed Java objects. I t seemed that under 57 * 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 58 * certain conditions the objects were optimized away which resulted in crashe s when trying to
55 * release the object, sometimes even on access. 59 * release the object, sometimes even on access.
56 * 60 *
57 * The only solution that really worked was to declare the variables holding t he references 61 * 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 62 * 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). 63 * variable might be changed at any time from any thread).
60 */ 64 */
61 private volatile JsEngine jsEngine; 65 private volatile JsEngine jsEngine;
62 private volatile FilterEngine filterEngine; 66 private volatile FilterEngine filterEngine;
63 private volatile LogSystem logSystem; 67 private volatile LogSystem logSystem;
64 private volatile AndroidWebRequest webRequest; 68 private volatile WebRequest webRequest;
65 private volatile UpdateAvailableCallback updateAvailableCallback; 69 private volatile UpdateAvailableCallback updateAvailableCallback;
66 private volatile UpdateCheckDoneCallback updateCheckDoneCallback; 70 private volatile UpdateCheckDoneCallback updateCheckDoneCallback;
67 private volatile FilterChangeCallback filterChangeCallback; 71 private volatile FilterChangeCallback filterChangeCallback;
68 private volatile ShowNotificationCallback showNotificationCallback; 72 private volatile ShowNotificationCallback showNotificationCallback;
69 private final boolean elemhideEnabled; 73 private volatile boolean elemhideEnabled;
70 private volatile boolean enabled = true; 74 private volatile boolean enabled = true;
71 private List<String> whitelistedDomains; 75 private volatile List<String> whitelistedDomains;
72
73 private AdblockEngine(final boolean enableElemhide)
74 {
75 this.elemhideEnabled = enableElemhide;
76 }
77 76
78 public static AppInfo generateAppInfo(final Context context, boolean developme ntBuild) 77 public static AppInfo generateAppInfo(final Context context, boolean developme ntBuild)
79 { 78 {
80 String version = "0"; 79 String version = "0";
81 try 80 try
82 { 81 {
83 final PackageInfo info = context.getPackageManager().getPackageInfo(contex t.getPackageName(), 0); 82 final PackageInfo info = context.getPackageManager().getPackageInfo(contex t.getPackageName(), 0);
84 version = info.versionName; 83 version = info.versionName;
85 if (developmentBuild) 84 if (developmentBuild)
86 version += "." + info.versionCode; 85 version += "." + info.versionCode;
87 } 86 }
88 catch (final NameNotFoundException e) 87 catch (final NameNotFoundException e)
89 { 88 {
90 Log.e(TAG, "Failed to get the application version number", e); 89 Log.e(TAG, "Failed to get the application version number", e);
91 } 90 }
92 final String sdkVersion = String.valueOf(VERSION.SDK_INT); 91 final String sdkVersion = String.valueOf(VERSION.SDK_INT);
93 final String locale = Locale.getDefault().toString().replace('_', '-'); 92 final String locale = Locale.getDefault().toString().replace('_', '-');
94 93
95 return AppInfo.builder() 94 return AppInfo.builder()
96 .setVersion(version) 95 .setVersion(version)
97 .setApplicationVersion(sdkVersion) 96 .setApplicationVersion(sdkVersion)
98 .setLocale(locale) 97 .setLocale(locale)
99 .setDevelopmentBuild(developmentBuild) 98 .setDevelopmentBuild(developmentBuild)
100 .build(); 99 .build();
101 } 100 }
102 101
103 public static AdblockEngine create(final AppInfo appInfo, 102 /**
104 final String basePath, boolean enableElemhi de, 103 * Builds Adblock engine
105 UpdateAvailableCallback updateAvailableCall back, 104 */
106 UpdateCheckDoneCallback updateCheckDoneCall back, 105 public static class Builder
anton 2017/03/20 08:28:45 I had to refactor this monster-ctor to builder as
diegocarloslima 2017/03/20 15:13:12 I liked the Builder approach, but as I pointed out
anton 2017/03/21 05:54:47 the issues are related by the code (the same file
diegocarloslima 2017/03/28 13:47:15 You're right, the two issues don't depend on each
107 ShowNotificationCallback showNotificationCa llback,
108 FilterChangeCallback filterChangeCallback)
109 { 106 {
110 Log.w(TAG, "Create"); 107 private Context context;
108 private Map<String, Integer> URLtoResourceIdMap;
109 private AndroidWebRequestResourceWrapper.Storage resourceStorage;
110 private AndroidWebRequest androidWebRequest;
111 private AppInfo appInfo;
112 private String basePath;
111 113
112 final AdblockEngine engine = new AdblockEngine(enableElemhide); 114 private AdblockEngine engine;
113 115
114 engine.jsEngine = new JsEngine(appInfo); 116 protected Builder(final AppInfo appInfo, final String basePath)
115 engine.jsEngine.setDefaultFileSystem(basePath); 117 {
118 engine = new AdblockEngine();
119 engine.elemhideEnabled = true;
116 120
117 engine.logSystem = new AndroidLogSystem(); 121 // we can't create JsEngine and FilterEngine right now as it starts to dow nload subscriptions
118 engine.jsEngine.setLogSystem(engine.logSystem); 122 // and requests (AndroidWebRequest and probbaly wrappers) are not specifie d yet
119 123 this.appInfo = appInfo;
120 engine.webRequest = new AndroidWebRequest(enableElemhide); 124 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 } 125 }
130 126
131 engine.updateCheckDoneCallback = updateCheckDoneCallback; 127 public Builder enableElementHiding(boolean enable)
132
133 engine.showNotificationCallback = showNotificationCallback;
134 if (engine.showNotificationCallback != null)
135 { 128 {
136 engine.filterEngine.setShowNotificationCallback(showNotificationCallback); 129 engine.elemhideEnabled = enable;
130 return this;
137 } 131 }
138 132
139 engine.filterChangeCallback = filterChangeCallback; 133 public Builder preloadSubscriptions(Context context,
140 if (engine.filterChangeCallback != null) 134 Map<String, Integer> URLtoResourceIdMap,
135 AndroidWebRequestResourceWrapper.Storage storage)
141 { 136 {
142 engine.filterEngine.setFilterChangeCallback(filterChangeCallback); 137 this.context = context;
138 this.URLtoResourceIdMap = URLtoResourceIdMap;
139 this.resourceStorage = storage;
140 return this;
143 } 141 }
144 142
145 engine.webRequest.updateSubscriptionURLs(engine.filterEngine); 143 public Builder setUpdateAvailableCallback(UpdateAvailableCallback callback)
144 {
145 engine.updateAvailableCallback = callback;
146 return this;
147 }
146 148
147 return engine; 149 public Builder setUpdateCheckDoneCallback(UpdateCheckDoneCallback callback)
150 {
151 engine.updateCheckDoneCallback = callback;
152 return this;
153 }
154
155 public Builder setShowNotificationCallback(ShowNotificationCallback callback )
156 {
157 engine.showNotificationCallback = callback;
158 return this;
159 }
160
161 public Builder setFilterChangeCallback(FilterChangeCallback callback)
162 {
163 engine.filterChangeCallback = callback;
164 return this;
165 }
166
167 private void initRequests()
168 {
169 androidWebRequest = new AndroidWebRequest(engine.elemhideEnabled);
170 engine.webRequest = androidWebRequest;
171
172 if (URLtoResourceIdMap != null)
173 {
174 AndroidWebRequestResourceWrapper wrapper = new AndroidWebRequestResource Wrapper(
175 context, engine.webRequest, URLtoResourceIdMap, resourceStorage);
176 wrapper.setListener(engine.resourceWrapperListener);
177
178 engine.webRequest = wrapper;
179 }
180 }
181
182 private void initCallbacks()
183 {
184 if (engine.updateAvailableCallback != null)
185 {
186 engine.filterEngine.setUpdateAvailableCallback(engine.updateAvailableCal lback);
187 }
188
189 if (engine.showNotificationCallback != null)
190 {
191 engine.filterEngine.setShowNotificationCallback(engine.showNotificationC allback);
192 }
193
194 if (engine.filterChangeCallback != null)
195 {
196 engine.filterEngine.setFilterChangeCallback(engine.filterChangeCallback) ;
197 }
198 }
199
200 public AdblockEngine build()
201 {
202 initRequests();
203
204 // webRequest should be ready to be used passed right after JsEngine is cr eated
205 createEngines();
anton 2017/03/20 08:28:45 this is completely strange that webRequest should
206
207 initCallbacks();
208
209 androidWebRequest.updateSubscriptionURLs(engine.filterEngine);
210
211 return engine;
212 }
213
214 private void createEngines()
215 {
216 engine.jsEngine = new JsEngine(appInfo);
217 engine.jsEngine.setDefaultFileSystem(basePath);
218
219 engine.jsEngine.setWebRequest(engine.webRequest);
220
221 engine.logSystem = new AndroidLogSystem();
222 engine.jsEngine.setLogSystem(engine.logSystem);
223
224 engine.filterEngine = new FilterEngine(engine.jsEngine);
225 }
148 } 226 }
149 227
150 public static AdblockEngine create(final AppInfo appInfo, 228 public static Builder builder(AppInfo appInfo, String basePath)
anton 2017/03/20 08:28:45 i used the same approach (`builder()`) instead of
151 final String basePath, boolean elemhideEnab led)
152 { 229 {
153 return create(appInfo, basePath, elemhideEnabled, null, null, null, null); 230 return new Builder(appInfo, basePath);
154 } 231 }
155 232
233 private AndroidWebRequestResourceWrapper.Listener resourceWrapperListener =
234 new AndroidWebRequestResourceWrapper.Listener()
235 {
236 private static final int UPDATE_DELAY_MS = 1 * 1000;
237
238 private Handler handler = new Handler(Looper.getMainLooper());
239
240 private Runnable forceUpdateRunnable = new Runnable()
241 {
242 public void run() {
243 // Filter Engine can be already disposed
244 if (filterEngine != null)
245 {
246 Log.d(TAG, "Force update subscriptions");
247 filterEngine.forceUpdateCheck(updateCheckDoneCallback);
248 }
249 }
250 };
251
252 @Override
253 public void onIntercepted(String url, int resourceId)
254 {
255 // we need to force update subscriptions ASAP after preloaded one is retur ned
anton 2017/03/20 08:28:45 Please think about it while reviewing!
diegocarloslima 2017/03/28 13:47:15 Is this onIntercepted() callback always called by
anton 2017/03/28 13:59:06 It's invoked in background thread (most likely) an
256 // but we should note that multiple interceptions (for main easylist and A A) and force update once only
257
258 // adding into main thread queue to avoid concurrency issues (start update while updating)
259 // as usually onIntercepted() is invoked in background thread
260 handler.removeCallbacks(forceUpdateRunnable);
261 handler.postDelayed(forceUpdateRunnable, UPDATE_DELAY_MS);
262
263 Log.d(TAG, "Scheduled force update in " + UPDATE_DELAY_MS);
264 }
265 };
266
156 public void dispose() 267 public void dispose()
157 { 268 {
158 Log.w(TAG, "Dispose"); 269 Log.w(TAG, "Dispose");
159 270
160 if (this.logSystem != null) 271 if (this.logSystem != null)
161 { 272 {
162 this.logSystem.dispose(); 273 this.logSystem.dispose();
163 this.logSystem = null; 274 this.logSystem = null;
164 } 275 }
165 276
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 public void setWhitelistedDomains(List<String> domains) 575 public void setWhitelistedDomains(List<String> domains)
465 { 576 {
466 this.whitelistedDomains = domains; 577 this.whitelistedDomains = domains;
467 } 578 }
468 579
469 public List<String> getWhitelistedDomains() 580 public List<String> getWhitelistedDomains()
470 { 581 {
471 return whitelistedDomains; 582 return whitelistedDomains;
472 } 583 }
473 } 584 }
OLDNEW

Powered by Google App Engine
This is Rietveld