Skip to content

Commit

Permalink
metrics: Add web filter metric for Family Link user
Browse files Browse the repository at this point in the history
Records the parental control metrics of web filter
control for Chrome OS Family Link user. Metrics will
be reported on the first Chrome OS session each day.

Bug: 1152622
Change-Id: I675c7d03e357a63ffa71f6d6765489af792c4074
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2593969
Commit-Queue: Xiqi Ruan <xiqiruan@chromium.org>
Reviewed-by: Alexei Svitkine <asvitkine@chromium.org>
Reviewed-by: Toby Huang <tobyhuang@chromium.org>
Reviewed-by: Aga Wronska <agawronska@chromium.org>
Cr-Commit-Position: refs/heads/master@{#857908}
  • Loading branch information
Xiqi Ruan authored and Chromium LUCI CQ committed Feb 25, 2021
1 parent 5b8068c commit 12aa2e4
Show file tree
Hide file tree
Showing 10 changed files with 359 additions and 16 deletions.
Expand Up @@ -7,6 +7,7 @@
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
#include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_context.h"

Expand All @@ -32,6 +33,7 @@ FamilyUserMetricsServiceFactory::FamilyUserMetricsServiceFactory()
BrowserContextDependencyManager::GetInstance()) {
DependsOn(apps::AppServiceProxyFactory::GetInstance());
DependsOn(ChildUserServiceFactory::GetInstance());
DependsOn(SupervisedUserServiceFactory::GetInstance());
}

FamilyUserMetricsServiceFactory::~FamilyUserMetricsServiceFactory() = default;
Expand Down
Expand Up @@ -13,9 +13,12 @@
#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/supervised_user/supervised_user_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#include "chrome/browser/supervised_user/supervised_user_url_filter.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"

