PolicyManager: Initial support of async PolicyRequests.

This patch adds the new method PolicyManager::AsyncPolicyRequest
that takes a callback to be called once the policy request finishes.

If the given policy request returns kAskMeAgainLater, its evaluation
will be re-scheduled until it returns a given value. On this initial
patch, the evaluation is re-scheduled to happen after a fixed amount
of time instead of using the information collected on the
EvaluationContext.

BUG=chromium:340871
TEST=Unittest added.

Change-Id: If0e2888f26c379b806d811d52c4c3d4a8a6d8efb
Reviewed-on: https://chromium-review.googlesource.com/189636
Tested-by: Alex Deymo <deymo@chromium.org>
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
diff --git a/policy_manager/policy_manager.h b/policy_manager/policy_manager.h
index b84f493..3966ec5 100644
--- a/policy_manager/policy_manager.h
+++ b/policy_manager/policy_manager.h
@@ -5,6 +5,10 @@
 #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_POLICY_MANAGER_H
 #define CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_POLICY_MANAGER_H
 
+#include <glib.h>
+
+#include <base/callback.h>
+#include <base/memory/ref_counted.h>
 #include <base/memory/scoped_ptr.h>
 
 #include "update_engine/policy_manager/default_policy.h"
@@ -41,11 +45,55 @@
   template<typename T, typename R, typename... Args>
   EvalStatus PolicyRequest(T policy_method, R* result, Args... args);
 
+  // Evaluates the given |policy_method| policy with the provided |args|
+  // arguments and calls the |callback| callback with the result when done.
+  //
+  // If the policy implementation should block, returning a
+  // EvalStatus::kAskMeAgainLater status the policy manager will re-evaluate the
+  // policy until another status is returned.
+  template<typename T, typename R, typename... Args>
+  void AsyncPolicyRequest(
+      base::Callback<void(EvalStatus, const R& result)> callback,
+      T policy_method, Args... args);
+
  private:
   friend class PmPolicyManagerTest;
   FRIEND_TEST(PmPolicyManagerTest, PolicyRequestCallsPolicy);
   FRIEND_TEST(PmPolicyManagerTest, PolicyRequestCallsDefaultOnError);
   FRIEND_TEST(PmPolicyManagerTest, PolicyRequestDoesntBlock);
+  FRIEND_TEST(PmPolicyManagerTest, AsyncPolicyRequestDelaysEvaluation);
+
+  // Schedules the passed |callback| to run from the GLib's main loop after a
+  // timeout if it is given.
+  static void RunFromMainLoop(const base::Closure& callback);
+  static void RunFromMainLoopAfterTimeout(const base::Closure& callback,
+                                          base::TimeDelta timeout);
+
+  // Called by the GLib's main loop when is time to call the callback scheduled
+  // with RunFromMainLopp() and similar functions. The pointer to the callback
+  // passed when scheduling it is passed to this functions as a gpointer on
+  // |user_data|.
+  static gboolean OnRanFromMainLoop(gpointer user_data);
+
+  // EvaluatePolicy() evaluates the passed |policy_method| method on the current
+  // policy with the given |args| arguments. If the method fails, the default
+  // policy is used instead.
+  template<typename T, typename R, typename... Args>
+  EvalStatus EvaluatePolicy(EvaluationContext* ec,
+                            T policy_method, R* result,
+                            Args... args);
+
+  // OnPolicyReadyToEvaluate() is called by the main loop when the evaluation
+  // of the given |policy_method| should be executed. If the evaluation finishes
+  // the |callback| callback is called passing the |result| and the |status|
+  // returned by the policy. If the evaluation returns an
+  // EvalStatus::kAskMeAgainLater state, the |callback| will NOT be called and
+  // the evaluation will be re-scheduled to be called later.
+  template<typename T, typename R, typename... Args>
+  void OnPolicyReadyToEvaluate(
+      scoped_refptr<EvaluationContext> ec,
+      base::Callback<void(EvalStatus status, const R& result)> callback,
+      T policy_method, Args... args);
 
   // The policy used by the PolicyManager. Note that since it is a const Policy,
   // policy implementations are not allowed to persist state on this class.