Bug 1557061 - Add summary information to the protection report. r=fluent-reviewers,mtigley,flod

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Erica Wright 2019-07-17 19:22:32 +00:00
Родитель 33ac809939
Коммит 345f8ad058
9 изменённых файлов: 194 добавлений и 51 удалений

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

@ -123,32 +123,36 @@ var AboutProtectionsHandler = {
win.openTrustedLinkIn("about:preferences#sync", "tab");
break;
case "FetchContentBlockingEvents":
TrackingDBService.getEventsByDateRange(
let sumEvents = await TrackingDBService.sumAllEvents();
let earliestDate = await TrackingDBService.getEarliestRecordedDate();
let eventsByDate = await 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;
}
);
let dataToSend = {};
let largest = 0;
for (let result of eventsByDate) {
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;
this.sendMessage(
aMessage.target,
"SendContentBlockingRecords",
dataToSend
);
});
}
dataToSend.earliestDate = earliestDate;
dataToSend.sumEvents = sumEvents;
this.sendMessage(
aMessage.target,
"SendContentBlockingRecords",
dataToSend
);
break;
case "FetchUserLoginsData":
this.sendMessage(

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

@ -8,17 +8,17 @@
--clickable-text-active: hsla(0,0%,70%,.3);
--card-divider: rgba(12,12,13,0.1) 1px solid;
--report-background: #FAFAFC;
--card-padding: 22px;
--social-color: #AB71FF;
--social-color-darker: #7F27FF;
--card-padding: 24px;
--social-color: #9059FF;
--social-color-darker: #7F40FF;
--cookie-color: #0090F4;
--cookie-color-darker: #0073C3;
--tracker-color: #2AC3A2;
--tracker-color-darker: #229C82;
--orange: #FFA436;
--dark-orange: #ffA40C;
--grey: #AFAFBB;
--dark-grey: #88889A;
--dark-orange: #FF981D;
--grey: #8F8F9D;
--dark-grey: #818191;
--tab-highlight: var(--social-color); /* start with social selected */
--blue-60: #0060DF;
--blue-70: #003eaa;
@ -172,25 +172,25 @@ body[focuseddatatype=cryptominer] {
border-top: var(--card-divider);
grid-column: span 2;
grid-row: 2;
margin-bottom: 24px;
}
.body-wrapper {
grid-column: 2;
}
.graph-week-summary,
.graph-total-summary {
#graph-week-summary,
#graph-total-summary {
font-size: 0.8rem;
}
.graph-week-summary {
#graph-week-summary {
font-weight: bold;
}
#graph-wrapper {
width: 100%;
margin-top: 40px;
margin-bottom: 25px;
}
#graph {

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

@ -0,0 +1,25 @@
# 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/.
### This file is not in a locales directory to prevent it from
### being translated as the feature is still in heavy development
### and strings are likely to change often.
# Variables:
# $count (Number) - Number of tracking events blocked.
graph-week-summary =
{ $count ->
[one] { -brand-short-name } blocked { $count } tracker over the past week
*[other] { -brand-short-name } blocked { $count } trackers over the past week
}
# Variables:
# $count (Number) - Number of tracking events blocked.
# $earliestDate (Number) - Unix timestamp in ms, representing a date. The
# earliest date recorded in the database.
graph-total-summary =
{ $count ->
[one] { $count } tracker blocked since { DATETIME($earliestDate, day: "numeric", month: "long", year: "numeric") }
*[other] { $count } trackers blocked since { DATETIME($earliestDate, day: "numeric", month: "long", year: "numeric") }
}

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

@ -7,6 +7,8 @@
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src chrome: blob:">
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/protections.ftl">
<link rel="stylesheet" type="text/css"
href="chrome://browser/content/protections.css">
<link rel="icon" href="chrome://global/skin/icons/warning.svg">
@ -35,26 +37,24 @@
</div>
<div class="card-body">
<div class="body-wrapper">
<p class="graph-week-summary">
Firefox blocked 970 trackers over the past week
</p>
<p id="graph-week-summary"></p>
<div id="graph-wrapper">
<div id="graph"></div>
<div id="legend">
<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"></label>
<input id="tab-cookie" data-type="cookie" type="radio" name="tabs">
<label for="tab-cookie" data-type="cookie">123</label>
<label for="tab-cookie" data-type="cookie"></label>
<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"></label>
<input id="tab-fingerprinter" data-type="fingerprinter" type="radio" name="tabs">
<label for="tab-fingerprinter" data-type="fingerprinter">45666</label>
<label for="tab-fingerprinter" data-type="fingerprinter"></label>
<input id="tab-cryptominer" data-type="cryptominer" type="radio" name="tabs">
<label for="tab-cryptominer" data-type="cryptominer">7</label>
<label for="tab-cryptominer" data-type="cryptominer"></label>
<div id="social" class="tab-content">
<p class="content-title">Social Media Trackers</p>
@ -78,9 +78,7 @@
</div>
</div>
</div>
<p class="graph-total-summary">
125,324 trackers blocked since August, 2018
</p>
<div id="graph-total-summary"></div>
</div>
</div>
</div>

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

