| Index: mobile/android/thirdparty/org/adblockplus/browser/SubscriptionContainer.java |
| =================================================================== |
| --- a/mobile/android/thirdparty/org/adblockplus/browser/SubscriptionContainer.java |
| +++ b/mobile/android/thirdparty/org/adblockplus/browser/SubscriptionContainer.java |
| @@ -14,36 +14,40 @@ |
| * 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.lang.ref.WeakReference; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| +import java.util.Iterator; |
| import java.util.List; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.Semaphore; |
| import org.mozilla.gecko.util.NativeJSObject; |
| +import org.mozilla.gecko.util.ThreadUtils; |
| 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 ConcurrentHashMap<String, Boolean> enableState = new ConcurrentHashMap<>(); |
| 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 final List<SubscriptionContainer.Subscription> entries = new ArrayList<>(); |
| + private final HashMap<String, SubscriptionContainer.Subscription> urlMap = new HashMap<>(); |
| + private final List<WeakReference<SubscriptionListener>> subscriptionListeners = new ArrayList<>(); |
| private SubscriptionContainer() |
| { |
| // prevent external instantiation |
| } |
| public final static SubscriptionContainer create() |
| { |
| @@ -82,17 +86,17 @@ final class SubscriptionContainer implem |
| } |
| this.entriesReady.acquireUninterruptibly(this.entries.size()); |
| } |
| } |
| public List<SubscriptionContainer.Subscription> getSubscriptions(boolean enabled) |
| { |
| - final List<SubscriptionContainer.Subscription> ret = new ArrayList<SubscriptionContainer.Subscription>(); |
| + final List<SubscriptionContainer.Subscription> ret = new ArrayList<>(); |
| for (final SubscriptionContainer.Subscription e : this.entries) |
| { |
| if (this.isSubscriptionListed(e.url) == enabled) |
| { |
| ret.add(e); |
| } |
| } |
| return ret; |
| @@ -116,16 +120,43 @@ final class SubscriptionContainer implem |
| else |
| { |
| SubscriptionChangeAction.post(e, SubscriptionPreferenceCategory.subscriptionContainer, |
| SubscriptionChangeAction.Mode.DISABLE_SUBSCRIPTION); |
| } |
| } |
| } |
| + public void addSubscriptionListener(SubscriptionListener listener) |
| + { |
| + final Iterator<WeakReference<SubscriptionListener>> iterator = this.subscriptionListeners.iterator(); |
| + boolean shouldAddListener = true; |
| + |
| + while (iterator.hasNext()) |
| + { |
| + final SubscriptionListener subscriptionListener = iterator.next().get(); |
| + if (subscriptionListener != null) |
| + { |
| + if (subscriptionListener.equals(listener)) |
| + { |
| + shouldAddListener = false; |
| + } |
| + } |
| + else |
| + { |
| + iterator.remove(); |
| + } |
| + } |
| + |
| + if (shouldAddListener) |
| + { |
| + this.subscriptionListeners.add(new WeakReference<>(listener)); |
| + } |
| + } |
| + |
| @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", ""))); |
| @@ -229,16 +260,41 @@ final class SubscriptionContainer implem |
| this.parent.enableState.put(this.subscription.url, |
| Boolean.valueOf(AddOnBridge.getBooleanFromJsObject(jsObject, "value", false))); |
| } |
| finally |
| { |
| this.parent.entriesReady.release(); |
| } |
| break; |
| + case ENABLE_SUBSCRIPTION: |
| + case DISABLE_SUBSCRIPTION: |
| + this.parent.enableState.put(this.subscription.url, this.mode == Mode.ENABLE_SUBSCRIPTION); |
| + final Iterator<WeakReference<SubscriptionListener>> iterator = this.parent.subscriptionListeners.iterator(); |
| + |
| + while (iterator.hasNext()) |
| + { |
| + final SubscriptionListener listener = iterator.next().get(); |
| + if (listener != null) |
| + { |
| + ThreadUtils.postToUiThread(new Runnable() |
| + { |
| + @Override |
| + public void run() |
| + { |
| + listener.onSubscriptionUpdated(); |
| + } |
| + }); |
| + } |
| + else |
| + { |
| + iterator.remove(); |
| + } |
| + } |
| + break; |
| default: |
| break; |
| } |
| } |
| @Override |
| public void onApiRequestFailed(String errorMessage) |
| { |
| @@ -272,9 +328,14 @@ final class SubscriptionContainer implem |
| } |
| @Override |
| public String toString() |
| { |
| return this.specialization + " (" + this.title + ") @ " + this.url; |
| } |
| } |
| + |
| + public interface SubscriptionListener |
| + { |
| + void onSubscriptionUpdated(); |
| + } |
| } |