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-2015 Eyeo GmbH | 3 * Copyright (C) 2006-2015 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.browser; | 18 package org.adblockplus.browser; |
19 | 19 |
| 20 import java.util.ArrayList; |
20 import java.util.HashMap; | 21 import java.util.HashMap; |
| 22 import java.util.List; |
21 import java.util.Map; | 23 import java.util.Map; |
22 | 24 |
23 import android.annotation.SuppressLint; | 25 import android.annotation.SuppressLint; |
| 26 import android.content.Context; |
| 27 import android.content.SharedPreferences; |
24 import android.os.Handler; | 28 import android.os.Handler; |
25 import android.os.HandlerThread; | 29 import android.os.HandlerThread; |
26 import android.util.Log; | 30 import android.util.Log; |
27 | 31 |
| 32 import org.json.JSONArray; |
28 import org.json.JSONException; | 33 import org.json.JSONException; |
29 import org.json.JSONObject; | 34 import org.json.JSONObject; |
| 35 import org.mozilla.gecko.EventDispatcher; |
30 import org.mozilla.gecko.GeckoAppShell; | 36 import org.mozilla.gecko.GeckoAppShell; |
| 37 import org.mozilla.gecko.util.GeckoEventListener; |
31 import org.mozilla.gecko.util.GeckoRequest; | 38 import org.mozilla.gecko.util.GeckoRequest; |
32 import org.mozilla.gecko.util.NativeJSObject; | 39 import org.mozilla.gecko.util.NativeJSObject; |
33 | 40 |
34 @SuppressLint("DefaultLocale") | 41 @SuppressLint("DefaultLocale") |
35 public class AddOnBridge | 42 public class AddOnBridge |
36 { | 43 { |
37 private static final String TAG = "AdblockBrowser.AddOnBridge"; | 44 private static final String TAG = "AdblockBrowser.AddOnBridge"; |
38 private static final String REQUEST_NAME = "AdblockPlus:Api"; | 45 private static final String REQUEST_NAME = "AdblockPlus:Api"; |
39 // Timeout for checking filter loading (in seconds) | |
40 private static final int QUERY_GET_FILTERS_LOADED_TIMEOUT = 30; | |
41 // How long to wait between retries (in milliseconds) | |
42 private static final int QUERY_GET_FILTERS_LOADED_DELAY = 500; | |
43 // Handler+HandlerThread for posting delayed re-tries without interfering with | 46 // Handler+HandlerThread for posting delayed re-tries without interfering with |
44 // other threads (e.g. the UI or Gecko thread) | 47 // other threads (e.g. the UI or Gecko thread) |
45 private static final HandlerThread PRIVATE_HANDLER_THREAD; | 48 private static final HandlerThread PRIVATE_HANDLER_THREAD; |
46 private static final Handler PRIVATE_HANDLER; | 49 private static final Handler PRIVATE_HANDLER; |
47 // Global handler, for e.g. UI tasks | 50 // Global handler, for e.g. UI tasks |
48 private static final HandlerThread GLOBAL_HANDLER_THREAD; | 51 private static final HandlerThread GLOBAL_HANDLER_THREAD; |
49 private static final Handler GLOBAL_HANDLER; | 52 private static final Handler GLOBAL_HANDLER; |
| 53 // Sometimes, the app is killed before the extension is able to save all chang
es regarding |
| 54 // AddOnBridge requests. Given that, we need to store the uncompleted requests
on SharedPrefs, |
| 55 // so we can resend them to the extension once the app restarts |
| 56 // See https://issues.adblockplus.org/ticket/2853 |
| 57 private static final AddOnEventListener ADD_ON_EVENT_LISTENER = new AddOnEvent
Listener(); |
| 58 private static final String ON_FILTERS_LOAD_EVENT = "Abb:OnFiltersLoad"; |
| 59 private static final String ON_FILTERS_SAVE_EVENT = "Abb:OnFiltersSave"; |
| 60 private static final List<AddOnRequest> PENDING_REQUESTS = new ArrayList<>(); |
| 61 private static final String UNCOMPLETED_REQUESTS_PREFS_KEY = "UNCOMPLETED_REQU
ESTS_PREFS_KEY"; |
| 62 |
| 63 private static SharedPreferences sharedPrefs; |
| 64 private static boolean filtersLoaded; |
50 | 65 |
51 static | 66 static |
52 { | 67 { |
53 PRIVATE_HANDLER_THREAD = new HandlerThread("abp-private-handler"); | 68 PRIVATE_HANDLER_THREAD = new HandlerThread("abp-private-handler"); |
54 PRIVATE_HANDLER_THREAD.setDaemon(true); | 69 PRIVATE_HANDLER_THREAD.setDaemon(true); |
55 PRIVATE_HANDLER_THREAD.start(); | 70 PRIVATE_HANDLER_THREAD.start(); |
56 PRIVATE_HANDLER = new Handler(PRIVATE_HANDLER_THREAD.getLooper()); | 71 PRIVATE_HANDLER = new Handler(PRIVATE_HANDLER_THREAD.getLooper()); |
57 | 72 |
58 GLOBAL_HANDLER_THREAD = new HandlerThread("abp-global-handler"); | 73 GLOBAL_HANDLER_THREAD = new HandlerThread("abp-global-handler"); |
59 GLOBAL_HANDLER_THREAD.setDaemon(true); | 74 GLOBAL_HANDLER_THREAD.setDaemon(true); |
60 GLOBAL_HANDLER_THREAD.start(); | 75 GLOBAL_HANDLER_THREAD.start(); |
61 GLOBAL_HANDLER = new Handler(GLOBAL_HANDLER_THREAD.getLooper()); | 76 GLOBAL_HANDLER = new Handler(GLOBAL_HANDLER_THREAD.getLooper()); |
62 } | 77 } |
63 | 78 |
| 79 public static void init(Context context) |
| 80 { |
| 81 sharedPrefs = context.getSharedPreferences(AddOnBridge.class.getName(), Cont
ext.MODE_PRIVATE); |
| 82 EventDispatcher.getInstance().registerGeckoThreadListener(ADD_ON_EVENT_LISTE
NER, ON_FILTERS_LOAD_EVENT, ON_FILTERS_SAVE_EVENT); |
| 83 loadUncompletedRequests(); |
| 84 } |
| 85 |
64 public static void postToHandler(Runnable runnable) | 86 public static void postToHandler(Runnable runnable) |
65 { | 87 { |
66 GLOBAL_HANDLER.post(runnable); | 88 GLOBAL_HANDLER.post(runnable); |
67 } | 89 } |
68 | 90 |
69 public static void postToHandlerDelayed(Runnable runnable, long delayMillis) | 91 public static void postToHandlerDelayed(Runnable runnable, long delayMillis) |
70 { | 92 { |
71 GLOBAL_HANDLER.postDelayed(runnable, delayMillis); | 93 GLOBAL_HANDLER.postDelayed(runnable, delayMillis); |
72 } | 94 } |
73 | 95 |
| 96 private static void loadUncompletedRequests() |
| 97 { |
| 98 PRIVATE_HANDLER.post(new Runnable() |
| 99 { |
| 100 @Override |
| 101 public void run() |
| 102 { |
| 103 final String jsonString = sharedPrefs.getString(UNCOMPLETED_REQUESTS_PRE
FS_KEY, null); |
| 104 PENDING_REQUESTS.addAll(0, jsonStringToRequestList(jsonString)); |
| 105 } |
| 106 }); |
| 107 } |
| 108 |
| 109 private static void sendOrEnqueueRequest(final AddOnRequest request) |
| 110 { |
| 111 PRIVATE_HANDLER.post(new Runnable() |
| 112 { |
| 113 @Override |
| 114 public void run() |
| 115 { |
| 116 if (!filtersLoaded) |
| 117 { |
| 118 PENDING_REQUESTS.add(request); |
| 119 } |
| 120 else |
| 121 { |
| 122 GeckoAppShell.sendRequestToGecko(request); |
| 123 } |
| 124 } |
| 125 }); |
| 126 } |
| 127 |
| 128 private static void sendPendingRequests() |
| 129 { |
| 130 PRIVATE_HANDLER.post(new Runnable() |
| 131 { |
| 132 @Override |
| 133 public void run() |
| 134 { |
| 135 for (final AddOnRequest request : PENDING_REQUESTS) |
| 136 { |
| 137 GeckoAppShell.sendRequestToGecko(request); |
| 138 } |
| 139 PENDING_REQUESTS.clear(); |
| 140 } |
| 141 }); |
| 142 } |
| 143 |
| 144 private static void clearUncompletedRequests() |
| 145 { |
| 146 PRIVATE_HANDLER.post(new Runnable() |
| 147 { |
| 148 @Override |
| 149 public void run() |
| 150 { |
| 151 storeStringPref(UNCOMPLETED_REQUESTS_PREFS_KEY, null); |
| 152 } |
| 153 }); |
| 154 } |
| 155 |
| 156 private static void storeUncompletedRequest(final AddOnRequest request) |
| 157 { |
| 158 PRIVATE_HANDLER.post(new Runnable() |
| 159 { |
| 160 @Override |
| 161 public void run() |
| 162 { |
| 163 final String jsonString = sharedPrefs.getString(UNCOMPLETED_REQUESTS_PRE
FS_KEY, null); |
| 164 try |
| 165 { |
| 166 final JSONArray jsonArray = jsonString != null ? new JSONArray(jsonStr
ing) : new JSONArray(); |
| 167 jsonArray.put(request.value); |
| 168 storeStringPref(UNCOMPLETED_REQUESTS_PREFS_KEY, jsonArray.toString()); |
| 169 } |
| 170 catch (JSONException e) |
| 171 { |
| 172 Log.e(TAG, "Failed to store uncompleted request with error: " + e.getM
essage(), e); |
| 173 } |
| 174 } |
| 175 }); |
| 176 } |
| 177 |
| 178 private static List<AddOnRequest> jsonStringToRequestList(final String jsonStr
ing) |
| 179 { |
| 180 final List<AddOnRequest> requestList = new ArrayList<>(); |
| 181 if (jsonString == null) |
| 182 { |
| 183 return requestList; |
| 184 } |
| 185 try |
| 186 { |
| 187 final JSONArray jsonArray = new JSONArray(jsonString); |
| 188 for (int i = 0; i < jsonArray.length(); i++) |
| 189 { |
| 190 final AddOnRequest request = new AddOnRequest(jsonArray.getJSONObject(i)
, null); |
| 191 requestList.add(request); |
| 192 } |
| 193 } |
| 194 catch (JSONException e) |
| 195 { |
| 196 Log.e(TAG, "Failed to parse json to request list with error: " + e.getMess
age(), e); |
| 197 } |
| 198 return requestList; |
| 199 } |
| 200 |
| 201 private static void storeStringPref(String key, String value) |
| 202 { |
| 203 final SharedPreferences.Editor editor = sharedPrefs.edit(); |
| 204 editor.putString(key, value); |
| 205 editor.commit(); |
| 206 } |
| 207 |
74 public static boolean getBooleanFromJsObject(final NativeJSObject obj, final S
tring name, | 208 public static boolean getBooleanFromJsObject(final NativeJSObject obj, final S
tring name, |
75 final boolean defaultValue) | 209 final boolean defaultValue) |
76 { | 210 { |
77 try | 211 try |
78 { | 212 { |
79 return obj.getBoolean(name); | 213 return obj.getBoolean(name); |
80 } | 214 } |
81 catch (final Exception e) | 215 catch (final Exception e) |
82 { | 216 { |
83 return defaultValue; | 217 return defaultValue; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 if (Character.isUpperCase(str.charAt(0))) | 266 if (Character.isUpperCase(str.charAt(0))) |
133 { | 267 { |
134 return str; | 268 return str; |
135 } | 269 } |
136 return Character.toString(Character.toUpperCase(str.charAt(0))) + str.substr
ing(1); | 270 return Character.toString(Character.toUpperCase(str.charAt(0))) + str.substr
ing(1); |
137 } | 271 } |
138 | 272 |
139 public static void queryValue(final AdblockPlusApiCallback callback, final Str
ing name) | 273 public static void queryValue(final AdblockPlusApiCallback callback, final Str
ing name) |
140 { | 274 { |
141 Log.d(TAG, "queryValue for " + name); | 275 Log.d(TAG, "queryValue for " + name); |
142 GeckoAppShell.sendRequestToGecko( | 276 final AddOnRequest request = |
143 new ChainedRequest( | 277 new AddOnRequest(createRequestData("get" + makeFirstCharacterUppercase(n
ame)), callback); |
144 createRequestData("get" + makeFirstCharacterUppercase(name)), | 278 sendOrEnqueueRequest(request); |
145 callback)); | |
146 } | 279 } |
147 | 280 |
148 public static void setBoolean(final AdblockPlusApiCallback callback, final Str
ing name, | 281 public static void setBoolean(final AdblockPlusApiCallback callback, final Str
ing name, |
149 final boolean enable) | 282 final boolean enable) |
150 { | 283 { |
151 Log.d(TAG, "setBoolean " + enable + " for " + name); | 284 Log.d(TAG, "setBoolean " + enable + " for " + name); |
152 GeckoAppShell.sendRequestToGecko( | 285 final AddOnRequest request = |
153 new ChainedRequest( | 286 new AddOnRequest(createRequestData("set" + makeFirstCharacterUppercase(n
ame), enable), callback); |
154 createRequestData("set" + makeFirstCharacterUppercase(name), enable)
, | 287 sendOrEnqueueRequest(request); |
155 callback)); | 288 storeUncompletedRequest(request); |
156 } | 289 } |
157 | 290 |
158 private static void callFunction(final AdblockPlusApiCallback callback, final
String name, | 291 private static void callFunction(final AdblockPlusApiCallback callback, final
String name, |
159 final Map<String, Object> parameters) | 292 final Map<String, Object> parameters) |
160 { | 293 { |
| 294 // By default, requests are not stored on the uncompleted request prefs. Thi
s should apply for |
| 295 // requests that doesn't result in save operations performed by the extensio
n |
| 296 callFunction(callback, name, parameters, false); |
| 297 } |
| 298 |
| 299 private static void callFunction(final AdblockPlusApiCallback callback, final
String name, |
| 300 final Map<String, Object> parameters, boolean resendIfAborted) |
| 301 { |
161 final JSONObject requestData = createRequestData(name); | 302 final JSONObject requestData = createRequestData(name); |
162 try | 303 try |
163 { | 304 { |
164 for (Map.Entry<String, Object> entry : parameters.entrySet()) | 305 for (Map.Entry<String, Object> entry : parameters.entrySet()) |
| 306 { |
165 requestData.put(entry.getKey(), entry.getValue()); | 307 requestData.put(entry.getKey(), entry.getValue()); |
| 308 } |
166 } | 309 } |
167 catch (JSONException e) | 310 catch (JSONException e) |
168 { | 311 { |
169 // we're only adding sane objects | 312 // we're only adding sane objects |
170 Log.e(TAG, "Creating request data failed with: " + e.getMessage(), e); | 313 Log.e(TAG, "Creating request data failed with: " + e.getMessage(), e); |
171 } | 314 } |
172 GeckoAppShell.sendRequestToGecko(new ChainedRequest(requestData, callback)); | 315 final AddOnRequest request = new AddOnRequest(requestData, callback); |
| 316 sendOrEnqueueRequest(request); |
| 317 if (resendIfAborted) |
| 318 { |
| 319 storeUncompletedRequest(request); |
| 320 } |
173 } | 321 } |
174 | 322 |
175 public static void querySubscriptionListStatus(final AdblockPlusApiCallback ca
llback, | 323 public static void querySubscriptionListStatus(final AdblockPlusApiCallback ca
llback, |
176 final String url) | 324 final String url) |
177 { | 325 { |
178 Log.d(TAG, "querySubscriptionListStatus for " + url); | 326 Log.d(TAG, "querySubscriptionListStatus for " + url); |
179 final Map<String, Object> parameters = new HashMap<String, Object>(); | 327 final Map<String, Object> parameters = new HashMap<String, Object>(); |
180 parameters.put("url", url); | 328 parameters.put("url", url); |
181 callFunction(callback, "isSubscriptionListed", parameters); | 329 callFunction(callback, "isSubscriptionListed", parameters); |
182 } | 330 } |
183 | 331 |
184 public static void addSubscription(final AdblockPlusApiCallback callback, | 332 public static void addSubscription(final AdblockPlusApiCallback callback, |
185 final String url, final String title) | 333 final String url, final String title) |
186 { | 334 { |
187 Log.d(TAG, "addSubscription for " + url + " (" + title + ")"); | 335 Log.d(TAG, "addSubscription for " + url + " (" + title + ")"); |
188 final Map<String, Object> parameters = new HashMap<String, Object>(); | 336 final Map<String, Object> parameters = new HashMap<String, Object>(); |
189 parameters.put("url", url); | 337 parameters.put("url", url); |
190 if (title != null) | 338 if (title != null) |
191 { | 339 { |
192 parameters.put("title", title); | 340 parameters.put("title", title); |
193 } | 341 } |
194 callFunction(callback, "addSubscription", parameters); | 342 callFunction(callback, "addSubscription", parameters, true); |
195 } | 343 } |
196 | 344 |
197 public static void queryActiveSubscriptions(final AdblockPlusApiCallback callb
ack) | 345 public static void queryActiveSubscriptions(final AdblockPlusApiCallback callb
ack) |
198 { | 346 { |
199 Log.d(TAG, "queryActiveSubscriptions"); | 347 Log.d(TAG, "queryActiveSubscriptions"); |
200 final Map<String, Object> parameters = new HashMap<String, Object>(); | 348 final Map<String, Object> parameters = new HashMap<String, Object>(); |
201 callFunction(callback, "getActiveSubscriptions", parameters); | 349 callFunction(callback, "getActiveSubscriptions", parameters); |
202 } | 350 } |
203 | 351 |
204 public static void removeSubscription(final AdblockPlusApiCallback callback, | 352 public static void removeSubscription(final AdblockPlusApiCallback callback, |
205 final String url) | 353 final String url) |
206 { | 354 { |
207 Log.d(TAG, "removeSubscription for " + url); | 355 Log.d(TAG, "removeSubscription for " + url); |
208 final Map<String, Object> parameters = new HashMap<String, Object>(); | 356 final Map<String, Object> parameters = new HashMap<String, Object>(); |
209 parameters.put("url", url); | 357 parameters.put("url", url); |
210 callFunction(callback, "removeSubscription", parameters); | 358 callFunction(callback, "removeSubscription", parameters, true); |
211 } | 359 } |
212 | 360 |
213 public static void queryIsLocal(final AdblockPlusApiCallback callback, | 361 public static void queryIsLocal(final AdblockPlusApiCallback callback, |
214 final String url) | 362 final String url) |
215 { | 363 { |
216 Log.d(TAG, "queryIsLocal for " + url); | 364 Log.d(TAG, "queryIsLocal for " + url); |
217 final Map<String, Object> parameters = new HashMap<String, Object>(); | 365 final Map<String, Object> parameters = new HashMap<String, Object>(); |
218 parameters.put("url", url); | 366 parameters.put("url", url); |
219 callFunction(callback, "isLocal", parameters); | 367 callFunction(callback, "isLocal", parameters); |
220 } | 368 } |
221 | 369 |
222 public static void queryIsPageWhitelisted(final AdblockPlusApiCallback callbac
k, | 370 public static void queryIsPageWhitelisted(final AdblockPlusApiCallback callbac
k, |
223 final String url) | 371 final String url) |
224 { | 372 { |
225 Log.d(TAG, "queryIsPageWhitelisted for " + url); | 373 Log.d(TAG, "queryIsPageWhitelisted for " + url); |
226 final Map<String, Object> parameters = new HashMap<String, Object>(); | 374 final Map<String, Object> parameters = new HashMap<String, Object>(); |
227 parameters.put("url", url); | 375 parameters.put("url", url); |
228 callFunction(callback, "isPageWhitelisted", parameters); | 376 callFunction(callback, "isPageWhitelisted", parameters); |
229 } | 377 } |
230 | 378 |
231 public static void whitelistSite(final AdblockPlusApiCallback callback, final
String url, | 379 public static void whitelistSite(final AdblockPlusApiCallback callback, final
String url, |
232 final boolean whitelisted) | 380 final boolean whitelisted) |
233 { | 381 { |
234 Log.d(TAG, "whitelistSite for " + url); | 382 Log.d(TAG, "whitelistSite for " + url); |
235 final Map<String, Object> parameters = new HashMap<String, Object>(); | 383 final Map<String, Object> parameters = new HashMap<String, Object>(); |
236 parameters.put("url", url); | 384 parameters.put("url", url); |
237 parameters.put("whitelisted", whitelisted); | 385 parameters.put("whitelisted", whitelisted); |
238 callFunction(callback, "whitelistSite", parameters); | 386 callFunction(callback, "whitelistSite", parameters, true); |
239 } | 387 } |
240 | 388 |
241 private static class ChainedRequest extends GeckoRequest | 389 private static class AddOnRequest extends GeckoRequest |
242 { | 390 { |
243 private final JSONObject value; | 391 private final JSONObject value; |
244 private final AdblockPlusApiCallback apiCallback; | 392 private final AdblockPlusApiCallback apiCallback; |
245 private final boolean checkForFiltersLoaded; | |
246 private final long creationTime; | |
247 | 393 |
248 public ChainedRequest(final JSONObject value, final AdblockPlusApiCallback c
allback, | 394 AddOnRequest(final JSONObject value, final AdblockPlusApiCallback callback) |
249 final boolean checkForFiltersLoaded, final long creationTime) | |
250 { | 395 { |
251 super(AddOnBridge.REQUEST_NAME, | 396 super(AddOnBridge.REQUEST_NAME, value); |
252 checkForFiltersLoaded ? createRequestData("getFiltersLoaded") : value)
; | |
253 this.value = value; | 397 this.value = value; |
254 this.apiCallback = callback; | 398 this.apiCallback = callback; |
255 this.checkForFiltersLoaded = checkForFiltersLoaded; | |
256 this.creationTime = creationTime; | |
257 } | |
258 | |
259 public ChainedRequest(final JSONObject value, final AdblockPlusApiCallback c
allback) | |
260 { | |
261 this(value, callback, true, System.currentTimeMillis()); | |
262 } | |
263 | |
264 public ChainedRequest cloneForRetry() | |
265 { | |
266 return new ChainedRequest(this.value, this.apiCallback, true, this.creatio
nTime); | |
267 } | |
268 | |
269 public ChainedRequest cloneForRequest() | |
270 { | |
271 return new ChainedRequest(this.value, this.apiCallback, false, this.creati
onTime); | |
272 } | 399 } |
273 | 400 |
274 private void invokeSuccessCallback(final NativeJSObject jsObject) | 401 private void invokeSuccessCallback(final NativeJSObject jsObject) |
275 { | 402 { |
276 try | 403 try |
277 { | 404 { |
278 if (this.apiCallback != null) | 405 if (this.apiCallback != null) |
279 { | 406 { |
280 this.apiCallback.onApiRequestSucceeded(jsObject); | 407 this.apiCallback.onApiRequestSucceeded(jsObject); |
281 } | 408 } |
(...skipping 10 matching lines...) Expand all Loading... |
292 { | 419 { |
293 this.apiCallback.onApiRequestFailed(msg); | 420 this.apiCallback.onApiRequestFailed(msg); |
294 } | 421 } |
295 } | 422 } |
296 | 423 |
297 private void invokeFailureCallback(final NativeJSObject jsObject) | 424 private void invokeFailureCallback(final NativeJSObject jsObject) |
298 { | 425 { |
299 invokeFailureCallback(getStringFromJsObject(jsObject, "error", "unknown er
ror")); | 426 invokeFailureCallback(getStringFromJsObject(jsObject, "error", "unknown er
ror")); |
300 } | 427 } |
301 | 428 |
302 private void attemptRetry() | |
303 { | |
304 if (System.currentTimeMillis() - this.creationTime > (QUERY_GET_FILTERS_LO
ADED_TIMEOUT * 1000)) | |
305 { | |
306 this.invokeFailureCallback("getFiltersLoaded timeout"); | |
307 } | |
308 else | |
309 { | |
310 Log.d(TAG, "Retrying: " + this.value); | |
311 final ChainedRequest next = this.cloneForRetry(); | |
312 PRIVATE_HANDLER.postDelayed(new Runnable() | |
313 { | |
314 @Override | |
315 public void run() | |
316 { | |
317 GeckoAppShell.sendRequestToGecko(next); | |
318 } | |
319 }, QUERY_GET_FILTERS_LOADED_DELAY); | |
320 } | |
321 } | |
322 | |
323 @Override | 429 @Override |
324 public void onError(final NativeJSObject error) | 430 public void onError(final NativeJSObject error) |
325 { | 431 { |
326 if (this.checkForFiltersLoaded) | 432 this.invokeFailureCallback( |
327 { | 433 "GeckoRequest error: " + error.optString("message", "<no message>") +
"\n" + |
328 this.attemptRetry(); | 434 error.optString("stack", "<no stack>")); |
329 } | |
330 else | |
331 { | |
332 this.invokeFailureCallback( | |
333 "GeckoRequest error: " + error.optString("message", "<no message>")
+ "\n" + | |
334 error.optString("stack", "<no stack>")); | |
335 } | |
336 } | 435 } |
337 | 436 |
338 @Override | 437 @Override |
339 public void onResponse(final NativeJSObject jsObject) | 438 public void onResponse(final NativeJSObject jsObject) |
340 { | 439 { |
341 if (this.checkForFiltersLoaded) | 440 if (getBooleanFromJsObject(jsObject, "success", false)) |
342 { | 441 { |
343 if (getBooleanFromJsObject(jsObject, "success", false) | 442 this.invokeSuccessCallback(jsObject); |
344 && getBooleanFromJsObject(jsObject, "value", false)) | |
345 { | |
346 GeckoAppShell.sendRequestToGecko(this.cloneForRequest()); | |
347 } | |
348 else | |
349 { | |
350 this.attemptRetry(); | |
351 } | |
352 } | 443 } |
353 else | 444 else |
354 { | 445 { |
355 if (getBooleanFromJsObject(jsObject, "success", false)) | 446 this.invokeFailureCallback(jsObject); |
356 { | 447 } |
357 this.invokeSuccessCallback(jsObject); | 448 } |
358 } | 449 } |
359 else | 450 |
360 { | 451 private static class AddOnEventListener implements GeckoEventListener |
361 this.invokeFailureCallback(jsObject); | 452 { |
362 } | 453 @Override |
| 454 public void handleMessage(String event, JSONObject message) |
| 455 { |
| 456 if (ON_FILTERS_LOAD_EVENT.equals(event)) |
| 457 { |
| 458 // The filters have been loaded by the extension. Given that, we can sen
d all pending requests |
| 459 filtersLoaded = true; |
| 460 sendPendingRequests(); |
| 461 } |
| 462 else if (ON_FILTERS_SAVE_EVENT.equals(event)) |
| 463 { |
| 464 // All changes have been saved by the extension. That way, we can clear
our list of |
| 465 // uncompleted requests |
| 466 // See https://issues.adblockplus.org/ticket/2853 |
| 467 clearUncompletedRequests(); |
363 } | 468 } |
364 } | 469 } |
365 } | 470 } |
366 } | 471 } |
OLD | NEW |