@ -32,12 +32,31 @@ document.addEventListener("DOMContentLoaded", e => {
RPMSendAsyncMessage("GetEnabledLockwiseCard");
let createGraph = data => {
let dateInMS = data.earliestDate
? new Date(data.earliestDate).getTime()
: Date.now();
let summary = document.getElementById("graph-total-summary");
summary.setAttribute(
"data-l10n-args",
JSON.stringify({ count: data.sumEvents, earliestDate: dateInMS })
);
summary.setAttribute("data-l10n-id", "graph-total-summary");
// Set a default top size for the height of the graph bars so that small
// numbers don't fill the whole graph.
let largest = 100;
if (largest < data.largest) {
largest = data.largest;
}
let weekCount = 0;
let weekTypeCounts = {
social: 0,
cookie: 0,
tracker: 0,
fingerprinter: 0,
cryptominer: 0,
};
let graph = document.getElementById("graph");
for (let i = weekdays.length - 1; i >= 0; i--) {
@ -54,6 +73,7 @@ document.addEventListener("DOMContentLoaded", e => {
count.textContent = content.total;
bar.appendChild(count);
let barHeight = (content.total / largest) * 100;
weekCount += content.total;
bar.style.height = `${barHeight}%`;
for (let type of dataTypes) {
if (content[type]) {
@ -62,6 +82,7 @@ document.addEventListener("DOMContentLoaded", e => {
div.className = `${type}-bar inner-bar`;
div.setAttribute("data-type", type);
div.style.height = `${dataHeight}%`;
weekTypeCounts[type] += content[type];
bar.appendChild(div);
}
}
@ -70,6 +91,17 @@ document.addEventListener("DOMContentLoaded", e => {
bar.classList.add("empty");
}
graph.appendChild(bar);
let weekSummary = document.getElementById("graph-week-summary");
weekSummary.setAttribute(
"data-l10n-args",
JSON.stringify({ count: weekCount })
);
weekSummary.setAttribute("data-l10n-id", "graph-week-summary");
for (let type of dataTypes) {
document.querySelector(`label[data-type=${type}]`).textContent =
weekTypeCounts[type];
}
let label = document.createElement("span");
label.className = "column-label";

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

@ -8,6 +8,7 @@
# having to create the same entry for each locale.
[localization] @AB_CD@.jar:
browser/protections.ftl (../components/protections/content/protections.ftl)
browser/aboutLogins.ftl (../components/aboutlogins/content/aboutLogins.ftl)
toolkit/certviewer.ftl (../../toolkit/components/certviewer/content/certviewer.ftl)
browser (%browser/**/*.ftl)

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

@ -56,6 +56,11 @@ const SQL = {
selectByDateRange:
"SELECT * FROM events " +
"WHERE timestamp BETWEEN date(:dateFrom) AND date(:dateTo);",
sumAllEvents: "SELECT sum(count) FROM events;",
getEarliestDate:
"SELECT timestamp FROM events ORDER BY timestamp DESC LIMIT 1;",
};
/**
@ -256,6 +261,26 @@ TrackingDBService.prototype = {
dateTo = new Date(dateTo).toISOString();
return db.execute(SQL.selectByDateRange, { dateFrom, dateTo });
},
async sumAllEvents() {
let db = await this.ensureDB();
let results = await db.execute(SQL.sumAllEvents);
if (!results[0]) {
return 0;
}
let total = results[0].getResultByName("sum(count)");
return total || 0;
},
async getEarliestRecordedDate() {
let db = await this.ensureDB();
let date = await db.execute(SQL.getEarliestDate);
if (!date[0]) {
return null;
}
let earliestDate = date[0].getResultByName("timestamp");
return earliestDate || null;
},
};
var EXPORTED_SYMBOLS = ["TrackingDBService"];

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

@ -45,6 +45,16 @@ interface nsITrackingDBService : nsISupports
*/
Promise getEventsByDateRange(in int64_t dateFrom, in int64_t dateTo);
/**
* Return a count of all tracking events.
*/
Promise sumAllEvents();
/**
* Return the earliest recorded date.
*/
Promise getEarliestRecordedDate();
const unsigned long OTHER_COOKIES_BLOCKED_ID = 0;
const unsigned long TRACKERS_ID = 1;
const unsigned long TRACKING_COOKIES_ID = 2;

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

@ -273,14 +273,7 @@ add_task(async function test_timestamp_aggragation() {
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 addEventsToDB = async db => {
let d = new Date(1521009000000);
let date = d.toISOString();
await db.execute(SQL.insertCustomTimeEvent, {
@ -316,7 +309,18 @@ add_task(async function test_getEventsByDateRange() {
count: 2,
timestamp: date,
});
};
// 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 });
await addEventsToDB(db);
let d = new Date(1521009000000);
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);
@ -349,3 +353,47 @@ add_task(async function test_getEventsByDateRange() {
await db.close();
Services.prefs.clearUserPref("browser.contentblocking.database.enabled");
});
// This tests that TrackingDBService.sumAllEvents returns the number of
// tracking events in the database, and can handle 0 entries.
add_task(async function test_sumAllEvents() {
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 sum = await TrackingDBService.sumAllEvents();
equal(sum, 0, "There have been 0 events recorded");
// populate the database
await addEventsToDB(db);
sum = await TrackingDBService.sumAllEvents();
equal(sum, 11, "There have been 11 events recorded");
await TrackingDBService.clearAll();
await db.close();
Services.prefs.clearUserPref("browser.contentblocking.database.enabled");
});
// This tests that TrackingDBService.getEarliestRecordedDate returns the
// earliest date recorded and can handle 0 entries.
add_task(async function test_getEarliestRecordedDate() {
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 date = await TrackingDBService.getEarliestRecordedDate();
equal(date, null, "There is no earliest recorded date");
// populate the database
await addEventsToDB(db);
date = await TrackingDBService.getEarliestRecordedDate();
equal(date, "2018-03-14", "The earliest recorded event is 2018-03-14");
await TrackingDBService.clearAll();
await db.close();
Services.prefs.clearUserPref("browser.contentblocking.database.enabled");
});