Bug 1557058 - use real data for protection report graph r=johannh

Differential Revision: https://phabricator.services.mozilla.com/D36249

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Erica Wright 2019-07-10 14:44:26 +00:00
Родитель 32230bbfe3
Коммит 95d34cd78d
10 изменённых файлов: 470 добавлений и 104 удалений

Просмотреть файл

@ -5,16 +5,32 @@
"use strict"; "use strict";
var EXPORTED_SYMBOLS = ["AboutProtectionsHandler"]; var EXPORTED_SYMBOLS = ["AboutProtectionsHandler"];
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const { RemotePages } = ChromeUtils.import( const { RemotePages } = ChromeUtils.import(
"resource://gre/modules/remotepagemanager/RemotePageManagerParent.jsm" "resource://gre/modules/remotepagemanager/RemotePageManagerParent.jsm"
); );
XPCOMUtils.defineLazyServiceGetter(
this,
"TrackingDBService",
"@mozilla.org/tracking-db-service;1",
"nsITrackingDBService"
);
let idToTextMap = new Map([
[Ci.nsITrackingDBService.TRACKERS_ID, "tracker"],
[Ci.nsITrackingDBService.TRACKING_COOKIES_ID, "cookie"],
[Ci.nsITrackingDBService.CRYPTOMINERS_ID, "cryptominer"],
[Ci.nsITrackingDBService.FINGERPRINTERS_ID, "fingerprinter"],
]);
var AboutProtectionsHandler = { var AboutProtectionsHandler = {
_inited: false, _inited: false,
_topics: ["openContentBlockingPreferences"], _topics: ["OpenContentBlockingPreferences", "FetchContentBlockingEvents"],
init() { init() {
this.receiveMessage = this.receiveMessage.bind(this);
this.pageListener = new RemotePages("about:protections"); this.pageListener = new RemotePages("about:protections");
for (let topic of this._topics) { for (let topic of this._topics) {
this.pageListener.addMessageListener(topic, this.receiveMessage); this.pageListener.addMessageListener(topic, this.receiveMessage);
@ -35,11 +51,38 @@ var AboutProtectionsHandler = {
receiveMessage(aMessage) { receiveMessage(aMessage) {
let win = aMessage.target.browser.ownerGlobal; let win = aMessage.target.browser.ownerGlobal;
switch (aMessage.name) { switch (aMessage.name) {
case "openContentBlockingPreferences": case "OpenContentBlockingPreferences":
win.openPreferences("privacy-trackingprotection", { win.openPreferences("privacy-trackingprotection", {
origin: "about-protections", origin: "about-protections",
}); });
break; break;
case "FetchContentBlockingEvents":
TrackingDBService.getEventsByDateRange(
aMessage.data.from,
aMessage.data.to
).then(results => {
let dataToSend = {};
let largest = 0;
for (let result of results) {
let count = result.getResultByName("count");
let type = result.getResultByName("type");
let timestamp = result.getResultByName("timestamp");
dataToSend[timestamp] = dataToSend[timestamp] || { total: 0 };
dataToSend[timestamp][idToTextMap.get(type)] = count;
dataToSend[timestamp].total += count;
// Record the largest amount of tracking events found per day,
// to create the tallest column on the graph and compare other days to.
if (largest < dataToSend[timestamp].total) {
largest = dataToSend[timestamp].total;
}
}
dataToSend.largest = largest;
aMessage.target.sendAsyncMessage(
"SendContentBlockingRecords",
dataToSend
);
});
break;
} }
}, },
}; };

Просмотреть файл

@ -11,8 +11,8 @@
--card-padding: 22px; --card-padding: 22px;
--social-color: #AB71FF; --social-color: #AB71FF;
--social-color-darker: #7F27FF; --social-color-darker: #7F27FF;
--crossSite-color: #0090F4; --cookie-color: #0090F4;
--crossSite-color-darker: #0073C3; --cookie-color-darker: #0073C3;
--tracker-color: #2AC3A2; --tracker-color: #2AC3A2;
--tracker-color-darker: #229C82; --tracker-color-darker: #229C82;
--fingerprinter-color: #FFBD4F; --fingerprinter-color: #FFBD4F;
@ -32,8 +32,8 @@ body[focuseddatatype=social] {
--tab-highlight: var(--social-color); --tab-highlight: var(--social-color);
} }
body[focuseddatatype=crossSite] { body[focuseddatatype=cookie] {
--tab-highlight: var(--crossSite-color); --tab-highlight: var(--cookie-color);
} }
body[focuseddatatype=tracker] { body[focuseddatatype=tracker] {
@ -172,12 +172,12 @@ body[focuseddatatype=cryptominer] {
background-color: var(--social-color-darker); background-color: var(--social-color-darker);
} }
.crossSite-bar { .cookie-bar {
background-color: var(--crossSite-color); background-color: var(--cookie-color);
} }
.hover-crossSite .crossSite-bar { .hover-cookie .cookie-bar {
background-color: var(--crossSite-color-darker); background-color: var(--cookie-color-darker);
} }
.tracker-bar { .tracker-bar {
@ -232,10 +232,11 @@ label[data-type="social"] {
color: var(--social-color); color: var(--social-color);
} }
label[data-type="crossSite"] { label[data-type="cookie"] {
color: var(--cookie-color);
background-image: url(chrome://browser/skin/controlcenter/3rdpartycookies.svg); background-image: url(chrome://browser/skin/controlcenter/3rdpartycookies.svg);
fill: var(--crossSite-color); fill: var(--cookie-color);
color: var(--crossSite-color); color: var(--cookie-color);
} }
label[data-type="tracker"] { label[data-type="tracker"] {
@ -257,7 +258,7 @@ label[data-type="cryptominer"] {
} }
.hover-social label[for="tab-social"], .hover-social label[for="tab-social"],
.hover-crossSite label[for="tab-crossSite"], .hover-cookie label[for="tab-cookie"],
.hover-tracker label[for="tab-tracker"], .hover-tracker label[for="tab-tracker"],
.hover-fingerprinter label[for="tab-fingerprinter"], .hover-fingerprinter label[for="tab-fingerprinter"],
.hover-cryptominer label[for="tab-cryptominer"], .hover-cryptominer label[for="tab-cryptominer"],
@ -290,7 +291,7 @@ label:hover {
} }
#tab-social:checked ~ #social, #tab-social:checked ~ #social,
#tab-crossSite:checked ~ #crossSite, #tab-cookie:checked ~ #cookie,
#tab-tracker:checked ~ #tracker, #tab-tracker:checked ~ #tracker,
#tab-fingerprinter:checked ~ #fingerprinter, #tab-fingerprinter:checked ~ #fingerprinter,
#tab-cryptominer:checked ~ #cryptominer { #tab-cryptominer:checked ~ #cryptominer {

Просмотреть файл

@ -43,8 +43,8 @@
<input id="tab-social" data-type="social" type="radio" name="tabs" checked> <input id="tab-social" data-type="social" type="radio" name="tabs" checked>
<label for="tab-social" data-type="social">345</label> <label for="tab-social" data-type="social">345</label>
<input id="tab-crossSite" data-type="crossSite" type="radio" name="tabs"> <input id="tab-cookie" data-type="cookie" type="radio" name="tabs">
<label for="tab-crossSite" data-type="crossSite">123</label> <label for="tab-cookie" data-type="cookie">123</label>
<input id="tab-tracker" data-type="tracker" type="radio" name="tabs"> <input id="tab-tracker" data-type="tracker" type="radio" name="tabs">
<label for="tab-tracker" data-type="tracker">1</label> <label for="tab-tracker" data-type="tracker">1</label>
@ -59,7 +59,7 @@
<p class="content-title">Social Media Trackers</p> <p class="content-title">Social Media Trackers</p>
<p>Social media like, post, and comment buttons on other websites can track you — even if you dont use them. Logging in to sites using your Facebook or Twitter account is another way they can track what you do on those sites. We remove these trackers so Facebook and Twitter see less of what you do online.</p> <p>Social media like, post, and comment buttons on other websites can track you — even if you dont use them. Logging in to sites using your Facebook or Twitter account is another way they can track what you do on those sites. We remove these trackers so Facebook and Twitter see less of what you do online.</p>
</div> </div>
<div id="crossSite" class="tab-content"> <div id="cookie" class="tab-content">
<p class="content-title">Cross-Site Tracking Cookies</p> <p class="content-title">Cross-Site Tracking Cookies</p>
<p>Cross-site tracking cookies follow you from site to site to collect data about your browsing habits. Advertisers and analytics companies gather this data to create a profile of your interests across many sites. Blocking them reduces the number of personalized ads that follow you around.</p> <p>Cross-site tracking cookies follow you from site to site to collect data about your browsing habits. Advertisers and analytics companies gather this data to create a profile of your interests across many sites. Blocking them reduces the number of personalized ads that follow you around.</p>
</div> </div>

Просмотреть файл

@ -5,114 +5,74 @@
/* eslint-env mozilla/frame-script */ /* eslint-env mozilla/frame-script */
document.addEventListener("DOMContentLoaded", e => { document.addEventListener("DOMContentLoaded", e => {
let todayInMs = Date.now();
let weekAgoInMs = todayInMs - 7 * 24 * 60 * 60 * 1000;
RPMSendAsyncMessage("FetchContentBlockingEvents", {
from: weekAgoInMs,
to: todayInMs,
});
let dataTypes = [ let dataTypes = [
"cryptominer", "cryptominer",
"fingerprinter", "fingerprinter",
"tracker", "tracker",
"crossSite", "cookie",
"social", "social",
]; ];
let weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; let weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
let today = new Date().getDay();
let protectionDetails = document.getElementById("protection-details"); let protectionDetails = document.getElementById("protection-details");
protectionDetails.addEventListener("click", () => { protectionDetails.addEventListener("click", () => {
RPMSendAsyncMessage("openContentBlockingPreferences"); RPMSendAsyncMessage("OpenContentBlockingPreferences");
}); });
let data = [ let createGraph = data => {
{ // Set a default top size for the height of the graph bars so that small
total: 41, // numbers don't fill the whole graph.
cryptominer: 1, let largest = 100;
fingerprinter: 10, if (largest < data.largest) {
tracker: 15, largest = data.largest;
crossSite: 12,
social: 3,
},
{
total: 246,
cryptominer: 5,
fingerprinter: 8,
tracker: 110,
crossSite: 103,
social: 20,
},
{
total: 59,
cryptominer: 0,
fingerprinter: 1,
tracker: 25,
crossSite: 25,
social: 8,
},
{
total: 177,
cryptominer: 0,
fingerprinter: 4,
tracker: 24,
crossSite: 136,
social: 13,
},
{
total: 16,
cryptominer: 1,
fingerprinter: 3,
tracker: 0,
crossSite: 7,
social: 5,
},
{
total: 232,
cryptominer: 0,
fingerprinter: 30,
tracker: 84,
crossSite: 86,
social: 32,
},
{
total: 153,
cryptominer: 0,
fingerprinter: 10,
tracker: 35,
crossSite: 95,
social: 13,
},
];
// Use this to populate the graph with real data in the future.
let createGraph = () => {
let largest = 10;
for (let day of data) {
if (largest < day.total) {
largest = day.total;
}
} }
let graph = document.getElementById("graph"); let graph = document.getElementById("graph");
for (let i = 0; i < weekdays.length; i++) { for (let i = weekdays.length - 1; i >= 0; i--) {
// Start 7 days ago and count down to today.
let date = new Date();
date.setDate(date.getDate() - i);
let dateString = date.toISOString().split("T")[0];
let bar = document.createElement("div"); let bar = document.createElement("div");
bar.className = "graph-bar"; bar.className = "graph-bar";
let barHeight = (data[i].total / largest) * 100; if (data[dateString]) {
bar.style.height = `${barHeight}%`; let content = data[dateString];
for (let type of dataTypes) { let barHeight = (content.total / largest) * 100;
let dataHeight = (data[i][type] / data[i].total) * 100; bar.style.height = `${barHeight}%`;
let div = document.createElement("div"); for (let type of dataTypes) {
div.className = `${type}-bar`; if (content[type]) {
div.setAttribute("data-type", type); let dataHeight = (content[type] / content.total) * 100;
div.style.height = `${dataHeight}%`; let div = document.createElement("div");
bar.appendChild(div); div.className = `${type}-bar`;
div.setAttribute("data-type", type);
div.style.height = `${dataHeight}%`;
bar.appendChild(div);
}
}
} else {
// There were no content blocking events on this day.
bar.style.height = `0`;
} }
graph.appendChild(bar); graph.appendChild(bar);
let label = document.createElement("span"); let label = document.createElement("span");
label.className = "column-label"; label.className = "column-label";
if (i == 6) { if (i == 6) {
label.innerText = "Today"; label.textContent = "Today";
} else { } else {
label.innerText = weekdays[(i + today) % 7]; label.textContent = weekdays[(i + 1 + new Date().getDay()) % 7];
} }
graph.appendChild(label); graph.prepend(label);
} }
addListeners();
}; };
let addListeners = () => { let addListeners = () => {
@ -130,7 +90,7 @@ document.addEventListener("DOMContentLoaded", e => {
}); });
wrapper.addEventListener("click", ev => { wrapper.addEventListener("click", ev => {
if (ev.originalTarget.dataset) { if (ev.originalTarget.dataset.type) {
document.getElementById(`tab-${ev.target.dataset.type}`).click(); document.getElementById(`tab-${ev.target.dataset.type}`).click();
} }
}); });
@ -143,6 +103,8 @@ document.addEventListener("DOMContentLoaded", e => {
}); });
} }
}; };
createGraph();
addListeners(); RPMAddMessageListener("SendContentBlockingRecords", message => {
createGraph(message.data);
});
}); });

Просмотреть файл

@ -4,6 +4,8 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
JAR_MANIFESTS += ['jar.mn'] JAR_MANIFESTS += ['jar.mn']
with Files('**'): with Files('**'):

Просмотреть файл

@ -0,0 +1,5 @@
[DEFAULT]
support-files =
!/browser/base/content/test/trackingUI/trackingPage.html
[browser_protections_report_ui.js]

Просмотреть файл

@ -0,0 +1,251 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Note: This test may cause intermittents if run at exactly midnight.
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
const { Sqlite } = ChromeUtils.import("resource://gre/modules/Sqlite.jsm");
XPCOMUtils.defineLazyServiceGetter(
this,
"TrackingDBService",
"@mozilla.org/tracking-db-service;1",
"nsITrackingDBService"
);
XPCOMUtils.defineLazyGetter(this, "DB_PATH", function() {
return OS.Path.join(OS.Constants.Path.profileDir, "protections.sqlite");
});
const SQL = {
insertCustomTimeEvent:
"INSERT INTO events (type, count, timestamp)" +
"VALUES (:type, :count, date(:timestamp));",
selectAll: "SELECT * FROM events",
};
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [["browser.contentblocking.database.enabled", true]],
});
});
add_task(async function test_graph_display() {
// This creates the schema.
await TrackingDBService.saveEvents(JSON.stringify({}));
let db = await Sqlite.openConnection({ path: DB_PATH });
let date = new Date().toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKERS_ID,
count: 1,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.CRYPTOMINERS_ID,
count: 2,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.FINGERPRINTERS_ID,
count: 3,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKING_COOKIES_ID,
count: 4,
timestamp: date,
});
date = new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKERS_ID,
count: 4,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.CRYPTOMINERS_ID,
count: 3,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.FINGERPRINTERS_ID,
count: 2,
timestamp: date,
});
date = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKERS_ID,
count: 4,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.CRYPTOMINERS_ID,
count: 3,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKING_COOKIES_ID,
count: 1,
timestamp: date,
});
date = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKERS_ID,
count: 3,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.FINGERPRINTERS_ID,
count: 2,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKING_COOKIES_ID,
count: 1,
timestamp: date,
});
date = new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.CRYPTOMINERS_ID,
count: 2,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.FINGERPRINTERS_ID,
count: 2,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKING_COOKIES_ID,
count: 1,
timestamp: date,
});
date = new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKERS_ID,
count: 3,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.CRYPTOMINERS_ID,
count: 3,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.FINGERPRINTERS_ID,
count: 2,
timestamp: date,
});
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKING_COOKIES_ID,
count: 8,
timestamp: date,
});
let tab = await BrowserTestUtils.openNewForegroundTab({
url: "about:protections",
gBrowser,
});
await ContentTask.spawn(tab.linkedBrowser, {}, async function() {
const DATA_TYPES = ["cryptominer", "fingerprinter", "tracker", "cookie"];
let allBars = null;
await ContentTaskUtils.waitForCondition(() => {
allBars = content.document.querySelectorAll(".graph-bar");
return allBars.length;
}, "The graph has been built");
is(allBars.length, 7, "7 bars have been found on the graph");
// today has each type
// yesterday will have no tracking cookies
// 2 days ago will have no fingerprinters
// 3 days ago will have no cryptominers
// 4 days ago will have no trackers
// 5 days ago will have no social (when we add social)
// 6 days ago will be empty
is(
allBars[6].childNodes.length,
DATA_TYPES.length,
"today has all of the data types shown"
);
is(
allBars[6].querySelector(".tracker-bar").style.height,
"10%",
"trackers take 10%"
);
is(
allBars[6].querySelector(".cryptominer-bar").style.height,
"20%",
"cryptominers take 20%"
);
is(
allBars[6].querySelector(".fingerprinter-bar").style.height,
"30%",
"fingerprinters take 30%"
);
is(
allBars[6].querySelector(".cookie-bar").style.height,
"40%",
"cross site tracking cookies take 40%"
);
is(
allBars[5].childNodes.length,
DATA_TYPES.length - 1,
"1 day ago is missing one type"
);
ok(
!allBars[5].querySelector(".cookie-bar"),
"there is no cross site tracking cookie section 1 day ago."
);
is(
allBars[4].childNodes.length,
DATA_TYPES.length - 1,
"2 days ago is missing one type"
);
ok(
!allBars[4].querySelector(".fingerprinter-bar"),
"there is no fingerprinter section 1 day ago."
);
is(
allBars[3].childNodes.length,
DATA_TYPES.length - 1,
"3 days ago is missing one type"
);
ok(
!allBars[3].querySelector(".cryptominer-bar"),
"there is no cryptominer section 1 day ago."
);
is(
allBars[2].childNodes.length,
DATA_TYPES.length - 1,
"4 days ago is missing one type"
);
ok(
!allBars[2].querySelector(".tracker-bar"),
"there is no tracker section 1 day ago."
);
// TODO test for social missing
is(allBars[0].childNodes.length, 0, "6 days ago has no content");
is(allBars[0].style.height, "0px", "6 days ago has no height");
});
// Use the TrackingDBService API to delete the data.
await TrackingDBService.clearAll();
// Make sure the data was deleted.
let rows = await db.execute(SQL.selectAll);
is(rows.length, 0, "length is 0");
await db.close();
BrowserTestUtils.removeTab(tab);
});

