Commit 13663e59 authored by Askar Aitzhan's avatar Askar Aitzhan Committed by Commit Bot

Append "event_id" by which "Chrome Reporting API" deduplicates events.

event_id is calculated by taking a hash from (event, context) pair. Both
event and context are flat dictionaries, they contain only primitive
types. Inside base::DictionaryValue is implemented with flat_map which
stores keys in sorted vector. This gives a stable result when
serializing to json string. Hash will be calculated from those stable
json strings, which gives stable hashes.

Bug: 996213
Change-Id: I2c88ab709bc78dd54471185e52e99a62054752de
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1783145
Commit-Queue: Askar Aitzhan <askaraitzhan@google.com>
Reviewed-by: default avatarSergey Poromov <poromov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#694301}
parent d26de08b
......@@ -226,11 +226,19 @@ class AppInstallEventLogManagerTest : public testing::Test {
NOTREACHED();
}
void BuildReport() {
base::Value event_list = ConvertEventsToValue(events_, nullptr);
base::Value context = reporting::GetContext(nullptr);
AppendEventId(&event_list, context);
events_value_ = RealtimeReportingJobConfiguration::BuildReport(
std::move(event_list), std::move(context));
}
void ExpectUploadAndCaptureCallback(
CloudPolicyClient::StatusCallback* callback) {
ClearEventsDict();
events_value_ = RealtimeReportingJobConfiguration::BuildReport(
ConvertEventsToValue(events_, nullptr), reporting::GetContext(nullptr));
BuildReport();
EXPECT_CALL(cloud_policy_client_,
UploadRealtimeReport(MatchEvents(&events_value_), _))
......@@ -244,8 +252,7 @@ class AppInstallEventLogManagerTest : public testing::Test {
void ExpectAndCompleteUpload() {
ClearEventsDict();
events_value_ = RealtimeReportingJobConfiguration::BuildReport(
ConvertEventsToValue(events_, nullptr), reporting::GetContext(nullptr));
BuildReport();
EXPECT_CALL(cloud_policy_client_,
UploadRealtimeReport(MatchEvents(&events_value_), _))
......
......@@ -99,8 +99,12 @@ void AppInstallEventLogUploader::StartSerialization() {
void AppInstallEventLogUploader::OnSerialized(
const em::AppInstallReportRequest* report) {
base::Value event_list = ConvertProtoToValue(report, profile_);
base::Value context = reporting::GetContext(profile_);
AppendEventId(&event_list, context);
base::Value value_report = RealtimeReportingJobConfiguration::BuildReport(
ConvertProtoToValue(report, profile_), reporting::GetContext(profile_));
std::move(event_list), std::move(context));
// base::Unretained() is safe here as the destructor cancels any pending
// upload, after which the |client_| is guaranteed to not call the callback.
......
......@@ -4,6 +4,8 @@
#include "chrome/browser/chromeos/policy/app_install_event_log_util.h"
#include "base/hash/md5.h"
#include "base/json/json_string_value_serializer.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
......@@ -31,6 +33,35 @@ constexpr char kSerialNumber[] = "serialNumber";
constexpr char kGaiaId[] = "gaiaId";
constexpr char kAndroidAppInstallEvent[] = "androidAppInstallEvent";
constexpr char kTime[] = "time";
constexpr char kEventId[] = "eventId";
// Calculates hash for the given |event| and |context|, and stores the hash in
// |hash|. Returns true if |event| and |context| are json serializable and
// |hash| is not nullptr, otherwise return false.
bool GetHash(const base::Value& event,
const base::Value& context,
std::string* hash) {
if (hash == nullptr)
return false;
std::string serialized_string;
JSONStringValueSerializer serializer(&serialized_string);
if (!serializer.Serialize(event))
return false;
base::MD5Context ctx;
base::MD5Init(&ctx);
base::MD5Update(&ctx, serialized_string);
if (!serializer.Serialize(context))
return false;
base::MD5Update(&ctx, serialized_string);
base::MD5Digest digest;
base::MD5Final(&digest, &ctx);
*hash = base::MD5DigestToBase16(digest);
return true;
}
} // namespace
......@@ -136,4 +167,15 @@ base::Value ConvertEventToValue(
return wrapper;
}
void AppendEventId(base::Value* event_list, const base::Value& context) {
DCHECK(event_list);
DCHECK(event_list->is_list());
for (auto& event : event_list->GetList()) {
std::string event_id;
if (GetHash(event, context, &event_id))
event.SetStringKey(kEventId, event_id);
}
}
} // namespace policy
......@@ -45,6 +45,12 @@ base::Value ConvertEventToValue(
const em::AppInstallReportLogEvent& app_install_report_log_event,
Profile* profile);
// Appends event_id to events in |event_list| by calculating hash of the (event,
// |context|) pair. If calculating hash is not possible for an event in
// |event_list|, event_id for that event will not be populated. event_id is used
// by "Chrome Reporting API" to deduplicate events.
void AppendEventId(base::Value* event_list, const base::Value& context);
} // namespace policy
#endif // CHROME_BROWSER_CHROMEOS_POLICY_APP_INSTALL_EVENT_LOG_UTIL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment