update_engine: Support DLC Cohorts
UE at the moment doesn't send the correct cohorts to Omaha for DLCs. In
fact, the platform cohorts that are persisted are used for all DLCs.
This is incorrect and this CL fixes it.
```
Example DLC Response:
... cohort="1:7:" cohortname="eve_dlc_pita_canary"...
localhost ~ # ls /var/lib/update_engine/prefs/dlc/pita/omaha-cohort*
/var/lib/update_engine/prefs/dlc/pita/omaha-cohort
/var/lib/update_engine/prefs/dlc/pita/omaha-cohort-name
localhost ~ # cat /var/lib/update_engine/prefs/dlc/pita/omaha-cohort
1:7:
localhost ~ # cat
/var/lib/update_engine/prefs/dlc/pita/omaha-cohort-name
eve_dlc_pita_canary
```
BUG=b:162463872
TEST=FEATURES=test emerge-$B update_engine
TEST=# cros deploy + comment above
Change-Id: Ie503f0a63d3b19a51abb88379cb2e8f85919858b
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/2515072
Tested-by: Jae Hoon Kim <kimjae@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
Commit-Queue: Jae Hoon Kim <kimjae@chromium.org>
diff --git a/cros/omaha_request_action.cc b/cros/omaha_request_action.cc
index 0916f9d..51c0ac9 100644
--- a/cros/omaha_request_action.cc
+++ b/cros/omaha_request_action.cc
@@ -763,17 +763,7 @@
}
// We persist the cohorts sent by omaha even if the status is "noupdate".
- for (const auto& app : parser_data->apps) {
- if (app.id == params_->GetAppId()) {
- if (app.cohort)
- PersistCohortData(kPrefsOmahaCohort, app.cohort.value());
- if (app.cohorthint)
- PersistCohortData(kPrefsOmahaCohortHint, app.cohorthint.value());
- if (app.cohortname)
- PersistCohortData(kPrefsOmahaCohortName, app.cohortname.value());
- break;
- }
- }
+ PersistCohorts(*parser_data);
PersistEolInfo(parser_data->updatecheck_attrs);
@@ -1398,16 +1388,53 @@
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);
+void OmahaRequestAction::PersistCohortData(const string& prefs_key,
+ const Optional<string>& new_value) {
+ if (!new_value)
+ return;
+ const string& value = new_value.value();
+ if (value.empty() && system_state_->prefs()->Exists(prefs_key)) {
+ if (!system_state_->prefs()->Delete(prefs_key))
+ LOG(ERROR) << "Failed to remove stored " << prefs_key << "value.";
+ else
+ LOG(INFO) << "Removed stored " << prefs_key << " value.";
+ } else if (!value.empty()) {
+ if (!system_state_->prefs()->SetString(prefs_key, value))
+ LOG(INFO) << "Failed to store new setting " << prefs_key << " as "
+ << value;
+ else
+ LOG(INFO) << "Stored cohort setting " << prefs_key << " as " << value;
}
- return true;
+}
+
+void OmahaRequestAction::PersistCohorts(const OmahaParserData& parser_data) {
+ for (const auto& app : parser_data.apps) {
+ // For platform App ID.
+ if (app.id == params_->GetAppId()) {
+ PersistCohortData(kPrefsOmahaCohort, app.cohort);
+ PersistCohortData(kPrefsOmahaCohortName, app.cohortname);
+ PersistCohortData(kPrefsOmahaCohortHint, app.cohorthint);
+ } else if (params_->IsDlcAppId(app.id)) {
+ string dlc_id;
+ if (!params_->GetDlcId(app.id, &dlc_id)) {
+ LOG(WARNING) << "Skip persisting cohorts for DLC App ID=" << app.id
+ << " as it is not in the request params.";
+ continue;
+ }
+ PrefsInterface* prefs = system_state_->prefs();
+ PersistCohortData(
+ prefs->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohort}),
+ app.cohort);
+ PersistCohortData(
+ prefs->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohortName}),
+ app.cohortname);
+ PersistCohortData(
+ prefs->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohortHint}),
+ app.cohorthint);
+ } else {
+ LOG(WARNING) << "Skip persisting cohorts for unknown App ID=" << app.id;
+ }
+ }
}
bool OmahaRequestAction::PersistEolInfo(const map<string, string>& attrs) {
diff --git a/cros/omaha_request_action.h b/cros/omaha_request_action.h
index 1a3a912..9576a05 100644
--- a/cros/omaha_request_action.h
+++ b/cros/omaha_request_action.h
@@ -28,6 +28,7 @@
#include <gtest/gtest_prod.h> // for FRIEND_TEST
+#include <base/optional.h>
#include <brillo/secure_blob.h>
#include <curl/curl.h>
@@ -176,12 +177,17 @@
int install_date_days,
InstallDateProvisioningSource source);
- // Persist the new cohort* value received in the XML file in the |prefs_key|
- // preference file. If the |new_value| is empty, the currently stored value
- // will be deleted. Don't call this function with an empty |new_value| if the
- // value was not set in the XML, since that would delete the stored value.
- bool PersistCohortData(const std::string& prefs_key,
- const std::string& new_value);
+ // Persist the new cohort value received in the XML file in the |prefs_key|
+ // preference file. If the |new_value| is empty, do nothing. If the
+ // |new_value| stores and empty value, the currently stored value will be
+ // deleted. Don't call this function with an empty |new_value| if the value
+ // was not set in the XML, since that would delete the stored value.
+ void PersistCohortData(const std::string& prefs_key,
+ const base::Optional<std::string>& new_value);
+
+ // Parses and persists the cohorts sent back in the updatecheck tag
+ // attributes.
+ void PersistCohorts(const OmahaParserData& parser_data);
// Parses and persists the end-of-life date flag sent back in the updatecheck
// tag attributes. The flags will be validated and stored in the Prefs.
diff --git a/cros/omaha_request_action_unittest.cc b/cros/omaha_request_action_unittest.cc
index c3842b8..8d94195 100644
--- a/cros/omaha_request_action_unittest.cc
+++ b/cros/omaha_request_action_unittest.cc
@@ -204,7 +204,13 @@
: "") +
(dlc_app_update
? "<app appid=\"" + request_params.GetDlcAppId(kDlcId1) +
- "\" status=\"ok\">"
+ "\" " +
+ (include_dlc_cohorts
+ ? "cohort=\"" + dlc_cohort + "\" cohorthint=\"" +
+ dlc_cohorthint + "\" cohortname=\"" +
+ dlc_cohortname + "\" "
+ : "") +
+ "status=\"ok\">"
"<updatecheck status=\"ok\"><urls><url codebase=\"" +
codebase + "\"/><url codebase=\"" + codebase2 +
"\"/></urls><manifest version=\"" + version +
@@ -216,7 +222,13 @@
: "") +
(dlc_app_no_update
? "<app appid=\"" + request_params.GetDlcAppId(kDlcId2) +
- "\"><updatecheck status=\"noupdate\"/></app>"
+ +"\" " +
+ (include_dlc_cohorts
+ ? "cohort=\"" + dlc_cohort + "\" cohorthint=\"" +
+ dlc_cohorthint + "\" cohortname=\"" +
+ dlc_cohortname + "\" "
+ : "") +
+ "><updatecheck status=\"noupdate\"/></app>"
: "") +
"</response>";
}
@@ -252,6 +264,11 @@
string cohort = "";
string cohorthint = "";
string cohortname = "";
+ // Whether to include Omaha cohorts for DLC apps.
+ bool include_dlc_cohorts = false;
+ string dlc_cohort = "";
+ string dlc_cohorthint = "";
+ string dlc_cohortname = "";
// Whether to include the CrOS <!ENTITY> in the XML response.
bool include_entity = false;
@@ -1240,8 +1257,16 @@
fake_update_response_.cohort = "s/154454/8479665";
fake_update_response_.cohorthint = "please-put-me-on-beta";
fake_update_response_.cohortname = "stable";
+ request_params_.set_dlc_apps_params(
+ {{request_params_.GetDlcAppId(kDlcId1), {.name = kDlcId1}}});
+ fake_update_response_.dlc_app_update = true;
+ fake_update_response_.include_dlc_cohorts = true;
+ fake_update_response_.dlc_cohort = "s/154454/8479665/dlc";
+ fake_update_response_.dlc_cohorthint = "please-put-me-on-beta-dlc";
+ fake_update_response_.dlc_cohortname = "stable-dlc";
tuc_params_.http_response = fake_update_response_.GetUpdateResponse();
+ EXPECT_CALL(mock_excluder_, IsExcluded(_)).WillRepeatedly(Return(false));
ASSERT_TRUE(TestUpdateCheck());
string value;
@@ -1253,18 +1278,52 @@
EXPECT_TRUE(fake_prefs_.GetString(kPrefsOmahaCohortName, &value));
EXPECT_EQ(fake_update_response_.cohortname, value);
+
+ EXPECT_TRUE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey({kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohort}),
+ &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohort, value);
+
+ EXPECT_TRUE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohortHint}),
+ &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohorthint, value);
+
+ EXPECT_TRUE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohortName}),
+ &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohortname, value);
}
TEST_F(OmahaRequestActionTest, CohortsAreUpdated) {
EXPECT_TRUE(fake_prefs_.SetString(kPrefsOmahaCohort, "old_value"));
EXPECT_TRUE(fake_prefs_.SetString(kPrefsOmahaCohortHint, "old_hint"));
EXPECT_TRUE(fake_prefs_.SetString(kPrefsOmahaCohortName, "old_name"));
+ const string dlc_cohort_key =
+ fake_prefs_.CreateSubKey({kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohort});
+ const string dlc_cohort_hint_key = fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohortHint});
+ const string dlc_cohort_name_key = fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohortName});
+ request_params_.set_dlc_apps_params(
+ {{request_params_.GetDlcAppId(kDlcId1), {.name = kDlcId1}}});
+ EXPECT_TRUE(fake_prefs_.SetString(dlc_cohort_key, "old_value_dlc"));
+ EXPECT_TRUE(fake_prefs_.SetString(dlc_cohort_hint_key, "old_hint_dlc"));
+ EXPECT_TRUE(fake_prefs_.SetString(dlc_cohort_name_key, "old_name_dlc"));
fake_update_response_.include_cohorts = true;
fake_update_response_.cohort = "s/154454/8479665";
fake_update_response_.cohorthint = "please-put-me-on-beta";
fake_update_response_.cohortname = "";
+ fake_update_response_.dlc_app_update = true;
+ fake_update_response_.include_dlc_cohorts = true;
+ fake_update_response_.dlc_cohort = "s/154454/8479665/dlc";
+ fake_update_response_.dlc_cohorthint = "please-put-me-on-beta-dlc";
+ fake_update_response_.dlc_cohortname = "";
tuc_params_.http_response = fake_update_response_.GetUpdateResponse();
+ EXPECT_CALL(mock_excluder_, IsExcluded(_)).WillRepeatedly(Return(false));
ASSERT_TRUE(TestUpdateCheck());
string value;
@@ -1275,12 +1334,23 @@
EXPECT_EQ(fake_update_response_.cohorthint, value);
EXPECT_FALSE(fake_prefs_.GetString(kPrefsOmahaCohortName, &value));
+
+ EXPECT_TRUE(fake_prefs_.GetString(dlc_cohort_key, &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohort, value);
+
+ EXPECT_TRUE(fake_prefs_.GetString(dlc_cohort_hint_key, &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohorthint, value);
+
+ EXPECT_FALSE(fake_prefs_.GetString(dlc_cohort_name_key, &value));
}
TEST_F(OmahaRequestActionTest, CohortsAreNotModifiedWhenMissing) {
tuc_params_.http_response = fake_update_response_.GetUpdateResponse();
EXPECT_TRUE(fake_prefs_.SetString(kPrefsOmahaCohort, "old_value"));
+ const string dlc_cohort_key =
+ fake_prefs_.CreateSubKey({kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohort});
+ EXPECT_TRUE(fake_prefs_.SetString(dlc_cohort_key, "old_value_dlc"));
ASSERT_TRUE(TestUpdateCheck());
string value;
@@ -1289,6 +1359,18 @@
EXPECT_FALSE(fake_prefs_.GetString(kPrefsOmahaCohortHint, &value));
EXPECT_FALSE(fake_prefs_.GetString(kPrefsOmahaCohortName, &value));
+
+ EXPECT_TRUE(fake_prefs_.GetString(dlc_cohort_key, &value));
+ EXPECT_EQ("old_value_dlc", value);
+
+ EXPECT_FALSE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohortHint}),
+ &value));
+ EXPECT_FALSE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohortName}),
+ &value));
}
TEST_F(OmahaRequestActionTest, CohortsArePersistedWhenNoUpdate) {
@@ -1319,8 +1401,18 @@
fake_update_response_.cohort = "s/154454/8479665";
fake_update_response_.cohorthint = "please-put-me-on-beta";
fake_update_response_.cohortname = "stable";
+ request_params_.set_dlc_apps_params(
+ {{request_params_.GetDlcAppId(kDlcId1), {.name = kDlcId1}},
+ {request_params_.GetDlcAppId(kDlcId2), {.name = kDlcId2}}});
+ fake_update_response_.dlc_app_update = true;
+ fake_update_response_.dlc_app_no_update = true;
+ fake_update_response_.include_dlc_cohorts = true;
+ fake_update_response_.dlc_cohort = "s/154454/8479665/dlc";
+ fake_update_response_.dlc_cohorthint = "please-put-me-on-beta-dlc";
+ fake_update_response_.dlc_cohortname = "stable-dlc";
tuc_params_.http_response = fake_update_response_.GetUpdateResponse();
+ EXPECT_CALL(mock_excluder_, IsExcluded(_)).WillRepeatedly(Return(false));
ASSERT_TRUE(TestUpdateCheck());
string value;
@@ -1332,6 +1424,37 @@
EXPECT_TRUE(fake_prefs_.GetString(kPrefsOmahaCohortName, &value));
EXPECT_EQ(fake_update_response_.cohortname, value);
+
+ EXPECT_TRUE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey({kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohort}),
+ &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohort, value);
+ EXPECT_TRUE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey({kDlcPrefsSubDir, kDlcId2, kPrefsOmahaCohort}),
+ &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohort, value);
+
+ EXPECT_TRUE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohortHint}),
+ &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohorthint, value);
+ EXPECT_TRUE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId2, kPrefsOmahaCohortHint}),
+ &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohorthint, value);
+
+ EXPECT_TRUE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId1, kPrefsOmahaCohortName}),
+ &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohortname, value);
+ EXPECT_TRUE(fake_prefs_.GetString(
+ fake_prefs_.CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId2, kPrefsOmahaCohortName}),
+ &value));
+ EXPECT_EQ(fake_update_response_.dlc_cohortname, value);
}
TEST_F(OmahaRequestActionTest, NoOutputPipeTest) {
diff --git a/cros/omaha_request_builder_xml.cc b/cros/omaha_request_builder_xml.cc
index 43ee548..739abbf 100644
--- a/cros/omaha_request_builder_xml.cc
+++ b/cros/omaha_request_builder_xml.cc
@@ -215,9 +215,10 @@
return app_body;
}
-string OmahaRequestBuilderXml::GetCohortArg(const string arg_name,
- const string prefs_key,
- const string override_value) const {
+string OmahaRequestBuilderXml::GetCohortArg(
+ const string& arg_name,
+ const string& prefs_key,
+ const string& override_value) const {
string cohort_value;
if (!override_value.empty()) {
// |override_value| take precedence over pref value.
@@ -296,14 +297,30 @@
}
string app_cohort_args;
- app_cohort_args += GetCohortArg("cohort", kPrefsOmahaCohort);
- app_cohort_args += GetCohortArg("cohortname", kPrefsOmahaCohortName);
+ string cohort_key = kPrefsOmahaCohort;
+ string cohortname_key = kPrefsOmahaCohortName;
+ string cohorthint_key = kPrefsOmahaCohortHint;
+ // Override the cohort keys for DLC App IDs.
+ const auto& dlc_apps_params = params_->dlc_apps_params();
+ auto itr = dlc_apps_params.find(app_data.id);
+ if (itr != dlc_apps_params.end()) {
+ auto dlc_id = itr->second.name;
+ cohort_key =
+ prefs_->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohort});
+ cohortname_key =
+ prefs_->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohortName});
+ cohorthint_key =
+ prefs_->CreateSubKey({kDlcPrefsSubDir, dlc_id, kPrefsOmahaCohortHint});
+ }
+
+ app_cohort_args += GetCohortArg("cohort", cohort_key);
+ app_cohort_args += GetCohortArg("cohortname", cohortname_key);
// Policy provided value overrides pref.
- string autoupdate_token = params_->autoupdate_token();
- app_cohort_args += GetCohortArg("cohorthint",
- kPrefsOmahaCohortHint,
- autoupdate_token /* override_value */);
+ app_cohort_args +=
+ GetCohortArg("cohorthint",
+ cohorthint_key,
+ params_->autoupdate_token() /* override_value */);
string fingerprint_arg;
if (!params_->os_build_fingerprint().empty()) {
diff --git a/cros/omaha_request_builder_xml.h b/cros/omaha_request_builder_xml.h
index 4f860dd..0aca7f3 100644
--- a/cros/omaha_request_builder_xml.h
+++ b/cros/omaha_request_builder_xml.h
@@ -168,9 +168,9 @@
// 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.
- std::string GetCohortArg(const std::string arg_name,
- const std::string prefs_key,
- const std::string override_value = "") const;
+ std::string GetCohortArg(const std::string& arg_name,
+ const std::string& prefs_key,
+ const std::string& override_value = "") const;
// Returns an XML ping element if any of the elapsed days need to be
// sent, or an empty string otherwise.
diff --git a/cros/omaha_request_builder_xml_unittest.cc b/cros/omaha_request_builder_xml_unittest.cc
index 055d0f3..c04c994 100644
--- a/cros/omaha_request_builder_xml_unittest.cc
+++ b/cros/omaha_request_builder_xml_unittest.cc
@@ -21,13 +21,19 @@
#include <vector>
#include <base/guid.h>
+#include <base/strings/stringprintf.h>
#include <gtest/gtest.h>
+#include "update_engine/common/fake_prefs.h"
#include "update_engine/cros/fake_system_state.h"
using std::pair;
using std::string;
using std::vector;
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgPointee;
namespace chromeos_update_engine {
@@ -398,4 +404,74 @@
"<event eventtype=\"3\" eventresult=\"0\" errorcode=\"62\"></event>"))
<< request_xml;
}
+
+TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlDlcCohortMissingCheck) {
+ OmahaRequestParams omaha_request_params{&fake_system_state_};
+ constexpr char kDlcId[] = "test-dlc-id";
+ omaha_request_params.set_dlc_apps_params(
+ {{omaha_request_params.GetDlcAppId(kDlcId), {.name = kDlcId}}});
+ auto* mock_prefs = fake_system_state_.mock_prefs();
+ OmahaEvent event(OmahaEvent::kTypeUpdateDownloadStarted);
+ OmahaRequestBuilderXml omaha_request{
+ &event, &omaha_request_params, false, false, 0, 0, 0, mock_prefs, ""};
+ // OS App ID Expectations.
+ EXPECT_CALL(*mock_prefs, Exists(kPrefsOmahaCohort));
+ EXPECT_CALL(*mock_prefs, Exists(kPrefsOmahaCohortName));
+ EXPECT_CALL(*mock_prefs, Exists(kPrefsOmahaCohortHint));
+ // DLC App ID Expectations.
+ EXPECT_CALL(*mock_prefs,
+ Exists(PrefsInterface::CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId, kPrefsOmahaCohort})));
+ EXPECT_CALL(*mock_prefs,
+ Exists(PrefsInterface::CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId, kPrefsOmahaCohortName})));
+ EXPECT_CALL(*mock_prefs,
+ Exists(PrefsInterface::CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId, kPrefsOmahaCohortHint})));
+ const string request_xml = omaha_request.GetRequest();
+
+ // Check that no cohorts are in the request.
+ EXPECT_EQ(0, CountSubstringInString(request_xml, "cohort=")) << request_xml;
+ EXPECT_EQ(0, CountSubstringInString(request_xml, "cohortname="))
+ << request_xml;
+ EXPECT_EQ(0, CountSubstringInString(request_xml, "cohorthint="))
+ << request_xml;
+}
+
+TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlDlcCohortCheck) {
+ OmahaRequestParams omaha_request_params{&fake_system_state_};
+ const string kDlcId = "test-dlc-id";
+ omaha_request_params.set_dlc_apps_params(
+ {{omaha_request_params.GetDlcAppId(kDlcId), {.name = kDlcId}}});
+ FakePrefs fake_prefs;
+ fake_system_state_.set_prefs(&fake_prefs);
+ OmahaEvent event(OmahaEvent::kTypeUpdateDownloadStarted);
+ OmahaRequestBuilderXml omaha_request{
+ &event, &omaha_request_params, false, false, 0, 0, 0, &fake_prefs, ""};
+ // DLC App ID Expectations.
+ const string dlc_cohort_key = PrefsInterface::CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId, kPrefsOmahaCohort});
+ const string kDlcCohortVal = "test-cohort";
+ EXPECT_TRUE(fake_prefs.SetString(dlc_cohort_key, kDlcCohortVal));
+ const string dlc_cohort_name_key = PrefsInterface::CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId, kPrefsOmahaCohortName});
+ const string kDlcCohortNameVal = "test-cohortname";
+ EXPECT_TRUE(fake_prefs.SetString(dlc_cohort_name_key, kDlcCohortNameVal));
+ const string dlc_cohort_hint_key = PrefsInterface::CreateSubKey(
+ {kDlcPrefsSubDir, kDlcId, kPrefsOmahaCohortHint});
+ const string kDlcCohortHintVal = "test-cohortval";
+ EXPECT_TRUE(fake_prefs.SetString(dlc_cohort_hint_key, kDlcCohortHintVal));
+ const string request_xml = omaha_request.GetRequest();
+
+ EXPECT_EQ(1,
+ CountSubstringInString(
+ request_xml,
+ base::StringPrintf(
+ "cohort=\"%s\" cohortname=\"%s\" cohorthint=\"%s\"",
+ kDlcCohortVal.c_str(),
+ kDlcCohortNameVal.c_str(),
+ kDlcCohortHintVal.c_str())))
+ << request_xml;
+}
+
} // namespace chromeos_update_engine
diff --git a/cros/omaha_request_params.cc b/cros/omaha_request_params.cc
index c814e00..e7e719b 100644
--- a/cros/omaha_request_params.cc
+++ b/cros/omaha_request_params.cc
@@ -274,6 +274,14 @@
return dlc_apps_params().find(app_id) != dlc_apps_params().end();
}
+bool OmahaRequestParams::GetDlcId(const string& app_id, string* dlc_id) const {
+ auto itr = dlc_apps_params_.find(app_id);
+ if (itr == dlc_apps_params_.end())
+ return false;
+ *dlc_id = itr->second.name;
+ return true;
+}
+
void OmahaRequestParams::SetDlcNoUpdate(const string& app_id) {
auto itr = dlc_apps_params_.find(app_id);
if (itr == dlc_apps_params_.end())
diff --git a/cros/omaha_request_params.h b/cros/omaha_request_params.h
index 26ea1c9..fa452ce 100644
--- a/cros/omaha_request_params.h
+++ b/cros/omaha_request_params.h
@@ -228,6 +228,10 @@
// request parameters.
virtual bool IsDlcAppId(const std::string& app_id) const;
+ // Returns the DLC App ID if the given App ID is a DLC that is currently part
+ // of the request parameters.
+ virtual bool GetDlcId(const std::string& app_id, std::string* dlc_id) const;
+
// If the App ID is a DLC App ID will set to no update.
void SetDlcNoUpdate(const std::string& app_id);
diff --git a/cros/omaha_request_params_unittest.cc b/cros/omaha_request_params_unittest.cc
index 71f3d4c..ff52fc2 100644
--- a/cros/omaha_request_params_unittest.cc
+++ b/cros/omaha_request_params_unittest.cc
@@ -261,4 +261,33 @@
EXPECT_TRUE(params_.Init("", "", {}));
EXPECT_EQ("fake_requisition", params_.device_requisition());
}
+
+TEST_F(OmahaRequestParamsTest, GetMissingDlcId) {
+ EXPECT_TRUE(params_.Init("", "", {}));
+
+ string dlc_id;
+ EXPECT_FALSE(params_.GetDlcId("some-dlc-app-id", &dlc_id));
+}
+
+TEST_F(OmahaRequestParamsTest, GetDlcId) {
+ EXPECT_TRUE(params_.Init("", "", {}));
+ const string kExpectedDlcId = "test-dlc";
+ const string dlc_app_id = params_.GetDlcAppId(kExpectedDlcId);
+ params_.set_dlc_apps_params({{dlc_app_id, {.name = kExpectedDlcId}}});
+
+ string dlc_id;
+ EXPECT_TRUE(params_.GetDlcId(dlc_app_id, &dlc_id));
+ EXPECT_EQ(kExpectedDlcId, dlc_id);
+}
+
+TEST_F(OmahaRequestParamsTest, GetDlcAppId) {
+ EXPECT_TRUE(params_.Init("", "", {}));
+ const string kAppId = "test-app-id";
+ params_.set_app_id(kAppId);
+ const string kDlcId = "test-dlc";
+ const string expected_dlc_app_id = kAppId + "_" + kDlcId;
+
+ EXPECT_EQ(expected_dlc_app_id, params_.GetDlcAppId(kDlcId));
+}
+
} // namespace chromeos_update_engine