update_engine: Add internal error codes that used for metrics.

Whenever we are dealing with some problem that require defining error
codes and sending UMA metrics, we need to define a new ErrorCode enum
value. These error codes then will be used to send which UMA metric
value to send. Some of the UMA metrics seems to have circumvent this
process by introducing their own error codes without adding them to the
global list of error codes.

This CL introduces three new error codes:
 - kInternalLibCurlError
 - kUnresolvedHostError
 - kUnresolvedHostRecovered (Technically not an error code, but fits the
   description and use case of it.)

That are then translated to the UMA metric values we send for
DownloadErrorCode.

In addition, this CL moves the responsibility of sending these UMA
metrics from LibCurlHttpFetcher to OmahaRequestAction which is the more
correct place to send it because that's where the operations are
completed (success or failure) and we can safely decide on the value of
UMA without risking to send overlapping or duplicated metrics.

For example, previously we send kInternalLibCurlError in conjunction
with the kUnresolvedHostError. But doing this can hide the fact that
these two error codes might be related and caused by the same underlying
issue.

Same goes for kUnresolvedHostError and kUnresolvedHosRecovered. If we
send both these metrics at the same time, then we need to subtract the
number of kUnresolvedHosRecovered from kUnresolvedHostError to figure out
the number of unresolved host errors that did not recover. By
exclusively sending one or another. We can see exactly how many are
recovered and how many did not. Although this might change the meaning
of kUnresolvedHostError metric, in the long term it will not be an issue
as all the results will converge to the new behavior.

The enum.xml (chrome) is updated in crrev.com/c/1774101

BUG=None
TEST=cros_workon_make --board=amd64-generic --test --noreconf update_engine

Change-Id: I3c7bb5f6159a0bc3a37d55666572b9cd6730f3cb
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/1759544
Reviewed-by: Nicolas Norvez <[email protected]>
Tested-by: Amin Hassani <[email protected]>
Commit-Queue: Amin Hassani <[email protected]>
diff --git a/common/error_code.h b/common/error_code.h
index 252cc42..3dd7402 100644
--- a/common/error_code.h
+++ b/common/error_code.h
@@ -80,6 +80,9 @@
   kRollbackNotPossible = 54,
   kFirstActiveOmahaPingSentPersistenceError = 55,
   kVerityCalculationError = 56,
+  kInternalLibCurlError = 57,
+  kUnresolvedHostError = 58,
+  kUnresolvedHostRecovered = 59,
 
   // VERY IMPORTANT! When adding new error codes:
   //
diff --git a/common/error_code_utils.cc b/common/error_code_utils.cc
index b0bbbd4..5bcbaa4 100644
--- a/common/error_code_utils.cc
+++ b/common/error_code_utils.cc
@@ -161,6 +161,12 @@
       return "ErrorCode::kFirstActiveOmahaPingSentPersistenceError";
     case ErrorCode::kVerityCalculationError:
       return "ErrorCode::kVerityCalculationError";
+    case ErrorCode::kInternalLibCurlError:
+      return "ErrorCode::kInternalLibCurlError";
+    case ErrorCode::kUnresolvedHostError:
+      return "ErrorCode::kUnresolvedHostError";
+    case ErrorCode::kUnresolvedHostRecovered:
+      return "ErrorCode::kUnresolvedHostRecovered";
       // Don't add a default case to let the compiler warn about newly added
       // error codes which should be added here.
   }
diff --git a/common/http_fetcher.h b/common/http_fetcher.h
index 94f31d7..f74a0f0 100644
--- a/common/http_fetcher.h
+++ b/common/http_fetcher.h
@@ -59,6 +59,12 @@
   HttpFetcherDelegate* delegate() const { return delegate_; }
   int http_response_code() const { return http_response_code_; }
 
+  // Returns additional error code that can't be expressed in terms of an HTTP
+  // response code. For example, if there was a specific internal error code in
+  // the objects used in the implementation of this class (like libcurl) that we
+  // are interested about, we can communicate it through this value.
+  ErrorCode GetAuxiliaryErrorCode() const { return auxiliary_error_code_; }
+
   // Optional: Post data to the server. The HttpFetcher should make a copy
   // of this data and upload it via HTTP POST during the transfer. The type of
   // the data is necessary for properly setting the Content-Type HTTP header.
@@ -159,6 +165,10 @@
   // set to the response code when the transfer is complete.
   int http_response_code_;
 
+  // Set when there is an error that can't be expressed in the form of
+  // |http_response_code_|.
+  ErrorCode auxiliary_error_code_{ErrorCode::kSuccess};
+
   // The delegate; may be null.
   HttpFetcherDelegate* delegate_;
 
@@ -209,13 +219,6 @@
   // situations. It's OK to destroy the |fetcher| object in this callback.
   virtual void TransferComplete(HttpFetcher* fetcher, bool successful) = 0;
   virtual void TransferTerminated(HttpFetcher* fetcher) {}
-
-  // This allows |HttpFetcher| to send UMA metrics for its internal states
-  // (unrecoverable libcurl internal error, etc.).
-  virtual void ReportUpdateCheckMetrics(
-      metrics::CheckResult result,
-      metrics::CheckReaction reaction,
-      metrics::DownloadErrorCode download_error_code) {}
 };
 
 }  // namespace chromeos_update_engine