shill: wimax: Monitor for WiMaxManager's presence on DBus.

Reset WiMaxProvider's state by destroying all WiMax devices when WiMaxManager
disappears. Connect to WiMaxManager only if its present. This makes shill more
resilient against wimax_manager crashes.

BUG=chrome-os-partner:10948
TEST=unit tests

Change-Id: I0a79d44fd19d6decc0b3964a144e6358711cd8b6
Reviewed-on: https://gerrit.chromium.org/gerrit/26665
Tested-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
Commit-Ready: Ben Chan <benchan@chromium.org>
diff --git a/wimax_provider.cc b/wimax_provider.cc
index e6ad489..38eebe2 100644
--- a/wimax_provider.cc
+++ b/wimax_provider.cc
@@ -45,24 +45,57 @@
 
 void WiMaxProvider::Start() {
   SLOG(WiMax, 2) << __func__;
-  if (manager_proxy_.get()) {
+  if (!on_wimax_manager_appear_.IsCancelled()) {
     return;
   }
-  manager_proxy_.reset(proxy_factory_->CreateWiMaxManagerProxy());
-  manager_proxy_->set_devices_changed_callback(
-      Bind(&WiMaxProvider::OnDevicesChanged, Unretained(this)));
-  Error error;
-  OnDevicesChanged(manager_proxy_->Devices(&error));
+  // Registers a watcher for the WiMaxManager service. This provider will
+  // connect to it if/when the OnWiMaxManagerAppear callback is invoked.
+  on_wimax_manager_appear_.Reset(
+      Bind(&WiMaxProvider::OnWiMaxManagerAppear, Unretained(this)));
+  on_wimax_manager_vanish_.Reset(
+      Bind(&WiMaxProvider::DisconnectFromWiMaxManager, Unretained(this)));
+  manager_->dbus_manager()->WatchName(
+      wimax_manager::kWiMaxManagerServiceName,
+      on_wimax_manager_appear_.callback(),
+      on_wimax_manager_vanish_.callback());
 }
 
 void WiMaxProvider::Stop() {
   SLOG(WiMax, 2) << __func__;
-  manager_proxy_.reset();
-  DestroyDeadDevices(RpcIdentifiers());
-  networks_.clear();
+  // TODO(petkov): Deregister the watcher from DBusManager to avoid potential
+  // memory leaks (crosbug.com/32226).
+  on_wimax_manager_appear_.Cancel();
+  on_wimax_manager_vanish_.Cancel();
+  DisconnectFromWiMaxManager();
   DestroyAllServices();
 }
 
+void WiMaxProvider::ConnectToWiMaxManager() {
+  DCHECK(!wimax_manager_proxy_.get());
+  LOG(INFO) << "Connecting to WiMaxManager.";
+  wimax_manager_proxy_.reset(proxy_factory_->CreateWiMaxManagerProxy());
+  wimax_manager_proxy_->set_devices_changed_callback(
+      Bind(&WiMaxProvider::OnDevicesChanged, Unretained(this)));
+  Error error;
+  OnDevicesChanged(wimax_manager_proxy_->Devices(&error));
+}
+
+void WiMaxProvider::DisconnectFromWiMaxManager() {
+  SLOG(WiMax, 2) << __func__;
+  if (!wimax_manager_proxy_.get()) {
+    return;
+  }
+  LOG(INFO) << "Disconnecting from WiMaxManager.";
+  wimax_manager_proxy_.reset();
+  OnDevicesChanged(RpcIdentifiers());
+}
+
+void WiMaxProvider::OnWiMaxManagerAppear(const string &owner) {
+  SLOG(WiMax, 2) << __func__ << "(" << owner << ")";
+  DisconnectFromWiMaxManager();
+  ConnectToWiMaxManager();
+}
+
 void WiMaxProvider::OnDeviceInfoAvailable(const string &link_name) {
   SLOG(WiMax, 2) << __func__ << "(" << link_name << ")";
   map<string, RpcIdentifier>::const_iterator find_it =