 Issue 29350065:
  Issue 2853 - Settings changes are sometimes not saved if the user quits the app  (Closed)
    
  
    Issue 29350065:
  Issue 2853 - Settings changes are sometimes not saved if the user quits the app  (Closed) 
  | Left: | ||
| Right: | 
| 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; | 
| 24 import java.util.concurrent.Semaphore; | |
| 22 | 25 | 
| 23 import android.annotation.SuppressLint; | 26 import android.annotation.SuppressLint; | 
| 27 import android.content.Context; | |
| 28 import android.content.SharedPreferences; | |
| 24 import android.os.Handler; | 29 import android.os.Handler; | 
| 25 import android.os.HandlerThread; | 30 import android.os.HandlerThread; | 
| 26 import android.util.Log; | 31 import android.util.Log; | 
| 27 | 32 | 
| 33 import org.json.JSONArray; | |
| 28 import org.json.JSONException; | 34 import org.json.JSONException; | 
| 29 import org.json.JSONObject; | 35 import org.json.JSONObject; | 
| 30 import org.mozilla.gecko.GeckoAppShell; | 36 import org.mozilla.gecko.GeckoAppShell; | 
| 31 import org.mozilla.gecko.util.GeckoRequest; | 37 import org.mozilla.gecko.util.GeckoRequest; | 
| 32 import org.mozilla.gecko.util.NativeJSObject; | 38 import org.mozilla.gecko.util.NativeJSObject; | 
| 33 | 39 | 
| 34 @SuppressLint("DefaultLocale") | 40 @SuppressLint("DefaultLocale") | 
| 35 public class AddOnBridge | 41 public class AddOnBridge | 
| 36 { | 42 { | 
| 37 private static final String TAG = "AdblockBrowser.AddOnBridge"; | 43 private static final String TAG = "AdblockBrowser.AddOnBridge"; | 
| 38 private static final String REQUEST_NAME = "AdblockPlus:Api"; | 44 private static final String REQUEST_NAME = "AdblockPlus:Api"; | 
| 39 // Timeout for checking filter loading (in seconds) | 45 // Timeout for checking filter loading (in seconds) | 
| 40 private static final int QUERY_GET_FILTERS_LOADED_TIMEOUT = 30; | 46 private static final int QUERY_GET_FILTERS_LOADED_TIMEOUT = 30; | 
| 41 // How long to wait between retries (in milliseconds) | 47 // How long to wait between retries (in milliseconds) | 
| 42 private static final int QUERY_GET_FILTERS_LOADED_DELAY = 500; | 48 private static final int QUERY_GET_FILTERS_LOADED_DELAY = 500; | 
| 43 // Handler+HandlerThread for posting delayed re-tries without interfering with | 49 // Handler+HandlerThread for posting delayed re-tries without interfering with | 
| 44 // other threads (e.g. the UI or Gecko thread) | 50 // other threads (e.g. the UI or Gecko thread) | 
| 45 private static final HandlerThread PRIVATE_HANDLER_THREAD; | 51 private static final HandlerThread PRIVATE_HANDLER_THREAD; | 
| 46 private static final Handler PRIVATE_HANDLER; | 52 private static final Handler PRIVATE_HANDLER; | 
| 47 // Global handler, for e.g. UI tasks | 53 // Global handler, for e.g. UI tasks | 
| 48 private static final HandlerThread GLOBAL_HANDLER_THREAD; | 54 private static final HandlerThread GLOBAL_HANDLER_THREAD; | 
| 49 private static final Handler GLOBAL_HANDLER; | 55 private static final Handler GLOBAL_HANDLER; | 
| 56 // Static members for syncing requests that might not have been saved by filte r storage | |
| 57 // See https://issues.adblockplus.org/ticket/2853 | |
| 58 private static final Semaphore SYNC_REQUESTS_SEMAPHORE = new Semaphore(1); | |
| 59 private static final int SYNC_REQUESTS_DELAY = 30 * 1000; | |
| 60 private static final List<ChainedRequest> PENDING_SYNC_REQUESTS = new ArrayLis t<>(); | |
| 
Felix Dahlke
2016/12/13 11:25:10
I'm a bit confused as to what the point of all thi
 | |
| 61 private static final String PENDING_SYNC_REQUESTS_KEY = "PENDING_SYNC_REQUESTS _KEY"; | |
| 62 | |
| 63 private static SharedPreferences sharedPrefs; | |
| 50 | 64 | 
| 51 static | 65 static | 
| 52 { | 66 { | 
| 53 PRIVATE_HANDLER_THREAD = new HandlerThread("abp-private-handler"); | 67 PRIVATE_HANDLER_THREAD = new HandlerThread("abp-private-handler"); | 
| 54 PRIVATE_HANDLER_THREAD.setDaemon(true); | 68 PRIVATE_HANDLER_THREAD.setDaemon(true); | 
| 55 PRIVATE_HANDLER_THREAD.start(); | 69 PRIVATE_HANDLER_THREAD.start(); | 
| 56 PRIVATE_HANDLER = new Handler(PRIVATE_HANDLER_THREAD.getLooper()); | 70 PRIVATE_HANDLER = new Handler(PRIVATE_HANDLER_THREAD.getLooper()); | 
| 57 | 71 | 
| 58 GLOBAL_HANDLER_THREAD = new HandlerThread("abp-global-handler"); | 72 GLOBAL_HANDLER_THREAD = new HandlerThread("abp-global-handler"); | 
| 59 GLOBAL_HANDLER_THREAD.setDaemon(true); | 73 GLOBAL_HANDLER_THREAD.setDaemon(true); | 
| 60 GLOBAL_HANDLER_THREAD.start(); | 74 GLOBAL_HANDLER_THREAD.start(); | 
| 61 GLOBAL_HANDLER = new Handler(GLOBAL_HANDLER_THREAD.getLooper()); | 75 GLOBAL_HANDLER = new Handler(GLOBAL_HANDLER_THREAD.getLooper()); | 
| 62 } | 76 } | 
| 63 | 77 | 
| 78 public static void init(Context context) | |
| 
Felix Dahlke
2016/12/13 11:25:10
It makes me a bit nervous to rely on outside code
 | |
| 79 { | |
| 80 sharedPrefs = context.getSharedPreferences(AddOnBridge.class.getName(), Cont ext.MODE_PRIVATE); | |
| 81 startSyncRequests(); | |
| 82 } | |
| 83 | |
| 64 public static void postToHandler(Runnable runnable) | 84 public static void postToHandler(Runnable runnable) | 
| 65 { | 85 { | 
| 66 GLOBAL_HANDLER.post(runnable); | 86 GLOBAL_HANDLER.post(runnable); | 
| 67 } | 87 } | 
| 68 | 88 | 
| 69 public static void postToHandlerDelayed(Runnable runnable, long delayMillis) | 89 public static void postToHandlerDelayed(Runnable runnable, long delayMillis) | 
| 70 { | 90 { | 
| 71 GLOBAL_HANDLER.postDelayed(runnable, delayMillis); | 91 GLOBAL_HANDLER.postDelayed(runnable, delayMillis); | 
| 72 } | 92 } | 
| 73 | 93 | 
| 94 public static void startSyncRequests() | |
| 
Felix Dahlke
2016/12/13 11:25:10
Does this have to be public? But see my suggestion
 | |
| 95 { | |
| 96 postToHandler(new Runnable() | |
| 97 { | |
| 98 @Override | |
| 99 public void run() | |
| 100 { | |
| 101 SYNC_REQUESTS_SEMAPHORE.acquireUninterruptibly(); | |
| 102 final String jsonString = sharedPrefs.getString(PENDING_SYNC_REQUESTS_KE Y, null); | |
| 103 PENDING_SYNC_REQUESTS.clear(); | |
| 104 PENDING_SYNC_REQUESTS.addAll(jsonStringToRequestList(jsonString)); | |
| 105 for (final ChainedRequest request : PENDING_SYNC_REQUESTS) | |
| 106 { | |
| 107 GeckoAppShell.sendRequestToGecko(request); | |
| 108 } | |
| 109 SYNC_REQUESTS_SEMAPHORE.release(); | |
| 110 performSyncRequests(); | |
| 111 } | |
| 112 }); | |
| 113 } | |
| 114 | |
| 115 private static void performSyncRequests() | |
| 116 { | |
| 117 SYNC_REQUESTS_SEMAPHORE.acquireUninterruptibly(); | |
| 118 if (PENDING_SYNC_REQUESTS.isEmpty()) | |
| 119 { | |
| 120 SYNC_REQUESTS_SEMAPHORE.release(); | |
| 121 scheduleSyncRequests(); | |
| 122 return; | |
| 123 } | |
| 124 queryValue(new AdblockPlusApiCallback() | |
| 125 { | |
| 126 @Override | |
| 127 public void onApiRequestSucceeded(NativeJSObject jsObject) | |
| 128 { | |
| 129 final boolean requestsSaved = AddOnBridge.getBooleanFromJsObject(jsObjec t, "value", false); | |
| 130 if (requestsSaved) | |
| 131 { | |
| 132 PENDING_SYNC_REQUESTS.clear(); | |
| 133 storeStringPref(PENDING_SYNC_REQUESTS_KEY, requestListToJsonString(PEN DING_SYNC_REQUESTS)); | |
| 134 } | |
| 135 SYNC_REQUESTS_SEMAPHORE.release(); | |
| 136 scheduleSyncRequests(); | |
| 137 } | |
| 138 | |
| 139 @Override | |
| 140 public void onApiRequestFailed(String errorMessage) | |
| 141 { | |
| 142 SYNC_REQUESTS_SEMAPHORE.release(); | |
| 143 scheduleSyncRequests(); | |
| 144 } | |
| 145 }, "requestsSaved"); | |
| 146 } | |
| 147 | |
| 148 private static void scheduleSyncRequests() | |
| 149 { | |
| 150 postToHandlerDelayed(new Runnable() | |
| 151 { | |
| 152 @Override | |
| 153 public void run() | |
| 154 { | |
| 155 performSyncRequests(); | |
| 156 } | |
| 157 }, SYNC_REQUESTS_DELAY); | |
| 158 } | |
| 159 | |
| 160 private static void addPendingSyncRequest(final ChainedRequest chainedRequest) | |
| 161 { | |
| 162 postToHandler(new Runnable() | |
| 163 { | |
| 164 @Override | |
| 165 public void run() | |
| 166 { | |
| 167 SYNC_REQUESTS_SEMAPHORE.acquireUninterruptibly(); | |
| 168 PENDING_SYNC_REQUESTS.add(chainedRequest); | |
| 169 storeStringPref(PENDING_SYNC_REQUESTS_KEY, requestListToJsonString(PENDI NG_SYNC_REQUESTS)); | |
| 170 SYNC_REQUESTS_SEMAPHORE.release(); | |
| 171 } | |
| 172 }); | |
| 173 } | |
| 174 | |
| 175 private static String requestListToJsonString(final List<ChainedRequest> reque stList) | |
| 176 { | |
| 177 if (requestList == null) | |
| 178 { | |
| 179 return null; | |
| 180 } | |
| 181 final JSONArray jsonArray = new JSONArray(); | |
| 182 for (final ChainedRequest request : requestList) | |
| 183 { | |
| 184 jsonArray.put(request.value); | |
| 185 } | |
| 186 return jsonArray.toString(); | |
| 187 } | |
| 188 | |
| 189 private static List<ChainedRequest> jsonStringToRequestList(final String jsonS tring) | |
| 190 { | |
| 191 final List<ChainedRequest> requestList = new ArrayList<>(); | |
| 192 if (jsonString == null) | |
| 193 { | |
| 194 return requestList; | |
| 195 } | |
| 196 try | |
| 197 { | |
| 198 final JSONArray jsonArray = new JSONArray(jsonString); | |
| 199 for (int i = 0; i < jsonArray.length(); i++) | |
| 200 { | |
| 201 final ChainedRequest request = new ChainedRequest(jsonArray.getJSONObjec t(i), null); | |
| 202 requestList.add(request); | |
| 203 } | |
| 204 } | |
| 205 catch (JSONException e) | |
| 206 { | |
| 207 } | |
| 208 return requestList; | |
| 209 } | |
| 210 | |
| 211 private static void storeStringPref(String key, String value) | |
| 212 { | |
| 213 final SharedPreferences.Editor editor = sharedPrefs.edit(); | |
| 214 editor.putString(key, value); | |
| 215 editor.commit(); | |
| 216 } | |
| 217 | |
| 74 public static boolean getBooleanFromJsObject(final NativeJSObject obj, final S tring name, | 218 public static boolean getBooleanFromJsObject(final NativeJSObject obj, final S tring name, | 
| 75 final boolean defaultValue) | 219 final boolean defaultValue) | 
| 76 { | 220 { | 
| 77 try | 221 try | 
| 78 { | 222 { | 
| 79 return obj.getBoolean(name); | 223 return obj.getBoolean(name); | 
| 80 } | 224 } | 
| 81 catch (final Exception e) | 225 catch (final Exception e) | 
| 82 { | 226 { | 
| 83 return defaultValue; | 227 return defaultValue; | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 GeckoAppShell.sendRequestToGecko( | 286 GeckoAppShell.sendRequestToGecko( | 
| 143 new ChainedRequest( | 287 new ChainedRequest( | 
| 144 createRequestData("get" + makeFirstCharacterUppercase(name)), | 288 createRequestData("get" + makeFirstCharacterUppercase(name)), | 
| 145 callback)); | 289 callback)); | 
| 146 } | 290 } | 
| 147 | 291 | 
| 148 public static void setBoolean(final AdblockPlusApiCallback callback, final Str ing name, | 292 public static void setBoolean(final AdblockPlusApiCallback callback, final Str ing name, | 
| 149 final boolean enable) | 293 final boolean enable) | 
| 150 { | 294 { | 
| 151 Log.d(TAG, "setBoolean " + enable + " for " + name); | 295 Log.d(TAG, "setBoolean " + enable + " for " + name); | 
| 152 GeckoAppShell.sendRequestToGecko( | 296 final ChainedRequest request = new ChainedRequest(createRequestData("set" + makeFirstCharacterUppercase(name), enable), callback); | 
| 153 new ChainedRequest( | 297 GeckoAppShell.sendRequestToGecko(request); | 
| 154 createRequestData("set" + makeFirstCharacterUppercase(name), enable) , | 298 addPendingSyncRequest(request); | 
| 155 callback)); | |
| 156 } | 299 } | 
| 157 | 300 | 
| 158 private static void callFunction(final AdblockPlusApiCallback callback, final String name, | 301 private static void callFunction(final AdblockPlusApiCallback callback, final String name, | 
| 159 final Map<String, Object> parameters) | 302 final Map<String, Object> parameters) | 
| 160 { | 303 { | 
| 304 // By default, requests are not synced | |
| 305 callFunction(callback, name, parameters, false); | |
| 306 } | |
| 307 | |
| 308 private static void callFunction(final AdblockPlusApiCallback callback, final String name, | |
| 309 final Map<String, Object> parameters, boolean shouldSyncRequest) | |
| 310 { | |
| 161 final JSONObject requestData = createRequestData(name); | 311 final JSONObject requestData = createRequestData(name); | 
| 162 try | 312 try | 
| 163 { | 313 { | 
| 164 for (Map.Entry<String, Object> entry : parameters.entrySet()) | 314 for (Map.Entry<String, Object> entry : parameters.entrySet()) | 
| 165 requestData.put(entry.getKey(), entry.getValue()); | 315 requestData.put(entry.getKey(), entry.getValue()); | 
| 166 } | 316 } | 
| 167 catch (JSONException e) | 317 catch (JSONException e) | 
| 168 { | 318 { | 
| 169 // we're only adding sane objects | 319 // we're only adding sane objects | 
| 170 Log.e(TAG, "Creating request data failed with: " + e.getMessage(), e); | 320 Log.e(TAG, "Creating request data failed with: " + e.getMessage(), e); | 
| 171 } | 321 } | 
| 172 GeckoAppShell.sendRequestToGecko(new ChainedRequest(requestData, callback)); | 322 final ChainedRequest request = new ChainedRequest(requestData, callback); | 
| 323 GeckoAppShell.sendRequestToGecko(request); | |
| 324 if (shouldSyncRequest) | |
| 325 { | |
| 326 addPendingSyncRequest(request); | |
| 327 } | |
| 173 } | 328 } | 
| 174 | 329 | 
| 175 public static void querySubscriptionListStatus(final AdblockPlusApiCallback ca llback, | 330 public static void querySubscriptionListStatus(final AdblockPlusApiCallback ca llback, | 
| 176 final String url) | 331 final String url) | 
| 177 { | 332 { | 
| 178 Log.d(TAG, "querySubscriptionListStatus for " + url); | 333 Log.d(TAG, "querySubscriptionListStatus for " + url); | 
| 179 final Map<String, Object> parameters = new HashMap<String, Object>(); | 334 final Map<String, Object> parameters = new HashMap<String, Object>(); | 
| 180 parameters.put("url", url); | 335 parameters.put("url", url); | 
| 181 callFunction(callback, "isSubscriptionListed", parameters); | 336 callFunction(callback, "isSubscriptionListed", parameters); | 
| 182 } | 337 } | 
| 183 | 338 | 
| 184 public static void addSubscription(final AdblockPlusApiCallback callback, | 339 public static void addSubscription(final AdblockPlusApiCallback callback, | 
| 185 final String url, final String title) | 340 final String url, final String title) | 
| 186 { | 341 { | 
| 187 Log.d(TAG, "addSubscription for " + url + " (" + title + ")"); | 342 Log.d(TAG, "addSubscription for " + url + " (" + title + ")"); | 
| 188 final Map<String, Object> parameters = new HashMap<String, Object>(); | 343 final Map<String, Object> parameters = new HashMap<String, Object>(); | 
| 189 parameters.put("url", url); | 344 parameters.put("url", url); | 
| 190 if (title != null) | 345 if (title != null) | 
| 191 { | 346 { | 
| 192 parameters.put("title", title); | 347 parameters.put("title", title); | 
| 193 } | 348 } | 
| 194 callFunction(callback, "addSubscription", parameters); | 349 callFunction(callback, "addSubscription", parameters, true); | 
| 195 } | 350 } | 
| 196 | 351 | 
| 197 public static void queryActiveSubscriptions(final AdblockPlusApiCallback callb ack) | 352 public static void queryActiveSubscriptions(final AdblockPlusApiCallback callb ack) | 
| 198 { | 353 { | 
| 199 Log.d(TAG, "queryActiveSubscriptions"); | 354 Log.d(TAG, "queryActiveSubscriptions"); | 
| 200 final Map<String, Object> parameters = new HashMap<String, Object>(); | 355 final Map<String, Object> parameters = new HashMap<String, Object>(); | 
| 201 callFunction(callback, "getActiveSubscriptions", parameters); | 356 callFunction(callback, "getActiveSubscriptions", parameters); | 
| 202 } | 357 } | 
| 203 | 358 | 
| 204 public static void removeSubscription(final AdblockPlusApiCallback callback, | 359 public static void removeSubscription(final AdblockPlusApiCallback callback, | 
| 205 final String url) | 360 final String url) | 
| 206 { | 361 { | 
| 207 Log.d(TAG, "removeSubscription for " + url); | 362 Log.d(TAG, "removeSubscription for " + url); | 
| 208 final Map<String, Object> parameters = new HashMap<String, Object>(); | 363 final Map<String, Object> parameters = new HashMap<String, Object>(); | 
| 209 parameters.put("url", url); | 364 parameters.put("url", url); | 
| 210 callFunction(callback, "removeSubscription", parameters); | 365 callFunction(callback, "removeSubscription", parameters, true); | 
| 211 } | 366 } | 
| 212 | 367 | 
| 213 public static void queryIsLocal(final AdblockPlusApiCallback callback, | 368 public static void queryIsLocal(final AdblockPlusApiCallback callback, | 
| 214 final String url) | 369 final String url) | 
| 215 { | 370 { | 
| 216 Log.d(TAG, "queryIsLocal for " + url); | 371 Log.d(TAG, "queryIsLocal for " + url); | 
| 217 final Map<String, Object> parameters = new HashMap<String, Object>(); | 372 final Map<String, Object> parameters = new HashMap<String, Object>(); | 
| 218 parameters.put("url", url); | 373 parameters.put("url", url); | 
| 219 callFunction(callback, "isLocal", parameters); | 374 callFunction(callback, "isLocal", parameters); | 
| 220 } | 375 } | 
| 221 | 376 | 
| 222 public static void queryIsPageWhitelisted(final AdblockPlusApiCallback callbac k, | 377 public static void queryIsPageWhitelisted(final AdblockPlusApiCallback callbac k, | 
| 223 final String url) | 378 final String url) | 
| 224 { | 379 { | 
| 225 Log.d(TAG, "queryIsPageWhitelisted for " + url); | 380 Log.d(TAG, "queryIsPageWhitelisted for " + url); | 
| 226 final Map<String, Object> parameters = new HashMap<String, Object>(); | 381 final Map<String, Object> parameters = new HashMap<String, Object>(); | 
| 227 parameters.put("url", url); | 382 parameters.put("url", url); | 
| 228 callFunction(callback, "isPageWhitelisted", parameters); | 383 callFunction(callback, "isPageWhitelisted", parameters); | 
| 229 } | 384 } | 
| 230 | 385 | 
| 231 public static void whitelistSite(final AdblockPlusApiCallback callback, final String url, | 386 public static void whitelistSite(final AdblockPlusApiCallback callback, final String url, | 
| 232 final boolean whitelisted) | 387 final boolean whitelisted) | 
| 233 { | 388 { | 
| 234 Log.d(TAG, "whitelistSite for " + url); | 389 Log.d(TAG, "whitelistSite for " + url); | 
| 235 final Map<String, Object> parameters = new HashMap<String, Object>(); | 390 final Map<String, Object> parameters = new HashMap<String, Object>(); | 
| 236 parameters.put("url", url); | 391 parameters.put("url", url); | 
| 237 parameters.put("whitelisted", whitelisted); | 392 parameters.put("whitelisted", whitelisted); | 
| 238 callFunction(callback, "whitelistSite", parameters); | 393 callFunction(callback, "whitelistSite", parameters, true); | 
| 239 } | 394 } | 
| 240 | 395 | 
| 241 private static class ChainedRequest extends GeckoRequest | 396 private static class ChainedRequest extends GeckoRequest | 
| 242 { | 397 { | 
| 243 private final JSONObject value; | 398 private final JSONObject value; | 
| 244 private final AdblockPlusApiCallback apiCallback; | 399 private final AdblockPlusApiCallback apiCallback; | 
| 245 private final boolean checkForFiltersLoaded; | 400 private final boolean checkForFiltersLoaded; | 
| 246 private final long creationTime; | 401 private final long creationTime; | 
| 247 | 402 | 
| 248 public ChainedRequest(final JSONObject value, final AdblockPlusApiCallback c allback, | 403 public ChainedRequest(final JSONObject value, final AdblockPlusApiCallback c allback, | 
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 this.invokeSuccessCallback(jsObject); | 512 this.invokeSuccessCallback(jsObject); | 
| 358 } | 513 } | 
| 359 else | 514 else | 
| 360 { | 515 { | 
| 361 this.invokeFailureCallback(jsObject); | 516 this.invokeFailureCallback(jsObject); | 
| 362 } | 517 } | 
| 363 } | 518 } | 
| 364 } | 519 } | 
| 365 } | 520 } | 
| 366 } | 521 } | 
| OLD | NEW |