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

Unified Diff: lib/filterHits.js

Issue 6337686776315904: Issue 394 - hit statistics tool data collection (Closed)
Patch Set: Created April 6, 2014, 3:16 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « defaults/prefs.js ('k') | lib/filterListener.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/filterHits.js
===================================================================
new file mode 100644
--- /dev/null
+++ b/lib/filterHits.js
@@ -0,0 +1,236 @@
+/*
+ * This file is part of Adblock Plus <http://adblockplus.org/>,
+ * Copyright (C) 2006-2014 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+let {IO} = require("io");
+let {Utils} = require("utils");
+let {Prefs} = require("prefs");
+let {TimeLine} = require("timeline");
+let {Filter} = require("filterClasses");
+
+/**
+ * This class reads filter hits statistics from disk, manages them in memory and writes them back.W
+ * @class
+ */
+let FilterHits = exports.FilterHits =
+{
+ statistics: {},
+
+ _loading: false,
+ _saving: false,
+ _needsSave: false,
+
+ /**
+ * File that the filter hits statistics has been loaded from and should be saved to
+ * @type nsIFile
+ */
+ get filterHitsFile()
+ {
+ let file = null;
+ if (!file)
+ {
+ // Place the file in the data dir
+ file = IO.resolveFilePath(Prefs.data_directory);
+ if (file)
+ file.append("filter-hits.ini");
+ }
+ if (!file)
+ {
+ // Data directory pref misconfigured? Try the default value
+ try
+ {
+ file = IO.resolveFilePath(Services.prefs.getDefaultBranch("extensions.adblockplus.").getCharPref("data_directory"));
+ if (file)
+ file.append("filter-hits.ini");
+ } catch(e) {}
+ }
+
+ if (!file)
+ Cu.reportError("Adblock Plus: Failed to resolve filter-hits file");
+
+ this.__defineGetter__("filterHitsFile", function() file);
+ return this.filterHitsFile;
+ },
+
+ /**
+ * Increases the filter hit count by one
+ * @param {Filter} filter
+ * @param {Window} window Window that the match originated in (required to get host name)
+ */
+ increaseFilterHits: function(filter, wnd)
+ {
+ if(!filter.text)
+ return;
+
+ if(filter.text in this.statistics)
+ this.statistics[filter.text].statsHitCount++;
+ else
+ this.statistics[filter.text] = {statsHitCount:1, lastHit: 0, domainsCount:{}};
+
+ if(filter.lastHit)
+ this.statistics[filter.text].lastHit = filter.lastHit;
+
+ // Get hostname from window object
+ let wndLocation = Utils.getOriginWindow(wnd).location.href;
+ let host = Utils.unwrapURL(wndLocation).host;
+
+ this._increaseDomainHit(this.statistics[filter.text], host);
+ },
+
+ /**
+ * Increases Domain hit count by one
+ * @param {statisticFilterObj} statisticFilterObj statistic's filter object
+ * @param {host} host String
+ */
+ _increaseDomainHit: function(statisticFilterObj, host)
+ {
+ if(host in statisticFilterObj.domainsCount)
+ statisticFilterObj.domainsCount[host]++;
+ else
+ statisticFilterObj.domainsCount[host] = 1;
+ },
+
+ resetFilterHits: function()
+ {
+ this.statistics = {};
+ },
+
+ /**
+ * send filter hits statistics to ABP sever and reset filter hits count
+ */
+ sendFilterHitsToServer: function()
+ {
+ //TODO implement ajax request to server sending this.statistics
+ //append user subscriptions and browser info before sending
+ //and reset filterhits on 200 response
+ this.resetFilterHits();
+ this.saveFilterHitsToDisk();
+ },
+
+ /**
+ * Loads Filter hit statistics from the disk
+ */
+ loadFilterHitsFromDisk: function()
+ {
+ if (this._loading)
+ return;
+
+ let sourceFile = FilterHits.filterHitsFile;
+ if(!sourceFile)
+ return;
+
+ TimeLine.enter("Entered FilterHits.loadFilterHitsFromDisk()");
+ this._loading = true;
+
+ let readFile = function()
+ {
+ TimeLine.enter("FilterHits.loadFilterHitsFromDisk() -> readFile()");
+ let parser = new FilterHitsParser();
+ IO.readFromFile(sourceFile, true, parser, function(e)
+ {
+ TimeLine.enter("FilterHits.loadFilterHitsFromDisk() read callback");
+ if (e)
+ Cu.reportError(e);
+
+ doneReading(parser);
+ }.bind(this), "FilterHitsRead");
+
+ TimeLine.leave("FilterHits.loadFilterHitsFromDisk() <- readFile()", "FilterHitsRead");
+ }.bind(this);
+
+ var doneReading = function(parser)
+ {
+ FilterHits.statistics = parser.statistics;
+ this._loading = false;
+ TimeLine.leave("FilterHits.loadFilterHitsFromDisk() read callback done");
+ }.bind(this);
+
+ readFile(sourceFile);
+ TimeLine.leave("FilterHits.loadFilterHitsFromDisk() done");
+ },
+
+ /**
+ * Stringify filter hits statistics object
+ */
+ _generateFilterHitData: function()
+ {
+ yield JSON.stringify(FilterHits.statistics);
+ },
+
+ /**
+ * Save Filters hit statistics to the disk
+ */
+ saveFilterHitsToDisk: function()
+ {
+ let targetFile = FilterHits.filterHitsFile;
+ if (!targetFile)
+ return;
+
+ if (this._saving)
+ {
+ this._needsSave = true;
+ return;
+ }
+ TimeLine.enter("Entered FilterHits.saveFilterHitsToDisk()");
+ // Make sure the file's parent directory exists
+ try {
+ targetFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
+ } catch (e) {}
+
+ let writeStats = function()
+ {
+ TimeLine.enter("FilterHits.saveFilterHitsToDisk() -> writeStats()");
+ IO.writeToFile(targetFile, true, this._generateFilterHitData(), function(e)
+ {
+ TimeLine.enter("FilterHits.saveFilterHitsToDisk() write callback");
+ this._saving = false;
+
+ if (e)
+ Cu.reportError(e);
+
+ if (this._needsSave)
+ {
+ this._needsSave = false;
+ this.saveFilterHitsToDisk();
+ }
+ TimeLine.leave("FilterHits.saveFilterHitsToDisk() write callback done");
+ }.bind(this), "FilterHitsWriteStats");
+ TimeLine.leave("FilterHits.saveFilterHitsToDisk() -> writeStats()", "FilterStorageWriteStats");
+ }.bind(this);
+
+ this._saving = true;
+ writeStats();
+ TimeLine.leave("FilterHits.saveFilterHitsToDisk() done");
+ }
+};
+
+/**
+ * IO.readFromFile() listener to parse filter-hits data.
+ * @constructor
+ */
+function FilterHitsParser()
+{
+ this.statistics = {__proto__: null};
+}
+FilterHitsParser.prototype =
+{
+ process: function(val)
+ {
+ if (val === null)
+ return;
+ this.statistics = JSON.parse(val);
+ }
+};
« no previous file with comments | « defaults/prefs.js ('k') | lib/filterListener.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld