update_engine: Include quick_fix_build_token in updatecheck request body

Get the value of the new device policy which is included in
AutoUpdateSettings as quick_fix_build_token, and include it
in the update request body if value is set.

BUG=chromium:932465
TEST=./build_packages --board=amd64-generic && \
     cros_run_unit_tests --board=amd64-generic --packages update_engine
Cq-Depend: chromium:1571634

Change-Id: Iaca35a08d973616a058864a11896ef9305d00174
Reviewed-on: https://chromium-review.googlesource.com/1581519
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Askar Aitzhan <askaraitzhan@google.com>
Reviewed-by: Nicolas Norvez <norvez@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index ec08333..bfbf6a4 100644
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -1463,6 +1463,7 @@
   request_params_.set_current_channel("unittest_track&lt;");
   request_params_.set_target_channel("unittest_track&lt;");
   request_params_.set_hwid("<OEM MODEL>");
+  request_params_.set_autoupdate_token("autoupdate_token>");
   fake_prefs_.SetString(kPrefsOmahaCohort, "evil\nstring");
   fake_prefs_.SetString(kPrefsOmahaCohortHint, "evil&string\\");
   fake_prefs_.SetString(
@@ -1489,6 +1490,8 @@
   // Values from Prefs that are too big are removed from the XML instead of
   // encoded.
   EXPECT_EQ(string::npos, post_str.find("cohortname="));
+  EXPECT_NE(string::npos, post_str.find("autoupdate_token&gt;"));
+  EXPECT_EQ(string::npos, post_str.find("autoupdate_token>"));
 }
 
 TEST_F(OmahaRequestActionTest, XmlDecodeTest) {
@@ -1692,6 +1695,21 @@
   EXPECT_EQ(ErrorCode::kError, error_event.error_code);
 }
 
+TEST_F(OmahaRequestActionTest, DeviceQuickFixBuildTokenIsSetTest) {
+  constexpr char autoupdate_token[] = "autoupdate_token";
+
+  tuc_params_.http_response = fake_update_response_.GetNoUpdateResponse();
+  tuc_params_.expected_check_result = metrics::CheckResult::kNoUpdateAvailable;
+  tuc_params_.expected_check_reaction = metrics::CheckReaction::kUnset;
+  request_params_.set_autoupdate_token(autoupdate_token);
+
+  ASSERT_TRUE(TestUpdateCheck());
+
+  EXPECT_NE(post_str.find("        <updatecheck token=\"" +
+                          string(autoupdate_token) + "\"></updatecheck>\n"),
+            string::npos);
+}
+
 void OmahaRequestActionTest::PingTest(bool ping_only) {
   NiceMock<MockPrefs> prefs;
   fake_system_state_.set_prefs(&prefs);
diff --git a/omaha_request_builder_xml.cc b/omaha_request_builder_xml.cc
index 899f17f..aac0136 100644
--- a/omaha_request_builder_xml.cc
+++ b/omaha_request_builder_xml.cc
@@ -122,6 +122,13 @@
             app_body += " rollback_allowed=\"true\"";
           }
         }
+        string autoupdate_token = params->autoupdate_token();
+        if (!autoupdate_token.empty()) {
+          app_body += base::StringPrintf(
+              " token=\"%s\"",
+              XmlEncodeWithDefault(autoupdate_token, "").c_str());
+        }
+
         app_body += "></updatecheck>\n";
       }
 
diff --git a/omaha_request_params.h b/omaha_request_params.h
index 2d2ab69..f3f68f4 100644
--- a/omaha_request_params.h
+++ b/omaha_request_params.h
@@ -193,6 +193,13 @@
   inline void set_is_install(bool is_install) { is_install_ = is_install; }
   inline bool is_install() const { return is_install_; }
 
+  inline void set_autoupdate_token(const std::string& token) {
+    autoupdate_token_ = token;
+  }
+  inline const std::string& autoupdate_token() const {
+    return autoupdate_token_;
+  }
+
   // Returns the app id corresponding to the current value of the
   // download channel.
   virtual std::string GetAppId() const;
@@ -371,6 +378,11 @@
   // current active partition instead of the inactive partition.
   bool is_install_;
 
+  // Token used when making an update request for a specific build.
+  // For example: Token for a Quick Fix Build:
+  // https://www.chromium.org/administrators/policy-list-3#DeviceQuickFixBuildToken.
+  std::string autoupdate_token_;
+
   DISALLOW_COPY_AND_ASSIGN(OmahaRequestParams);
 };
 
diff --git a/update_attempter.cc b/update_attempter.cc
index 44eea77..4bbf5a1 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -427,6 +427,14 @@
   omaha_request_params_->set_dlc_module_ids(dlc_module_ids_);
   omaha_request_params_->set_is_install(is_install_);
 
