PM: Shift to signal-based inference of network connection.

Instead of making DBus calls to shill on-demand, and estimating the time
a connection has changed, the RealShillProvider now listens to the
appropriate DBus signal and update its internal state accordingly. Note
that checking for the connection type still requires a DBus call, if the
connection has changed since its type was last checked.

In order to pass all unit tests (including those of PolicyManager and
RealState), there's a substantial portion of DBus mock set up code that
was added. This code will be removed very soon, once we begin injecting
providers into RealState, instead of low-level DBus and/or clock
interfaces.

BUG=chromium:338585
TEST=Unit tests.

Change-Id: Ia7a2f9db18f905f1b7a2cc1234acb31eaa60009e
Reviewed-on: https://chromium-review.googlesource.com/189692
Reviewed-by: Gilad Arnold <garnold@chromium.org>
Commit-Queue: Gilad Arnold <garnold@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
diff --git a/policy_manager/real_shill_provider.h b/policy_manager/real_shill_provider.h
index 80b4802..ba24234 100644
--- a/policy_manager/real_shill_provider.h
+++ b/policy_manager/real_shill_provider.h
@@ -22,55 +22,40 @@
 
 namespace chromeos_policy_manager {
 
-// A tracker for the last reported value. Whenever Update() is called with a new
-// value, the current time is written to a pointed time object.
-template<typename T>
-class LastValueTracker {
- public:
-  LastValueTracker(ClockInterface* clock, T init_val, base::Time* time_p)
-      : clock_(clock), last_val_(init_val), time_p_(time_p) {}
-
-  const T& Update(const T& curr_val) {
-    if (curr_val != last_val_) {
-      last_val_ = curr_val;
-      *time_p_ = clock_->GetWallclockTime();
-    }
-    return curr_val;
-  }
-
- private:
-  ClockInterface* const clock_;
-  T last_val_;
-  base::Time* time_p_;
-};
-
-// A DBus connector for making shill queries.
+// A DBus connector for making all shill related calls.
 class ShillConnector {
  public:
-  ShillConnector(DBusWrapperInterface* dbus) : dbus_(dbus) {}
+  // Expected type for the PropertyChanged signal handler.
+  typedef void (*PropertyChangedHandler)(DBusGProxy*, const char*, GValue*,
+                                         void*);
 
-  ~ShillConnector() {
-    if (manager_proxy_)
-      dbus_->ProxyUnref(manager_proxy_);
-  }
+  ShillConnector(DBusWrapperInterface* dbus,
+                 PropertyChangedHandler signal_handler, void* signal_data)
+      : dbus_(dbus), signal_handler_(signal_handler),
+        signal_data_(signal_data) {}
+
+  ~ShillConnector();
 
   // Initializes the DBus connector. Returns |true| on success.
   bool Init();
 
-  // Obtains the default network connection, storing the connection status to
-  // |*is_connected_p| and (if connected) the service path for the default
-  // connection in |*default_service_path_p|. Returns |true| on success; |false|
-  // on failure, in which case no values are written.
-  bool GetDefaultConnection(bool* is_connected_p,
-                            std::string* default_service_path_p);
-
   // Obtains the type of a network connection described by |service_path|,
   // storing it to |*conn_type_p|. Returns |true| on success; |false| on
   // failure, in which case no value is written.
   bool GetConnectionType(const std::string& service_path,
                          ShillConnType* conn_type_p);
 
+  // Issues a GetProperties call to shill's manager interface, storing the
+  // result to |*result_p|. Returns |true| on success.
+  bool GetManagerProperties(GHashTable** result_p) {
+    return GetProperties(manager_proxy_, result_p);
+  }
+
  private:
+  // Issues a GetProperties call through a given |proxy|, storing the result to
+  // |*result_p|. Returns |true| on success.
+  bool GetProperties(DBusGProxy* proxy, GHashTable** result_p);
+
   typedef struct {
     const char *str;
     ShillConnType type;
@@ -79,21 +64,24 @@
   // A mapping from shill connection type strings to enum values.
   static const ConnStrToType shill_conn_str_to_type[];
 
+  // An initialization flag.
+  bool is_init_ = false;
+
   // The DBus interface and connection, and a shill manager proxy.
   DBusWrapperInterface* dbus_;
   DBusGConnection* connection_ = NULL;
   DBusGProxy* manager_proxy_ = NULL;
 
+  // The shill manager signal handler credentials.
+  PropertyChangedHandler signal_handler_ = NULL;
+  void* signal_data_ = NULL;
+
   // Return a DBus proxy for a given |path| and |interface| within shill.
   DBusGProxy* GetProxy(const char* path, const char* interface);
 
   // Converts a shill connection type string into a symbolic value.
   ShillConnType ParseConnType(const char* str);
 
-  // Issues a GetProperties call through a given |proxy|, storing the result to
-  // |*result_p|. Returns |true| on success.
-  bool GetProperties(DBusGProxy* proxy, GHashTable** result_p);
-
   DISALLOW_COPY_AND_ASSIGN(ShillConnector);
 };
 
@@ -101,17 +89,37 @@
 class RealShillProvider : public ShillProvider {
  public:
   RealShillProvider(DBusWrapperInterface* dbus, ClockInterface* clock)
-      : conn_last_changed_(clock->GetWallclockTime()),
-        dbus_(dbus), clock_(clock),
-        is_connected_tracker_(clock, false, &conn_last_changed_) {}
+      : dbus_(dbus), clock_(clock) {}
 
  protected:
   virtual bool DoInit();
 
  private:
+  // Process a default connection value, update last change time as needed.
+  bool ProcessDefaultService(GValue* value);
+
+  // A handler for manager PropertyChanged signal, and a static version.
+  void HandlePropertyChanged(DBusGProxy* proxy, const char *name,
+                             GValue* value);
+  static void HandlePropertyChangedStatic(DBusGProxy* proxy, const char* name,
+                                          GValue* value, void* data);
+
+
   // The time when the connection type last changed.
   base::Time conn_last_changed_;
 
+  // The current connection status.
+  bool is_connected_;
+
+  // The current default service path, if connected.
+  std::string default_service_path_;
+
+  // The last known type of the default connection.
+  ShillConnType conn_type_ = kShillConnTypeUnknown;
+
+  // Whether the last known connection type is valid.
+  bool is_conn_type_valid_ = false;
+
   // A shill DBus connector.
   scoped_ptr<ShillConnector> connector_;
 
@@ -121,9 +129,7 @@
   // A clock abstraction (mockable).
   ClockInterface* const clock_;
 
-  // Tracker for the latest connection status.
-  LastValueTracker<bool> is_connected_tracker_;
-
+  friend class ConnTypeVariable;
   DISALLOW_COPY_AND_ASSIGN(RealShillProvider);
 };