Index: mobile/android/thirdparty/org/adblockplus/browser/SubscriptionContainer.java |
diff --git a/mobile/android/thirdparty/org/adblockplus/browser/SubscriptionContainer.java b/mobile/android/thirdparty/org/adblockplus/browser/SubscriptionContainer.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1a9a740eb9541e2b06064f9258979b02aec2725a |
--- /dev/null |
+++ b/mobile/android/thirdparty/org/adblockplus/browser/SubscriptionContainer.java |
@@ -0,0 +1,280 @@ |
+/* |
+ * This file is part of Adblock Plus <https://adblockplus.org/>, |
+ * Copyright (C) 2006-2015 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.browser; |
+ |
+import java.io.IOException; |
+import java.io.StringReader; |
+import java.util.ArrayList; |
+import java.util.HashMap; |
+import java.util.List; |
+import java.util.concurrent.ConcurrentHashMap; |
+import java.util.concurrent.Semaphore; |
+ |
+import org.mozilla.gecko.util.NativeJSObject; |
+import org.xmlpull.v1.XmlPullParser; |
+import org.xmlpull.v1.XmlPullParserException; |
+ |
+import android.util.Log; |
+import android.util.Xml; |
+ |
+final class SubscriptionContainer implements AdblockPlusApiCallback |
+{ |
+ private static final String TAG = SubscriptionContainer.class.getName(); |
+ private final ConcurrentHashMap<String, Boolean> enableState = new ConcurrentHashMap<String, Boolean>(); |
+ private final Semaphore entriesReady = new Semaphore(0); |
+ private final List<SubscriptionContainer.Subscription> entries = new ArrayList<SubscriptionContainer.Subscription>(); |
+ private final HashMap<String, SubscriptionContainer.Subscription> urlMap = new HashMap<String, SubscriptionContainer.Subscription>(); |
+ |
+ private SubscriptionContainer() |
+ { |
+ // prevent external instantiation |
+ } |
+ |
+ public final static SubscriptionContainer create() |
+ { |
+ return create(true); |
+ } |
+ |
+ public final static SubscriptionContainer create(final boolean refresh) |
+ { |
+ final SubscriptionContainer sc = new SubscriptionContainer(); |
+ AddOnBridge.queryValue(sc, "subscriptionsXml"); |
+ sc.entriesReady.acquireUninterruptibly(); |
+ |
+ for (final SubscriptionContainer.Subscription e : sc.entries) |
+ { |
+ sc.urlMap.put(e.url, e); |
+ sc.enableState.put(e.url, Boolean.FALSE); |
+ } |
+ |
+ if (refresh) |
+ { |
+ sc.refresh(); |
+ } |
+ |
+ return sc; |
+ } |
+ |
+ public void refresh() |
+ { |
+ if (!this.entries.isEmpty()) |
+ { |
+ for (int i = 0; i < this.entries.size(); i++) |
+ { |
+ SubscriptionChangeAction.post(this.entries.get(i), |
+ this, |
+ SubscriptionChangeAction.Mode.QUERY_SUBSCRIPTION_ENABLED); |
+ } |
+ |
+ this.entriesReady.acquireUninterruptibly(this.entries.size()); |
+ } |
+ } |
+ |
+ public List<SubscriptionContainer.Subscription> getSubscriptions(boolean enabled) |
+ { |
+ final List<SubscriptionContainer.Subscription> ret = new ArrayList<SubscriptionContainer.Subscription>(); |
+ for (final SubscriptionContainer.Subscription e : this.entries) |
+ { |
+ if (this.isSubscriptionListed(e.url) == enabled) |
+ { |
+ ret.add(e); |
+ } |
+ } |
+ return ret; |
+ } |
+ |
+ public boolean isSubscriptionListed(final String url) |
+ { |
+ return this.enableState.containsKey(url) && this.enableState.get(url).booleanValue(); |
+ } |
+ |
+ public void changeSubscriptionState(final String url, final boolean enable) |
+ { |
+ final SubscriptionContainer.Subscription e = this.urlMap.get(url); |
+ if (e != null) |
+ { |
+ if (enable) |
+ { |
+ SubscriptionChangeAction.post(e, SubscriptionPreferenceCategory.subscriptionContainer, |
+ SubscriptionChangeAction.Mode.ENABLE_SUBSCRIPTION); |
+ } |
+ else |
+ { |
+ SubscriptionChangeAction.post(e, SubscriptionPreferenceCategory.subscriptionContainer, |
+ SubscriptionChangeAction.Mode.DISABLE_SUBSCRIPTION); |
+ } |
+ } |
+ } |
+ |
+ @Override |
+ public void onApiRequestSucceeded(NativeJSObject jsObject) |
+ { |
+ final XmlPullParser parser = Xml.newPullParser(); |
+ try |
+ { |
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); |
+ parser.setInput(new StringReader(AddOnBridge.getStringFromJsObject(jsObject, "value", ""))); |
+ parser.nextTag(); |
+ parser.require(XmlPullParser.START_TAG, null, "subscriptions"); |
+ while (parser.next() != XmlPullParser.END_TAG) |
+ { |
+ if (parser.getEventType() != XmlPullParser.START_TAG) |
+ { |
+ continue; |
+ } |
+ if ("subscription".equals(parser.getName())) |
+ { |
+ final String title = parser.getAttributeValue(null, "title"); |
+ final String specialization = parser.getAttributeValue(null, "specialization"); |
+ final String url = parser.getAttributeValue(null, "url"); |
+ this.entries.add(new Subscription(title, specialization, url)); |
+ } |
+ parser.next(); |
+ } |
+ } |
+ catch (XmlPullParserException e) |
+ { |
+ Log.e(TAG, "Failed to parse subscriptions.xml: " + e.getMessage(), e); |
+ } |
+ catch (IOException e) |
+ { |
+ Log.e(TAG, "Failed to parse subscriptions.xml: " + e.getMessage(), e); |
+ } |
+ finally |
+ { |
+ this.entriesReady.release(); |
+ } |
+ } |
+ |
+ @Override |
+ public void onApiRequestFailed(String errorMessage) |
+ { |
+ Log.e(TAG, "Error: " + errorMessage); |
+ this.entriesReady.release(); |
+ } |
+ |
+ private static class SubscriptionChangeAction implements AdblockPlusApiCallback |
+ { |
+ private static final String TAG = SubscriptionContainer.SubscriptionChangeAction.class.getName(); |
+ |
+ private final SubscriptionContainer.Subscription subscription; |
+ private final SubscriptionContainer parent; |
+ private final SubscriptionChangeAction.Mode mode; |
+ |
+ public enum Mode |
+ { |
+ QUERY_SUBSCRIPTION_ENABLED, |
+ ENABLE_SUBSCRIPTION, |
+ DISABLE_SUBSCRIPTION, |
+ } |
+ |
+ public SubscriptionChangeAction(final SubscriptionContainer.Subscription subscription, |
+ final SubscriptionContainer parent, |
+ final SubscriptionChangeAction.Mode mode) |
+ { |
+ this.subscription = subscription; |
+ this.parent = parent; |
+ this.mode = mode; |
+ } |
+ |
+ public static SubscriptionContainer.SubscriptionChangeAction post(final SubscriptionContainer.Subscription subscription, |
+ final SubscriptionContainer parent, |
+ final SubscriptionChangeAction.Mode mode) |
+ { |
+ return new SubscriptionChangeAction(subscription, parent, mode).post(); |
+ } |
+ |
+ public SubscriptionContainer.SubscriptionChangeAction post() |
+ { |
+ switch (this.mode) |
+ { |
+ case QUERY_SUBSCRIPTION_ENABLED: |
+ AddOnBridge.querySubscriptionListStatus(this, this.subscription.url); |
+ break; |
+ case ENABLE_SUBSCRIPTION: |
+ AddOnBridge.addSubscription(this, this.subscription.url, this.subscription.title); |
+ break; |
+ case DISABLE_SUBSCRIPTION: |
+ AddOnBridge.removeSubscription(this, this.subscription.url); |
+ break; |
+ default: |
+ break; |
+ } |
+ return this; |
+ } |
+ |
+ @Override |
+ public void onApiRequestSucceeded(NativeJSObject jsObject) |
+ { |
+ switch (this.mode) |
+ { |
+ case QUERY_SUBSCRIPTION_ENABLED: |
+ try |
+ { |
+ this.parent.enableState.put(this.subscription.url, |
+ Boolean.valueOf(AddOnBridge.getBooleanFromJsObject(jsObject, "value", false))); |
+ } |
+ finally |
+ { |
+ this.parent.entriesReady.release(); |
+ } |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
+ |
+ @Override |
+ public void onApiRequestFailed(String errorMessage) |
+ { |
+ switch (this.mode) |
+ { |
+ case QUERY_SUBSCRIPTION_ENABLED: |
+ this.parent.enableState.put(this.subscription.url, Boolean.FALSE); |
+ this.parent.entriesReady.release(); |
+ break; |
+ default: |
+ break; |
+ } |
+ |
+ Log.e(TAG, "Error for '" + this.subscription.url |
+ + "', mode: " + this.mode + ": " |
+ + errorMessage); |
+ } |
+ } |
+ |
+ public static class Subscription |
+ { |
+ public final String title; |
+ public final String specialization; |
+ public final String url; |
+ |
+ public Subscription(final String title, final String specialization, final String url) |
+ { |
+ this.title = title; |
+ this.specialization = specialization; |
+ this.url = url; |
+ } |
+ |
+ @Override |
+ public String toString() |
+ { |
+ return this.specialization + " (" + this.title + ") @ " + this.url; |
+ } |
+ } |
+} |