PolicyManager: Schedule re-evaluations based on variable usage.

This patch makes the EvaluationContext re-schedule a policy request
based on the variables used by that method, waiting for the Async
variables and polling the Poll variables on the suggested interval.

In order to use the main loop functions from the EvaluationContext
they were moved to its own file called event_loop.h.

BUG=chromium:340871
TEST=Unit tests added.

Change-Id: Ibfc52e4dfd12c5e1ef87b5ad9cc318f9821dcfdd
Reviewed-on: https://chromium-review.googlesource.com/190424
Reviewed-by: Gilad Arnold <garnold@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/policy_manager/policy_manager-inl.h b/policy_manager/policy_manager-inl.h
index 4317e77..f0d4937 100644
--- a/policy_manager/policy_manager-inl.h
+++ b/policy_manager/policy_manager-inl.h
@@ -5,9 +5,12 @@
 #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_POLICY_MANAGER_INL_H_
 #define CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_POLICY_MANAGER_INL_H_
 
+#include <string>
+
 #include <base/bind.h>
 
 #include "update_engine/policy_manager/evaluation_context.h"
+#include "update_engine/policy_manager/event_loop.h"
 
 namespace chromeos_policy_manager {
 
@@ -35,7 +38,6 @@
   return status;
 }
 
-
 template<typename T, typename R, typename... Args>
 void PolicyManager::OnPolicyReadyToEvaluate(
     scoped_refptr<EvaluationContext> ec,
@@ -49,14 +51,20 @@
     callback.Run(status, result);
     return;
   }
-  // Re-schedule the policy request.
-  // TODO(deymo): Use the information gathered on the EvaluationContext to
-  // hook on proper events from changes on the State in order to re-evaluate
-  // the policy after some period of time.
+  // Re-schedule the policy request based on used variables.
   base::Closure closure = base::Bind(
       &PolicyManager::OnPolicyReadyToEvaluate<T, R, Args...>,
       base::Unretained(this), ec, callback, policy_method, args...);
-  RunFromMainLoopAfterTimeout(closure, base::TimeDelta::FromSeconds(20));
+
+  if (!ec->RunOnValueChangeOrTimeout(closure)) {
+    // The policy method didn't use any non-const variable nor there's any
+    // time-based event that will change the status of evaluation. We call the
+    // callback with EvalStatus::kAskMeAgainLater.
+    LOG(ERROR) << "Policy implementation didn't use any non-const variable "
+                  "but returned kAskMeAgainLater.";
+    callback.Run(EvalStatus::kAskMeAgainLater, result);
+    return;
+  }
 }
 
 template<typename T, typename R, typename... Args>