[go: up one dir, main page]

Consolidate disk-related udev handling in cros-disks.

BUG=chromium-os:15740
TEST=Tested inserting/removing USB/SD devices on a Cr48.

Change-Id: I40c6bf43057ba04944c720821d0b5a6b71066957
Reviewed-on: http://gerrit.chromium.org/gerrit/2484
Tested-by: Ben Chan <benchan@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
diff --git a/SConstruct.chromiumos b/SConstruct.chromiumos
index c17387a..55f475c 100644
--- a/SConstruct.chromiumos
+++ b/SConstruct.chromiumos
@@ -116,10 +116,10 @@
 ''')
 
 env = base_env.Clone()
-env.Append(LIBS=['chromeos', 'base', 'rt', 'rootdev'])
+env.Append(LIBS=['chromeos', 'base', 'rt'])
 
 # glib, dbus, and ibus environment
-env.ParseConfig('%s --cflags --libs dbus-1 glib-2.0 gudev-1.0 dbus-glib-1 '
+env.ParseConfig('%s --cflags --libs dbus-1 glib-2.0 dbus-glib-1 '
                 'ibus-1.0 libpcrecpp x11' % env['ENV']['PKG_CONFIG'])
 
 env.GlibMarshal('marshal.glibmarshal.c', 'marshal.list')
diff --git a/chromeos_mount.cc b/chromeos_mount.cc
index 2b7e784..8dbd3ca 100644
--- a/chromeos_mount.cc
+++ b/chromeos_mount.cc
@@ -5,6 +5,7 @@
 #include "chromeos_mount.h" // NOLINT
 
 #include <base/logging.h>
+#include <base/memory/scoped_vector.h>
 
 #include <algorithm>
 #include <cstdlib>
@@ -17,9 +18,6 @@
 #include "chromeos/dbus/dbus.h"
 #include "chromeos/glib/object.h"
 #include "chromeos/string.h"
-#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
-#include <gudev/gudev.h>
-#include <rootdev/rootdev.h>
 
 namespace chromeos { // NOLINT
 
@@ -222,6 +220,16 @@
   delete cb_data;
 }
 
+struct MountEventCallbackData {
+  MountEventCallbackData(MountEventConnection connection,
+                         MountEventType type)
+      : event_connection(connection),
+        event_type(type) {}
+
+  MountEventConnection event_connection;
+  MountEventType event_type;
+};
+
 void MountRequestNotify(DBusGProxy* gproxy,
                         DBusGProxyCall* call_id,
                         void* user_data) {
@@ -491,98 +499,79 @@
 
 class OpaqueMountEventConnection {
  public:
-  typedef dbus::MonitorConnection<void (const char*)>* ConnectionType;
+  typedef dbus::MonitorConnection<void (const char*)> ConnectionType;
 
   OpaqueMountEventConnection(const MountEventMonitor& monitor,
                              const dbus::Proxy& mount,
                              void* object)
-     : gudev_client(NULL),
-       monitor_(monitor),
+     : monitor_(monitor),
        object_(object),
-       mount_(mount),
-       addconnection_(NULL),
-       removeconnection_(NULL) {
+       mount_(mount) {
+  }
+
+  ~OpaqueMountEventConnection() {
+    TearDownConnections();
+  }
+
+  void SetUpConnections() {
+    static const struct {
+      const char *signal_name;
+      MountEventType event_type;
+    } kSignalEventTuples[] = {
+      { "DeviceAdded", DEVICE_ADDED },
+      { "DeviceScanned", DEVICE_SCANNED },
+      { "DeviceRemoved", DEVICE_REMOVED },
+      { "DiskAdded", DISK_ADDED },
+      { "DiskChanged", DISK_CHANGED },
+      { "DiskRemoved", DISK_REMOVED },
+    };
+    static const size_t kNumSignalEventTuples =
+      sizeof(kSignalEventTuples) / sizeof(kSignalEventTuples[0]);
+
+    callback_data_.reserve(kNumSignalEventTuples);
+    connections_.reserve(kNumSignalEventTuples);
+
+    for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
+      MountEventCallbackData* cb_data = new MountEventCallbackData(this,
+          kSignalEventTuples[i].event_type);
+      callback_data_.push_back(cb_data);
+
+      ConnectionType* connection = dbus::Monitor(mount_,
+          kSignalEventTuples[i].signal_name,
+          &OpaqueMountEventConnection::MountEventCallback,
+          cb_data);
+      connections_.push_back(connection);
+    }
+  }
+
+  void TearDownConnections() {
+    for (std::vector<ConnectionType*>::const_iterator
+        connection_iter = connections_.begin();
+        connection_iter != connections_.end();
+        ++connection_iter) {
+      // dbus::Disconnect also deletes the connection object.
+      dbus::Disconnect(*connection_iter);
+    }
+    connections_.clear();
+    callback_data_.reset();
   }
 
   void FireEvent(MountEventType evt, const char* path) {
     monitor_(object_, evt, path);
   }
 
-  static void Added(void* object, const char* device) {
-    MountEventConnection self =
-        reinterpret_cast<MountEventConnection>(object);
-    self->FireEvent(DISK_ADDED, device);
+  static void MountEventCallback(void* data, const char* device) {
+    MountEventCallbackData* cb_data =
+        reinterpret_cast<MountEventCallbackData*>(data);
+    cb_data->event_connection->FireEvent(cb_data->event_type, device);
   }
 
-  static void Removed(void* object, const char* device) {
-    MountEventConnection self =
-        reinterpret_cast<MountEventConnection>(object);
-    self->FireEvent(DISK_REMOVED, device);
-  }
-
-  static void Changed(void* object, const char* device) {
-    MountEventConnection self =
-        reinterpret_cast<MountEventConnection>(object);
-    self->FireEvent(DISK_CHANGED, device);
-  }
-
-  static void OnUDevEvent(GUdevClient* client,
-                          const char* action,
-                          GUdevDevice* device,
-                          gpointer object) {
-    MountEventConnection self = reinterpret_cast<MountEventConnection>(object);
-    std::set<std::string>::iterator iter;
-    // can be scsi or block
-    const char* subsystem = g_udev_device_get_subsystem(device);
-    if (subsystem == NULL || strcmp(subsystem, "scsi") != 0) {
-      return;
-    }
-    if (strcmp(action, "add") == 0) {
-      const char* device_path = g_udev_device_get_sysfs_path(device);
-      if (device_path == NULL)
-        return;
-      std::string device_string(device_path);
-      iter = self->paths_.find(device_string);
-      if (iter != self->paths_.end()) {
-        self->FireEvent(DEVICE_SCANNED, device_path);
-      } else {
-        self->paths_.insert(device_string);
-        self->FireEvent(DEVICE_ADDED, device_path);
-      }
-    } else if (strcmp(action, "remove") == 0) {
-      const char* device_path = g_udev_device_get_sysfs_path(device);
-      if (device_path == NULL)
-        return;
-      std::string device_string(device_path);
-      iter = self->paths_.find(device_string);
-      if (iter != self->paths_.end()) {
-        self->paths_.erase(iter);
-        self->FireEvent(DEVICE_REMOVED, device_path);
-      }
-    }
-  }
-  ConnectionType& addedconnection() {
-    return addconnection_;
-  }
-
-  ConnectionType& removedconnection() {
-    return removeconnection_;
-  }
-
-  ConnectionType& changedconnection() {
-    return changedconnection_;
-  }
-
-  GUdevClient* gudev_client;
-
  private:
   MountEventMonitor monitor_;
   void* object_;
-  std::set<std::string> paths_;
   dbus::Proxy mount_;
-  ConnectionType addconnection_;
-  ConnectionType removeconnection_;
-  ConnectionType changedconnection_;
+  ScopedVector<MountEventCallbackData> callback_data_;
+  std::vector<ConnectionType*> connections_;
 };
 
 extern "C"
@@ -593,58 +582,10 @@
                     kCrosDisksInterface,
                     kCrosDisksPath,
                     kCrosDisksInterface);
-  MountEventConnection result =
-     new OpaqueMountEventConnection(monitor, mount, object);
-  ::dbus_g_proxy_add_signal(mount.gproxy(),
-                            "DeviceAdded",
-                            G_TYPE_STRING,
-                            G_TYPE_INVALID);
-  ::dbus_g_proxy_add_signal(mount.gproxy(),
-                            "DeviceRemoved",
-                            G_TYPE_STRING,
-                            G_TYPE_INVALID);
-  ::dbus_g_proxy_add_signal(mount.gproxy(),
-                            "DeviceChanged",
-                            G_TYPE_STRING,
-                            G_TYPE_INVALID);
-  typedef dbus::MonitorConnection<void (const char*)> ConnectionType;
-
-  ConnectionType* added = new ConnectionType(mount, "DeviceAdded",
-      &OpaqueMountEventConnection::Added, result);
-
-  ::dbus_g_proxy_connect_signal(mount.gproxy(), "DeviceAdded",
-                                G_CALLBACK(&ConnectionType::Run),
-                                added, NULL);
-  result->addedconnection() = added;
-
-
-  ConnectionType* removed = new ConnectionType(mount, "DeviceRemoved",
-      &OpaqueMountEventConnection::Removed, result);
-
-  ::dbus_g_proxy_connect_signal(mount.gproxy(), "DeviceRemoved",
-                                G_CALLBACK(&ConnectionType::Run),
-                                removed, NULL);
-  result->removedconnection() = removed;
-
-
-  ConnectionType* changed = new ConnectionType(mount, "DeviceChanged",
-      &OpaqueMountEventConnection::Changed, result);
-
-  ::dbus_g_proxy_connect_signal(mount.gproxy(), "DeviceChanged",
-                                G_CALLBACK(&ConnectionType::Run),
-                                changed, NULL);
-  result->changedconnection() = changed;
-
-  // Listen to udev events
-
-  const char *subsystems[] = {"scsi", "block", NULL};
-  result->gudev_client = g_udev_client_new(subsystems);
-  g_signal_connect(result->gudev_client,
-                   "uevent",
-                   G_CALLBACK(&OpaqueMountEventConnection::OnUDevEvent),
-                   result);
-
-  return result;
+  MountEventConnection connection =
+    new OpaqueMountEventConnection(monitor, mount, object);
+  connection->SetUpConnections();
+  return connection;
 }
 
 extern "C"
@@ -676,9 +617,6 @@
 
 extern "C"
 void ChromeOSDisconnectMountEventMonitor(MountEventConnection connection) {
-  dbus::Disconnect(connection->addedconnection());
-  dbus::Disconnect(connection->removedconnection());
-  dbus::Disconnect(connection->changedconnection());
   delete connection;
 }