blob: 5cf61e4c918566efbf87b15569e539113dea7457 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/update_client/protocol_serializer_xml.h"
#include <memory>
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/update_client/updater_state.h"
namespace update_client {
std::string ProtocolSerializerXml::Serialize(
const protocol_request::Request& request) const {
std::string msg;
base::StringAppendF(&msg,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<request protocol=\"%s\"",
kProtocolVersion);
// Constant information for this updater.
base::StringAppendF(&msg, " dedup=\"cr\" acceptformat=\"crx2,crx3\"");
if (!request.additional_attributes.empty()) {
for (const auto& attr : request.additional_attributes) {
base::StringAppendF(&msg, " %s=\"%s\"", attr.first.c_str(),
attr.second.c_str());
}
}
// Session id and request id.
base::StringAppendF(&msg, " sessionid=\"%s\" requestid=\"%s\"",
request.session_id.c_str(), request.request_id.c_str());
// Chrome version and platform information.
base::StringAppendF(&msg,
" updater=\"%s\" updaterversion=\"%s\" prodversion=\"%s\""
" lang=\"%s\" os=\"%s\" arch=\"%s\" nacl_arch=\"%s\"",
request.updatername.c_str(),
request.updaterversion.c_str(),
request.prodversion.c_str(), request.lang.c_str(),
request.operating_system.c_str(), request.arch.c_str(),
request.nacl_arch.c_str());
#if defined(OS_WIN)
if (request.is_wow64)
base::StringAppendF(&msg, " wow64=\"%d\"", request.is_wow64);
#endif // OS_WIN
if (!request.updaterchannel.empty()) {
base::StringAppendF(&msg, " updaterchannel=\"%s\"",
request.updaterchannel.c_str());
}
if (!request.prodchannel.empty()) {
base::StringAppendF(&msg, " prodchannel=\"%s\"",
request.prodchannel.c_str());
}
if (!request.dlpref.empty())
base::StringAppendF(&msg, " dlpref=\"%s\"", request.dlpref.c_str());
if (request.domain_joined) {
base::StringAppendF(&msg, " %s=\"%d\"", UpdaterState::kIsEnterpriseManaged,
*request.domain_joined);
}
base::StringAppendF(&msg, ">");
// HW platform information.
base::StringAppendF(&msg, "<hw physmemory=\"%d\"/>", request.hw.physmemory);
// OS version and platform information.
base::StringAppendF(&msg, "<os platform=\"%s\" arch=\"%s\"",
request.os.platform.c_str(), request.os.arch.c_str());
if (!request.os.version.empty())
base::StringAppendF(&msg, " version=\"%s\"", request.os.version.c_str());
if (!request.os.service_pack.empty())
base::StringAppendF(&msg, " sp=\"%s\"", request.os.service_pack.c_str());
base::StringAppendF(&msg, "/>");
#if defined(GOOGLE_CHROME_BUILD)
if (request.updater) {
const auto& updater = *request.updater;
base::StringAppendF(&msg, "<updater name=\"%s\"", updater.name.c_str());
if (!updater.version.empty())
base::StringAppendF(&msg, " version=\"%s\"", updater.version.c_str());
if (updater.last_checked)
base::StringAppendF(&msg, " lastchecked=\"%d\"", *updater.last_checked);
if (updater.last_started)
base::StringAppendF(&msg, " laststarted=\"%d\"", *updater.last_started);
base::StringAppendF(
&msg,
" ismachine=\"%d\" autoupdatecheckenabled=\"%d\" updatepolicy=\"%d\"/>",
updater.is_machine, updater.autoupdate_check_enabled,
updater.update_policy);
}
#endif
for (const auto& app : request.apps) {
// Begin <app> attributes.
base::StringAppendF(&msg, "<app appid=\"%s\"", app.app_id.c_str());
base::StringAppendF(&msg, " version=\"%s\"", app.version.c_str());
if (!app.brand_code.empty())
base::StringAppendF(&msg, " brand=\"%s\"", app.brand_code.c_str());
if (!app.install_source.empty()) {
base::StringAppendF(&msg, " installsource=\"%s\"",
app.install_source.c_str());
}
if (!app.install_location.empty()) {
base::StringAppendF(&msg, " installedby=\"%s\"",
app.install_location.c_str());
}
for (const auto& attr : app.installer_attributes) {
base::StringAppendF(&msg, " %s=\"%s\"", attr.first.c_str(),
attr.second.c_str());
}
if (!app.cohort.empty())
base::StringAppendF(&msg, " cohort=\"%s\"", app.cohort.c_str());
if (!app.cohort_name.empty())
base::StringAppendF(&msg, " cohortname=\"%s\"", app.cohort_name.c_str());
if (!app.cohort_hint.empty())
base::StringAppendF(&msg, " cohorthint=\"%s\"", app.cohort_hint.c_str());
if (app.enabled)
base::StringAppendF(&msg, " enabled=\"%d\"", *app.enabled ? 1 : 0);
base::StringAppendF(&msg, ">");
// End <app> attributes.
if (app.disabled_reasons) {
for (const int disabled_reason : *app.disabled_reasons)
base::StringAppendF(&msg, "<disabled reason=\"%d\"/>", disabled_reason);
}
if (app.update_check) {
base::StringAppendF(&msg, "<updatecheck");
if (app.update_check->is_update_disabled)
base::StringAppendF(&msg, " updatedisabled=\"true\"");
base::StringAppendF(&msg, "/>");
}
if (app.ping) {
base::StringAppendF(&msg, "<ping");
// Output "ad" or "a" only if the this app has been seen 'active'.
if (app.ping->date_last_active) {
base::StringAppendF(&msg, " ad=\"%d\"", *app.ping->date_last_active);
} else if (app.ping->days_since_last_active_ping) {
base::StringAppendF(&msg, " a=\"%d\"",
*app.ping->days_since_last_active_ping);
}
// Output "rd" if valid or "r" as a last resort roll call metric.
if (app.ping->date_last_roll_call)
base::StringAppendF(&msg, " rd=\"%d\"", *app.ping->date_last_roll_call);
else
base::StringAppendF(&msg, " r=\"%d\"",
app.ping->days_since_last_roll_call);
if (!app.ping->ping_freshness.empty())
base::StringAppendF(&msg, " ping_freshness=\"%s\"",
app.ping->ping_freshness.c_str());
base::StringAppendF(&msg, "/>"); // End <ping>.
}
if (!app.fingerprint.empty()) {
base::StringAppendF(&msg,
"<packages>"
"<package fp=\"%s\"/>"
"</packages>",
app.fingerprint.c_str());
}
if (app.events) {
for (const auto& event : *app.events) {
DCHECK(event.is_dict());
DCHECK(!event.DictEmpty());
base::StringAppendF(&msg, "<event");
const auto& attrs = event.DictItems();
for (auto it = attrs.begin(); it != attrs.end(); ++it) {
base::StringAppendF(&msg, " %s=", (*it).first.c_str());
const auto& value = (*it).second;
if (value.is_string())
base::StringAppendF(&msg, "\"%s\"", value.GetString().c_str());
else if (value.is_int())
base::StringAppendF(&msg, "\"%d\"", value.GetInt());
else if (value.is_double())
base::StringAppendF(&msg, "\"%.0f\"", value.GetDouble());
else
NOTREACHED();
}
base::StringAppendF(&msg, "/>");
}
}
base::StringAppendF(&msg, "</app>");
}
base::StringAppendF(&msg, "</request>");
return msg;
}
} // namespace update_client