Add Installer.UpdatesAbandonedCount metric

This patch adds a new metric Installer.UpdatesAbandonedCount to track
the number of update attempts that didn't complete because a newer
update was detected during the download. This is implemented by
counting the number of different responses seen since the last
successful update.

Updates are typically only abandoned if a device is suspended or
powered off while an update is happening. This can happen either
because the device was not turned on for a very long time or because
it had little or no connectivity to Omaha and/or the servers serving
the payload.

This metric will help show how many users run into this problem.

BUG=chromium:248800
TEST=New units tests + Unit tests pass + Manually tested

Change-Id: I524a380a931c2fb30916d033b7e5b0c700f57103
Reviewed-on: https://gerrit.chromium.org/gerrit/59098
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: David Zeuthen <zeuthen@chromium.org>
Commit-Queue: David Zeuthen <zeuthen@chromium.org>
diff --git a/payload_state_unittest.cc b/payload_state_unittest.cc
index 77a8d02..13052ef 100644
--- a/payload_state_unittest.cc
+++ b/payload_state_unittest.cc
@@ -130,6 +130,7 @@
   EXPECT_EQ("", payload_state.GetCurrentUrl());
   EXPECT_EQ(0, payload_state.GetUrlFailureCount());
   EXPECT_EQ(0, payload_state.GetUrlSwitchCount());
+  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
 }
 
 TEST(PayloadStateTest, SetResponseWorksWithSingleUrl) {
@@ -177,6 +178,7 @@
   EXPECT_EQ("https://single.url.test", payload_state.GetCurrentUrl());
   EXPECT_EQ(0, payload_state.GetUrlFailureCount());
   EXPECT_EQ(0, payload_state.GetUrlSwitchCount());
+  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
 }
 
 TEST(PayloadStateTest, SetResponseWorksWithMultipleUrls) {
@@ -223,6 +225,7 @@
   EXPECT_EQ("http://multiple.url.test", payload_state.GetCurrentUrl());
   EXPECT_EQ(0, payload_state.GetUrlFailureCount());
   EXPECT_EQ(0, payload_state.GetUrlSwitchCount());
+  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
 }
 
 TEST(PayloadStateTest, CanAdvanceUrlIndexCorrectly) {
@@ -284,6 +287,7 @@
 
   // Set the first response.
   SetupPayloadStateWith2Urls("Hash5823", true, &payload_state, &response);
+  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
 
   // Advance the URL index to 1 by faking an error.
   ErrorCode error = kErrorCodeDownloadMetadataSignatureMismatch;
@@ -293,6 +297,7 @@
 
   // Now, slightly change the response and set it again.
   SetupPayloadStateWith2Urls("Hash8225", true, &payload_state, &response);
+  EXPECT_EQ(2, payload_state.GetNumResponsesSeen());
 
   // Make sure the url index was reset to 0 because of the new response.
   EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
@@ -354,6 +359,7 @@
   EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
 
   SetupPayloadStateWith2Urls("Hash5873", true, &payload_state, &response);
+  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
 
   // This should advance the URL index.
   payload_state.UpdateFailed(kErrorCodeDownloadMetadataSignatureMismatch);
@@ -424,6 +430,7 @@
 
   // Now, slightly change the response and set it again.
   SetupPayloadStateWith2Urls("Hash8532", true, &payload_state, &response);
+  EXPECT_EQ(2, payload_state.GetNumResponsesSeen());
 
   // Make sure the url index was reset to 0 because of the new response.
   EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
@@ -612,6 +619,7 @@
 
   EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
   SetupPayloadStateWith2Urls("Hash3286", true, &payload_state, &response);
+  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
 
   // Simulate a previous attempt with in order to set an initial non-zero value
   // for the total bytes downloaded for HTTP.
@@ -628,6 +636,7 @@
   // Change the response hash so as to simulate a new response which will
   // reset the current bytes downloaded, but not the total bytes downloaded.
   SetupPayloadStateWith2Urls("Hash9904", true, &payload_state, &response);
+  EXPECT_EQ(2, payload_state.GetNumResponsesSeen());
 
   // First, simulate successful download of a few bytes over HTTP.
   int first_chunk = 5000000;
@@ -717,6 +726,7 @@
                  kDownloadSourceHttpsServer));
   EXPECT_EQ(0,
             payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
+  EXPECT_EQ(0, payload_state.GetNumResponsesSeen());
 }
 
 TEST(PayloadStateTest, RestartingUpdateResetsMetrics) {