shill: Create an APN list for the home GSM provider and broadcast it.

BUG=chromium-os:23201
TEST=unit tests

Change-Id: I7eda725099cb83d118099af75530f776f9f73d7d
Reviewed-on: https://gerrit.chromium.org/gerrit/11981
Tested-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Reviewed-by: Eric Shienbrood <ers@chromium.org>
Commit-Ready: Darin Petkov <petkov@chromium.org>
diff --git a/cellular_capability_gsm.cc b/cellular_capability_gsm.cc
index 842e30f..c33cf14 100644
--- a/cellular_capability_gsm.cc
+++ b/cellular_capability_gsm.cc
@@ -11,6 +11,7 @@
 #include <mm/mm-modem.h>
 #include <mobile_provider.h>
 
+#include "shill/adaptor_interfaces.h"
 #include "shill/cellular_service.h"
 #include "shill/property_accessor.h"
 #include "shill/proxy_factory.h"
@@ -52,6 +53,8 @@
   HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
                                 &CellularCapabilityGSM::SimLockStatusToProperty,
                                 NULL);
+  store->RegisterConstStringmaps(flimflam::kCellularApnListProperty,
+                                 &apn_list_);
 }
 
 StrIntPair CellularCapabilityGSM::SimLockStatusToProperty(Error */*error*/) {
@@ -201,7 +204,7 @@
     oper.SetName(spn_);
   }
   cellular()->set_home_provider(oper);
-  // TODO(petkov): Create APN list (crosbug.com/23201).
+  InitAPNList();
 }
 
 void CellularCapabilityGSM::UpdateOperatorInfo() {
@@ -236,6 +239,49 @@
   }
 }
 
+void CellularCapabilityGSM::InitAPNList() {
+  VLOG(2) << __func__;
+  if (!home_provider_) {
+    return;
+  }
+  apn_list_.clear();
+  for (int i = 0; i < home_provider_->num_apns; ++i) {
+    Stringmap props;
+    mobile_apn *apn = home_provider_->apns[i];
+    if (apn->value) {
+      props[flimflam::kApnProperty] = apn->value;
+    }
+    if (apn->username) {
+      props[flimflam::kApnUsernameProperty] = apn->username;
+    }
+    if (apn->password) {
+      props[flimflam::kApnPasswordProperty] = apn->password;
+    }
+    // Find the first localized and non-localized name, if any.
+    const localized_name *lname = NULL;
+    const localized_name *name = NULL;
+    for (int j = 0; j < apn->num_names; ++j) {
+      if (apn->names[j]->lang) {
+        if (!lname) {
+          lname = apn->names[j];
+        }
+      } else if (!name) {
+        name = apn->names[j];
+      }
+    }
+    if (name) {
+      props[flimflam::kApnNameProperty] = name->name;
+    }
+    if (lname) {
+      props[flimflam::kApnLocalizedNameProperty] = lname->name;
+      props[flimflam::kApnLanguageProperty] = lname->lang;
+    }
+    apn_list_.push_back(props);
+  }
+  cellular()->adaptor()->EmitStringmapsChanged(
+      flimflam::kCellularApnListProperty, apn_list_);
+}
+
 void CellularCapabilityGSM::Register() {
   LOG(INFO) << __func__ << " \"" << selected_network_ << "\"";
   // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).