shill: WiFi: Reset PendingService if hidden network times out

If a hidden service times out associate, it will likely have
no endpoints, since wpa_supplicant failed to attain a CurrentBSS.
If so, the service has no reference to a wifi_ device and thus
cannot call WiFi::DisconnectFrom() to reset pending_service_.
In this case, we must perform the disconnect here ourselves.

BUG=chromium:226688
TEST=Unit tests + manual: while connected, attempt a connection
to a non-existent hidden network.  After the "out-of-range"
error appears, the system should re-connect where it was
originally connected.

Change-Id: I1d3b6940f9b077b890189dea649f48405dd6a494
Reviewed-on: https://gerrit.chromium.org/gerrit/47366
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
Commit-Queue: Paul Stewart <pstew@chromium.org>
diff --git a/wifi.cc b/wifi.cc
index 3f1021d..e769d69 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -1337,6 +1337,17 @@
   CHECK(pending_service_);
   pending_service_->DisconnectWithFailure(
       Service::kFailureOutOfRange, &unused_error);
+
+  // A hidden service may have no endpoints, since wpa_supplicant
+  // failed to attain a CurrentBSS.  If so, the service has no
+  // reference to |this| device and cannot call WiFi::DisconnectFrom()
+  // to reset pending_service_.  In this case, we must perform the
+  // disconnect here ourselves.
+  if (pending_service_) {
+    CHECK(!pending_service_->HasEndpoints());
+    LOG(INFO) << "Hidden service was not found.";
+    DisconnectFrom(pending_service_);
+  }
 }
 
 void WiFi::StartReconnectTimer() {