update_engine: Add Cohort, CohortName, CohortHint to Omaha protocol.
This patch persists and sends back to omaha the cohort, cohorthint and
cohortname arguments in the <app> tag. To avoid problems, these strings
are limited to 1024 chars.
BUG=chromium:448995
TEST=unittest added.
Change-Id: I05e7677ee43ab795b670b274d3984803cb6b9522
Reviewed-on: https://chromium-review.googlesource.com/262967
Trybot-Ready: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
Reviewed-by: Don Garrett <dgarrett@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
diff --git a/omaha_request_action.cc b/omaha_request_action.cc
index 0955983..a1cc429 100644
--- a/omaha_request_action.cc
+++ b/omaha_request_action.cc
@@ -141,6 +141,33 @@
return app_body;
}
+// Returns the cohort* argument to include in the <app> tag for the passed
+// |arg_name| and |prefs_key|, if any. The return value is suitable to
+// concatenate to the list of arguments and includes a space at the end.
+string GetCohortArgXml(PrefsInterface* prefs,
+ const std::string arg_name,
+ const std::string prefs_key) {
+ // There's nothing wrong with not having a given cohort setting, so we check
+ // existance first to avoid the warning log message.
+ if (!prefs->Exists(prefs_key))
+ return "";
+ string cohort_value;
+ if (!prefs->GetString(prefs_key, &cohort_value) || cohort_value.empty())
+ return "";
+ // This is a sanity check to avoid sending a huge XML file back to Ohama due
+ // to a compromised stateful partition making the update check fail in low
+ // network environments envent after a reboot.
+ if (cohort_value.size() > 1024) {
+ LOG(WARNING) << "The omaha cohort setting " << arg_name
+ << " has a too big value, which must be an error or an "
+ "attacker trying to inhibit updates.";
+ return "";
+ }
+
+ return base::StringPrintf("%s=\"%s\" ",
+ arg_name.c_str(), XmlEncode(cohort_value).c_str());
+}
+
// Returns an XML that corresponds to the entire <app> node of the Omaha
// request based on the given parameters.
string GetAppXml(const OmahaEvent* event,
@@ -184,8 +211,17 @@
install_date_in_days);
}
+ string app_cohort_args;
+ app_cohort_args += GetCohortArgXml(system_state->prefs(),
+ "cohort", kPrefsOmahaCohort);
+ app_cohort_args += GetCohortArgXml(system_state->prefs(),
+ "cohorthint", kPrefsOmahaCohortHint);
+ app_cohort_args += GetCohortArgXml(system_state->prefs(),
+ "cohortname", kPrefsOmahaCohortName);
+
string app_xml =
" <app appid=\"" + XmlEncode(params->GetAppId()) + "\" " +
+ app_cohort_args +
app_versions +
app_channels +
"lang=\"" + XmlEncode(params->app_lang()) + "\" " +
@@ -260,6 +296,12 @@
string current_path;
// These are the values extracted from the XML.
+ string app_cohort;
+ string app_cohorthint;
+ string app_cohortname;
+ bool app_cohort_set = false;
+ bool app_cohorthint_set = false;
+ bool app_cohortname_set = false;
string updatecheck_status;
string updatecheck_poll_interval;
string daystart_elapsed_days;
@@ -292,7 +334,20 @@
}
}
- if (data->current_path == "/response/app/updatecheck") {
+ if (data->current_path == "/response/app") {
+ if (attrs.find("cohort") != attrs.end()) {
+ data->app_cohort_set = true;
+ data->app_cohort = attrs["cohort"];
+ }
+ if (attrs.find("cohorthint") != attrs.end()) {
+ data->app_cohorthint_set = true;
+ data->app_cohorthint = attrs["cohorthint"];
+ }
+ if (attrs.find("cohortname") != attrs.end()) {
+ data->app_cohortname_set = true;
+ data->app_cohortname = attrs["cohortname"];
+ }
+ } else if (data->current_path == "/response/app/updatecheck") {
// There is only supposed to be a single <updatecheck> element.
data->updatecheck_status = attrs["status"];
data->updatecheck_poll_interval = attrs["PollInterval"];
@@ -629,6 +684,13 @@
if (!ParseParams(parser_data, output_object, completer))
return false;
+ if (parser_data->app_cohort_set)
+ PersistCohortData(kPrefsOmahaCohort, parser_data->app_cohort);
+ if (parser_data->app_cohorthint_set)
+ PersistCohortData(kPrefsOmahaCohortHint, parser_data->app_cohorthint);
+ if (parser_data->app_cohortname_set)
+ PersistCohortData(kPrefsOmahaCohortName, parser_data->app_cohortname);
+
return true;
}
@@ -1232,6 +1294,19 @@
return true;
}
+bool OmahaRequestAction::PersistCohortData(
+ const string& prefs_key,
+ const string& new_value) {
+ if (new_value.empty() && system_state_->prefs()->Exists(prefs_key)) {
+ LOG(INFO) << "Removing stored " << prefs_key << " value.";
+ return system_state_->prefs()->Delete(prefs_key);
+ } else if (!new_value.empty()) {
+ LOG(INFO) << "Storing new setting " << prefs_key << " as " << new_value;
+ return system_state_->prefs()->SetString(prefs_key, new_value);
+ }
+ return true;
+}
+
void OmahaRequestAction::ActionCompleted(ErrorCode code) {
// We only want to report this on "update check".
if (ping_only_ || event_ != nullptr)