| Index: libadblockplus-android/src/org/adblockplus/libadblockplus/android/AndroidWebRequestResourceWrapper.java |
| diff --git a/libadblockplus-android/src/org/adblockplus/libadblockplus/android/AndroidWebRequestResourceWrapper.java b/libadblockplus-android/src/org/adblockplus/libadblockplus/android/AndroidWebRequestResourceWrapper.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4af10c8cfbabeee4ebfad686df38e9c8ae7dab60 |
| --- /dev/null |
| +++ b/libadblockplus-android/src/org/adblockplus/libadblockplus/android/AndroidWebRequestResourceWrapper.java |
| @@ -0,0 +1,256 @@ |
| +/* |
| + * This file is part of Adblock Plus <https://adblockplus.org/>, |
| + * Copyright (C) 2006-2016 Eyeo GmbH |
| + * |
| + * Adblock Plus is free software: you can redistribute it and/or modify |
| + * it under the terms of the GNU General Public License version 3 as |
| + * published by the Free Software Foundation. |
| + * |
| + * Adblock Plus is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU General Public License |
| + * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| + */ |
| +package org.adblockplus.libadblockplus.android; |
| + |
| +import android.content.Context; |
| +import android.content.SharedPreferences; |
| +import android.util.Log; |
| + |
| +import org.adblockplus.libadblockplus.HeaderEntry; |
| +import org.adblockplus.libadblockplus.ServerResponse; |
| +import org.adblockplus.libadblockplus.WebRequest; |
| + |
| +import java.io.BufferedReader; |
| +import java.io.IOException; |
| +import java.io.InputStream; |
| +import java.io.InputStreamReader; |
| +import java.util.Collections; |
| +import java.util.HashSet; |
| +import java.util.List; |
| +import java.util.Map; |
| +import java.util.Set; |
| + |
| +/** |
| + * WebRequest wrapper to return request response from android resources for selected URLs |
| + */ |
| +public class AndroidWebRequestResourceWrapper extends WebRequest |
| +{ |
| + private static final String TAG = Utils.getTag(AndroidWebRequestResourceWrapper.class); |
| + |
| + public static final String EASYLIST = |
| + "https://easylist-downloads.adblockplus.org/easylist.txt"; |
| + public static final String EASYLIST_INDONESIAN = |
| + "https://easylist-downloads.adblockplus.org/abpindo+easylist.txt"; |
| + public static final String EASYLIST_BULGARIAN = |
| + "https://easylist-downloads.adblockplus.org/bulgarian_list+easylist.txt"; |
| + public static final String EASYLIST_CHINESE = |
| + "https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt"; |
| + public static final String EASYLIST_CZECH_SLOVAK = |
| + "https://easylist-downloads.adblockplus.org/easylistczechslovak+easylist.txt"; |
| + public static final String EASYLIST_DUTCH = |
| + "https://easylist-downloads.adblockplus.org/easylistdutch+easylist.txt"; |
| + public static final String EASYLIST_GERMAN = |
| + "https://easylist-downloads.adblockplus.org/easylistgermany+easylist.txt"; |
| + public static final String EASYLIST_ISRAELI = |
| + "https://easylist-downloads.adblockplus.org/israellist+easylist.txt"; |
| + public static final String EASYLIST_ITALIAN = |
| + "https://easylist-downloads.adblockplus.org/easylistitaly+easylist.txt"; |
| + public static final String EASYLIST_LITHUANIAN = |
| + "https://easylist-downloads.adblockplus.org/easylistlithuania+easylist.txt"; |
| + public static final String EASYLIST_LATVIAN = |
| + "https://easylist-downloads.adblockplus.org/latvianlist+easylist.txt"; |
| + public static final String EASYLIST_ARABIAN_FRENCH = |
| + "https://easylist-downloads.adblockplus.org/liste_ar+liste_fr+easylist.txt"; |
| + public static final String EASYLIST_FRENCH = |
| + "https://easylist-downloads.adblockplus.org/liste_fr+easylist.txt"; |
| + public static final String EASYLIST_ROMANIAN = |
| + "https://easylist-downloads.adblockplus.org/rolist+easylist.txt"; |
| + public static final String EASYLIST_RUSSIAN = |
| + "https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt"; |
| + public static final String ACCEPTABLE_ADS = |
| + "https://easylist-downloads.adblockplus.org/exceptionrules.txt"; |
| + |
| + private Context context; |
| + private WebRequest request; |
| + private Map<String, Integer> urlToResourceIdMap; |
| + private Storage storage; |
| + private Listener listener; |
| + |
| + /** |
| + * Constructor |
| + * @param context android context |
| + * @param request wrapped request to perform the request if it's not preloaded subscription requested |
| + * @param urlToResourceIdMap map URL -> android resource id for preloaded subscriptions |
| + * See AndroidWebRequestResourceWrapper.EASYLIST_... constants |
| + * @param storage Storage impl to remember served interceptions |
| + */ |
| + public AndroidWebRequestResourceWrapper(Context context, WebRequest request, |
| + Map<String, Integer> urlToResourceIdMap, |
| + Storage storage) |
| + { |
| + this.context = context; |
| + this.request = request; |
| + this.urlToResourceIdMap = Collections.synchronizedMap(urlToResourceIdMap); |
| + this.storage = storage; |
| + } |
| + |
| + public Listener getListener() |
| + { |
| + return listener; |
| + } |
| + |
| + public void setListener(Listener listener) |
| + { |
| + this.listener = listener; |
| + } |
| + |
| + @Override |
| + public ServerResponse httpGET(String url, List<HeaderEntry> headers) |
| + { |
| + // since parameters may vary we need to ignore them |
| + String urlWithoutParams = url.substring(0, url.indexOf("?")); |
| + Integer resourceId = urlToResourceIdMap.get(urlWithoutParams); |
| + |
| + if (resourceId != null) |
| + { |
| + if (!storage.contains(urlWithoutParams)) |
| + { |
| + Log.w(TAG, "Intercepting request for " + url + " with resource #" + resourceId.intValue()); |
| + ServerResponse response = buildResourceContentResponse(resourceId); |
| + storage.put(urlWithoutParams); |
| + |
| + if (listener != null) |
| + { |
| + listener.onIntercepted(url, resourceId); |
| + } |
| + |
| + return response; |
| + } |
| + else |
| + { |
| + Log.d(TAG, "Skip intercepting"); |
| + } |
| + } |
| + |
| + // delegate to wrapper request |
| + return request.httpGET(url, headers); |
| + } |
| + |
| + protected String readResourceContent(int resourceId) throws IOException |
| + { |
| + Log.d(TAG, "Reading from resource ..."); |
| + |
| + InputStream is = null; |
| + |
| + try |
| + { |
| + is = context.getResources().openRawResource(resourceId); |
| + BufferedReader br = new BufferedReader(new InputStreamReader(is)); |
| + StringBuilder sb = new StringBuilder(); |
| + String line; |
| + boolean firstLine = true; |
| + while ((line = br.readLine()) != null) |
| + { |
| + if (firstLine) |
| + { |
| + firstLine = false; |
| + } |
| + else |
| + { |
| + sb.append("\r\n"); |
| + } |
| + sb.append(line); |
| + } |
| + |
| + Log.d(TAG, "Resource read (" + sb.length() + " bytes)"); |
| + return sb.toString(); |
| + } |
| + finally |
| + { |
| + if (is != null) |
| + { |
| + is.close(); |
| + } |
| + } |
| + } |
| + |
| + protected ServerResponse buildResourceContentResponse(int resourceId) |
| + { |
| + ServerResponse response = new ServerResponse(); |
| + try |
| + { |
| + response.setResponse(readResourceContent(resourceId)); |
| + response.setResponseStatus(200); |
| + response.setStatus(ServerResponse.NsStatus.OK); |
| + } |
| + catch (IOException e) |
| + { |
| + Log.e(TAG, "Error injecting response", e); |
| + response.setStatus(ServerResponse.NsStatus.ERROR_FAILURE); |
| + } |
| + |
| + return response; |
| + } |
| + |
| + @Override |
| + public void dispose() |
| + { |
| + request.dispose(); |
| + super.dispose(); |
| + } |
| + |
| + /** |
| + * Listener for events |
| + */ |
| + public interface Listener |
| + { |
| + void onIntercepted(String url, int resourceId); |
| + } |
| + |
| + /** |
| + * Interface to remember intercepted subscription requests |
| + */ |
| + public interface Storage |
| + { |
| + void put(String url); |
| + boolean contains(String url); |
| + } |
| + |
| + /** |
| + * Storage impl in Shared Preferences |
| + */ |
| + public static class SharedPrefsStorage implements Storage |
| + { |
| + private static final String URLS = "urls"; |
| + |
| + private SharedPreferences prefs; |
| + private Set<String> urls; |
| + |
| + public SharedPrefsStorage(SharedPreferences prefs) |
| + { |
| + this.prefs = prefs; |
| + this.urls = prefs.getStringSet(URLS, new HashSet<String>()); |
| + } |
| + |
| + @Override |
| + public synchronized void put(String url) |
| + { |
| + urls.add(url); |
| + |
| + prefs |
| + .edit() |
| + .putStringSet(URLS, urls) |
| + .commit(); |
| + } |
| + |
| + @Override |
| + public synchronized boolean contains(String url) |
| + { |
| + return urls.contains(url); |
| + } |
| + } |
| +} |