Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/filterHits.js

Issue 6337686776315904: Issue 394 - hit statistics tool data collection (Closed)
Patch Set: Created Feb. 17, 2015, 4:34 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 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: "",
Thomas Greiner 2015/02/23 18:43:05 Where is the value for this supposed to be coming
34 _lastPush: 0,
35 _pushInterval: MILLIS_IN_DAY * 7,
36 _loading: false,
37 _saving: false,
38 _sending: false,
saroyanm 2015/02/28 15:24:30 Done.
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))
Thomas Greiner 2015/02/23 18:43:05 This means that if the first subscription a filter
48 return;
49
50 if (!(filter.text in this.filters))
51 this.filters[filter.text] = {};
52
53 var statFilter = this.filters[filter.text];
Thomas Greiner 2015/02/23 18:43:05 Any reason why you're using `var` here?
54 let filterType = filter.thirdParty ? "thirdParty" : "firstParty";
55
56 if (!(filterType in statFilter))
57 statFilter[filterType] = {};
58
59 if (!("subscriptions" in statFilter))
60 statFilter.subscriptions = [];
61
62 if (filter.subscriptions)
63 {
64 for (let i = 0; i < filter.subscriptions.length; i++)
65 {
66 if (statFilter.subscriptions.indexOf(filter.subscriptions[i]._title) == -1)
67 statFilter.subscriptions.push(filter.subscriptions[i]._title);
68 }
69 }
70
71 let wndLocation = Utils.getOriginWindow(wnd).location.href;
72 let host = Utils.unwrapURL(wndLocation).host;
73
74 if (!(host in statFilter[filterType]))
75 statFilter[filterType][host] = {hits: 1, latest: filter.lastHit};
76 else
77 {
78 statFilter[filterType][host].hits++;
79 statFilter[filterType][host].latest = filter.lastHit;
80 }
81 },
82
83 resetFilterHits: function()
84 {
85 this.filters = {};
86 this.saveFilterHitsToDatabase();
87 },
88
89 sendFilterHitsToServer: function()
90 {
91 let prepareData = function()
saroyanm 2015/02/28 15:24:30 Done.
92 {
93 let {addonName, addonVersion, application, applicationVersion, platform, p latformVersion} = require("info");
94 return {
95 version: 1,
96 timeSincePush: this._lastPush,
97 addonName: addonName,
98 addonVersion: addonVersion,
99 application: application,
100 applicationVersion: applicationVersion,
101 platform: platform,
102 platformVersion: platformVersion,
103 filters: this.filters
104 }
105 }.bind(this);
106
107 let request = new XMLHttpRequest();
108 request.open("POST", this._serviceURL);
109 request.setRequestHeader("Content-Type", "application/json");
110 request.addEventListener("load", function(event)
111 {
112 let request = event.target;
saroyanm 2015/02/28 15:24:30 Done.
113 FilterHits._sending = false;
114 if (request.status == 200)
115 {
116 FilterHits._lastPush = new Date().getTime();
117 FilterHits.resetFilterHits();
118 }
119 else
120 Cu.reportError("could not send filter hit statistics to AdBlock Plus ser ver");
Thomas Greiner 2015/02/23 18:43:05 Detail: In the other error messages you start with
saroyanm 2015/02/28 15:24:30 Done.
saroyanm 2015/02/28 15:24:30 Done.
121 }, false);
122 this._sending = true;
123 request.send(JSON.stringify(prepareData()));
124 },
125
126 getStorageFile: function()
127 {
128 return FileUtils.getFile("ProfD", ["adblockplus.sqlite"]);
129 },
130
131 checkCreateTable: function(connection)
132 {
133 if (!connection.tableExists("filterhits"))
134 connection.executeSimpleSQL("CREATE TABLE filterhits (id INTEGER PRIMARY K EY, filters TEXT, date INTEGER)");
135 },
136
137 /**
138 * Load Filter hits from database
139 */
140 loadFilterHitsFromDatabase: function()
141 {
142 let storageFile = this.getStorageFile();
143 if (!storageFile)
144 return;
145
146 let connection = Services.storage.openDatabase(storageFile);
147 this.checkCreateTable(connection);
148
149 let statement = connection.createStatement("SELECT * FROM filterhits");
150 if (!this._loading)
151 {
152 this._loading = true;
153 statement.executeAsync(
154 {
155 handleResult: function(aResultSet)
156 {
157 let row = aResultSet.getNextRow();
158 if (row)
159 {
160 let filters = row.getResultByName("filters");
161 let lastDate = row.getResultByName("date");
162 FilterHits.filters = JSON.parse(filters);
163 FilterHits._lastPush = lastDate;
164 }
165 FilterHits._loading = false;
Thomas Greiner 2015/02/23 18:43:05 This seems redundant since `_loading` should alrea
166 },
167
168 handleError: function(aError)
169 {
170 Cu.reportError(aError.message);
Thomas Greiner 2015/02/23 18:43:05 Unless `handleCompletion` is also called when ther
saroyanm 2015/02/28 15:24:30 Right, updated to always set `_loading` variable t
171 },
172
173 handleCompletion: function(aReason)
174 {
175 if (aReason != Components.interfaces.mozIStorageStatementCallback.REAS ON_FINISHED)
176 {
177 Cu.reportError("Loading of filter hits canceled or aborted.");
178 FilterHits._loading = false;
179 }
180 }
181 });
182 }
183
184 connection.asyncClose();
185 },
186
187 /**
188 * Save Filter hits to database
189 */
190 saveFilterHitsToDatabase: function()
191 {
192 if (!this._lastPush)
193 this._lastPush = new Date().getTime();
Thomas Greiner 2015/02/23 18:43:05 You're using `new Date().getTime()` twice so best
saroyanm 2015/02/28 15:24:30 Done.
194
195 if (!this._sending && new Date().getTime() - this._lastPush > this._pushInte rval)
196 {
197 this.sendFilterHitsToServer();
198 return;
199 }
200
201 let storageFile = this.getStorageFile();
202 if (!storageFile)
203 return;
204
205 let connection = Services.storage.openDatabase(storageFile);
206 this.checkCreateTable(connection);
207
208 let statement = connection.createStatement("INSERT OR REPLACE INTO filterhit s (id, filters, date) VALUES(0, :filters, :date)");
209 statement.params.filters = JSON.stringify(this.filters);
210 statement.params.date = this._lastPush;
211 if (!this._saving)
212 {
213 this._saving = true;
214 statement.executeAsync(
215 {
216 handleError: function(aError)
217 {
218 Cu.reportError(aError.message);
saroyanm 2015/02/28 15:24:30 Handle completion should also be triggered during
219 },
220
221 handleCompletion: function(aReason)
222 {
223 if (aReason != Components.interfaces.mozIStorageStatementCallback.REAS ON_FINISHED)
224 Cu.reportError("Writing of filter hits canceled or aborted.");
225 FilterHits._saving = false;
226 }
227 });
228 }
229
230 connection.asyncClose();
231 }
232 };
OLDNEW

Powered by Google App Engine
This is Rietveld