shill: Make cellular Connect work for GSM networks.

Add the APN to the properties map passed to Connect.
Set up the list of APNs to try, and step through it when
a connect attempt fails with the InvalidApn error. The
order in which APNs are tried is

  - APN which most recently resulted in a successful
    connection on the current network
  - a user-specified APN, specified by setting the Cellular.APN
    property on the service
  - the list of APNs found for the home network provider in the
    mobile broadband provider database
  - if all those fail, a null APN

BUG=chromium-os:23259
TEST=manual testing, some of which involved modifying the
mobile provider DB to create invalid APN entries. Created
two new unit tests as well, and ran all unit tests.

Change-Id: I38c869228fe1aaf7421de8a826c54e7b62c209b2
Reviewed-on: https://gerrit.chromium.org/gerrit/19122
Tested-by: Eric Shienbrood <ers@chromium.org>
Reviewed-by: Jason Glasgow <jglasgow@chromium.org>
Commit-Ready: Eric Shienbrood <ers@chromium.org>
diff --git a/cellular_capability_gsm.h b/cellular_capability_gsm.h
index 916506b..2f22628 100644
--- a/cellular_capability_gsm.h
+++ b/cellular_capability_gsm.h
@@ -5,6 +5,8 @@
 #ifndef SHILL_CELLULAR_CAPABILITY_GSM_
 #define SHILL_CELLULAR_CAPABILITY_GSM_
 
+#include <deque>
+
 #include <base/memory/scoped_ptr.h>
 #include <base/memory/weak_ptr.h>
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
@@ -68,6 +70,10 @@
  protected:
   virtual void InitProxies();
   virtual void ReleaseProxies();
+  // Override OnConnectReply in order to handle the possibility of
+  // retrying the Connect operation.
+  virtual void OnConnectReply(const ResultCallback &callback,
+                              const Error &error);
 
  private:
   friend class CellularTest;
@@ -93,7 +99,9 @@
   FRIEND_TEST(CellularCapabilityGSMTest, UpdateOperatorInfo);
   FRIEND_TEST(CellularCapabilityGSMTest, GetRegistrationState);
   FRIEND_TEST(CellularCapabilityGSMTest, OnModemManagerPropertiesChanged);
+  FRIEND_TEST(CellularCapabilityGSMTest, SetupApnTryList);
   FRIEND_TEST(CellularCapabilityTest, AllowRoaming);
+  FRIEND_TEST(CellularCapabilityTest, TryApns);
   FRIEND_TEST(CellularTest, StartGSMRegister);
   FRIEND_TEST(ModemTest, CreateDeviceFromProperties);
 
@@ -138,6 +146,9 @@
 
   KeyValueStore SimLockStatusToProperty(Error *error);
 
+  void SetupApnTryList();
+  void FillConnectPropertyMap(DBusPropertiesMap *properties);
+
   void HelpRegisterDerivedKeyValueStore(
       const std::string &name,
       KeyValueStore(CellularCapabilityGSM::*get)(Error *error),
@@ -189,6 +200,7 @@
   // Properties.
   std::string selected_network_;
   Stringmaps found_networks_;
+  std::deque<Stringmap> apn_try_list_;
   bool scanning_;
   uint16 scan_interval_;
   SimLockStatus sim_lock_status_;