+  // Set Quick Fix Build token if policy is set.
+  string token;
+  if (system_state_ && system_state_->device_policy()) {
+    if (!system_state_->device_policy()->GetDeviceQuickFixBuildToken(&token))
+      token.clear();
+  }
+  omaha_request_params_->set_autoupdate_token(token);
+
   LOG(INFO) << "target_version_prefix = "
             << omaha_request_params_->target_version_prefix()
             << ", rollback_allowed = "
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index 14fad38..16819f8 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -188,6 +188,7 @@
   void P2PEnabledInteractiveStart();
   void P2PEnabledStartingFailsStart();
   void P2PEnabledHousekeepingFailsStart();
+  void UpdateToQuickFixBuildStart();
   void ResetRollbackHappenedStart(bool is_consumer,
                                   bool is_policy_available,
                                   bool expected_reset);
@@ -461,23 +462,23 @@
 
 namespace {
 // Actions that will be built as part of an update check.
-const string kUpdateActionTypes[] = {  // NOLINT(runtime/string)
-    OmahaRequestAction::StaticType(),
-    OmahaResponseHandlerAction::StaticType(),
-    UpdateBootFlagsAction::StaticType(),
-    OmahaRequestAction::StaticType(),
-    DownloadAction::StaticType(),
-    OmahaRequestAction::StaticType(),
-    FilesystemVerifierAction::StaticType(),
-    PostinstallRunnerAction::StaticType(),
-    OmahaRequestAction::StaticType()};
+vector<string> GetUpdateActionTypes() {
+  return {OmahaRequestAction::StaticType(),
+          OmahaResponseHandlerAction::StaticType(),
+          UpdateBootFlagsAction::StaticType(),
+          OmahaRequestAction::StaticType(),
+          DownloadAction::StaticType(),
+          OmahaRequestAction::StaticType(),
+          FilesystemVerifierAction::StaticType(),
+          PostinstallRunnerAction::StaticType(),
+          OmahaRequestAction::StaticType()};
+}
 
 // Actions that will be built as part of a user-initiated rollback.
-const string kRollbackActionTypes[] = {
-    // NOLINT(runtime/string)
-    InstallPlanAction::StaticType(),
-    PostinstallRunnerAction::StaticType(),
-};
+vector<string> GetRollbackActionTypes() {
+  return {InstallPlanAction::StaticType(),
+          PostinstallRunnerAction::StaticType()};
+}
 
 const StagingSchedule kValidStagingSchedule = {
     {4, 10}, {10, 40}, {19, 70}, {26, 100}};
@@ -498,10 +499,10 @@
 
   {
     InSequence s;
-    for (size_t i = 0; i < arraysize(kUpdateActionTypes); ++i) {
+    for (const auto& update_action_type : GetUpdateActionTypes()) {
       EXPECT_CALL(*processor_,
                   EnqueueAction(Pointee(
-                      Property(&AbstractAction::Type, kUpdateActionTypes[i]))));
+                      Property(&AbstractAction::Type, update_action_type))));
     }
     EXPECT_CALL(*processor_, StartProcessing());
   }
@@ -557,10 +558,10 @@
 
   if (is_rollback_allowed) {
     InSequence s;
-    for (size_t i = 0; i < arraysize(kRollbackActionTypes); ++i) {
+    for (const auto& rollback_action_type : GetRollbackActionTypes()) {
       EXPECT_CALL(*processor_,
-                  EnqueueAction(Pointee(Property(&AbstractAction::Type,
-                                                 kRollbackActionTypes[i]))));
+                  EnqueueAction(Pointee(
+                      Property(&AbstractAction::Type, rollback_action_type))));
     }
     EXPECT_CALL(*processor_, StartProcessing());
 
@@ -1582,4 +1583,29 @@
   attempter_.ProcessingDone(nullptr, ErrorCode::kSuccess);
 }
 
+void UpdateAttempterTest::UpdateToQuickFixBuildStart() {
+  // Tests that checks if device_quick_fix_build_token arrives when
+  // policy is set.
+  const char kToken[] = "some_token";
+
+  auto device_policy = std::make_unique<policy::MockDevicePolicy>();
+  fake_system_state_.set_device_policy(device_policy.get());
+
+  EXPECT_CALL(*device_policy, LoadPolicy()).WillRepeatedly(Return(true));
+  EXPECT_CALL(*device_policy, GetDeviceQuickFixBuildToken(_))
+      .WillOnce(DoAll(SetArgPointee<0>(string(kToken)), Return(true)));
+  attempter_.policy_provider_.reset(
+      new policy::PolicyProvider(std::move(device_policy)));
+  attempter_.Update("", "", "", "", false, false, 0, false, false);
+
+  ScheduleQuitMainLoop();
+}
+
+TEST_F(UpdateAttempterTest, UpdateToQuickFixBuildStart) {
+  loop_.PostTask(FROM_HERE,
+                 base::Bind(&UpdateAttempterTest::UpdateToQuickFixBuildStart,
+                            base::Unretained(this)));
+  loop_.Run();
+}
+
 }  // namespace chromeos_update_engine