Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | |
3 * Copyright (C) 2006-2015 Eyeo GmbH | |
4 * | |
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 | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * Adblock Plus is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
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/>. | |
16 */ | |
17 | |
18 package org.adblockplus.browser; | |
19 | |
20 import java.util.HashMap; | |
21 import java.util.HashSet; | |
22 import java.util.Map.Entry; | |
23 import java.util.concurrent.Semaphore; | |
24 | |
25 import org.adblockplus.browser.SubscriptionPreferenceCategory.SubscriptionContai ner; | |
Felix Dahlke
2015/07/26 17:06:22
May be non-trivial, but I think it'd make more sen
René Jeschke
2015/07/28 10:55:26
Done.
| |
26 import org.mozilla.gecko.R; | |
27 import org.mozilla.gecko.util.NativeJSObject; | |
28 import org.mozilla.gecko.util.ThreadUtils; | |
29 | |
30 import android.app.ProgressDialog; | |
31 import android.content.Context; | |
32 import android.os.Build; | |
33 import android.preference.CheckBoxPreference; | |
34 import android.preference.Preference; | |
35 import android.preference.PreferenceGroup; | |
36 import android.util.AttributeSet; | |
37 import android.util.Log; | |
38 import android.view.View; | |
39 import android.view.ViewGroup; | |
40 | |
41 public class OtherPreferenceGroup extends PreferenceGroup implements | |
Felix Dahlke
2015/07/26 17:06:22
Nit: `OtherPreferenceGroup` sounds pretty generic,
René Jeschke
2015/07/28 10:55:26
Done.
| |
42 UrlInputDialog.UrlReadyCallback | |
43 { | |
44 private static final String TAG = "AdblockBrowser.OtherPreferenceGroup"; | |
45 private static final HashMap<String, Integer> BUILTIN_URL_TO_INDEX = new HashM ap<String, Integer>(); | |
46 private static final HashSet<String> IGNORED_URLS = new HashSet<String>(); | |
47 private static SubscriptionContainer recommendedSubscriptions = null; | |
48 | |
49 private final CheckBoxChangeListener checkBoxChangeListener = new CheckBoxChan geListener(); | |
50 private final ActiveSubscriptionContainer activeSubscriptions = new ActiveSubs criptionContainer(); | |
51 private ProgressDialog progressDialog; | |
52 | |
53 private static final int[] BUILTIN_TITLES = | |
54 { | |
55 R.string.abb_disable_tracking, | |
56 R.string.abb_disable_malware, | |
57 R.string.abb_disable_anti_adblock, | |
58 R.string.abb_disable_social_media | |
59 }; | |
60 | |
61 private static final String[] BUILTIN_LISTS = | |
62 { | |
63 "EasyPrivacy", | |
64 "https://easylist-downloads.adblockplus.org/easyprivacy.txt", | |
65 "Malware Domains", | |
66 "https://easylist-downloads.adblockplus.org/malwaredomains_full.txt", | |
67 "Adblock Warning Removal List", | |
68 "https://easylist-downloads.adblockplus.org/antiadblockfilters.txt", | |
69 "Fanboy's Social Blocking List", | |
70 "https://easylist-downloads.adblockplus.org/fanboy-social.txt" | |
71 }; | |
72 | |
73 private static final String[] OTHER_BUILTINS = | |
Felix Dahlke
2015/07/26 17:06:22
Nit: Considering how they're used, `IGNORED_BUILTI
René Jeschke
2015/07/28 10:55:26
Done.
| |
74 { | |
75 "https://easylist-downloads.adblockplus.org/exceptionrules.txt" | |
76 }; | |
77 | |
78 static | |
79 { | |
80 for (int i = 0; i < BUILTIN_TITLES.length; i++) | |
81 { | |
82 BUILTIN_URL_TO_INDEX.put(BUILTIN_LISTS[i * 2 + 1], Integer.valueOf(i)); | |
83 } | |
84 | |
85 for (int i = 0; i < OTHER_BUILTINS.length; i++) | |
86 { | |
87 IGNORED_URLS.add(OTHER_BUILTINS[i]); | |
88 } | |
89 } | |
90 | |
91 private synchronized static void initRecommendedSubscriptions() | |
92 { | |
93 if (recommendedSubscriptions == null) | |
94 { | |
95 recommendedSubscriptions = SubscriptionContainer.create(false); | |
96 | |
97 for (SubscriptionContainer.Subscription s : recommendedSubscriptions.getSu bscriptions(false)) | |
98 { | |
99 IGNORED_URLS.add(s.url); | |
100 } | |
101 } | |
102 } | |
103 | |
104 public OtherPreferenceGroup(final Context context, final AttributeSet attrs) | |
105 { | |
106 super(context, attrs); | |
107 } | |
108 | |
109 public OtherPreferenceGroup(final Context context, final AttributeSet attrs, | |
110 final int defStyleAttr) | |
111 { | |
112 super(context, attrs, defStyleAttr); | |
113 } | |
114 | |
115 @Override | |
116 protected View onCreateView(final ViewGroup parent) | |
117 { | |
118 this.setLayoutResource(R.layout.abb_minimal_widget); | |
119 return super.onCreateView(parent); | |
120 } | |
121 | |
122 public static Preference createCheckBoxOrSwitch(final Context context) | |
123 { | |
124 if (Build.VERSION.SDK_INT < 14) | |
125 { | |
126 return new CheckBoxPreference(context); | |
127 } | |
128 try | |
129 { | |
130 return (Preference) Class.forName("android.preference.SwitchPreference") | |
131 .getConstructor(Context.class) | |
132 .newInstance(context); | |
133 } | |
134 catch (Exception e) | |
135 { | |
136 Log.e(TAG, "Failed to create SwitchPreference, falling back to CheckBoxPre ference", e); | |
137 return new CheckBoxPreference(context); | |
138 } | |
139 } | |
140 | |
141 @Override | |
142 protected void onAttachedToActivity() | |
143 { | |
144 this.setEnabled(false); | |
145 this.setShouldDisableView(true); | |
146 | |
147 super.onAttachedToActivity(); | |
148 | |
149 this.progressDialog = new ProgressDialog(this.getContext()); | |
150 this.progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); | |
151 this.progressDialog.setMessage(this.getContext().getString(R.string.abb_adbl ocking_waiting)); | |
152 this.progressDialog.show(); | |
153 | |
154 UrlInputOpenerPreference.setRedirectUrlReadyCallback(this); | |
155 | |
156 AddOnBridge.handlerPost(new Runnable() | |
157 { | |
158 @Override | |
159 public void run() | |
160 { | |
161 initRecommendedSubscriptions(); | |
162 OtherPreferenceGroup.this.activeSubscriptions.refresh(); | |
163 | |
164 ThreadUtils.postToUiThread(new Runnable() | |
165 { | |
166 @Override | |
167 public void run() | |
168 { | |
169 OtherPreferenceGroup.this.initEntries(); | |
170 } | |
171 }); | |
172 } | |
173 }); | |
174 } | |
175 | |
176 private void initEntries() | |
177 { | |
178 this.removeAll(); | |
179 int i = 0; | |
180 for (; i < BUILTIN_TITLES.length; i++) | |
181 { | |
182 final CheckBoxPreference cbp = new CheckBoxPreference(this.getContext()); | |
183 final String url = BUILTIN_LISTS[i * 2 + 1]; | |
184 cbp.setOrder(i); | |
185 cbp.setTitle(BUILTIN_TITLES[i]); | |
186 cbp.setKey(url); | |
187 cbp.setChecked(this.activeSubscriptions.enabledSubscriptions.containsKey(u rl)); | |
188 cbp.setOnPreferenceChangeListener(this.checkBoxChangeListener); | |
189 cbp.setPersistent(false); | |
190 this.addPreference(cbp); | |
191 } | |
192 | |
193 for (Entry<String, String> e : this.activeSubscriptions.enabledSubscriptions .entrySet()) | |
Felix Dahlke
2015/07/26 17:06:22
What about disabled subscriptions? Would it make s
René Jeschke
2015/07/28 10:55:26
As ABP does not store custom, removed subscription
| |
194 { | |
195 if (!BUILTIN_URL_TO_INDEX.containsKey(e.getKey())) | |
196 { | |
197 final CheckBoxPreference cbp = new CheckBoxPreference(this.getContext()) ; | |
198 cbp.setOrder(i++); | |
199 cbp.setTitle(e.getValue()); | |
200 cbp.setKey(e.getKey()); | |
201 cbp.setChecked(true); | |
202 cbp.setOnPreferenceChangeListener(this.checkBoxChangeListener); | |
203 cbp.setPersistent(false); | |
204 this.addPreference(cbp); | |
205 } | |
206 } | |
207 | |
208 this.setEnabled(true); | |
209 this.setShouldDisableView(false); | |
210 if (this.progressDialog != null) | |
211 { | |
212 this.progressDialog.dismiss(); | |
213 this.progressDialog = null; | |
214 } | |
215 } | |
216 | |
217 private void addNewSubscription(final String url) | |
218 { | |
219 this.progressDialog = new ProgressDialog(this.getContext()); | |
220 this.progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); | |
221 this.progressDialog.setMessage(this.getContext().getString(R.string.abb_bloc k_list_adding)); | |
222 this.progressDialog.show(); | |
223 | |
224 AddOnBridge.handlerPost(new Runnable() | |
225 { | |
226 @Override | |
227 public void run() | |
228 { | |
229 try | |
230 { | |
231 final Semaphore finished = new Semaphore(0); | |
232 | |
233 AddOnBridge.addSubscription(new AdblockPlusApiCallback() | |
234 { | |
235 @Override | |
236 public void onApiRequestSucceeded(NativeJSObject jsObject) | |
237 { | |
238 finished.release(); | |
239 } | |
240 | |
241 @Override | |
242 public void onApiRequestFailed(String errorMessage) | |
243 { | |
244 finished.release(); | |
245 } | |
246 }, url, null); | |
247 | |
248 finished.acquireUninterruptibly(); | |
249 | |
250 OtherPreferenceGroup.this.activeSubscriptions.refresh(); | |
251 | |
252 ThreadUtils.postToUiThread(new Runnable() | |
253 { | |
254 @Override | |
255 public void run() | |
256 { | |
257 OtherPreferenceGroup.this.initEntries(); | |
258 } | |
259 }); | |
260 } | |
261 catch (Throwable t) | |
262 { | |
263 if (OtherPreferenceGroup.this.progressDialog != null) | |
264 { | |
265 OtherPreferenceGroup.this.progressDialog.dismiss(); | |
266 OtherPreferenceGroup.this.progressDialog = null; | |
267 } | |
268 } | |
269 } | |
270 }); | |
271 } | |
272 | |
273 @Override | |
274 public void callback(final String url) | |
275 { | |
276 if (url == null) | |
277 { | |
278 return; | |
279 } | |
280 | |
281 Log.d(TAG, "Adding: " + url); | |
282 this.addNewSubscription(url); | |
283 } | |
284 | |
285 private static class ActiveSubscriptionContainer implements AdblockPlusApiCall back | |
286 { | |
287 public final HashMap<String, String> enabledSubscriptions = new HashMap<Stri ng, String>(); | |
288 private final Semaphore entriesReady = new Semaphore(0); | |
289 | |
290 public void refresh() | |
291 { | |
292 AddOnBridge.queryActiveSubscriptions(this); | |
293 this.entriesReady.acquireUninterruptibly(); | |
294 } | |
295 | |
296 @Override | |
297 public void onApiRequestSucceeded(NativeJSObject jsObject) | |
298 { | |
299 try | |
300 { | |
301 this.enabledSubscriptions.clear(); | |
302 if (jsObject.getBoolean("success")) | |
303 { | |
304 NativeJSObject[] subs = jsObject.getObjectArray("value"); | |
305 for (int i = 0; i < subs.length; i++) | |
306 { | |
307 final String url = subs[i].getString("url"); | |
308 final String title = subs[i].has("title") ? subs[i].getString("title ") : url; | |
309 if (!IGNORED_URLS.contains(url)) | |
310 { | |
311 Log.d(TAG, "Adding: " + url + ", " + title); | |
312 this.enabledSubscriptions.put(url, title); | |
313 } | |
314 } | |
315 } | |
316 } | |
317 finally | |
318 { | |
319 this.entriesReady.release(); | |
320 } | |
321 } | |
322 | |
323 @Override | |
324 public void onApiRequestFailed(String errorMessage) | |
325 { | |
326 this.entriesReady.release(); | |
327 } | |
328 } | |
329 | |
330 private static class CheckBoxChangeListener implements OnPreferenceChangeListe ner, | |
331 AdblockPlusApiCallback | |
332 { | |
333 @Override | |
334 public boolean onPreferenceChange(Preference preference, Object newValue) | |
335 { | |
336 if (preference instanceof CheckBoxPreference && newValue instanceof Boolea n) | |
337 { | |
338 final CheckBoxPreference cbp = (CheckBoxPreference) preference; | |
339 final boolean enable = ((Boolean) newValue).booleanValue(); | |
340 | |
341 if (enable) | |
342 { | |
343 AddOnBridge.addSubscription(this, cbp.getKey(), null); | |
344 } | |
345 else | |
346 { | |
347 AddOnBridge.removeSubscription(this, cbp.getKey()); | |
348 } | |
349 } | |
350 return true; | |
351 } | |
352 | |
353 @Override | |
354 public void onApiRequestSucceeded(NativeJSObject jsObject) | |
355 { | |
356 // ignored | |
357 } | |
358 | |
359 @Override | |
360 public void onApiRequestFailed(String errorMessage) | |
361 { | |
362 // ignored | |
363 } | |
364 } | |
365 } | |
OLD | NEW |