Bug 1549832 - Send content blocking log to the parent process on document unload. r=baku

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Johann Hofmann 2019-05-31 15:13:33 +00:00
parent 409c6cf471
commit 2718631dd6
11 changed files with 179 additions and 4 deletions

View File

@ -13,6 +13,9 @@
#include "mozilla/Telemetry.h"
#include "mozilla/Unused.h"
#include "mozilla/XorShift128PlusRNG.h"
#include "mozilla/ipc/IPCStreamUtils.h"
using mozilla::ipc::AutoIPCStream;
static LazyLogModule gContentBlockingLog("ContentBlockingLog");
#define LOG(fmt, ...) \
@ -109,13 +112,43 @@ static void ReportOriginSingleHash(OriginMetricID aId,
nsCString(aOrigin));
}
void ContentBlockingLog::ReportLog() {
void ContentBlockingLog::ReportLog(nsIPrincipal* aFirstPartyPrincipal) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aFirstPartyPrincipal);
if (!StaticPrefs::browser_contentblocking_database_enabled()) {
return;
}
if (mLog.IsEmpty()) {
return;
}
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
if (NS_WARN_IF(!contentChild)) {
return;
}
nsAutoCString json = Stringify();
nsCOMPtr<nsIInputStream> stream;
nsresult rv = NS_NewCStringInputStream(getter_AddRefs(stream), json);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
AutoIPCStream ipcStream;
ipcStream.Serialize(stream, contentChild);
Unused << contentChild->SendReportContentBlockingLog(
IPC::Principal(aFirstPartyPrincipal), ipcStream.TakeValue());
}
void ContentBlockingLog::ReportOrigins() {
if (!IsReportingEnabled()) {
return;
}
LOG("ContentBlockingLog::ReportLog [this=%p]", this);
LOG("ContentBlockingLog::ReportOrigins [this=%p]", this);
const bool testMode =
StaticPrefs::telemetry_origin_telemetry_test_mode_enabled();
OriginMetricID metricId =

View File

@ -158,7 +158,8 @@ class ContentBlockingLog final {
}
}
void ReportLog();
void ReportOrigins();
void ReportLog(nsIPrincipal* aFirstPartyPrincipal);
nsAutoCString Stringify() {
nsAutoCString buffer;

View File

@ -9822,7 +9822,8 @@ void Document::Destroy() {
// Make sure to report before IPC closed.
if (!nsContentUtils::IsInPrivateBrowsing(this)) {
mContentBlockingLog.ReportLog();
mContentBlockingLog.ReportLog(NodePrincipal());
mContentBlockingLog.ReportOrigins();
}
mIsGoingAway = true;

View File

@ -216,6 +216,7 @@
#include "nsPluginHost.h"
#include "nsPluginTags.h"
#include "nsIBlocklistService.h"
#include "nsITrackingDBService.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
#include "nsICaptivePortalService.h"
@ -223,6 +224,8 @@
#include "nsIBidiKeyboard.h"
#include "nsLayoutStylesheetCache.h"
#include "MMPrinter.h"
#include "nsStreamUtils.h"
#include "nsIAsyncInputStream.h"
#include "mozilla/Sprintf.h"
@ -5497,6 +5500,26 @@ mozilla::ipc::IPCResult ContentParent::RecvRecordOrigin(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvReportContentBlockingLog(
const Principal& aPrincipal, const IPCStream& aIPCStream) {
nsCOMPtr<nsITrackingDBService> trackingDBService =
do_GetService("@mozilla.org/tracking-db-service;1");
if (NS_WARN_IF(!trackingDBService)) {
return IPC_FAIL_NO_REASON(this);
}
nsCOMPtr<nsIPrincipal> principal(aPrincipal);
nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(aIPCStream);
nsCOMPtr<nsIAsyncInputStream> asyncStream;
nsresult rv = NS_MakeAsyncNonBlockingInputStream(stream.forget(),
getter_AddRefs(asyncStream));
if (NS_WARN_IF(NS_FAILED(rv))) {
return IPC_FAIL_NO_REASON(this);
}
trackingDBService->RecordContentBlockingLog(principal, asyncStream);
return IPC_OK();
}
//////////////////////////////////////////////////////////////////
// PURLClassifierParent

View File

@ -1176,6 +1176,8 @@ class ContentParent final : public PContentParent,
const DiscardedData& aDiscardedData);
mozilla::ipc::IPCResult RecvRecordOrigin(const uint32_t& aMetricId,
const nsCString& aOrigin);
mozilla::ipc::IPCResult RecvReportContentBlockingLog(
const Principal& aPrincipal, const IPCStream& aIPCStream);
mozilla::ipc::IPCResult RecvBHRThreadHang(const HangDetails& aHangDetails);

View File

@ -49,6 +49,7 @@ include protocol PSessionStorageObserver;
include DOMTypes;
include JavaScriptTypes;
include IPCBlob;
include IPCStream;
include PTabContext;
include URIParams;
include PluginTypes;
@ -1368,6 +1369,8 @@ parent:
async RecordDiscardedData(DiscardedData data);
async RecordOrigin(uint32_t metricId, nsCString origin);
async ReportContentBlockingLog(Principal firstPartyPrincipal, IPCStream aJSONStream);
sync GetA11yContentId() returns (uint32_t aContentId);
async A11yHandlerControl(uint32_t aPid,
IHandlerControlHolder aHandlerControl);

View File

@ -708,6 +708,13 @@ VARCACHE_PREF(
bool, true
)
VARCACHE_PREF(
Live,
"browser.contentblocking.database.enabled",
browser_contentblocking_database_enabled,
bool, true
)
// How many recent block/unblock actions per origins we remember in the
// Content Blocking log for each top-level window.
VARCACHE_PREF(

View File

@ -0,0 +1,53 @@
/* 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/. */
"use strict";
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
this.TrackingDBService = function() {
this._initialize();
};
TrackingDBService.prototype = Object.freeze({
classID: Components.ID("{3c9c43b6-09eb-4ed2-9b87-e29f4221eef0}"),
QueryInterface: ChromeUtils.generateQI([Ci.nsITrackingDBService]),
_xpcom_factory: XPCOMUtils.generateSingletonFactory(TrackingDBService),
_initialize() {
// Start up the database here
},
_readAsyncStream(stream) {
return new Promise(function(resolve, reject) {
let result = "";
let source = Cc["@mozilla.org/binaryinputstream;1"]
.createInstance(Ci.nsIBinaryInputStream);
source.setInputStream(stream);
function readData() {
try {
result += source.readBytes(source.available());
stream.asyncWait(readData, 0, 0, Services.tm.currentThread);
} catch (e) {
if (e.result == Cr.NS_BASE_STREAM_CLOSED) {
resolve(result);
} else {
reject(e);
}
}
}
stream.asyncWait(readData, 0, 0, Services.tm.currentThread);
});
},
async recordContentBlockingLog(principal, inputStream) {
let json = await this._readAsyncStream(inputStream);
// Simulate parsing this for perf tests.
let log = JSON.parse(json);
void log;
},
});
var EXPORTED_SYMBOLS = ["TrackingDBService"];

View File

@ -0,0 +1,14 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
Classes = [
{
'cid': '{3c9c43b6-09eb-4ed2-9b87-e29f4221eef0}',
'contract_ids': ['@mozilla.org/tracking-db-service;1'],
'jsm': 'resource://gre/modules/TrackingDBService.jsm',
'constructor': 'TrackingDBService',
},
]

View File

@ -7,6 +7,20 @@
with Files('**'):
BUG_COMPONENT = ('Core', 'DOM: Security')
XPIDL_SOURCES += [
'nsITrackingDBService.idl',
]
XPIDL_MODULE = 'toolkit_antitracking'
EXTRA_JS_MODULES += [
'TrackingDBService.jsm',
]
XPCOM_MANIFESTS += [
'components.conf',
]
EXPORTS.mozilla = [
'AntiTrackingCommon.h',
'StorageAccess.h',

View File

@ -0,0 +1,24 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
#include "nsISupports.idl"
interface nsIPrincipal;
interface nsIAsyncInputStream;
[scriptable, uuid(650934db-1939-4424-be26-6ffb0375424d)]
interface nsITrackingDBService : nsISupports
{
/**
* Record entries from a content blocking log in the tracking database.
* This function is typically called at the end of the document lifecycle,
* since calling it multiple times results in multiple new entries.
*
* @param aFirstPartyPrincipal the principal of the first party that was
* loaded in the document that the content blocking log belongs to
* @param aInputStream the content blocking log as an input stream that outputs a JSON string
*/
void recordContentBlockingLog(in nsIPrincipal aFirstPartyPrincipal, in nsIAsyncInputStream aInputStream);
};