shill: Add Technology class

Move Technology enum out into its own class, and create static
functions for converting between these and strings.

BUG=chromium-os:20114
TEST=Rerun unit tests

Change-Id: I9e3aea44e5d0b14d844328f023b01d7f8ea04c42
Reviewed-on: http://gerrit.chromium.org/gerrit/8204
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/Makefile b/Makefile
index 05a2f6d..967696d 100644
--- a/Makefile
+++ b/Makefile
@@ -130,6 +130,7 @@
 	sockets.o \
 	supplicant_interface_proxy.o \
 	supplicant_process_proxy.o \
+	technology.o \
 	wifi.o \
 	wifi_endpoint.o \
 	wifi_service.o
diff --git a/cellular.cc b/cellular.cc
index 9995354..e333a3b 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -719,8 +719,8 @@
   }
 }
 
-bool Cellular::TechnologyIs(const Device::Technology type) const {
-  return type == Device::kCellular;
+bool Cellular::TechnologyIs(const Technology::Identifier type) const {
+  return type == Technology::kCellular;
 }
 
 void Cellular::Connect(Error *error) {
diff --git a/cellular.h b/cellular.h
index 0046238..c633bea 100644
--- a/cellular.h
+++ b/cellular.h
@@ -137,7 +137,7 @@
   // Inherited from Device.
   virtual void Start();
   virtual void Stop();
-  virtual bool TechnologyIs(Technology type) const;
+  virtual bool TechnologyIs(Technology::Identifier type) const;
   virtual void LinkEvent(unsigned int flags, unsigned int change);
   virtual void Scan(Error *error);
   virtual void RegisterOnNetwork(const std::string &network_id, Error *error);
diff --git a/device.cc b/device.cc
index 1a16245..7f72cdf 100644
--- a/device.cc
+++ b/device.cc
@@ -135,7 +135,7 @@
           << (selected_service_.get() ? "is set." : "is not set.");
 }
 
-bool Device::TechnologyIs(const Technology type) const {
+bool Device::TechnologyIs(const Technology::Identifier type) const {
   return false;
 }
 
diff --git a/device.h b/device.h
index 7574e4e..17e7775 100644
--- a/device.h
+++ b/device.h
@@ -18,6 +18,7 @@
 #include "shill/refptr_types.h"
 #include "shill/service.h"
 #include "shill/shill_event.h"
+#include "shill/technology.h"
 
 namespace shill {
 
@@ -34,15 +35,6 @@
 // this class.
 class Device : public base::RefCounted<Device> {
  public:
-  enum Technology {
-    kEthernet,
-    kWifi,
-    kCellular,
-    kBlacklisted,
-    kUnknown,
-    kNumTechnologies
-  };
-
   // A constructor for the Device object
   Device(ControlInterface *control_interface,
          EventDispatcher *dispatcher,
@@ -60,7 +52,7 @@
   virtual void Stop();
 
   // Base method always returns false.
-  virtual bool TechnologyIs(const Technology type) const;
+  virtual bool TechnologyIs(const Technology::Identifier type) const;
 
   virtual void LinkEvent(unsigned flags, unsigned change);
 
diff --git a/device_info.cc b/device_info.cc
index 3517a96..c886eb1 100644
--- a/device_info.cc
+++ b/device_info.cc
@@ -96,14 +96,15 @@
           << device->interface_index() << ")";
   CHECK(!GetDevice(device->interface_index()).get());
   infos_[device->interface_index()].device = device;
-  if (device->TechnologyIs(Device::kCellular) ||
-      device->TechnologyIs(Device::kEthernet) ||
-      device->TechnologyIs(Device::kWifi)) {
+  if (device->TechnologyIs(Technology::kCellular) ||
+      device->TechnologyIs(Technology::kEthernet) ||
+      device->TechnologyIs(Technology::kWifi)) {
     manager_->RegisterDevice(device);
   }
 }
 
-Device::Technology DeviceInfo::GetDeviceTechnology(const string &iface_name) {
+Technology::Identifier DeviceInfo::GetDeviceTechnology(
+    const string &iface_name) {
   char contents[1024];
   int length;
   int fd;
@@ -115,11 +116,11 @@
 
   fd = open(uevent_file.c_str(), O_RDONLY);
   if (fd < 0)
-    return Device::kUnknown;
+    return Technology::kUnknown;
 
   length = read(fd, contents, sizeof(contents) - 1);
   if (length < 0)
-    return Device::kUnknown;
+    return Technology::kUnknown;
 
   /*
    * If the "uevent" file contains the string "DEVTYPE=wlan\n" at the
@@ -129,11 +130,11 @@
   contents[length] = '\0';
   wifi_type = strstr(contents, "DEVTYPE=wlan\n");
   if (wifi_type != NULL && (wifi_type == contents || wifi_type[-1] == '\n'))
-    return Device::kWifi;
+    return Technology::kWifi;
 
   length = readlink(driver_file.c_str(), contents, sizeof(contents)-1);
   if (length < 0)
-    return Device::kUnknown;
+    return Technology::kUnknown;
 
   contents[length] = '\0';
   driver_name = strrchr(contents, '/');
@@ -142,17 +143,17 @@
     // See if driver for this interface is in a list of known modem driver names
     for (modem_idx = 0; kModemDrivers[modem_idx] != NULL; modem_idx++)
       if (strcmp(driver_name, kModemDrivers[modem_idx]) == 0)
-        return Device::kCellular;
+        return Technology::kCellular;
   }
 
-  return Device::kEthernet;
+  return Technology::kEthernet;
 }
 
 void DeviceInfo::AddLinkMsgHandler(const RTNLMessage &msg) {
   DCHECK(msg.type() == RTNLMessage::kTypeLink &&
          msg.mode() == RTNLMessage::kModeAdd);
   int dev_index = msg.interface_index();
-  Device::Technology technology = Device::kUnknown;
+  Technology::Identifier technology = Technology::kUnknown;
 
   unsigned int flags = msg.link_status().flags;
   unsigned int change = msg.link_status().change;
@@ -182,7 +183,7 @@
 
     if (!link_name.empty()) {
       if (ContainsKey(black_list_, link_name)) {
-        technology = Device::kBlacklisted;
+        technology = Technology::kBlacklisted;
       } else {
         technology = GetDeviceTechnology(link_name);
       }
@@ -190,17 +191,17 @@
     string address =
         StringToLowerASCII(infos_[dev_index].mac_address.HexEncode());
     switch (technology) {
-      case Device::kCellular:
+      case Technology::kCellular:
         // Cellular devices are managed by ModemInfo.
         VLOG(2) << "Cellular link " << link_name << " at index " << dev_index
                 << " ignored.";
         return;
-      case Device::kEthernet:
+      case Technology::kEthernet:
         EnableDeviceIPv6Privacy(link_name);
         device = new Ethernet(control_interface_, dispatcher_, manager_,
                               link_name, address, dev_index);
         break;
-      case Device::kWifi:
+      case Technology::kWifi:
         EnableDeviceIPv6Privacy(link_name);
         device = new WiFi(control_interface_, dispatcher_, manager_,
                           link_name, address, dev_index);
diff --git a/device_info.h b/device_info.h
index 4e1e41a..2d5091d 100644
--- a/device_info.h
+++ b/device_info.h
@@ -78,7 +78,8 @@
   static const char *kModemDrivers[];
   static const char kInterfaceIPv6Privacy[];
 
-  static Device::Technology GetDeviceTechnology(const std::string &face_name);
+  static Technology::Identifier GetDeviceTechnology(
+      const std::string &face_name);
 
   void AddLinkMsgHandler(const RTNLMessage &msg);
   void DelLinkMsgHandler(const RTNLMessage &msg);
diff --git a/device_info_unittest.cc b/device_info_unittest.cc
index 5c80e40..6b44252 100644
--- a/device_info_unittest.cc
+++ b/device_info_unittest.cc
@@ -187,7 +187,7 @@
 
   DeviceRefPtr device = device_info_.GetDevice(kTestDeviceIndex);
   ASSERT_TRUE(device.get());
-  EXPECT_TRUE(device->TechnologyIs(Device::kBlacklisted));
+  EXPECT_TRUE(device->TechnologyIs(Technology::kBlacklisted));
 
   device_info_.Stop();
 }
diff --git a/device_stub.h b/device_stub.h
index 4775097..b7f6f10 100644
--- a/device_stub.h
+++ b/device_stub.h
@@ -32,16 +32,18 @@
              const std::string &link_name,
              const std::string &address,
              int interface_index,
-             Technology technology)
+             Technology::Identifier technology)
       : Device(control_interface, dispatcher, manager, link_name, address,
                interface_index),
         technology_(technology) {}
   void Start() {}
   void Stop() {}
-  bool TechnologyIs(const Technology type) const { return type == technology_; }
+  bool TechnologyIs(const Technology::Identifier type) const {
+    return type == technology_;
+  }
 
  private:
-  Technology technology_;
+  Technology::Identifier technology_;
 
   DISALLOW_COPY_AND_ASSIGN(DeviceStub);
 };
diff --git a/device_unittest.cc b/device_unittest.cc
index 1270a49..1980929 100644
--- a/device_unittest.cc
+++ b/device_unittest.cc
@@ -118,7 +118,7 @@
 }
 
 TEST_F(DeviceTest, TechnologyIs) {
-  EXPECT_FALSE(device_->TechnologyIs(Device::kEthernet));
+  EXPECT_FALSE(device_->TechnologyIs(Technology::kEthernet));
 }
 
 TEST_F(DeviceTest, DestroyIPConfig) {
diff --git a/ethernet.cc b/ethernet.cc
index a971bc5..2592b0f 100644
--- a/ethernet.cc
+++ b/ethernet.cc
@@ -63,8 +63,8 @@
   Device::Stop();
 }
 
-bool Ethernet::TechnologyIs(const Device::Technology type) const {
-  return type == Device::kEthernet;
+bool Ethernet::TechnologyIs(const Technology::Identifier type) const {
+  return type == Technology::kEthernet;
 }
 
 void Ethernet::LinkEvent(unsigned int flags, unsigned int change) {
diff --git a/ethernet.h b/ethernet.h
index c0ea433..e36f7eb 100644
--- a/ethernet.h
+++ b/ethernet.h
@@ -25,7 +25,7 @@
 
   void Start();
   void Stop();
-  bool TechnologyIs(Device::Technology type) const;
+  bool TechnologyIs(Technology::Identifier type) const;
   void LinkEvent(unsigned int flags, unsigned int change);
 
  private:
diff --git a/manager.cc b/manager.cc
index 3b109e2..85160cd 100644
--- a/manager.cc
+++ b/manager.cc
@@ -225,7 +225,7 @@
   // TODO(pstew): This should trigger re-sorting of services, autoconnect, etc.
 }
 
-void Manager::FilterByTechnology(Device::Technology tech,
+void Manager::FilterByTechnology(Technology::Identifier tech,
                                  vector<DeviceRefPtr> *found) {
   CHECK(found);
   vector<DeviceRefPtr>::iterator it;
@@ -328,7 +328,7 @@
 void Manager::RequestScan(const std::string &technology, Error *error) {
   if (technology == flimflam::kTypeWifi || technology == "") {
     vector<DeviceRefPtr> wifi_devices;
-    FilterByTechnology(Device::kWifi, &wifi_devices);
+    FilterByTechnology(Technology::kWifi, &wifi_devices);
 
     for (vector<DeviceRefPtr>::iterator it = wifi_devices.begin();
          it != wifi_devices.end();
diff --git a/manager.h b/manager.h
index bd03330..6c29c1e 100644
--- a/manager.h
+++ b/manager.h
@@ -63,7 +63,7 @@
   virtual void DeregisterService(const ServiceConstRefPtr &to_forget);
   virtual void UpdateService(const ServiceConstRefPtr &to_update);
 
-  void FilterByTechnology(Device::Technology tech,
+  void FilterByTechnology(Technology::Identifier tech,
                           std::vector<DeviceRefPtr> *found);
 
   ServiceRefPtr FindService(const std::string& name);
diff --git a/manager_unittest.cc b/manager_unittest.cc
index 242d6e9..673be36 100644
--- a/manager_unittest.cc
+++ b/manager_unittest.cc
@@ -69,7 +69,8 @@
   }
   virtual ~ManagerTest() {}
 
-  bool IsDeviceRegistered(const DeviceRefPtr &device, Device::Technology tech) {
+  bool IsDeviceRegistered(const DeviceRefPtr &device,
+                          Technology::Identifier tech) {
     vector<DeviceRefPtr> devices;
     manager()->FilterByTechnology(tech, &devices);
     return (devices.size() == 1 && devices[0].get() == device.get());
@@ -88,41 +89,41 @@
 }
 
 TEST_F(ManagerTest, DeviceRegistration) {
-  ON_CALL(*mock_device_.get(), TechnologyIs(Device::kEthernet))
+  ON_CALL(*mock_device_.get(), TechnologyIs(Technology::kEthernet))
       .WillByDefault(Return(true));
-  ON_CALL(*mock_device2_.get(), TechnologyIs(Device::kWifi))
+  ON_CALL(*mock_device2_.get(), TechnologyIs(Technology::kWifi))
       .WillByDefault(Return(true));
-  ON_CALL(*mock_device3_.get(), TechnologyIs(Device::kCellular))
+  ON_CALL(*mock_device3_.get(), TechnologyIs(Technology::kCellular))
       .WillByDefault(Return(true));
 
   manager()->RegisterDevice(mock_device_);
   manager()->RegisterDevice(mock_device2_);
   manager()->RegisterDevice(mock_device3_);
 
-  EXPECT_TRUE(IsDeviceRegistered(mock_device_, Device::kEthernet));
-  EXPECT_TRUE(IsDeviceRegistered(mock_device2_, Device::kWifi));
-  EXPECT_TRUE(IsDeviceRegistered(mock_device3_, Device::kCellular));
+  EXPECT_TRUE(IsDeviceRegistered(mock_device_, Technology::kEthernet));
+  EXPECT_TRUE(IsDeviceRegistered(mock_device2_, Technology::kWifi));
+  EXPECT_TRUE(IsDeviceRegistered(mock_device3_, Technology::kCellular));
 }
 
 TEST_F(ManagerTest, DeviceDeregistration) {
-  ON_CALL(*mock_device_.get(), TechnologyIs(Device::kEthernet))
+  ON_CALL(*mock_device_.get(), TechnologyIs(Technology::kEthernet))
       .WillByDefault(Return(true));
-  ON_CALL(*mock_device2_.get(), TechnologyIs(Device::kWifi))
+  ON_CALL(*mock_device2_.get(), TechnologyIs(Technology::kWifi))
       .WillByDefault(Return(true));
 
   manager()->RegisterDevice(mock_device_.get());
   manager()->RegisterDevice(mock_device2_.get());
 
-  ASSERT_TRUE(IsDeviceRegistered(mock_device_, Device::kEthernet));
-  ASSERT_TRUE(IsDeviceRegistered(mock_device2_, Device::kWifi));
+  ASSERT_TRUE(IsDeviceRegistered(mock_device_, Technology::kEthernet));
+  ASSERT_TRUE(IsDeviceRegistered(mock_device2_, Technology::kWifi));
 
   EXPECT_CALL(*mock_device_.get(), Stop());
   manager()->DeregisterDevice(mock_device_.get());
-  EXPECT_FALSE(IsDeviceRegistered(mock_device_, Device::kEthernet));
+  EXPECT_FALSE(IsDeviceRegistered(mock_device_, Technology::kEthernet));
 
   EXPECT_CALL(*mock_device2_.get(), Stop());
   manager()->DeregisterDevice(mock_device2_.get());
-  EXPECT_FALSE(IsDeviceRegistered(mock_device2_, Device::kWifi));
+  EXPECT_FALSE(IsDeviceRegistered(mock_device2_, Technology::kWifi));
 }
 
 TEST_F(ManagerTest, ServiceRegistration) {
@@ -311,10 +312,10 @@
     Error error;
     manager()->RegisterDevice(mock_device_.get());
     manager()->RegisterDevice(mock_device2_.get());
-    EXPECT_CALL(*mock_device_, TechnologyIs(Device::kWifi))
+    EXPECT_CALL(*mock_device_, TechnologyIs(Technology::kWifi))
         .WillRepeatedly(Return(true));
     EXPECT_CALL(*mock_device_, Scan(_));
-    EXPECT_CALL(*mock_device2_, TechnologyIs(Device::kWifi))
+    EXPECT_CALL(*mock_device2_, TechnologyIs(Technology::kWifi))
         .WillRepeatedly(Return(false));
     EXPECT_CALL(*mock_device2_, Scan(_)).Times(0);
     manager()->RequestScan(flimflam::kTypeWifi, &error);
diff --git a/mock_device.h b/mock_device.h
index d86c07c..f4e356e 100644
--- a/mock_device.h
+++ b/mock_device.h
@@ -27,7 +27,8 @@
   MOCK_METHOD0(Start, void());
   MOCK_METHOD0(Stop, void());
   MOCK_METHOD1(Scan, void(Error *error));
-  MOCK_CONST_METHOD1(TechnologyIs, bool(const Technology technology));
+  MOCK_CONST_METHOD1(TechnologyIs,
+                     bool(const Technology::Identifier technology));
   MOCK_METHOD1(Save, bool(StoreInterface*));
 
  private:
diff --git a/modem_unittest.cc b/modem_unittest.cc
index 70306c9..5129776 100644
--- a/modem_unittest.cc
+++ b/modem_unittest.cc
@@ -168,7 +168,7 @@
   EXPECT_EQ(Cellular::kModemStateDisabled, modem_.device_->modem_state());
 
   vector<DeviceRefPtr> devices;
-  manager_.FilterByTechnology(Device::kCellular, &devices);
+  manager_.FilterByTechnology(Technology::kCellular, &devices);
   EXPECT_EQ(1, devices.size());
   EXPECT_TRUE(devices[0].get() == modem_.device_.get());
 }
diff --git a/technology.cc b/technology.cc
new file mode 100644
index 0000000..1be4184
--- /dev/null
+++ b/technology.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "shill/technology.h"
+
+#include <string>
+
+#include <chromeos/dbus/service_constants.h>
+
+namespace shill {
+
+using std::string;
+
+const char Technology::kUnknownName[] = "Unknown";
+
+
+Technology::Identifier Technology::IdentifierFromName(const std::string &name) {
+  if (name == flimflam::kTypeEthernet) {
+    return kEthernet;
+  } else if (name == flimflam::kTypeWifi) {
+    return kWifi;
+  } else if (name == flimflam::kTypeCellular) {
+    return kCellular;
+  } else {
+    return kUnknown;
+  }
+}
+
+std::string Technology::NameFromIdentifier(Technology::Identifier id) {
+  if (id == kEthernet) {
+    return flimflam::kTypeEthernet;
+  } else if (id == kWifi) {
+    return flimflam::kTypeWifi;
+  } else if (id == kCellular) {
+    return flimflam::kTypeCellular;
+  } else {
+    return kUnknownName;
+  }
+}
+
+}  // namespace shill
diff --git a/technology.h b/technology.h
new file mode 100644
index 0000000..11d4b8b
--- /dev/null
+++ b/technology.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SHILL_TECHNOLOGY_
+#define SHILL_TECHNOLOGY_
+
+#include <string>
+
+namespace shill {
+
+class Technology {
+ public:
+  enum Identifier {
+    kEthernet,
+    kWifi,
+    kCellular,
+    kBlacklisted,
+    kUnknown,
+    kNumTechnologies
+  };
+
+  static Identifier IdentifierFromName(const std::string &name);
+  static std::string NameFromIdentifier(Identifier id);
+
+ private:
+  static const char kUnknownName[];
+};
+
+}  // namespace shill
+
+#endif  // SHILL_TECHNOLOGY_
diff --git a/wifi.cc b/wifi.cc
index 18195ec..17a371a 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -188,8 +188,8 @@
       task_factory_.NewRunnableMethod(&WiFi::ScanTask));
 }
 
-bool WiFi::TechnologyIs(const Device::Technology type) const {
-  return type == Device::kWifi;
+bool WiFi::TechnologyIs(const Technology::Identifier type) const {
+  return type == Technology::kWifi;
 }
 
 void WiFi::LinkEvent(unsigned int flags, unsigned int change) {
diff --git a/wifi.h b/wifi.h
index a92174f..7687215 100644
--- a/wifi.h
+++ b/wifi.h
@@ -37,7 +37,7 @@
   virtual void Start();
   virtual void Stop();
   virtual void Scan(Error *error);
-  virtual bool TechnologyIs(const Technology type) const;
+  virtual bool TechnologyIs(const Technology::Identifier type) const;
   virtual void LinkEvent(unsigned int flags, unsigned int change);
 
   // called by SupplicantInterfaceProxy, in response to events from