1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/reporting/websites/website_usage_observer.h"
#include <memory>
#include <optional>
#include "base/functional/bind.h"
#include "base/json/values_util.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/apps/app_service/metrics/website_metrics.h"
#include "chrome/browser/chromeos/reporting/metric_default_utils.h"
#include "chrome/browser/chromeos/reporting/metric_reporting_prefs.h"
#include "chrome/browser/chromeos/reporting/websites/website_metrics_retriever_interface.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/reporting/metrics/reporting_settings.h"
#include "url/gurl.h"
namespace reporting {
WebsiteUsageObserver::WebsiteUsageObserver(
base::WeakPtr<Profile> profile,
const ReportingSettings* reporting_settings,
std::unique_ptr<WebsiteMetricsRetrieverInterface> website_metrics_retriever)
: profile_(profile),
reporting_settings_(reporting_settings),
website_metrics_retriever_(std::move(website_metrics_retriever)) {
CHECK(website_metrics_retriever_);
website_metrics_retriever_->GetWebsiteMetrics(
base::BindOnce(&WebsiteUsageObserver::InitUsageObserver,
weak_ptr_factory_.GetWeakPtr()));
}
WebsiteUsageObserver::~WebsiteUsageObserver() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void WebsiteUsageObserver::OnUrlUsage(const GURL& url,
base::TimeDelta running_time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CHECK(reporting_settings_);
if (!profile_ || !IsWebsiteUsageTelemetryEnabled() ||
!IsWebsiteUrlAllowlisted(url, reporting_settings_,
kReportWebsiteTelemetryAllowlist)) {
return;
}
if (running_time < metrics::kMinimumWebsiteUsageTime) {
// Skip if there is no usage in millisecond granularity. Needed because we
// track website usage in milliseconds while `base::TimeDelta` internals use
// microsecond granularity.
return;
}
if (!profile_->GetPrefs()->HasPrefPath(kWebsiteUsage)) {
// No data in the pref store, so we create an empty dictionary for now.
profile_->GetPrefs()->SetDict(kWebsiteUsage, base::Value::Dict());
}
CreateOrUpdateWebsiteUsageEntry(url, running_time);
}
void WebsiteUsageObserver::InitUsageObserver(
::apps::WebsiteMetrics* website_metrics) {
if (!website_metrics) {
// This can happen if the `WebsiteMetrics` component initialization failed
// (for example, component was destructed). We just abort initialization of
// the usage observer when this happens.
return;
}
observer_.Observe(website_metrics);
}
void WebsiteUsageObserver::OnWebsiteMetricsDestroyed() {
observer_.Reset();
}
void WebsiteUsageObserver::CreateOrUpdateWebsiteUsageEntry(
const GURL& url,
const base::TimeDelta& running_time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CHECK(profile_);
ScopedDictPrefUpdate usage_dict_pref(profile_->GetPrefs(), kWebsiteUsage);
const std::string& url_string = url.spec();
if (!usage_dict_pref->contains(url_string)) {
// Create a new entry in the pref store for given URL if one does not exist
// already.
usage_dict_pref->Set(url_string, base::TimeDeltaToValue(running_time));
return;
}
// Aggregate and update the running time otherwise.
const std::optional<const base::TimeDelta> saved_running_time_value =
base::ValueToTimeDelta(usage_dict_pref->Find(url_string));
if (saved_running_time_value.has_value()) {
usage_dict_pref->Set(
url_string, base::TimeDeltaToValue(saved_running_time_value.value() +
running_time));
}
}
bool WebsiteUsageObserver::IsWebsiteUsageTelemetryEnabled() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CHECK(reporting_settings_);
const base::Value::List* allowed_telemetry_types;
if (!reporting_settings_->GetList(kReportWebsiteTelemetry,
&allowed_telemetry_types)) {
// Policy likely unset. Disallow website usage telemetry tracking in any
// case.
return false;
}
// `allowed_telemetry_types` is not expected to change as we iterate and check
// for `usage` telemetry type below since this is triggered on the main
// (owning) sequence.
CHECK(allowed_telemetry_types);
auto it = std::find_if(
allowed_telemetry_types->begin(), allowed_telemetry_types->end(),
[](const base::Value& telemetry_type_value) {
return telemetry_type_value.GetString() == kWebsiteTelemetryUsageType;
});
const auto is_usage_telemetry_reporting_enabled =
(it != allowed_telemetry_types->end());
return is_usage_telemetry_reporting_enabled;
}
} // namespace reporting
|