#include "components/user_manager/user_manager.h"
namespace chromeos {

namespace {
Expand All @@ -27,11 +30,23 @@ namespace {
constexpr char kTimeLimitPolicyTypesHistogramName[] =
"FamilyUser.TimeLimitPolicyTypes";

// UMA histogram FamilyUser.WebFilterType
// Reports WebFilterType which indicates web filter behaviour are used for
// current Family Link user.
constexpr char kWebFilterTypeHistogramName[] = "FamilyUser.WebFilterType";

// UMA histogram FamilyUser.ManualSiteListType
// Reports ManualSiteListType which indicates approved list and blocked list
// usage for current Family Link user.
constexpr char kManagedSiteListHistogramName[] = "FamilyUser.ManagedSiteList";

} // namespace

FamilyUserParentalControlMetrics::FamilyUserParentalControlMetrics(
Profile* profile)
: profile_(profile) {
: profile_(profile),
first_report_on_current_device_(
user_manager::UserManager::Get()->IsCurrentUserNew()) {
DCHECK(profile_);
DCHECK(profile_->IsChild());
}
Expand All @@ -44,7 +59,19 @@ const char* FamilyUserParentalControlMetrics::
return kTimeLimitPolicyTypesHistogramName;
}

void FamilyUserParentalControlMetrics::OnNewDay() {
// static
const char*
FamilyUserParentalControlMetrics::GetWebFilterTypeHistogramNameForTest() {
return kWebFilterTypeHistogramName;
}

// static
const char*
FamilyUserParentalControlMetrics::GetManagedSiteListHistogramNameForTest() {
return kManagedSiteListHistogramName;
}

void FamilyUserParentalControlMetrics::ReportTimeLimitPolicy() const {
const base::DictionaryValue* time_limit_prefs =
profile_->GetPrefs()->GetDictionary(prefs::kUsageTimeLimit);
DCHECK(time_limit_prefs);
Expand All @@ -70,5 +97,36 @@ void FamilyUserParentalControlMetrics::OnNewDay() {
/*sample=*/policy);
}
}
void FamilyUserParentalControlMetrics::ReportWebFilterPolicy() const {
// Ignores reports when prefs::kDefaultSupervisedUserFilteringBehavior is
// reset to default value. It might happen during sign out.
SupervisedUserService* supervised_user_service =
SupervisedUserServiceFactory::GetForProfile(profile_);
if (supervised_user_service->IsFilteringBehaviorPrefDefault() ||
!supervised_user_service->GetURLFilter()) {
return;
}

base::UmaHistogramEnumeration(
kWebFilterTypeHistogramName,
supervised_user_service->GetURLFilter()->GetWebFilterType());
base::UmaHistogramEnumeration(
kManagedSiteListHistogramName,
supervised_user_service->GetURLFilter()->GetManagedSiteList());
}

void FamilyUserParentalControlMetrics::OnNewDay() {
// Reports Family Link user time limit policy type.
ReportTimeLimitPolicy();

// Ignores the first report during OOBE. Prefs related to web filter policy
// may not have been successfully sync during OOBE process, which introduces
// bias.
if (first_report_on_current_device_) {
first_report_on_current_device_ = false;
} else {
ReportWebFilterPolicy();
}
}

} // namespace chromeos
Expand Up @@ -11,9 +11,9 @@ class Profile;

namespace chromeos {

// A class for recording time limit metrics for Family Link users on Chrome OS.
// These metrics will be recorded at the beginning of the first active session
// daily.
// A class for recording time limit metrics and web filter metrics for Family
// Link users on Chrome OS. These metrics will be recorded at the beginning of
// the first active session daily.
class FamilyUserParentalControlMetrics
: public FamilyUserMetricsService::Observer {
public:
Expand Down Expand Up @@ -44,14 +44,21 @@ class FamilyUserParentalControlMetrics
~FamilyUserParentalControlMetrics() override;

static const char* GetTimeLimitPolicyTypesHistogramNameForTest();
static const char* GetWebFilterTypeHistogramNameForTest();
static const char* GetManagedSiteListHistogramNameForTest();

// TODO(crbug/1152622): listen to the policy by using PrefChangeRegistrar to
// observe pref. Report when policy change in addition to OnNewDay().
// FamilyUserMetricsService::Observer:
void OnNewDay() override;

private:
void ReportTimeLimitPolicy() const;
void ReportWebFilterPolicy() const;

private:
Profile* const profile_;
bool first_report_on_current_device_ = false;
};
} // namespace chromeos

Expand Down
Expand Up @@ -12,7 +12,6 @@
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/apps/app_service/app_service_test.h"
Expand All @@ -28,6 +27,9 @@
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/supervised_user/supervised_user_constants.h"
#include "chrome/browser/supervised_user/supervised_user_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#include "chrome/browser/supervised_user/supervised_user_url_filter.h"
#include "chrome/browser/ui/app_list/arc/arc_app_test.h"
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
#include "chrome/common/chrome_features.h"
Expand All @@ -46,7 +48,10 @@ namespace {

constexpr base::TimeDelta kOneHour = base::TimeDelta::FromHours(1);
constexpr base::TimeDelta kOneDay = base::TimeDelta::FromDays(1);
constexpr char kStartTime[] = "1 Jan 2020 21:15";

constexpr char kExampleHost0[] = "http://www.example0.com";
constexpr char kExampleURL1[] = "http://www.example1.com/123";
const app_time::AppId kArcApp(apps::mojom::AppType::kArc, "packageName");

arc::mojom::ArcPackageInfoPtr CreateArcAppPackage(
Expand Down Expand Up @@ -82,6 +87,12 @@ class FamilyUserParentalControlMetricsTest : public testing::Test {
features::kWebTimeLimits},
/*disabled_features=*/{});

base::Time start_time;
EXPECT_TRUE(base::Time::FromString(kStartTime, &start_time));
base::TimeDelta forward_by = start_time - base::Time::Now();
EXPECT_LT(base::TimeDelta(), forward_by);
task_environment_.AdvanceClock(forward_by);

// Build a child profile.
std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> prefs =
std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
Expand All @@ -93,6 +104,9 @@ class FamilyUserParentalControlMetricsTest : public testing::Test {
EXPECT_TRUE(profile_->IsChild());
parental_control_metrics_ =
std::make_unique<FamilyUserParentalControlMetrics>(profile_.get());
supervised_user_service_ =
SupervisedUserServiceFactory::GetForProfile(profile_.get());
supervised_user_service_->Init();
}

void TearDown() override {
Expand All @@ -111,13 +125,16 @@ class FamilyUserParentalControlMetricsTest : public testing::Test {

void OnNewDay() { parental_control_metrics_->OnNewDay(); }

PrefService* GetPrefs() { return profile_->GetPrefs(); }

std::unique_ptr<TestingProfile> profile_;
content::BrowserTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};

private:
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<FamilyUserParentalControlMetrics> parental_control_metrics_;
SupervisedUserService* supervised_user_service_ = nullptr;
};

TEST_F(FamilyUserParentalControlMetricsTest, BedAndScreenTimeLimitMetrics) {
Expand All @@ -138,7 +155,7 @@ TEST_F(FamilyUserParentalControlMetricsTest, BedAndScreenTimeLimitMetrics) {
/*quota*/ kOneHour,
/*last_updated=*/base::Time::Now());

profile_->GetPrefs()->Set(prefs::kUsageTimeLimit, policy_content);
GetPrefs()->Set(prefs::kUsageTimeLimit, policy_content);
// Triggers report:
OnNewDay();

Expand Down Expand Up @@ -171,10 +188,9 @@ TEST_F(FamilyUserParentalControlMetricsTest, OverrideTimeLimitMetrics) {
utils::AddOverrideWithDuration(
/*policy=*/&policy_content,
/*action=*/usage_time_limit::TimeLimitOverride::Action::kLock,
/*created_at=*/base::Time::Now() - kOneDay -
base::TimeDelta::FromSeconds(1),
/*created_at=*/base::Time::Now() - kOneDay,
/*duration=*/base::TimeDelta::FromHours(2));
profile_->GetPrefs()->Set(prefs::kUsageTimeLimit, policy_content);
GetPrefs()->Set(prefs::kUsageTimeLimit, policy_content);

// Triggers report.
OnNewDay();
Expand All @@ -200,7 +216,7 @@ TEST_F(FamilyUserParentalControlMetricsTest, OverrideTimeLimitMetrics) {
/*action=*/usage_time_limit::TimeLimitOverride::Action::kLock,
/*created_at=*/base::Time::Now() - base::TimeDelta::FromHours(23),
/*duration=*/base::TimeDelta::FromHours(2));
profile_->GetPrefs()->Set(prefs::kUsageTimeLimit, policy_content);
GetPrefs()->Set(prefs::kUsageTimeLimit, policy_content);

// Triggers report.
OnNewDay();
Expand Down Expand Up @@ -254,8 +270,7 @@ TEST_F(FamilyUserParentalControlMetricsTest, AppAndWebTimeLimitMetrics) {
base::TimeDelta::FromHours(1), base::Time::Now()));

builder.SetResetTime(6, 0);
DictionaryPrefUpdate update(profile_.get()->GetPrefs(),
prefs::kPerAppTimeLimitsPolicy);
DictionaryPrefUpdate update(GetPrefs(), prefs::kPerAppTimeLimitsPolicy);
base::Value* value = update.Get();
*value = builder.value().Clone();
}
Expand All @@ -280,4 +295,109 @@ TEST_F(FamilyUserParentalControlMetricsTest, AppAndWebTimeLimitMetrics) {
/*expected_count=*/2);
}

TEST_F(FamilyUserParentalControlMetricsTest, WebFilterTypeMetric) {
base::HistogramTester histogram_tester;

GetPrefs()->SetInteger(prefs::kDefaultSupervisedUserFilteringBehavior,
SupervisedUserURLFilter::ALLOW);
GetPrefs()->SetBoolean(prefs::kSupervisedUserSafeSites, true);
OnNewDay();
histogram_tester.ExpectUniqueSample(
FamilyUserParentalControlMetrics::FamilyUserParentalControlMetrics::
GetWebFilterTypeHistogramNameForTest(),
/*sample=*/
SupervisedUserURLFilter::WebFilterType::kTryToBlockMatureSites,
/*expected_count=*/1);

// Tests filter "allow all sites".
GetPrefs()->SetBoolean(prefs::kSupervisedUserSafeSites, false);
OnNewDay();
histogram_tester.ExpectBucketCount(
FamilyUserParentalControlMetrics::GetWebFilterTypeHistogramNameForTest(),
/*sample=*/
SupervisedUserURLFilter::WebFilterType::kAllowAllSites,
/*expected_count=*/1);

// Tests filter "only allow certain sites" on Family Link app.
GetPrefs()->SetInteger(prefs::kDefaultSupervisedUserFilteringBehavior,
SupervisedUserURLFilter::BLOCK);
OnNewDay();
histogram_tester.ExpectBucketCount(
FamilyUserParentalControlMetrics::GetWebFilterTypeHistogramNameForTest(),
/*sample=*/
SupervisedUserURLFilter::WebFilterType::kCertainSites,
/*expected_count=*/1);

histogram_tester.ExpectTotalCount(
FamilyUserParentalControlMetrics::GetWebFilterTypeHistogramNameForTest(),
/*expected_count=*/3);
}

TEST_F(FamilyUserParentalControlMetricsTest, ManagedSiteListTypeMetric) {
base::HistogramTester histogram_tester;

GetPrefs()->SetInteger(prefs::kDefaultSupervisedUserFilteringBehavior,
SupervisedUserURLFilter::ALLOW);
GetPrefs()->Set(prefs::kSupervisedUserManualHosts, base::DictionaryValue());
GetPrefs()->Set(prefs::kSupervisedUserManualURLs, base::DictionaryValue());

OnNewDay();
histogram_tester.ExpectBucketCount(
FamilyUserParentalControlMetrics::
GetManagedSiteListHistogramNameForTest(),
/*sample=*/
SupervisedUserURLFilter::ManagedSiteList::kEmpty,
/*expected_count=*/1);

// Blocks `kExampleHost0`.
{
DictionaryPrefUpdate hosts_update(GetPrefs(),
prefs::kSupervisedUserManualHosts);
base::DictionaryValue* hosts = hosts_update.Get();
hosts->SetKey(kExampleHost0, base::Value(false));
}
OnNewDay();
histogram_tester.ExpectBucketCount(
FamilyUserParentalControlMetrics::
GetManagedSiteListHistogramNameForTest(),
/*sample=*/
SupervisedUserURLFilter::ManagedSiteList::kBlockedListOnly,
/*expected_count=*/1);

// Approves `kExampleHost0`.
{
DictionaryPrefUpdate hosts_update(GetPrefs(),
prefs::kSupervisedUserManualHosts);
base::DictionaryValue* hosts = hosts_update.Get();
hosts->SetKey(kExampleHost0, base::Value(true));
}
OnNewDay();
histogram_tester.ExpectBucketCount(
FamilyUserParentalControlMetrics::
GetManagedSiteListHistogramNameForTest(),
/*sample=*/
SupervisedUserURLFilter::ManagedSiteList::kApprovedListOnly,
/*expected_count=*/1);

// Blocks `kExampleURL1`.
{
DictionaryPrefUpdate urls_update(GetPrefs(),
prefs::kSupervisedUserManualURLs);
base::DictionaryValue* urls = urls_update.Get();
urls->SetKey(kExampleURL1, base::Value(false));
}
OnNewDay();
histogram_tester.ExpectBucketCount(
FamilyUserParentalControlMetrics::
GetManagedSiteListHistogramNameForTest(),
/*sample=*/
SupervisedUserURLFilter::ManagedSiteList::kBoth,
/*expected_count=*/1);

histogram_tester.ExpectTotalCount(
FamilyUserParentalControlMetrics::
GetManagedSiteListHistogramNameForTest(),
/*expected_count=*/4);
}

} // namespace chromeos
7 changes: 6 additions & 1 deletion chrome/browser/supervised_user/supervised_user_service.cc
Expand Up @@ -180,7 +180,6 @@ SupervisedUserURLFilter* SupervisedUserService::GetURLFilter() {
return &url_filter_;
}


bool SupervisedUserService::AccessRequestsEnabled() {
return FindEnabledPermissionRequestCreator(0) < permissions_creators_.size();
}
Expand Down Expand Up @@ -406,6 +405,12 @@ void SupervisedUserService::RecordExtensionEnablementUmaMetrics(
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)

bool SupervisedUserService::IsFilteringBehaviorPrefDefault() const {
return profile_->GetPrefs()
->FindPreference(prefs::kDefaultSupervisedUserFilteringBehavior)
->IsDefaultValue();
}

void SupervisedUserService::SetActive(bool active) {
if (active_ == active)
return;
Expand Down

0 comments on commit 12aa2e4

Please sign in to comment.