Просмотреть файл

@ -52,6 +52,10 @@ const SQL = {
deleteEventsRecords: "DELETE FROM events;", deleteEventsRecords: "DELETE FROM events;",
removeRecordsSince: "DELETE FROM events WHERE timestamp >= date(:date);", removeRecordsSince: "DELETE FROM events WHERE timestamp >= date(:date);",
selectByDateRange:
"SELECT * FROM events " +
"WHERE timestamp BETWEEN date(:dateFrom) AND date(:dateTo);",
}; };
/** /**
@ -242,8 +246,16 @@ TrackingDBService.prototype = {
async clearSince(date) { async clearSince(date) {
let db = await this.ensureDB(); let db = await this.ensureDB();
date = new Date(date).toISOString();
await removeRecordsSince(db, date); await removeRecordsSince(db, date);
}, },
async getEventsByDateRange(dateFrom, dateTo) {
let db = await this.ensureDB();
dateFrom = new Date(dateFrom).toISOString();
dateTo = new Date(dateTo).toISOString();
return db.execute(SQL.selectByDateRange, { dateFrom, dateTo });
},
}; };
var EXPORTED_SYMBOLS = ["TrackingDBService"]; var EXPORTED_SYMBOLS = ["TrackingDBService"];

Просмотреть файл

@ -38,6 +38,13 @@ interface nsITrackingDBService : nsISupports
*/ */
Promise clearSince(in int64_t since); Promise clearSince(in int64_t since);
/**
* Fetch events from the content blocking database
* @param dateFrom a unix timestamp.
* @param dateTo a unix timestamp.
*/
Promise getEventsByDateRange(in int64_t dateFrom, in int64_t dateTo);
const unsigned long OTHER_COOKIES_BLOCKED_ID = 0; const unsigned long OTHER_COOKIES_BLOCKED_ID = 0;
const unsigned long TRACKERS_ID = 1; const unsigned long TRACKERS_ID = 1;
const unsigned long TRACKING_COOKIES_ID = 2; const unsigned long TRACKING_COOKIES_ID = 2;

