Implement {Available|Connected|Enabled}Technolgies and DefaultTechnology

This is Part 1 of a series of changes required for the Manager to generate
the right set of DBus events allowing shill to properly tell Chrome about
connectivity.

Some other side-effects in the change (needed to implement the above):
- Emit these manager properties over DBus everytime we re-sort the Service
  vector.
- Add a technology data member to Device, this allows easy enumeration of
  technologies.
- Add interface for getting a handle to the selected service on a device.
- Map connected state to online instead of ready state. This is needed for
  so that Chrome doesn't wait for the portal detection code to switch the
  state from ready->online.
- Default set the ethernet service as connectable.

BUG=chromium-os:14887
TEST=1) manual test to verify shill properly configures the ethernet
     device and Chrome correctly detects that.
     2) new unit tests

Change-Id: Ib10f2f0836f8d4aacaad1491f58ed9b3b5d37e7d
Reviewed-on: https://gerrit.chromium.org/gerrit/12019
Tested-by: Gaurav Shah <gauravsh@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
diff --git a/manager.cc b/manager.cc
index c9dda91..d7824ac 100644
--- a/manager.cc
+++ b/manager.cc
@@ -15,6 +15,7 @@
 #include <base/file_util.h>
 #include <base/logging.h>
 #include <base/memory/ref_counted.h>
+#include <base/stl_util-inl.h>
 #include <base/string_split.h>
 #include <base/string_util.h>
 #include <chromeos/dbus/service_constants.h>
@@ -38,6 +39,7 @@
 #include "shill/wifi_service.h"
 
 using std::map;
+using std::set;
 using std::string;
 using std::vector;
 
@@ -318,6 +320,12 @@
   // unit tests sometimes do things in otherwise invalid states.
   if (running_ && to_manage->powered())
     to_manage->Start();
+
+  Error error;
+  adaptor_->EmitStringsChanged(flimflam::kAvailableTechnologiesProperty,
+                               AvailableTechnologies(&error));
+  adaptor_->EmitStringsChanged(flimflam::kEnabledTechnologiesProperty,
+                               EnabledTechnologies(&error));
 }
 
 void Manager::DeregisterDevice(const DeviceRefPtr &to_forget) {
@@ -327,6 +335,11 @@
       VLOG(2) << "Deregistered device: " << to_forget->UniqueName();
       to_forget->Stop();
       devices_.erase(it);
+      Error error;
+      adaptor_->EmitStringsChanged(flimflam::kAvailableTechnologiesProperty,
+                                   AvailableTechnologies(&error));
+      adaptor_->EmitStringsChanged(flimflam::kEnabledTechnologiesProperty,
+                                   EnabledTechnologies(&error));
       return;
     }
   }
@@ -429,6 +442,12 @@
   }
   adaptor_->EmitRpcIdentifierArrayChanged(flimflam::kServicesProperty,
                                           service_paths);
+
+  Error error;
+  adaptor_->EmitStringsChanged(flimflam::kConnectedTechnologiesProperty,
+                               ConnectedTechnologies(&error));
+  adaptor_->EmitStringChanged(flimflam::kDefaultTechnologyProperty,
+                              DefaultTechnology(&error));
 }
 
 string Manager::CalculateState(Error */*error*/) {
@@ -436,19 +455,35 @@
 }
 
 vector<string> Manager::AvailableTechnologies(Error */*error*/) {
-  return vector<string>();
+  set<string> unique_technologies;
+  for (vector<DeviceRefPtr>::iterator it = devices_.begin();
+       it != devices_.end(); ++it) {
+    unique_technologies.insert(
+        Technology::NameFromIdentifier((*it)->technology()));
+  }
+  return vector<string>(unique_technologies.begin(), unique_technologies.end());
 }
 
 vector<string> Manager::ConnectedTechnologies(Error */*error*/) {
-  return vector<string>();
+  set<string> unique_technologies;
+  for (vector<DeviceRefPtr>::iterator it = devices_.begin();
+       it != devices_.end(); ++it) {
+    if ((*it)->IsConnected())
+      unique_technologies.insert(
+          Technology::NameFromIdentifier((*it)->technology()));
+  }
+  return vector<string>(unique_technologies.begin(), unique_technologies.end());
 }
 
-string Manager::DefaultTechnology(Error */*error*/) {
-  return "";
+string Manager::DefaultTechnology(Error *error) {
+  return (!services_.empty() && services_[0]->IsConnected()) ?
+      services_[0]->GetTechnologyString(error) : "";
 }
 
-vector<string> Manager::EnabledTechnologies(Error */*error*/) {
-  return vector<string>();
+vector<string> Manager::EnabledTechnologies(Error *error) {
+  // TODO(gauravsh): This must be wired up to the RPC interface to handle
+  // enabled/disabled devices as set by the user. crosbug.com/23319
+  return AvailableTechnologies(error);
 }
 
 vector<string> Manager::EnumerateDevices(Error */*error*/) {