UM: Policy for deciding download URL.

This adds a new private policy (UpdateDownloadUrl) for determining which
download URL should be used for obtaining the update payload. We further
extend an existing public policy (UpdateCanStart) to return the download
URL details, based on the current URL index and the number of failures
associated with it. This renders the explicit notion of "HTTP download
allowed" in the return value unnecessary: If HTTP is not allowed, then
HTTP URLs will not be considered.

We also implement logic for logging the start/end of a policy
evaluation, so that intermediate log messages emitted during evaluation
have a clear context.

BUG=chromium:358329
TEST=Unit tests.

Change-Id: Ib5343417480d8825082f83bed2630a6611360b61
Reviewed-on: https://chromium-review.googlesource.com/203373
Tested-by: Gilad Arnold <garnold@chromium.org>
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Gilad Arnold <garnold@chromium.org>
diff --git a/update_manager/policy.h b/update_manager/policy.h
index 65f236c..6515b77 100644
--- a/update_manager/policy.h
+++ b/update_manager/policy.h
@@ -6,7 +6,9 @@
 #define CHROMEOS_PLATFORM_UPDATE_ENGINE_UPDATE_MANAGER_POLICY_H_
 
 #include <string>
+#include <vector>
 
+#include "update_engine/error_code.h"
 #include "update_engine/update_manager/evaluation_context.h"
 #include "update_engine/update_manager/state.h"
 
@@ -31,10 +33,30 @@
 //
 // A snapshot of the state of the current update process.
 struct UpdateState {
+  // Information pertaining to the Omaha update response.
+  //
   // Time when update was first offered by Omaha.
   base::Time first_seen;
   // Number of update checks returning the current update.
   int num_checks;
+
+  // Information pertaining to the update download URL.
+  //
+  // An array of download URLs provided by Omaha.
+  std::vector<std::string> download_urls;
+  // Max number of failures allowed per download URL.
+  int download_failures_max;
+  // The index of the URL to use, as previously determined by the policy. This
+  // number is significant iff |num_checks| is greater than 1.
+  int download_url_idx;
+  // The number of failures already associated with this URL.
+  int download_url_num_failures;
+  // An array of failure error codes that occurred since the latest reported
+  // ones (included in the number above).
+  std::vector<chromeos_update_engine::ErrorCode> download_url_error_codes;
+
+  // Information pertaining to update scattering.
+  //
   // Scattering wallclock-based wait period, as returned by the policy.
   base::TimeDelta scatter_wait_period;
   // Maximum wait period allowed for this update, as determined by Omaha.
@@ -57,17 +79,24 @@
   kCheckDue,
   kDisabledByPolicy,
   kScattering,
+  kCannotDownload,
 };
 
 struct UpdateCanStartResult {
   // Whether the update attempt is allowed to proceed.
   bool update_can_start;
+
   // Attributes pertaining to the case where update is allowed. The update
   // engine uses them to choose the means for downloading and applying an
   // update.
-  bool http_allowed;
   bool p2p_allowed;
   std::string target_channel;
+  // The index of the download URL to use, and the number of failures associated
+  // with this URL. An index value of -1 indicates that no suitable URL is
+  // available, but there may be other means for download (like P2P).
+  int download_url_idx;
+  int download_url_num_failures;
+
   // Attributes pertaining to the case where update is not allowed. Some are
   // needed for storing values to persistent storage, others for
   // logging/metrics.
@@ -86,6 +115,31 @@
  public:
   virtual ~Policy() {}
 
+  // Returns the name of a public policy request.
+  // IMPORTANT: Be sure to add a conditional for each new public policy that is
+  // being added to this class in the future.
+  template<typename R, typename... Args>
+  std::string PolicyRequestName(
+      EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
+                                          std::string*, R*,
+                                          Args...) const) const {
+    std::string class_name = PolicyName() + "::";
+
+    if (reinterpret_cast<typeof(&Policy::UpdateCheckAllowed)>(
+            policy_method) == &Policy::UpdateCheckAllowed)
+      return class_name + "UpdateCheckAllowed";
+    if (reinterpret_cast<typeof(&Policy::UpdateCanStart)>(
+            policy_method) == &Policy::UpdateCanStart)
+      return class_name + "UpdateCanStart";
+    if (reinterpret_cast<typeof(&Policy::UpdateCurrentConnectionAllowed)>(
+            policy_method) == &Policy::UpdateCurrentConnectionAllowed)
+      return class_name + "UpdateCurrentConnectionAllowed";
+
+    NOTREACHED();
+    return class_name + "(unknown)";
+  }
+
+
   // List of policy requests. A policy request takes an EvaluationContext as the
   // first argument, a State instance, a returned error message, a returned
   // value and optionally followed by one or more arbitrary constant arguments.
@@ -128,6 +182,9 @@
  protected:
   Policy() {}
 
+  // Returns the name of the actual policy class.
+  virtual std::string PolicyName() const = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(Policy);
 };