Просмотреть файл

@ -1,3 +1,9 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Note: This test may cause intermittents if run at exactly midnight.
"use strict"; "use strict";
const { XPCOMUtils } = ChromeUtils.import( const { XPCOMUtils } = ChromeUtils.import(
@ -266,3 +272,80 @@ add_task(async function test_timestamp_aggragation() {
await db.close(); await db.close();
Services.prefs.clearUserPref("browser.contentblocking.database.enabled"); Services.prefs.clearUserPref("browser.contentblocking.database.enabled");
}); });
// This tests that TrackingDBService.getEventsByDateRange can accept two timestamps in unix epoch time
// and return entries that occur within the timestamps, rounded to the nearest day and inclusive.
add_task(async function test_getEventsByDateRange() {
Services.prefs.setBoolPref("browser.contentblocking.database.enabled", true);
// This creates the schema.
await TrackingDBService.saveEvents(JSON.stringify({}));
let db = await Sqlite.openConnection({ path: DB_PATH });
let d = new Date(1521009000000);
let date = d.toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.CRYPTOMINERS_ID,
count: 3,
timestamp: date,
});
date = new Date(d - 2 * 24 * 60 * 60 * 1000).toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKERS_ID,
count: 2,
timestamp: date,
});
date = new Date(d - 3 * 24 * 60 * 60 * 1000).toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKING_COOKIES_ID,
count: 2,
timestamp: date,
});
date = new Date(d - 4 * 24 * 60 * 60 * 1000).toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.TRACKING_COOKIES_ID,
count: 2,
timestamp: date,
});
date = new Date(d - 9 * 24 * 60 * 60 * 1000).toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
type: TrackingDBService.FINGERPRINTERS_ID,
count: 2,
timestamp: date,
});
let daysBefore1 = new Date(d - 24 * 60 * 60 * 1000);
let daysBefore4 = new Date(d - 4 * 24 * 60 * 60 * 1000);
let daysBefore9 = new Date(d - 9 * 24 * 60 * 60 * 1000);
let events = await TrackingDBService.getEventsByDateRange(daysBefore1, d);
equal(
events.length,
1,
"There is 1 event entry between the date and one day before, inclusive"
);
events = await TrackingDBService.getEventsByDateRange(daysBefore4, d);
equal(
events.length,
4,
"There is 4 event entries between the date and four days before, inclusive"
);
events = await TrackingDBService.getEventsByDateRange(
daysBefore9,
daysBefore4
);
equal(
events.length,
2,
"There is 2 event entries between nine and four days before, inclusive"
);
await TrackingDBService.clearAll();
await db.close();
Services.prefs.clearUserPref("browser.contentblocking.database.enabled");
});