blob: 739abbff7543db7e577f43e31d9274bed5838973 [file] [log] [blame]
Amin Hassani7fca2862019-03-28 16:09:22 -07001//
2// Copyright (C) 2019 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
Amin Hassaniec7bc112020-10-29 16:47:58 -070017#include "update_engine/cros/omaha_request_builder_xml.h"
Amin Hassani7fca2862019-03-28 16:09:22 -070018
19#include <inttypes.h>
20
21#include <string>
22
Jae Hoon Kim6ada5912019-06-14 10:11:34 -070023#include <base/guid.h>
Amin Hassani7fca2862019-03-28 16:09:22 -070024#include <base/logging.h>
25#include <base/strings/string_number_conversions.h>
26#include <base/strings/string_util.h>
27#include <base/strings/stringprintf.h>
28#include <base/time/time.h>
29
30#include "update_engine/common/constants.h"
31#include "update_engine/common/prefs_interface.h"
32#include "update_engine/common/utils.h"
Amin Hassaniec7bc112020-10-29 16:47:58 -070033#include "update_engine/cros/omaha_request_params.h"
Amin Hassani7fca2862019-03-28 16:09:22 -070034
35using std::string;
36
37namespace chromeos_update_engine {
38
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -080039const char kNoVersion[] = "0.0.0.0";
Andrewe045aef2020-01-08 16:29:22 -080040const int kPingNeverPinged = -1;
41const int kPingUnknownValue = -2;
42const int kPingActiveValue = 1;
43const int kPingInactiveValue = 0;
Amin Hassani7fca2862019-03-28 16:09:22 -070044
45bool XmlEncode(const string& input, string* output) {
46 if (std::find_if(input.begin(), input.end(), [](const char c) {
47 return c & 0x80;
48 }) != input.end()) {
49 LOG(WARNING) << "Invalid ASCII-7 string passed to the XML encoder:";
50 utils::HexDumpString(input);
51 return false;
52 }
53 output->clear();
54 // We need at least input.size() space in the output, but the code below will
55 // handle it if we need more.
56 output->reserve(input.size());
57 for (char c : input) {
58 switch (c) {
59 case '\"':
60 output->append("&quot;");
61 break;
62 case '\'':
63 output->append("&apos;");
64 break;
65 case '&':
66 output->append("&amp;");
67 break;
68 case '<':
69 output->append("&lt;");
70 break;
71 case '>':
72 output->append("&gt;");
73 break;
74 default:
75 output->push_back(c);
76 }
77 }
78 return true;
79}
80
81string XmlEncodeWithDefault(const string& input, const string& default_value) {
82 string output;
83 if (XmlEncode(input, &output))
84 return output;
85 return default_value;
86}
87
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -070088string OmahaRequestBuilderXml::GetPing() const {
89 // Returns an XML ping element attribute assignment with attribute
90 // |name| and value |ping_days| if |ping_days| has a value that needs
91 // to be sent, or an empty string otherwise.
92 auto GetPingAttribute = [](const char* name, int ping_days) -> string {
Andrewe045aef2020-01-08 16:29:22 -080093 if (ping_days > 0 || ping_days == kPingNeverPinged)
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -070094 return base::StringPrintf(" %s=\"%d\"", name, ping_days);
95 return "";
96 };
Amin Hassani7fca2862019-03-28 16:09:22 -070097
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -070098 string ping_active = GetPingAttribute("a", ping_active_days_);
99 string ping_roll_call = GetPingAttribute("r", ping_roll_call_days_);
Amin Hassani7fca2862019-03-28 16:09:22 -0700100 if (!ping_active.empty() || !ping_roll_call.empty()) {
101 return base::StringPrintf(" <ping active=\"1\"%s%s></ping>\n",
102 ping_active.c_str(),
103 ping_roll_call.c_str());
104 }
105 return "";
106}
107
Andrewe045aef2020-01-08 16:29:22 -0800108string OmahaRequestBuilderXml::GetPingDateBased(
109 const OmahaRequestParams::AppParams& app_params) const {
110 if (!app_params.send_ping)
111 return "";
112 string ping_active = "";
113 string ping_ad = "";
114 if (app_params.ping_active == kPingActiveValue) {
115 ping_active =
116 base::StringPrintf(" active=\"%" PRId64 "\"", app_params.ping_active);
117 ping_ad = base::StringPrintf(" ad=\"%" PRId64 "\"",
118 app_params.ping_date_last_active);
119 }
120
121 string ping_rd = base::StringPrintf(" rd=\"%" PRId64 "\"",
122 app_params.ping_date_last_rollcall);
123
124 return base::StringPrintf(" <ping%s%s%s></ping>\n",
125 ping_active.c_str(),
126 ping_ad.c_str(),
127 ping_rd.c_str());
128}
129
130string OmahaRequestBuilderXml::GetAppBody(const OmahaAppData& app_data) const {
Amin Hassani7fca2862019-03-28 16:09:22 -0700131 string app_body;
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700132 if (event_ == nullptr) {
Andrewe045aef2020-01-08 16:29:22 -0800133 if (app_data.app_params.send_ping) {
134 switch (app_data.app_params.active_counting_type) {
135 case OmahaRequestParams::kDayBased:
136 app_body = GetPing();
137 break;
138 case OmahaRequestParams::kDateBased:
139 app_body = GetPingDateBased(app_data.app_params);
140 break;
141 default:
142 NOTREACHED();
143 }
144 }
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700145 if (!ping_only_) {
Andrewe045aef2020-01-08 16:29:22 -0800146 if (!app_data.skip_update) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700147 app_body += " <updatecheck";
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700148 if (!params_->target_version_prefix().empty()) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700149 app_body += base::StringPrintf(
150 " targetversionprefix=\"%s\"",
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700151 XmlEncodeWithDefault(params_->target_version_prefix()).c_str());
Amin Hassani7fca2862019-03-28 16:09:22 -0700152 // Rollback requires target_version_prefix set.
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700153 if (params_->rollback_allowed()) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700154 app_body += " rollback_allowed=\"true\"";
155 }
156 }
Amin Hassani37b67232020-08-13 09:29:48 -0700157 if (!params_->lts_tag().empty()) {
158 app_body += base::StringPrintf(
159 " ltstag=\"%s\"",
160 XmlEncodeWithDefault(params_->lts_tag()).c_str());
161 }
Amin Hassani7fca2862019-03-28 16:09:22 -0700162 app_body += "></updatecheck>\n";
163 }
164
165 // If this is the first update check after a reboot following a previous
166 // update, generate an event containing the previous version number. If
167 // the previous version preference file doesn't exist the event is still
168 // generated with a previous version of 0.0.0.0 -- this is relevant for
169 // older clients or new installs. The previous version event is not sent
170 // for ping-only requests because they come before the client has
171 // rebooted. The previous version event is also not sent if it was already
172 // sent for this new version with a previous updatecheck.
173 string prev_version;
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700174 if (!prefs_->GetString(kPrefsPreviousVersion, &prev_version)) {
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800175 prev_version = kNoVersion;
Amin Hassani7fca2862019-03-28 16:09:22 -0700176 }
177 // We only store a non-empty previous version value after a successful
178 // update in the previous boot. After reporting it back to the server,
179 // we clear the previous version value so it doesn't get reported again.
180 if (!prev_version.empty()) {
181 app_body += base::StringPrintf(
182 " <event eventtype=\"%d\" eventresult=\"%d\" "
183 "previousversion=\"%s\"></event>\n",
184 OmahaEvent::kTypeRebootedAfterUpdate,
185 OmahaEvent::kResultSuccess,
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800186 XmlEncodeWithDefault(prev_version, kNoVersion).c_str());
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700187 LOG_IF(WARNING, !prefs_->SetString(kPrefsPreviousVersion, ""))
Amin Hassani7fca2862019-03-28 16:09:22 -0700188 << "Unable to reset the previous version.";
189 }
190 }
191 } else {
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700192 int event_result = event_->result;
Amin Hassani7fca2862019-03-28 16:09:22 -0700193 // The error code is an optional attribute so append it only if the result
194 // is not success.
195 string error_code;
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700196 if (event_result != OmahaEvent::kResultSuccess) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700197 error_code = base::StringPrintf(" errorcode=\"%d\"",
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700198 static_cast<int>(event_->error_code));
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700199 } else if (app_data.is_dlc && !app_data.app_params.updated) {
200 // On a |OmahaEvent::kResultSuccess|, if the event is for an update
201 // completion and the App is a DLC, send error for excluded DLCs as they
202 // did not update.
203 event_result = OmahaEvent::Result::kResultError;
204 error_code = base::StringPrintf(
205 " errorcode=\"%d\"",
206 static_cast<int>(ErrorCode::kPackageExcludedFromUpdate));
Amin Hassani7fca2862019-03-28 16:09:22 -0700207 }
208 app_body = base::StringPrintf(
209 " <event eventtype=\"%d\" eventresult=\"%d\"%s></event>\n",
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700210 event_->type,
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700211 event_result,
Amin Hassani7fca2862019-03-28 16:09:22 -0700212 error_code.c_str());
213 }
214
215 return app_body;
216}
217
Jae Hoon Kime2cac612020-11-02 18:30:29 -0800218string OmahaRequestBuilderXml::GetCohortArg(
219 const string& arg_name,
220 const string& prefs_key,
221 const string& override_value) const {
Amin Hassani7fca2862019-03-28 16:09:22 -0700222 string cohort_value;
Askar Aitzhan18fff842019-06-21 23:24:37 +0200223 if (!override_value.empty()) {
224 // |override_value| take precedence over pref value.
225 cohort_value = override_value;
226 } else {
227 // There's nothing wrong with not having a given cohort setting, so we check
228 // existence first to avoid the warning log message.
229 if (!prefs_->Exists(prefs_key))
230 return "";
231 if (!prefs_->GetString(prefs_key, &cohort_value) || cohort_value.empty())
232 return "";
233 }
Kelvin Zhangebd5e252020-07-22 18:27:06 -0400234 // This is a validity check to avoid sending a huge XML file back to Ohama due
Amin Hassani7fca2862019-03-28 16:09:22 -0700235 // to a compromised stateful partition making the update check fail in low
236 // network environments envent after a reboot.
237 if (cohort_value.size() > 1024) {
238 LOG(WARNING) << "The omaha cohort setting " << arg_name
239 << " has a too big value, which must be an error or an "
240 "attacker trying to inhibit updates.";
241 return "";
242 }
243
244 string escaped_xml_value;
245 if (!XmlEncode(cohort_value, &escaped_xml_value)) {
246 LOG(WARNING) << "The omaha cohort setting " << arg_name
247 << " is ASCII-7 invalid, ignoring it.";
248 return "";
249 }
250
251 return base::StringPrintf(
252 "%s=\"%s\" ", arg_name.c_str(), escaped_xml_value.c_str());
253}
254
255bool IsValidComponentID(const string& id) {
256 for (char c : id) {
257 if (!isalnum(c) && c != '-' && c != '_' && c != '.')
258 return false;
259 }
260 return true;
261}
262
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700263string OmahaRequestBuilderXml::GetApp(const OmahaAppData& app_data) const {
Andrewe045aef2020-01-08 16:29:22 -0800264 string app_body = GetAppBody(app_data);
Amin Hassani7fca2862019-03-28 16:09:22 -0700265 string app_versions;
266
267 // If we are downgrading to a more stable channel and we are allowed to do
268 // powerwash, then pass 0.0.0.0 as the version. This is needed to get the
269 // highest-versioned payload on the destination channel.
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700270 if (params_->ShouldPowerwash()) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700271 LOG(INFO) << "Passing OS version as 0.0.0.0 as we are set to powerwash "
272 << "on downgrading to the version in the more stable channel";
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800273 app_versions = "version=\"" + string(kNoVersion) + "\" from_version=\"" +
274 XmlEncodeWithDefault(app_data.version, kNoVersion) + "\" ";
Amin Hassani7fca2862019-03-28 16:09:22 -0700275 } else {
276 app_versions = "version=\"" +
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800277 XmlEncodeWithDefault(app_data.version, kNoVersion) + "\" ";
Amin Hassani7fca2862019-03-28 16:09:22 -0700278 }
279
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700280 string download_channel = params_->download_channel();
Amin Hassani7fca2862019-03-28 16:09:22 -0700281 string app_channels =
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700282 "track=\"" + XmlEncodeWithDefault(download_channel) + "\" ";
283 if (params_->current_channel() != download_channel) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700284 app_channels += "from_track=\"" +
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700285 XmlEncodeWithDefault(params_->current_channel()) + "\" ";
Amin Hassani7fca2862019-03-28 16:09:22 -0700286 }
287
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800288 string delta_okay_str =
289 params_->delta_okay() && !params_->is_install() ? "true" : "false";
Amin Hassani7fca2862019-03-28 16:09:22 -0700290
291 // If install_date_days is not set (e.g. its value is -1 ), don't
292 // include the attribute.
293 string install_date_in_days_str = "";
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700294 if (install_date_in_days_ >= 0) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700295 install_date_in_days_str =
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700296 base::StringPrintf("installdate=\"%d\" ", install_date_in_days_);
Amin Hassani7fca2862019-03-28 16:09:22 -0700297 }
298
299 string app_cohort_args;
Jae Hoon Kime2cac612020-11-02 18:30:29 -0800300 string cohort_key = kPrefsOmahaCohort;
301 string cohortname_key = kPrefsOmahaCohortName;
302 string cohorthint_key = kPrefsOmahaCohortHint;
Amin Hassani7fca2862019-03-28 16:09:22 -0700303
Jae Hoon Kime2cac612020-11-02 18:30:29 -0800304 // Override the cohort keys for DLC App IDs.
305 const auto& dlc_apps_params = params_->dlc_apps_params();
306 auto itr = dlc_apps_params.find(app_data.id);
307 if (itr != dlc_apps_params.end()) {
308 auto dlc_id = itr->second.name;
309 cohort_key =
310 prefs_->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohort});
311 cohortname_key =
312 prefs_->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohortName});
313 cohorthint_key =
314 prefs_->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohortHint});
315 }
316
317 app_cohort_args += GetCohortArg("cohort", cohort_key);
318 app_cohort_args += GetCohortArg("cohortname", cohortname_key);
Askar Aitzhan18fff842019-06-21 23:24:37 +0200319 // Policy provided value overrides pref.
Jae Hoon Kime2cac612020-11-02 18:30:29 -0800320 app_cohort_args +=
321 GetCohortArg("cohorthint",
322 cohorthint_key,
323 params_->autoupdate_token() /* override_value */);
Askar Aitzhan18fff842019-06-21 23:24:37 +0200324
Amin Hassani7fca2862019-03-28 16:09:22 -0700325 string fingerprint_arg;
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700326 if (!params_->os_build_fingerprint().empty()) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700327 fingerprint_arg = "fingerprint=\"" +
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700328 XmlEncodeWithDefault(params_->os_build_fingerprint()) +
Amin Hassani7fca2862019-03-28 16:09:22 -0700329 "\" ";
330 }
331
332 string buildtype_arg;
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700333 if (!params_->os_build_type().empty()) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700334 buildtype_arg = "os_build_type=\"" +
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700335 XmlEncodeWithDefault(params_->os_build_type()) + "\" ";
Amin Hassani7fca2862019-03-28 16:09:22 -0700336 }
337
338 string product_components_args;
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700339 if (!params_->ShouldPowerwash() && !app_data.product_components.empty()) {
Amin Hassani7fca2862019-03-28 16:09:22 -0700340 brillo::KeyValueStore store;
341 if (store.LoadFromString(app_data.product_components)) {
342 for (const string& key : store.GetKeys()) {
343 if (!IsValidComponentID(key)) {
344 LOG(ERROR) << "Invalid component id: " << key;
345 continue;
346 }
347 string version;
348 if (!store.GetString(key, &version)) {
349 LOG(ERROR) << "Failed to get version for " << key
350 << " in product_components.";
351 continue;
352 }
353 product_components_args +=
354 base::StringPrintf("_%s.version=\"%s\" ",
355 key.c_str(),
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700356 XmlEncodeWithDefault(version).c_str());
Amin Hassani7fca2862019-03-28 16:09:22 -0700357 }
358 } else {
359 LOG(ERROR) << "Failed to parse product_components:\n"
360 << app_data.product_components;
361 }
362 }
363
Matt Ziegelbaumaa8e1a42019-05-09 21:41:58 -0400364 string requisition_arg;
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700365 if (!params_->device_requisition().empty()) {
Matt Ziegelbaumaa8e1a42019-05-09 21:41:58 -0400366 requisition_arg = "requisition=\"" +
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700367 XmlEncodeWithDefault(params_->device_requisition()) +
Matt Ziegelbaumaa8e1a42019-05-09 21:41:58 -0400368 "\" ";
369 }
370
Amin Hassani7fca2862019-03-28 16:09:22 -0700371 // clang-format off
372 string app_xml = " <app "
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700373 "appid=\"" + XmlEncodeWithDefault(app_data.id) + "\" " +
Amin Hassani7fca2862019-03-28 16:09:22 -0700374 app_cohort_args +
375 app_versions +
376 app_channels +
377 product_components_args +
378 fingerprint_arg +
379 buildtype_arg +
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700380 "board=\"" + XmlEncodeWithDefault(params_->os_board()) + "\" " +
381 "hardware_class=\"" + XmlEncodeWithDefault(params_->hwid()) + "\" " +
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800382 "delta_okay=\"" + delta_okay_str + "\" " +
383 install_date_in_days_str +
384
385 // DLC excluded for installs and updates.
386 (app_data.is_dlc ? "" :
387 "lang=\"" + XmlEncodeWithDefault(params_->app_lang(), "en-US") + "\" " +
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800388 requisition_arg) +
389
Amin Hassani7fca2862019-03-28 16:09:22 -0700390 ">\n" +
391 app_body +
392 " </app>\n";
393 // clang-format on
394 return app_xml;
395}
396
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700397string OmahaRequestBuilderXml::GetOs() const {
Amin Hassani7fca2862019-03-28 16:09:22 -0700398 string os_xml =
399 " <os "
400 "version=\"" +
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700401 XmlEncodeWithDefault(params_->os_version()) + "\" " + "platform=\"" +
402 XmlEncodeWithDefault(params_->os_platform()) + "\" " + "sp=\"" +
403 XmlEncodeWithDefault(params_->os_sp()) +
Amin Hassani7fca2862019-03-28 16:09:22 -0700404 "\">"
405 "</os>\n";
406 return os_xml;
407}
408
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700409string OmahaRequestBuilderXml::GetRequest() const {
410 string os_xml = GetOs();
411 string app_xml = GetApps();
Amin Hassani7fca2862019-03-28 16:09:22 -0700412
413 string request_xml = base::StringPrintf(
414 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
Jae Hoon Kimedb65502019-06-14 11:52:17 -0700415 "<request requestid=\"%s\" sessionid=\"%s\""
Jae Hoon Kim6ada5912019-06-14 10:11:34 -0700416 " protocol=\"3.0\" updater=\"%s\" updaterversion=\"%s\""
Amin Hassani7fca2862019-03-28 16:09:22 -0700417 " installsource=\"%s\" ismachine=\"1\">\n%s%s</request>\n",
Jae Hoon Kim6ada5912019-06-14 10:11:34 -0700418 base::GenerateGUID().c_str() /* requestid */,
Jae Hoon Kimedb65502019-06-14 11:52:17 -0700419 session_id_.c_str(),
Amin Hassani7fca2862019-03-28 16:09:22 -0700420 constants::kOmahaUpdaterID,
421 kOmahaUpdaterVersion,
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700422 params_->interactive() ? "ondemandupdate" : "scheduler",
Amin Hassani7fca2862019-03-28 16:09:22 -0700423 os_xml.c_str(),
424 app_xml.c_str());
425
426 return request_xml;
427}
428
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700429string OmahaRequestBuilderXml::GetApps() const {
430 string app_xml = "";
431 OmahaAppData product_app = {
432 .id = params_->GetAppId(),
433 .version = params_->app_version(),
434 .product_components = params_->product_components(),
435 // Skips updatecheck for platform app in case of an install operation.
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800436 .skip_update = params_->is_install(),
Andrewe045aef2020-01-08 16:29:22 -0800437 .is_dlc = false,
438
439 .app_params = {.active_counting_type = OmahaRequestParams::kDayBased,
440 .send_ping = include_ping_}};
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700441 app_xml += GetApp(product_app);
Andrewe045aef2020-01-08 16:29:22 -0800442 for (const auto& it : params_->dlc_apps_params()) {
Amin Hassani2b68e6b2020-04-17 10:49:12 -0700443 OmahaAppData dlc_app_data = {
Andrewe045aef2020-01-08 16:29:22 -0800444 .id = it.first,
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800445 .version = params_->is_install() ? kNoVersion : params_->app_version(),
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800446 .skip_update = false,
Andrewe045aef2020-01-08 16:29:22 -0800447 .is_dlc = true,
448 .app_params = it.second};
Amin Hassani2b68e6b2020-04-17 10:49:12 -0700449 app_xml += GetApp(dlc_app_data);
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -0700450 }
451 return app_xml;
452}
453
Amin Hassani7fca2862019-03-28 16:09:22 -0700454} // namespace chromeos_update_engine