Index: lib/filterClasses.js
===================================================================
--- a/lib/filterClasses.js
+++ b/lib/filterClasses.js
@@ -55,23 +55,16 @@
  * Abstract base class for filters
  *
  * @param {string} text   string representation of the filter
  * @constructor
  */
 function Filter(text)
 {
   this.text = text;
-
-  /**
-   * Subscriptions to which this filter belongs.
-   * @type {(Subscription|Set.<Subscription>)?}
-   * @private
-   */
-  this._subscriptions = null;
 }
 exports.Filter = Filter;
 
 Filter.prototype =
 {
   /**
    * String representation of the filter
    * @type {string}
@@ -83,46 +76,73 @@
    * @type {string}
    */
   get type()
   {
     throw new Error("Please define filter type in the subclass");
   },
 
   /**
+   * Subscriptions to which this filter belongs.
+   * @type {?(Subscription|Set.<Subscription>)}
+   * @private
+   */
+  _subscriptions: null,
+
+  /**
+   * Whether the filter's subscriptions have already been added to the filter.
+   * @type {boolean}
+   * @package
+   */
+  get subscriptionsAdded()
+  {
+    return this.hasOwnProperty("_subscriptions");
+  },
+  set subscriptionsAdded(value)
+  {
+    // Once set to true, this cannot be set back to false even if all
+    // subscriptions are removed.
+    if (value)
+      this._subscriptions = this._subscriptions;
+  },
+
+  /**
    * Yields subscriptions to which the filter belongs.
    * @yields {Subscription}
+   * @package
    */
   *subscriptions()
   {
     if (this._subscriptions)
     {
       if (this._subscriptions instanceof Set)
         yield* this._subscriptions;
       else
         yield this._subscriptions;
     }
   },
 
   /**
    * The number of subscriptions to which the filter belongs.
    * @type {number}
+   * @package
    */
   get subscriptionCount()
   {
     if (this._subscriptions instanceof Set)
       return this._subscriptions.size;
 
     return this._subscriptions ? 1 : 0;
   },
 
   /**
    * Adds a subscription to the set of subscriptions to which the filter
    * belongs.
    * @param {Subscription} subscription
+   * @package
    */
   addSubscription(subscription)
   {
     // Since we use truthy checks in our logic, we must avoid adding a
     // subscription that isn't a non-null object.
     if (subscription === null || typeof subscription != "object")
       return;
 
@@ -138,16 +158,17 @@
       this._subscriptions = subscription;
     }
   },
 
   /**
    * Removes a subscription from the set of subscriptions to which the filter
    * belongs.
    * @param {Subscription} subscription
+   * @package
    */
   removeSubscription(subscription)
   {
     if (this._subscriptions)
     {
       if (this._subscriptions instanceof Set)
       {
         this._subscriptions.delete(subscription);
Index: lib/filterListener.js
===================================================================
--- a/lib/filterListener.js
+++ b/lib/filterListener.js
@@ -137,17 +137,17 @@
  */
 function addFilter(filter)
 {
   if (!(filter instanceof ActiveFilter) || filter.disabled)
     return;
 
   let hasEnabled = false;
   let allowSnippets = false;
-  for (let subscription of filter.subscriptions())
+  for (let subscription of filterStorage.subscriptionsForFilter(filter))
   {
     if (!subscription.disabled)
     {
       hasEnabled = true;
 
       // Allow snippets to be executed only by the circumvention lists or the
       // user's own filters.
       if (subscription.type == "circumvention" ||
@@ -185,17 +185,17 @@
 function removeFilter(filter)
 {
   if (!(filter instanceof ActiveFilter))
     return;
 
   if (!filter.disabled)
   {
     let hasEnabled = false;
-    for (let subscription of filter.subscriptions())
+    for (let subscription of filterStorage.subscriptionsForFilter(filter))
     {
       if (!subscription.disabled)
       {
         hasEnabled = true;
         break;
       }
     }
     if (hasEnabled)
Index: lib/filterStorage.js
===================================================================
--- a/lib/filterStorage.js
+++ b/lib/filterStorage.js
@@ -123,16 +123,43 @@
    * @type {number}
    */
   get subscriptionCount()
   {
     return this.knownSubscriptions.size;
   }
 
   /**
+   * Yields subscriptions in the storage to which the given filter belongs.
+   * @param {Filter} filter
+   * @yields {Subscription}
+   */
+  *subscriptionsForFilter(filter)
+  {
+    if (!filter.subscriptionsAdded)
+      addSubscriptionsToFilter(filter);
+
+    yield* filter.subscriptions();
+  }
+
+  /**
+   * Returns the number of subscriptions in the storage to which the given
+   * filter belongs.
+   * @param {Filter} filter
+   * @return {number}
+   */
+  getSubscriptionCountForFilter(filter)
+  {
+    if (!filter.subscriptionsAdded)
+      addSubscriptionsToFilter(filter);
+
+    return filter.subscriptionCount;
+  }
+
+  /**
    * Finds the filter group that a filter should be added to by default. Will
    * return <code>null</code> if this group doesn't exist yet.
    * @param {Filter} filter
    * @returns {?SpecialSubscription}
    */
   getGroupForFilter(filter)
   {
     let generalSubscription = null;
@@ -221,17 +248,17 @@
    * @param {number} [position] The position within the subscription at which
    *   the filter should be added. If not specified, the filter is added at the
    *   end of the subscription.
    */
   addFilter(filter, subscription, position)
   {
     if (!subscription)
     {
-      for (let currentSubscription of filter.subscriptions())
+      for (let currentSubscription of this.subscriptionsForFilter(filter))
       {
         if (currentSubscription instanceof SpecialSubscription &&
             !currentSubscription.disabled)
         {
           return;   // No need to add
         }
       }
       subscription = this.getGroupForFilter(filter);
@@ -260,17 +287,17 @@
    *   removed from all subscriptions.
    * @param {number} [position] The position within the subscription at which
    *   the filter should be removed. If not specified, all instances of the
    *   filter will be removed.
    */
   removeFilter(filter, subscription, position)
   {
     let subscriptions = (
-      subscription ? [subscription] : filter.subscriptions()
+      subscription ? [subscription] : this.subscriptionsForFilter(filter)
     );
     for (let currentSubscription of subscriptions)
     {
       if (currentSubscription instanceof SpecialSubscription)
       {
         let positions = [];
         if (typeof position == "undefined")
         {
@@ -657,16 +684,32 @@
  * Reads the user's filters from disk, manages them in memory, and writes them
  * back to disk.
  */
 let filterStorage = new FilterStorage();
 
 exports.filterStorage = filterStorage;
 
 /**
+ * Adds to a filter any subscriptions in the storage to which the filter
+ * belongs.
+ * @param {Filter} filter
+ */
+function addSubscriptionsToFilter(filter)
+{
+  for (let subscription of filterStorage.subscriptions())
+  {
+    if (subscription.hasFilter(filter))
+      filter.addSubscription(subscription);
+  }
+
+  filter.subscriptionsAdded = true;
+}
+
+/**
  * Connects a subscription to its filters without any notifications.
  * @param {Subscription} subscription The subscription that should be
  *   connected to its filters.
  * @param {?Array.<Filter>} [filters] A list of filters to which the
  *   subscription should be connected. If this is not given, the subscription
  *   is connected to its own filters.
  */
 function connectSubscriptionFilters(subscription, filters)
