shill: Ensure valid cellular service before using it.

Cellular::OnConnectFailed() and CellularCapabilityGSM::OnConnectReply()
may be called when there are no cellular service.  This CL checks to
make sure the service is valid before using it.

BUG=chromium-os:31016
TEST=Unit tests, network_3GModemControl

Change-Id: I79ffeccf80f79c5cbe62ce93c6feaabf86ae5ea1
Reviewed-on: https://gerrit.chromium.org/gerrit/23042
Commit-Ready: Thieu Le <thieule@chromium.org>
Reviewed-by: Thieu Le <thieule@chromium.org>
Tested-by: Thieu Le <thieule@chromium.org>
diff --git a/cellular_capability_gsm.cc b/cellular_capability_gsm.cc
index 6042415..016e288 100644
--- a/cellular_capability_gsm.cc
+++ b/cellular_capability_gsm.cc
@@ -261,8 +261,13 @@
 
 void CellularCapabilityGSM::OnConnectReply(const ResultCallback &callback,
                                            const Error &error) {
-  if (error.IsFailure()) {
-    cellular()->service()->ClearLastGoodApn();
+  CellularServiceRefPtr service = cellular()->service();
+  if (!service) {
+    // The service could have been deleted before our Connect() request
+    // completes if the modem was enabled and then quickly disabled.
+    apn_try_list_.clear();
+  } else if (error.IsFailure()) {
+    service->ClearLastGoodApn();
     // The APN that was just tried (and failed) is still at the
     // front of the list, about to be removed. If the list is empty
     // after that, try one last time without an APN. This may succeed
@@ -278,7 +283,7 @@
       return;
     }
   } else if (!apn_try_list_.empty()) {
-    cellular()->service()->SetLastGoodApn(apn_try_list_.front());
+    service->SetLastGoodApn(apn_try_list_.front());
     apn_try_list_.clear();
   }
   if (!callback.is_null())