| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 /* | 
|  | 2  * This file is part of Adblock Plus <http://adblockplus.org/>, | 
|  | 3  * Copyright (C) 2006-2014 Eyeo GmbH | 
|  | 4  * | 
|  | 5  * Adblock Plus is free software: you can redistribute it and/or modify | 
|  | 6  * it under the terms of the GNU General Public License version 3 as | 
|  | 7  * published by the Free Software Foundation. | 
|  | 8  * | 
|  | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
|  | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 12  * GNU General Public License for more details. | 
|  | 13  * | 
|  | 14  * You should have received a copy of the GNU General Public License | 
|  | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 16  */ | 
|  | 17 | 
|  | 18 let {Services} = Cu.import("resource://gre/modules/Services.jsm", null); | 
|  | 19 let {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", null); | 
|  | 20 | 
|  | 21 let {Utils} = require("utils"); | 
|  | 22 let {MILLIS_IN_DAY} = require("downloader"); | 
|  | 23 | 
|  | 24 /** | 
|  | 25  * This class reads filter hits statistics from SQLite database, | 
|  | 26  * manages them in memory and writes them back. | 
|  | 27  * @class | 
|  | 28  */ | 
|  | 29 let FilterHits = exports.FilterHits = | 
|  | 30 { | 
|  | 31   filters: {}, | 
|  | 32 | 
|  | 33   _serviceURL: "", | 
|  | 34   _lastPush: 0, | 
|  | 35   _pushInterval: MILLIS_IN_DAY * 7, | 
|  | 36   _loading: false, | 
|  | 37   _saving: false, | 
|  | 38   _sending: false, | 
|  | 39 | 
|  | 40   /** | 
|  | 41    * Increases the filter hit count | 
|  | 42    * @param {Filter} filter | 
|  | 43    * @param {Window} window  Window that the match originated in (required to ge
     t host) | 
|  | 44    */ | 
|  | 45   increaseFilterHits: function(filter, wnd) | 
|  | 46   { | 
|  | 47     if (!filter.text || (filter.subscriptions[0] && filter.subscriptions[0].url.
     indexOf("~user~") == 0)) | 
|  | 48       return; | 
|  | 49 | 
|  | 50     if (!(filter.text in this.filters)) | 
|  | 51       this.filters[filter.text] = {}; | 
|  | 52 | 
|  | 53     let filterType = filter.thirdParty ? "thirdParty" : "firstParty"; | 
|  | 54 | 
|  | 55     if (!(filterType in this.filters[filter.text])) | 
|  | 56       this.filters[filter.text][filterType] = {}; | 
|  | 57 | 
|  | 58     if (!("subscriptions" in this.filters[filter.text])) | 
|  | 59       this.filters[filter.text].subscriptions = []; | 
|  | 60 | 
|  | 61     if (filter.subscriptions) | 
|  | 62     { | 
|  | 63       for (let i = 0; i < filter.subscriptions.length; i++) | 
|  | 64       { | 
|  | 65         if (this.filters[filter.text].subscriptions.indexOf(filter.subscriptions
     [i]._title) == -1) | 
|  | 66           this.filters[filter.text].subscriptions.push(filter.subscriptions[i]._
     title); | 
|  | 67       } | 
|  | 68     } | 
|  | 69 | 
|  | 70     let wndLocation = Utils.getOriginWindow(wnd).location.href; | 
|  | 71     let host = Utils.unwrapURL(wndLocation).host; | 
|  | 72 | 
|  | 73     if (!(host in this.filters[filter.text][filterType])) | 
|  | 74       this.filters[filter.text][filterType][host] = {hits: 1, latest: filter.lat
     est}; | 
|  | 75     else | 
|  | 76     { | 
|  | 77       this.filters[filter.text][filterType][host].hits++; | 
|  | 78       this.filters[filter.text][filterType][host].latest = filter.latest; | 
|  | 79     } | 
|  | 80   }, | 
|  | 81 | 
|  | 82   resetFilterHits: function() | 
|  | 83   { | 
|  | 84     this.filters = {}; | 
|  | 85     this.saveFilterHitsToDatabase(); | 
|  | 86   }, | 
|  | 87 | 
|  | 88   sendFilterHitsToServer: function() | 
|  | 89   { | 
|  | 90     let prepareData = function() | 
|  | 91     { | 
|  | 92       let {addonName, addonVersion, application, applicationVersion, platform, p
     latformVersion} = require("info"); | 
|  | 93       return { | 
|  | 94         version: 1, | 
|  | 95         timeSincePush: this._lastPush, | 
|  | 96         addonName: addonName, | 
|  | 97         addonVersion: addonVersion, | 
|  | 98         application: application, | 
|  | 99         applicationVersion: applicationVersion, | 
|  | 100         platform: platform, | 
|  | 101         platformVersion: platformVersion, | 
|  | 102         filters: this.filters | 
|  | 103       } | 
|  | 104     }.bind(this); | 
|  | 105 | 
|  | 106     let request = new XMLHttpRequest(); | 
|  | 107     request.open("POST", this._serviceURL); | 
|  | 108     request.setRequestHeader("Content-Type", "application/json"); | 
|  | 109     request.addEventListener("load", function(event) | 
|  | 110     { | 
|  | 111       let request = event.target; | 
|  | 112       FilterHits._sending = false; | 
|  | 113       if (request.status == 200) | 
|  | 114       { | 
|  | 115         FilterHits._lastPush = new Date().getTime(); | 
|  | 116         FilterHits.resetFilterHits(); | 
|  | 117       } | 
|  | 118       else | 
|  | 119         Cu.reportError("could not send filter hit statistics to AdBlock Plus ser
     ver"); | 
|  | 120     }, false); | 
|  | 121     this._sending = true; | 
|  | 122     request.send(JSON.stringify(prepareData())); | 
|  | 123   }, | 
|  | 124 | 
|  | 125   getStorageFile: function() | 
|  | 126   { | 
|  | 127     return FileUtils.getFile("ProfD", ["adblockplus.sqlite"]); | 
|  | 128   }, | 
|  | 129 | 
|  | 130   checkCreateTable: function(connection) | 
|  | 131   { | 
|  | 132     if (!connection.tableExists("filterhits")) | 
|  | 133       connection.executeSimpleSQL("CREATE TABLE filterhits (id INTEGER PRIMARY K
     EY, filters TEXT, date INTEGER)"); | 
|  | 134   }, | 
|  | 135 | 
|  | 136   /** | 
|  | 137    * Load Filter hits from database | 
|  | 138    */ | 
|  | 139   loadFilterHitsFromDatabase: function() | 
|  | 140   { | 
|  | 141     let storageFile = this.getStorageFile(); | 
|  | 142     if (!storageFile) | 
|  | 143       return; | 
|  | 144 | 
|  | 145     let connection = Services.storage.openDatabase(storageFile); | 
|  | 146     this.checkCreateTable(connection); | 
|  | 147 | 
|  | 148     let statement = connection.createStatement("SELECT * FROM filterhits"); | 
|  | 149     if (!this._loading) | 
|  | 150     { | 
|  | 151       this._loading = true; | 
|  | 152       statement.executeAsync( | 
|  | 153       { | 
|  | 154         handleResult: function(aResultSet) | 
|  | 155         { | 
|  | 156           let row = aResultSet.getNextRow(); | 
|  | 157           if (row) | 
|  | 158           { | 
|  | 159             let filters = row.getResultByName("filters"); | 
|  | 160             let lastDate = row.getResultByName("date"); | 
|  | 161             FilterHits.filters = JSON.parse(filters); | 
|  | 162             FilterHits._lastPush = lastDate; | 
|  | 163           } | 
|  | 164           FilterHits._loading = false; | 
|  | 165         }, | 
|  | 166 | 
|  | 167         handleError: function(aError) | 
|  | 168         { | 
|  | 169           Cu.reportError(aError.message); | 
|  | 170         }, | 
|  | 171 | 
|  | 172         handleCompletion: function(aReason) | 
|  | 173         { | 
|  | 174           if (aReason != Components.interfaces.mozIStorageStatementCallback.REAS
     ON_FINISHED) | 
|  | 175           { | 
|  | 176             Cu.reportError("Loading of filter hits canceled or aborted."); | 
|  | 177             FilterHits._loading = false; | 
|  | 178           } | 
|  | 179         } | 
|  | 180       }); | 
|  | 181     } | 
|  | 182 | 
|  | 183     connection.asyncClose(); | 
|  | 184   }, | 
|  | 185 | 
|  | 186   /** | 
|  | 187    * Save Filter hits to database | 
|  | 188    */ | 
|  | 189   saveFilterHitsToDatabase: function() | 
|  | 190   { | 
|  | 191     if (!this._lastPush) | 
|  | 192       this._lastPush = new Date().getTime(); | 
|  | 193 | 
|  | 194     if (!this._sending && new Date().getTime() - this._lastPush > this._pushInte
     rval) | 
|  | 195     { | 
|  | 196       this.sendFilterHitsToServer(); | 
|  | 197       return; | 
|  | 198     } | 
|  | 199 | 
|  | 200     let storageFile = this.getStorageFile(); | 
|  | 201     if (!storageFile) | 
|  | 202       return; | 
|  | 203 | 
|  | 204     let connection = Services.storage.openDatabase(storageFile); | 
|  | 205     this.checkCreateTable(connection); | 
|  | 206 | 
|  | 207     let statement = connection.createStatement("INSERT OR REPLACE INTO filterhit
     s (id, filters, date) VALUES(0, :filters, :date)"); | 
|  | 208     statement.params.filters = JSON.stringify(this.filters); | 
|  | 209     statement.params.date = this._lastPush; | 
|  | 210     if (!this._saving) | 
|  | 211     { | 
|  | 212       this._saving = true; | 
|  | 213       statement.executeAsync( | 
|  | 214       { | 
|  | 215         handleError: function(aError) | 
|  | 216         { | 
|  | 217           Cu.reportError(aError.message); | 
|  | 218         }, | 
|  | 219 | 
|  | 220         handleCompletion: function(aReason) | 
|  | 221         { | 
|  | 222           if (aReason != Components.interfaces.mozIStorageStatementCallback.REAS
     ON_FINISHED) | 
|  | 223             Cu.reportError("Writing of filter hits canceled or aborted."); | 
|  | 224           FilterHits._saving = false; | 
|  | 225         } | 
|  | 226       }); | 
|  | 227     } | 
|  | 228 | 
|  | 229     connection.asyncClose(); | 
|  | 230   } | 
|  | 231 }; | 
| OLD | NEW | 
|---|