Mozdev
weavesync/chrome/content/weaveIntegration.js
author Wladimir Palant <trev@adblockplus.org>
Mon Jun 01 12:11:19 2009 +0200 (14 months ago)
changeset 1860 03b6fcbdc78b
parent 1858d868e76577af
permissions -rw-r--r--
Removing outdated comment
     1 /* ***** BEGIN LICENSE BLOCK *****
     2  * Version: MPL 1.1
     3  *
     4  * The contents of this file are subject to the Mozilla Public License Version
     5  * 1.1 (the "License"); you may not use this file except in compliance with
     6  * the License. You may obtain a copy of the License at
     7  * http://www.mozilla.org/MPL/
     8  *
     9  * Software distributed under the License is distributed on an "AS IS" basis,
    10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    11  * for the specific language governing rights and limitations under the
    12  * License.
    13  *
    14  * The Original Code is Weave Sync for Adblock Plus.
    15  *
    16  * The Initial Developer of the Original Code is
    17  * Wladimir Palant.
    18  * Portions created by the Initial Developer are Copyright (C) 2009
    19  * the Initial Developer. All Rights Reserved.
    20  *
    21  * Contributor(s):
    22  *
    23  * ***** END LICENSE BLOCK ***** */
    24 
    25 /*
    26  * This file is loaded by Startup.js component.
    27  */
    28 
    29 var abp = Components.classes["@mozilla.org/adblockplus;1"].createInstance().wrappedJSObject;
    30 
    31 Components.utils.import("resource://weave/engines.js");
    32 Components.utils.import("resource://weave/stores.js");
    33 Components.utils.import("resource://weave/trackers.js");
    34 Components.utils.import("resource://weave/base_records/crypto.js");
    35 Components.utils.import("resource://weave/async.js");
    36 Components.utils.import("resource://weave/util.js");
    37 
    38 Function.prototype.async = Async.sugar;
    39 
    40 function ABPRecord(uri)
    41 {
    42   CryptoWrapper.call(this, uri);
    43   this.cleartext = {};
    44 }
    45 ABPRecord.prototype =
    46 {
    47   __proto__: CryptoWrapper.prototype,
    48   _logname: "Record.AdblockPlus",
    49 
    50   _source: null,
    51   get source() this._source,
    52   set source(source)
    53   {
    54     this._source = source;
    55 
    56     if (source instanceof abp.Filter)
    57     {
    58       this.cleartext.type = "filter";
    59       this.cleartext.text = source.text;
    60       if (source instanceof abp.ActiveFilter)
    61         this.cleartext.disabled = source.disabled;
    62     }
    63     else if (source instanceof abp.Subscription)
    64     {
    65       this.cleartext.type = "subscription";
    66       this.cleartext.url = source.url;
    67       this.cleartext.disabled = source.disabled;
    68       if (source instanceof abp.RegularSubscription)
    69         this.cleartext.title = source.title;
    70       if (source instanceof abp.DownloadableSubscription)
    71         this.cleartext.autoDownload = source.autoDownload;
    72     }
    73     else if (typeof source == "string")
    74     {
    75       this.cleartext.type = "pref";
    76       this.cleartext.name = source;
    77       this.cleartext.value = abp.prefs[source];
    78     }
    79     else
    80     {
    81       this.deleted = true;
    82       this.payload = null;  // Weave 0.3 compatibility
    83     }
    84   },
    85 
    86   _saveBack: function()
    87   {
    88     switch (this.cleartext.type)
    89     {
    90       case "filter":
    91         let filter = abp.Filter.fromText(this.cleartext.text);
    92         if (!filter)
    93           break;
    94 
    95         if (filter instanceof abp.ActiveFilter && this.cleartext.disabled != filter.disabled)
    96         {
    97           filter.disabled = this.cleartext.disabled;
    98           abp.filterStorage.triggerFilterObservers(filter.disabled ? "disable" : "enable", [filter]);
    99         }
   100 
   101         this._source = filter;
   102         break;
   103       case "subscription":
   104         let subscription = abp.Subscription.fromURL(this.cleartext.url);
   105         if (!subscription)
   106           break;
   107 
   108         if (this.cleartext.disabled != subscription.disabled)
   109         {
   110           subscription.disabled = this.cleartext.disabled;
   111           abp.filterStorage.triggerSubscriptionObservers(subscription.disabled ? "disable" : "enable", [subscription]);
   112         }
   113 
   114         let changed = false;
   115         if (subscription instanceof abp.RegularSubscription && this.cleartext.title != subscription.title)
   116         {
   117           subscription.title = this.cleartext.title;
   118           changed = true;
   119         }
   120         if (subscription instanceof abp.DownloadableSubscription && this.cleartext.autoDownload != subscription.autoDownload)
   121         {
   122           subscription.autoDownload = this.cleartext.autoDownload;
   123           changed = true;
   124         }
   125         if (changed)
   126           abp.filterStorage.triggerSubscriptionObservers("updateinfo", [subscription]);
   127 
   128         this._source = subscription;
   129         break;
   130       case "pref":
   131         let prefName = this.cleartext.name;
   132         if (this.cleartext.value != abp.prefs[prefName])
   133         {
   134           abp.prefs[prefName] = this.cleartext.value;
   135           abp.prefs.save();
   136         }
   137 
   138         this._source = prefName;
   139         break;
   140     }
   141   }
   142 };
   143 
   144 function ABPStore()
   145 {
   146   Store.call(this);
   147 }
   148 ABPStore.prototype =
   149 {
   150   __proto__: Store.prototype,
   151   _logName: "AdblockPlus",
   152   _abpItems: null,
   153 
   154   createRecord: function(id, cryptoMetaURL)
   155   {
   156     let record = this.cache.get(id);
   157     if (record)
   158       return record;
   159 
   160     record = new ABPRecord();
   161     record.id = id;
   162     record.encryption = cryptoMetaURL;
   163     if (id in this._abpItems)
   164       record.source = this._abpItems[id];
   165     else
   166     {
   167       record.deleted = true;
   168       record.payload = null;  // Weave 0.3 compatibility
   169     }
   170 
   171     this.cache.put(id, record);
   172     return record;
   173   },
   174 
   175   itemExists: function(id)
   176   {
   177     return (id in this._abpItems);
   178   },
   179 
   180   // This method shouldn't be called because Engine._recordLike() always returns false
   181   changeItemID: function(oldId, newId) {},
   182 
   183   getAllIDs: function()
   184   {
   185     let result = {};
   186     for each (let subscription in abp.filterStorage.subscriptions)
   187     {
   188       if (!(subscription instanceof abp.ExternalSubscription))
   189         result[Utils.sha1("subscription " + subscription.url)] = subscription;
   190 
   191       if (subscription instanceof abp.SpecialSubscription)
   192       {
   193         for each (let filter in subscription.filters)
   194           result[Utils.sha1("filter " + filter.text)] = filter;
   195       }
   196     }
   197     for each (let [prefName, prefType, defaultValue] in abp.prefs.prefList)
   198       if (prefName != "currentVersion")
   199         result[Utils.sha1("pref " + prefName)] = prefName;
   200 
   201     return result;
   202   },
   203 
   204   wipe: function()
   205   {
   206     this._log.debug("Wiping all client data");
   207 
   208     let subscriptions = abp.filterStorage.subscriptions.slice();
   209     for each (let subscription in subscriptions)
   210     {
   211       if (subscription instanceof abp.SpecialSubscription)
   212         abp.filterStorage.updateSubscriptionFilters(subscription, []);
   213       else if (!(subscription instanceof abp.ExternalSubscription))
   214         abp.filterStorage.removeSubscription(subscription);
   215     }
   216 
   217     for each (let [prefName, prefType, defaultValue] in abp.prefs.prefList)
   218     {
   219       if (prefName != "currentVersion")
   220         abp.prefs[prefName] = defaultValue;
   221     }
   222     abp.prefs.save();
   223   },
   224 
   225   create: function(record)
   226   {
   227     this._log.debug("Got create command for " + record.id);
   228 
   229     record._saveBack();
   230     if (record.source instanceof abp.Filter)
   231       abp.filterStorage.addFilter(record.source);
   232     else if (record.source instanceof abp.DownloadableSubscription)
   233     {
   234       abp.filterStorage.addSubscription(record.source);
   235       if (!record.source.lastDownload)
   236         synchronizer.execute(record.source);
   237     }
   238   },
   239   update: function(record)
   240   {
   241     this._log.debug("Got update command for " + record.id);
   242 
   243     record._saveBack();
   244   },
   245   remove: function(record)
   246   {
   247     this._log.debug("Got remove command for " + record.id);
   248 
   249     if (record.id in this._abpItems)
   250     {
   251       let item = this._abpItems[record.id];
   252       if (item instanceof abp.Filter)
   253         abp.filterStorage.removeFilter(item);
   254       else if (item instanceof abp.DownloadableSubscription)
   255         abp.filterStorage.removeSubscription(item);
   256     }
   257   },
   258 
   259   cacheABPItems: function()
   260   {
   261     this._log.debug("Caching all ABP items");
   262     this._abpItems = this.getAllIDs();
   263   },
   264   clearABPCache: function()
   265   {
   266     this._log.debug("Clearing ABP item cache");
   267     this._abpItems = null;
   268   }
   269 };
   270 
   271 function ABPTracker()
   272 {
   273   Tracker.call(this);
   274 
   275   let me = this;
   276   abp.prefs.addListener(function() { me.onPrefChange.apply(me, arguments); });
   277   abp.filterStorage.addSubscriptionObserver(function() { me.onSubscriptionChange.apply(me, arguments); });
   278   abp.filterStorage.addFilterObserver(function() { me.onFilterChange.apply(me, arguments); });
   279 }
   280 ABPTracker.prototype =
   281 {
   282   __proto__: Tracker.prototype,
   283   _logName: "Tracker.AdblockPlus",
   284   file: "abpdata",
   285 
   286   onPrefChange: function()
   287   {
   288     for each (let [prefName, prefType, defaultValue] in abp.prefs.prefList)
   289       if (prefName != "currentVersion")
   290         this.addChangedID(Utils.sha1("pref " + prefName));
   291     this._score += 20;
   292   },
   293 
   294   onSubscriptionChange: function(action, subscriptions)
   295   {
   296     for each (let subscription in subscriptions)
   297     {
   298       if (!(subscription instanceof abp.ExternalSubscription))
   299         this.addChangedID(Utils.sha1("subscription " + subscription.url));
   300 
   301       if (subscription instanceof abp.SpecialSubscription && action == "update")
   302       {
   303         let oldFilters = {__proto__: null};
   304         for each (let filter in subscription.oldFilters)
   305           oldFilters[filter.text] = true;
   306         let newFilters = {__proto__: null};
   307         for each (let filter in subscription.filters)
   308           newFilters[filter.text] = true;
   309 
   310         for (let text in oldFilters)
   311           if (!(text in newFilters))
   312             this.addChangedID(Utils.sha1("filter " + text));
   313 
   314         for (let text in newFilters)
   315           if (!(text in oldFilters))
   316             this.addChangedID(Utils.sha1("filter " + text));
   317       }
   318     }
   319     this._score += 5;
   320   },
   321 
   322   onFilterChange: function(action, filters)
   323   {
   324     if (action == "hit")
   325       return;
   326 
   327     for each (let filter in filters)
   328       this.addChangedID(Utils.sha1("filter " + filter.text));
   329     this._score += 10;
   330   }
   331 };
   332 
   333 function ABPEngine()
   334 {
   335   SyncEngine.call(this);
   336 }
   337 ABPEngine.prototype =
   338 {
   339   __proto__: SyncEngine.prototype,
   340   name: "abpdata",
   341   displayName: Cc["@mozilla.org/intl/stringbundle;1"]
   342                 .getService(Ci.nsIStringBundleService)
   343                 .createBundle("chrome://abpweavesync/locale/global.properties")
   344                 .GetStringFromName("dataProvider_name"),
   345   logName: "AdblockPlus",
   346   _storeObj: ABPStore,
   347   _trackerObj: ABPTracker,
   348   _recordObj: ABPRecord,
   349 
   350   _recordLike: function() false,
   351 
   352   // Work-around for https://bugzilla.mozilla.org/show_bug.cgi?id=493256
   353   _isEqual: function(item)
   354   {
   355     if (item.deleted || item.payload === null /* Weave 0.3 compatibility */)
   356       return false;
   357 
   358     return this.__proto__.__proto__._isEqual.apply(this, arguments);
   359   },
   360 
   361   _syncStartup: function()
   362   {
   363     let self = yield;
   364     this._store.cacheABPItems();
   365     yield SyncEngine.prototype._syncStartup.async(this, self.cb);
   366   },
   367   _syncFinish: function()
   368   {
   369     let self = yield;
   370     this._store.clearABPCache();
   371     yield SyncEngine.prototype._syncFinish.async(this, self.cb);
   372   }
   373 };
   374 
   375 if ("isArray" in Utils)
   376   Engines.register(ABPEngine);
   377 else
   378   Engines.register(new ABPEngine());  /* Weave 0.3 compatibility */