Invalidate non-existing DBus proxy for power manager.

Upon observing an org.freedesktop.DBus.NameHasOwner signal, invalidate
the DBus proxy of the old power manager instance to avoid calling
UnregisterSuspendDelay on a non-existing instance.

BUG=chrome-os-partner:10380
TEST=Verify that wimax-manager does not call UnregisterSuspendDelay on
non-existing power manager instance.

Change-Id: I000c46f739e7ba174e95cc5d9b7b4d5e3704cfb6
Reviewed-on: https://gerrit.chromium.org/gerrit/25009
Tested-by: Ben Chan <benchan@chromium.org>
Reviewed-by: Darin Petkov <petkov@chromium.org>
Commit-Ready: Ben Chan <benchan@chromium.org>
diff --git a/dbus_proxiable.h b/dbus_proxiable.h
index 7ef77b6..c2f2581 100644
--- a/dbus_proxiable.h
+++ b/dbus_proxiable.h
@@ -29,6 +29,10 @@
     CHECK(dbus_proxy_.get());
   }
 
+  void InvalidateDBusProxy() {
+    dbus_proxy_.reset();
+  }
+
   Proxy *dbus_proxy() const { return dbus_proxy_.get(); }
 
  private:
diff --git a/dbus_service.cc b/dbus_service.cc
index fa1c176..1d9646f 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -25,7 +25,7 @@
 
 void DBusService::Initialize() {
   if (NameHasOwner(power_manager::kPowerManagerServiceName))
-    CreatePowerManager();
+    SetPowerManager(new(std::nothrow) PowerManager(manager_));
 }
 
 void DBusService::Finalize() {
@@ -51,17 +51,27 @@
   if (name == power_manager::kPowerManagerServiceName) {
     LOG(INFO) << "Owner of '" << name << "' changed from '"
               << old_owner << "' to '" << new_owner << "'.";
-    if (new_owner.empty()) {
-      power_manager_.reset();
-    } else {
-      CreatePowerManager();
-    }
+    if (new_owner.empty())
+      SetPowerManager(NULL);
+    else
+      SetPowerManager(new(std::nothrow) PowerManager(manager_));
   }
 }
 
-void DBusService::CreatePowerManager() {
+void DBusService::SetPowerManager(PowerManager *power_manager) {
+  // The old power manager instance no longer exists, invalidate its DBus
+  // proxy to prevent calling UnregisterSuspendDelay on it at destruction.
+  if (power_manager_.get()) {
+    LOG(INFO) << "Destroy old power manager proxy.";
+    power_manager_->InvalidateDBusProxy();
+    power_manager_.reset();
+  }
+
+  if (!power_manager)
+    return;
+
   LOG(INFO) << "Create a new power manager proxy.";
-  power_manager_.reset(new(std::nothrow) PowerManager(manager_));
+  power_manager_.reset(power_manager);
   CHECK(power_manager_.get());
   power_manager_->CreateDBusProxy();
   power_manager_->Initialize();
diff --git a/dbus_service.h b/dbus_service.h
index 5e9f763..8524164 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -31,7 +31,7 @@
                           const std::string &new_owner);
 
  private:
-  void CreatePowerManager();
+  void SetPowerManager(PowerManager *power_manager);
 
   Manager *manager_;
   scoped_ptr<PowerManager> power_manager_;
diff --git a/main.cc b/main.cc
index 0cb0686..a95df65 100644
--- a/main.cc
+++ b/main.cc
@@ -15,8 +15,6 @@
 
 #include "wimax_manager/manager.h"
 #include "wimax_manager/manager_dbus_adaptor.h"
-#include "wimax_manager/power_manager.h"
-#include "wimax_manager/power_manager_dbus_proxy.h"
 
 DEFINE_bool(foreground, false,
             "Don't daemon()ize; run in foreground.");
diff --git a/power_manager.cc b/power_manager.cc
index 7919047..ca29b46 100644
--- a/power_manager.cc
+++ b/power_manager.cc
@@ -56,10 +56,15 @@
 }
 
 void PowerManager::UnregisterSuspendDelay() {
-  if (!suspend_delay_registered_ || !dbus_proxy())
+  if (!suspend_delay_registered_)
     return;
 
-  LOG(INFO) << "Unregister suspend delay";
+  if (!dbus_proxy()) {
+    suspend_delay_registered_ = false;
+    return;
+  }
+
+  LOG(INFO) << "Unregister suspend delay.";
   try {
     dbus_proxy()->UnregisterSuspendDelay();
     suspend_delay_registered_ = false;