Skip to content
This repository was archived by the owner on Sep 9, 2022. It is now read-only.

Commit 76b89c0

Browse files
committed
Implement Stats data capture feature
1 parent dfea165 commit 76b89c0

File tree

3 files changed

+188
-2
lines changed

3 files changed

+188
-2
lines changed

platform/chromium/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"manifest_version": 2,
33

44
"name": "uBlock",
5-
"version": "0.9.5.3-beta.2",
6-
5+
"version": "0.9.5.4",
6+
77
"default_locale": "en",
88
"description": "__MSG_extShortDesc__",
99
"icons": {

src/background.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@
2929
<script src="js/contextmenu.js"></script>
3030
<script src="js/mirrors.js"></script>
3131
<script src="js/start.js"></script>
32+
<script src="js/stats.js"></script>
3233
</body>
3334
</html>

src/js/stats.js

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
2+
µBlock.stats = (function () {
3+
4+
var µb = µBlock;
5+
6+
var reOS = /(CrOS\ \w+|Windows\ NT|Mac\ OS\ X|Linux)\ ([\d\._]+)?/;
7+
8+
var matches = reOS.exec(navigator.userAgent);
9+
10+
var operatingSystem = (matches || [])[1] || "Unknown";
11+
12+
var operatingSystemVersion = (matches || [])[2] || "Unknown";
13+
14+
var reBW = /(MSIE|Trident|(?!Gecko.+)Firefox|(?!AppleWebKit.+Chrome.+)Safari(?!.+Edge)|(?!AppleWebKit.+)Chrome(?!.+Edge)|(?!AppleWebKit.+Chrome.+Safari.+)Edge|AppleWebKit(?!.+Chrome|.+Safari)|Gecko(?!.+Firefox))(?: |\/)([\d\.apre]+)/;
15+
16+
var matches = reBW.exec(navigator.userAgent);
17+
18+
var browser = (matches || [])[1] || "Unknown";
19+
20+
var browserFlavor;
21+
22+
if (window.opr)
23+
browserFlavor = "O"; // Opera
24+
else if (window.safari)
25+
browserFlavor = "S"; // Safari
26+
else if(browser == "Firefox")
27+
browserFlavor = "F"; // Firefox
28+
else
29+
browserFlavor = "E"; // Chrome
30+
31+
var browserVersion = (matches || [])[2] || "Unknown";
32+
33+
var browserLanguage = navigator.language.match(/^[a-z]+/i)[0];
34+
35+
var storageStatsAttr = {
36+
userId: null,
37+
totalPings: 0
38+
};
39+
40+
var exports = {};
41+
42+
var generateUserId = function() {
43+
44+
var timeSuffix = (Date.now()) % 1e8; // 8 digits from end of timestamp
45+
46+
var alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';
47+
48+
var result = [];
49+
50+
for (var i = 0; i < 8; i++) {
51+
var choice = Math.floor(Math.random() * alphabet.length);
52+
53+
result.push(alphabet[choice]);
54+
}
55+
return result.join('') + timeSuffix;
56+
}
57+
58+
var ajaxCall = function(params){
59+
console.log('Sending Stats Information');
60+
var xhr = new XMLHttpRequest();
61+
var url = "https://ping.ublock.org/api/stats"
62+
xhr.open('POST', url, true);
63+
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
64+
xhr.overrideMimeType('text/html;charset=utf-8');
65+
xhr.responseType = 'text';
66+
xhr.onreadystatechange = function() {
67+
if(xhr.readyState == 4 && xhr.status == 200) {
68+
console.log(xhr.responseText);
69+
}
70+
}
71+
xhr.send(JSON.stringify(params));
72+
}
73+
74+
var getStatsEntries = function(callback) {
75+
76+
if(storageStatsAttr.userId != null) {
77+
callback(storageStatsAttr);
78+
return;
79+
}
80+
var onDataReceived = function(data) {
81+
82+
entries = data.stats || {userId: generateUserId(),totalPings: 0 };
83+
84+
storageStatsAttr = entries;
85+
86+
callback(entries);
87+
}
88+
vAPI.storage.get('stats',onDataReceived);
89+
}
90+
91+
exports.sendStats = function() {
92+
93+
var processData = function(details) {
94+
95+
details.totalPings = details.totalPings + 1;
96+
97+
var statsData = {
98+
n: vAPI.app.name,
99+
v: vAPI.app.version,
100+
b: µb.localSettings.blockedRequestCount,
101+
a: µb.localSettings.allowedRequestCount,
102+
ad: µb.userSettings.advancedUserEnabled === true ? 1 : 0,
103+
df: µb.userSettings.dynamicFilteringEnabled === true ? 1 : 0,
104+
u: details.userId,
105+
f: browserFlavor,
106+
o: operatingSystem,
107+
bv: browserVersion,
108+
ov: operatingSystemVersion,
109+
l: browserLanguage
110+
}
111+
112+
if (details.totalPings > 5000) {
113+
if (details.totalPings > 5000 && details.totalPings < 100000 && ((details.totalPings % 5000) !== 0)) {
114+
return;
115+
}
116+
if (details.totalPings >= 100000 && ((details.totalPings % 50000) !== 0)) {
117+
return;
118+
}
119+
}
120+
121+
vAPI.storage.set({ 'stats': details });
122+
123+
if(browser == "Chrome") {
124+
if (chrome.management && chrome.management.getSelf) {
125+
chrome.management.getSelf(function(info) {
126+
statsData["it"] = info.installType.charAt(0);
127+
ajaxCall(statsData);
128+
});
129+
}
130+
}
131+
else {
132+
ajaxCall(statsData);
133+
}
134+
scheduleStatsEvent();
135+
}
136+
getStatsEntries(processData);
137+
}
138+
139+
var scheduleStatsEvent = function() {
140+
141+
var delayTiming = getNextScheduleTiming(function(delayTiming){
142+
143+
console.log('delayTiming = %O',delayTiming);
144+
145+
µBlock.asyncJobs.add(
146+
'sendStats',
147+
null,
148+
µBlock.stats.bind(µBlock),
149+
delayTiming,
150+
true
151+
);
152+
});
153+
}
154+
var getNextScheduleTiming = function(callback) {
155+
156+
var processData = function(details) {
157+
158+
var totalPings = details.totalPings;
159+
160+
var delay_hours;
161+
162+
delayHours = 1;
163+
164+
if (totalPings == 1) // Ping one hour after install
165+
delayHours = 1;
166+
else if (totalPings < 9) // Then every day for a week
167+
delayHours = 24;
168+
else // Then weekly forever
169+
delayHours = 24 * 7 ;
170+
171+
var millis = 1000 * 60 * 60 * delayHours;
172+
173+
callback(millis);
174+
}
175+
176+
getStatsEntries(processData);
177+
}
178+
179+
exports.sendStats();
180+
181+
return exports;
182+
183+
});
184+
185+
µBlock.stats();

0 commit comments

Comments
 (0)