Bug 1963385 part 1 - add settings telemetry for Content Analysis a=diannaS
Records telemetry for the settings used with Content Analysis. Note that there is no way in C++ to get the default value of a pref that was set via an Enterprise Policy (with setAndLockPref()) because that method actually sets the default value, so I had to modify some of my plans for telemetry to gather. For example, I was going to record interception points whose Enabled value differed from the default, but instead we record any interception points whose Enabled value is false. (right now these are equivalent, but Downloads will be default-off so this will change) For the allow/deny URL lists I didn't want to record the actual URLs on those lists, so we really do want to just record whether the values are different from the default. I hard-coded the default into ContentAnalysis.cpp, and we can rely on the JS test test_ca_enterprise_config_with_default_prefs_telemetry() to start failing if that changes. Also adds a forceRecreateClientForTest() method to ContentAnalysis that tests can use to force trying to connect to a client. (since this is when we record the settings telemetry) Original Revision: https://phabricator.services.mozilla.com/D252570 Differential Revision: https://phabricator.services.mozilla.com/D258214
This commit is contained in:
committed by
dsmith@mozilla.com
parent
972e0fdf7c
commit
0acca0e06b
@@ -23,6 +23,7 @@
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
#include "mozilla/glean/ContentanalysisMetrics.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/Services.h"
|
||||
@@ -77,6 +78,14 @@ const char* kPipePathNamePref = "browser.contentanalysis.pipe_path_name";
|
||||
const char* kClientSignature = "browser.contentanalysis.client_signature";
|
||||
const char* kAllowUrlPref = "browser.contentanalysis.allow_url_regex_list";
|
||||
const char* kDenyUrlPref = "browser.contentanalysis.deny_url_regex_list";
|
||||
const char* kAgentNamePref = "browser.contentanalysis.agent_name";
|
||||
const char* kInterceptionPointPrefNames[] = {
|
||||
"browser.contentanalysis.interception_point.clipboard.enabled",
|
||||
"browser.contentanalysis.interception_point.download.enabled",
|
||||
"browser.contentanalysis.interception_point.drag_and_drop.enabled",
|
||||
"browser.contentanalysis.interception_point.file_upload.enabled",
|
||||
"browser.contentanalysis.interception_point.print.enabled",
|
||||
};
|
||||
|
||||
// Allow up to this many threads to be concurrently engaged in synchronous
|
||||
// communcations with the agent. That limit is set by
|
||||
@@ -1445,6 +1454,10 @@ bool ContentAnalysis::IsShutDown() {
|
||||
return *lock;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ContentAnalysis::ForceRecreateClientForTest() {
|
||||
return CreateClientIfNecessary(/* aForceCreate */ true);
|
||||
}
|
||||
|
||||
nsresult ContentAnalysis::CreateClientIfNecessary(
|
||||
bool aForceCreate /* = false */) {
|
||||
AssertIsOnMainThread();
|
||||
@@ -1479,6 +1492,7 @@ nsresult ContentAnalysis::CreateClientIfNecessary(
|
||||
nsString clientSignature;
|
||||
// It's OK if this fails, we will default to the empty string
|
||||
Preferences::GetString(kClientSignature, clientSignature);
|
||||
RecordConnectionSettingsTelemetry(clientSignature);
|
||||
LOGD("Dispatching background task to create Content Analysis client");
|
||||
rv = NS_DispatchBackgroundTask(NS_NewCancelableRunnableFunction(
|
||||
"ContentAnalysis::CreateContentAnalysisClient",
|
||||
@@ -1494,6 +1508,59 @@ nsresult ContentAnalysis::CreateClientIfNecessary(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void ContentAnalysis::RecordConnectionSettingsTelemetry(
|
||||
const nsString& clientSignature) {
|
||||
AssertIsOnMainThread();
|
||||
{
|
||||
nsCString agentName;
|
||||
Preferences::GetCString(kAgentNamePref, agentName);
|
||||
glean::content_analysis::agent_name.Set(agentName);
|
||||
}
|
||||
AutoTArray<nsCString, 1> interceptionPointsOff;
|
||||
for (const char* interceptionPointPrefName : kInterceptionPointPrefNames) {
|
||||
bool interceptionPointPrefValue;
|
||||
Preferences::GetBool(interceptionPointPrefName,
|
||||
&interceptionPointPrefValue);
|
||||
if (!interceptionPointPrefValue) {
|
||||
interceptionPointsOff.AppendElement(interceptionPointPrefName);
|
||||
}
|
||||
}
|
||||
if (!interceptionPointsOff.IsEmpty()) {
|
||||
glean::content_analysis::interception_points_turned_off.Set(
|
||||
interceptionPointsOff);
|
||||
}
|
||||
glean::content_analysis::show_blocked_result.Set(
|
||||
StaticPrefs::browser_contentanalysis_show_blocked_result());
|
||||
glean::content_analysis::default_result.Set(
|
||||
StaticPrefs::browser_contentanalysis_default_result());
|
||||
glean::content_analysis::timeout_result.Set(
|
||||
StaticPrefs::browser_contentanalysis_timeout_result());
|
||||
if (!clientSignature.IsEmpty()) {
|
||||
glean::content_analysis::client_signature.Set(
|
||||
NS_ConvertUTF16toUTF8(clientSignature));
|
||||
}
|
||||
glean::content_analysis::bypass_for_same_tab_operations.Set(
|
||||
StaticPrefs::browser_contentanalysis_bypass_for_same_tab_operations());
|
||||
{
|
||||
nsCString allowUrlRegexList;
|
||||
Preferences::GetCString(kAllowUrlPref, allowUrlRegexList);
|
||||
// Unfortunately because of the way enterprise policies set and lock prefs,
|
||||
// we can't check if the value is different than the default in
|
||||
// StaticPrefList.yaml, and instead we have to duplicate that value here. At
|
||||
// least we have a test around this so we can update this value if the
|
||||
// default changes.
|
||||
const char* defaultAllowUrlRegexList = "^about:(?!blank|srcdoc).*";
|
||||
glean::content_analysis::allow_url_regex_list_set.Set(
|
||||
!allowUrlRegexList.Equals(defaultAllowUrlRegexList));
|
||||
}
|
||||
{
|
||||
nsCString denyUrlRegexList;
|
||||
Preferences::GetCString(kDenyUrlPref, denyUrlRegexList);
|
||||
glean::content_analysis::deny_url_regex_list_set.Set(
|
||||
!denyUrlRegexList.IsEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentAnalysis::GetIsActive(bool* aIsActive) {
|
||||
*aIsActive = false;
|
||||
|
||||
@@ -306,6 +306,7 @@ class ContentAnalysis final : public nsIContentAnalysis,
|
||||
template <typename T, typename U>
|
||||
RefPtr<MozPromise<T, nsresult, true>> CallClientWithRetry(
|
||||
StaticString aMethodName, U&& aClientCallFunc);
|
||||
void RecordConnectionSettingsTelemetry(const nsString& clientSignature);
|
||||
|
||||
nsresult RunAnalyzeRequestTask(
|
||||
const RefPtr<nsIContentAnalysisRequest>& aRequest, bool aAutoAcknowledge,
|
||||
|
||||
152
toolkit/components/contentanalysis/metrics.yaml
Normal file
152
toolkit/components/contentanalysis/metrics.yaml
Normal file
@@ -0,0 +1,152 @@
|
||||
# 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/.
|
||||
|
||||
# Adding a new metric? We have docs for that!
|
||||
# https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/new_definitions_file.html
|
||||
|
||||
---
|
||||
$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0
|
||||
$tags:
|
||||
- 'Firefox :: Data Loss Prevention'
|
||||
|
||||
# The following metrics are used to track the usage of the Data Loss Prevention feature.
|
||||
|
||||
content_analysis:
|
||||
agent_name:
|
||||
type: string
|
||||
description: The name of the DLP agent that Firefox is
|
||||
connected to. This is set via enterprise policy.
|
||||
bugs:
|
||||
- https://bugzil.la/1963385
|
||||
data_reviews:
|
||||
- https://bugzil.la/1963385
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
notification_emails:
|
||||
- gstoll@mozilla.com
|
||||
- haftandilian@mozilla.com
|
||||
- dparks@mozilla.com
|
||||
interception_points_turned_off:
|
||||
type: string_list
|
||||
description: The interception points that are turned off
|
||||
via enterprise policy.
|
||||
bugs:
|
||||
- https://bugzil.la/1963385
|
||||
data_reviews:
|
||||
- https://bugzil.la/1963385
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
notification_emails:
|
||||
- gstoll@mozilla.com
|
||||
- haftandilian@mozilla.com
|
||||
- dparks@mozilla.com
|
||||
show_blocked_result:
|
||||
type: boolean
|
||||
description: The show_blocked_result pref that is set
|
||||
via enterprise policy.
|
||||
bugs:
|
||||
- https://bugzil.la/1963385
|
||||
data_reviews:
|
||||
- https://bugzil.la/1963385
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
notification_emails:
|
||||
- gstoll@mozilla.com
|
||||
- haftandilian@mozilla.com
|
||||
- dparks@mozilla.com
|
||||
default_result:
|
||||
type: quantity
|
||||
description: The default_result pref that is set
|
||||
via enterprise policy.
|
||||
bugs:
|
||||
- https://bugzil.la/1963385
|
||||
data_reviews:
|
||||
- https://bugzil.la/1963385
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
notification_emails:
|
||||
- gstoll@mozilla.com
|
||||
- haftandilian@mozilla.com
|
||||
- dparks@mozilla.com
|
||||
unit: BlockWarnAllow
|
||||
timeout_result:
|
||||
type: quantity
|
||||
description: The timeout_result pref that is set
|
||||
via enterprise policy.
|
||||
bugs:
|
||||
- https://bugzil.la/1963385
|
||||
data_reviews:
|
||||
- https://bugzil.la/1963385
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
notification_emails:
|
||||
- gstoll@mozilla.com
|
||||
- haftandilian@mozilla.com
|
||||
- dparks@mozilla.com
|
||||
unit: BlockWarnAllow
|
||||
client_signature:
|
||||
type: string
|
||||
description: The client_signature pref that is set
|
||||
via enterprise policy.
|
||||
bugs:
|
||||
- https://bugzil.la/1963385
|
||||
data_reviews:
|
||||
- https://bugzil.la/1963385
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
notification_emails:
|
||||
- gstoll@mozilla.com
|
||||
- haftandilian@mozilla.com
|
||||
- dparks@mozilla.com
|
||||
bypass_for_same_tab_operations:
|
||||
type: boolean
|
||||
description: The bypass_for_same_tab_operations pref that is set
|
||||
via enterprise policy.
|
||||
bugs:
|
||||
- https://bugzil.la/1963385
|
||||
data_reviews:
|
||||
- https://bugzil.la/1963385
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
notification_emails:
|
||||
- gstoll@mozilla.com
|
||||
- haftandilian@mozilla.com
|
||||
- dparks@mozilla.com
|
||||
allow_url_regex_list_set:
|
||||
type: boolean
|
||||
description: Whether the allow_url_regex_list pref is set
|
||||
to a non-default value.
|
||||
bugs:
|
||||
- https://bugzil.la/1963385
|
||||
data_reviews:
|
||||
- https://bugzil.la/1963385
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
notification_emails:
|
||||
- gstoll@mozilla.com
|
||||
- haftandilian@mozilla.com
|
||||
- dparks@mozilla.com
|
||||
deny_url_regex_list_set:
|
||||
type: boolean
|
||||
description: Whether the deny_url_regex_list pref is set
|
||||
to a non-default value.
|
||||
bugs:
|
||||
- https://bugzil.la/1963385
|
||||
data_reviews:
|
||||
- https://bugzil.la/1963385
|
||||
data_sensitivity:
|
||||
- technical
|
||||
expires: never
|
||||
notification_emails:
|
||||
- gstoll@mozilla.com
|
||||
- haftandilian@mozilla.com
|
||||
- dparks@mozilla.com
|
||||
@@ -509,4 +509,8 @@ interface nsIContentAnalysis : nsISupports
|
||||
*/
|
||||
void sendCancelToAgent(in ACString aUserActionId);
|
||||
|
||||
/**
|
||||
* Force the content analysis client to be recreated. For use in tests only.
|
||||
*/
|
||||
void forceRecreateClientForTest();
|
||||
};
|
||||
|
||||
@@ -46,6 +46,12 @@ const kInterceptionPoints = [
|
||||
"file_upload",
|
||||
"print",
|
||||
];
|
||||
// Everything is on by default except download.
|
||||
let kInterceptionPointsOnByDefault = kInterceptionPoints.slice();
|
||||
kInterceptionPointsOnByDefault.splice(
|
||||
kInterceptionPointsOnByDefault.indexOf("download"),
|
||||
1
|
||||
);
|
||||
const kInterceptionPointsPlainTextOnly = ["clipboard", "drag_and_drop"];
|
||||
|
||||
const ca = Cc["@mozilla.org/contentanalysis;1"].getService(
|
||||
@@ -111,7 +117,7 @@ add_task(async function test_ca_active() {
|
||||
PoliciesPrefTracker.stop();
|
||||
});
|
||||
|
||||
add_task(async function test_ca_enterprise_config() {
|
||||
add_task(async function test_ca_enterprise_config_with_default_prefs() {
|
||||
PoliciesPrefTracker.start();
|
||||
await EnterprisePolicyTesting.setupPolicyEngineWithJson({
|
||||
policies: {
|
||||
@@ -150,6 +156,79 @@ add_task(async function test_ca_enterprise_config() {
|
||||
PoliciesPrefTracker.stop();
|
||||
});
|
||||
|
||||
add_task(
|
||||
async function test_ca_enterprise_config_with_default_prefs_telemetry() {
|
||||
PoliciesPrefTracker.start();
|
||||
Services.fog.testResetFOG();
|
||||
await EnterprisePolicyTesting.setupPolicyEngineWithJson({
|
||||
policies: {
|
||||
ContentAnalysis: {
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
// Trigger the content analysis service to ensure telemetry is recorded.
|
||||
let contentAnalysisService = Cc[
|
||||
"@mozilla.org/contentanalysis;1"
|
||||
].getService(Ci.nsIContentAnalysis);
|
||||
is(
|
||||
contentAnalysisService.isActive,
|
||||
true,
|
||||
"Content Analysis service is active"
|
||||
);
|
||||
contentAnalysisService.forceRecreateClientForTest();
|
||||
|
||||
is(
|
||||
Glean.contentAnalysis.agentName.testGetValue(),
|
||||
"A DLP agent",
|
||||
"agentName default"
|
||||
);
|
||||
is(
|
||||
Glean.contentAnalysis.interceptionPointsTurnedOff.testGetValue().length,
|
||||
1,
|
||||
"interceptionPointsTurnedOff default"
|
||||
);
|
||||
is(
|
||||
Glean.contentAnalysis.interceptionPointsTurnedOff.testGetValue()[0],
|
||||
"browser.contentanalysis.interception_point.download.enabled",
|
||||
"interceptionPointsTurnedOff default"
|
||||
);
|
||||
ok(
|
||||
Glean.contentAnalysis.showBlockedResult.testGetValue(),
|
||||
"showBlockedResult default"
|
||||
);
|
||||
is(
|
||||
Glean.contentAnalysis.defaultResult.testGetValue(),
|
||||
0,
|
||||
"defaultResult default"
|
||||
);
|
||||
is(
|
||||
Glean.contentAnalysis.timeoutResult.testGetValue(),
|
||||
0,
|
||||
"timeoutResult default"
|
||||
);
|
||||
is(
|
||||
Glean.contentAnalysis.clientSignature.testGetValue(),
|
||||
null,
|
||||
"clientSignature default"
|
||||
);
|
||||
ok(
|
||||
!Glean.contentAnalysis.bypassForSameTabOperations.testGetValue(),
|
||||
"bypassForSameTabOperations default"
|
||||
);
|
||||
ok(
|
||||
!Glean.contentAnalysis.allowUrlRegexListSet.testGetValue(),
|
||||
"allowUrlRegexListSet default"
|
||||
);
|
||||
ok(
|
||||
!Glean.contentAnalysis.denyUrlRegexListSet.testGetValue(),
|
||||
"denyUrlRegexListSet default"
|
||||
);
|
||||
|
||||
PoliciesPrefTracker.stop();
|
||||
}
|
||||
);
|
||||
|
||||
add_task(async function test_ca_enterprise_config() {
|
||||
PoliciesPrefTracker.start();
|
||||
const string1 = "this is a string";
|
||||
@@ -277,6 +356,107 @@ add_task(async function test_ca_enterprise_config() {
|
||||
PoliciesPrefTracker.stop();
|
||||
});
|
||||
|
||||
add_task(async function test_ca_enterprise_config_telemetry() {
|
||||
PoliciesPrefTracker.start();
|
||||
const string1 = "this is a string";
|
||||
const string2 = "this is another string";
|
||||
const string3 = "an agent name";
|
||||
const string4 = "a client signature";
|
||||
|
||||
Services.fog.testResetFOG();
|
||||
|
||||
await EnterprisePolicyTesting.setupPolicyEngineWithJson({
|
||||
policies: {
|
||||
ContentAnalysis: {
|
||||
Enabled: true,
|
||||
PipePathName: "abc",
|
||||
AgentTimeout: 99,
|
||||
AllowUrlRegexList: string1,
|
||||
DenyUrlRegexList: string2,
|
||||
AgentName: string3,
|
||||
ClientSignature: string4,
|
||||
IsPerUser: true,
|
||||
MaxConnectionsCount: 3,
|
||||
ShowBlockedResult: false,
|
||||
DefaultResult: 1,
|
||||
TimeoutResult: 2,
|
||||
BypassForSameTabOperations: true,
|
||||
InterceptionPoints: {
|
||||
Clipboard: {
|
||||
Enabled: false,
|
||||
PlainTextOnly: false,
|
||||
},
|
||||
Download: {
|
||||
Enabled: true,
|
||||
},
|
||||
DragAndDrop: {
|
||||
Enabled: false,
|
||||
PlainTextOnly: false,
|
||||
},
|
||||
FileUpload: {
|
||||
Enabled: false,
|
||||
},
|
||||
Print: {
|
||||
Enabled: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Trigger the content analysis service to ensure telemetry is recorded.
|
||||
let contentAnalysisService = Cc["@mozilla.org/contentanalysis;1"].getService(
|
||||
Ci.nsIContentAnalysis
|
||||
);
|
||||
contentAnalysisService.forceRecreateClientForTest();
|
||||
is(
|
||||
contentAnalysisService.isActive,
|
||||
true,
|
||||
"Content Analysis service is active"
|
||||
);
|
||||
|
||||
is(Glean.contentAnalysis.agentName.testGetValue(), string3, "agentName");
|
||||
const interceptionPointsTurnedOff =
|
||||
Glean.contentAnalysis.interceptionPointsTurnedOff.testGetValue();
|
||||
is(
|
||||
interceptionPointsTurnedOff.length,
|
||||
4,
|
||||
"interceptionPointsTurnedOff length"
|
||||
);
|
||||
for (let i = 0; i < interceptionPointsTurnedOff.length; i++) {
|
||||
is(
|
||||
interceptionPointsTurnedOff[i],
|
||||
`browser.contentanalysis.interception_point.${kInterceptionPointsOnByDefault[i]}.enabled`,
|
||||
`interceptionPointsTurnedOff ${kInterceptionPointsOnByDefault[i]}`
|
||||
);
|
||||
}
|
||||
ok(
|
||||
!Glean.contentAnalysis.showBlockedResult.testGetValue(),
|
||||
"showBlockedResult"
|
||||
);
|
||||
is(Glean.contentAnalysis.defaultResult.testGetValue(), 1, "defaultResult");
|
||||
is(Glean.contentAnalysis.timeoutResult.testGetValue(), 2, "timeoutResult");
|
||||
is(
|
||||
Glean.contentAnalysis.clientSignature.testGetValue(),
|
||||
string4,
|
||||
"clientSignature"
|
||||
);
|
||||
ok(
|
||||
Glean.contentAnalysis.bypassForSameTabOperations.testGetValue(),
|
||||
"bypassForSameTabOperations"
|
||||
);
|
||||
ok(
|
||||
Glean.contentAnalysis.allowUrlRegexListSet.testGetValue(),
|
||||
"allowUrlRegexListSet"
|
||||
);
|
||||
ok(
|
||||
Glean.contentAnalysis.denyUrlRegexListSet.testGetValue(),
|
||||
"denyUrlRegexListSet"
|
||||
);
|
||||
|
||||
PoliciesPrefTracker.stop();
|
||||
});
|
||||
|
||||
add_task(async function test_cleanup() {
|
||||
ca.testOnlySetCACmdLineArg(false);
|
||||
await EnterprisePolicyTesting.setupPolicyEngineWithJson({
|
||||
|
||||
@@ -141,6 +141,7 @@ firefox_desktop_metrics = [
|
||||
"browser/modules/metrics.yaml",
|
||||
"dom/media/platforms/wmf/metrics.yaml",
|
||||
"services/fxaccounts/metrics.yaml",
|
||||
"toolkit/components/contentanalysis/metrics.yaml",
|
||||
"toolkit/components/contentrelevancy/metrics.yaml",
|
||||
"toolkit/components/crashes/metrics.yaml",
|
||||
"toolkit/components/nimbus/metrics.yaml",
|
||||
|
||||
Reference in New Issue
Block a user