Classify errors and advance URL index according to the error code.

In CL https://gerrit.chromium.org/gerrit/39638, we always incremented
the URL index irrespective of the error code. That would cause the first
URL to be given up too quickly in favor of the second one even for
transient errors such as when user closes a lid and reopens after some
time.

The right behavior in this case is to just count those failures towards
the URL and only after repeated failures with no progress should we
advance the URL index.

This CL implements this logic and completes the multiple URL-related
work items outlined in the design doc.

BUG=chromium-os:37206
TEST=Tested all uses cases on my ZGB. Added and updated unit tests.

Change-Id: Ida0cfbfeb9bfab732144049d1b27e3b8958bc252
Reviewed-on: https://gerrit.chromium.org/gerrit/39885
Commit-Queue: Jay Srinivasan <jaysri@chromium.org>
Reviewed-by: Jay Srinivasan <jaysri@chromium.org>
Tested-by: Jay Srinivasan <jaysri@chromium.org>
diff --git a/utils.cc b/utils.cc
index b4763e4..5a1d812 100644
--- a/utils.cc
+++ b/utils.cc
@@ -709,26 +709,34 @@
                       exp_time.second);
 }
 
-void SendErrorCodeToUma(MetricsLibraryInterface* metrics_lib,
-                        ActionExitCode code)
-{
-  string metric = utils::IsNormalBootMode() ? "Installer.NormalErrorCodes" :
-                                              "Installer.DevModeErrorCodes";
-
+ActionExitCode GetBaseErrorCode(ActionExitCode code) {
   // Ignore the higher order bits in the code by applying the mask as
   // we want the enumerations to be in the small contiguous range
   // with values less than kActionCodeUmaReportedMax.
-  int reported_code = code & kActualCodeMask;
+  ActionExitCode base_code = static_cast<ActionExitCode>(
+      code & kActualCodeMask);
 
-  // Make additional adjustments required for UMA.
-  // TODO(jaysri): Move this logic to UeErrorCode.cc when we
-  // fix BUG 34369.
-  if (reported_code >= kActionCodeOmahaRequestHTTPResponseBase) {
+  // Make additional adjustments required for UMA and error classification.
+  // TODO(jaysri): Move this logic to UeErrorCode.cc when we fix
+  // chromium-os:34369.
+  if (base_code >= kActionCodeOmahaRequestHTTPResponseBase) {
     // Since we want to keep the enums to a small value, aggregate all HTTP
-    // errors into this one bucket for UMA purposes.
-    reported_code = kActionCodeOmahaErrorInHTTPResponse;
+    // errors into this one bucket for UMA and error classification purposes.
+    base_code = kActionCodeOmahaErrorInHTTPResponse;
   }
 
+  return base_code;
+}
+
+
+
+void SendErrorCodeToUma(MetricsLibraryInterface* metrics_lib,
+                        ActionExitCode code) {
+  string metric = utils::IsNormalBootMode() ? "Installer.NormalErrorCodes" :
+                                              "Installer.DevModeErrorCodes";
+
+  ActionExitCode reported_code = GetBaseErrorCode(code);
+
   LOG(INFO) << "Sending error code " << reported_code
             << " to UMA metric: " << metric;
   metrics_lib->SendEnumToUMA(metric, reported_code, kActionCodeUmaReportedMax);