shill: WiFiService: Associate to 1EEE 802.11w APs

Detect whether any of the Endpoints seen by the service requires
802.11w (Protected Management Frame) support.  If so, set a
boolean service property and instruct wpa_supplicant to enable
support for this feature.

BUG=chromium-os:37698
TEST=New unit tests.  New autotest at https://gerrit.chromium.org/gerrit/40985
CQ-DEPEND=I1fb5f35cd85f2b8c0e7a0bb2ac69cc920d988830

Change-Id: I79679af871edea057691ab12f91070b71e89ba51
Reviewed-on: https://gerrit.chromium.org/gerrit/40986
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Queue: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/wifi_service_unittest.cc b/wifi_service_unittest.cc
index 2bef7b1..03aa47b 100644
--- a/wifi_service_unittest.cc
+++ b/wifi_service_unittest.cc
@@ -327,6 +327,12 @@
       ContainsKey(arg, wpa_supplicant::kPropertyPreSharedKey);
 }
 
+MATCHER(WPA80211wSecurityArgs, "") {
+  return ContainsKey(arg, wpa_supplicant::kPropertySecurityProtocol) &&
+      ContainsKey(arg, wpa_supplicant::kPropertyPreSharedKey) &&
+      ContainsKey(arg, wpa_supplicant::kNetworkPropertyIeee80211w);
+}
+
 MATCHER(EAPSecurityArgs, "") {
   return ContainsKey(arg, wpa_supplicant::kNetworkPropertyEapIdentity) &&
       ContainsKey(arg, wpa_supplicant::kNetworkPropertyCaPath);
@@ -511,6 +517,27 @@
   wifi_service->Connect(NULL);
 }
 
+TEST_F(WiFiServiceTest, ConnectTaskWPA80211w) {
+  vector<uint8_t> ssid(1, 'a');
+  WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
+                                                   dispatcher(),
+                                                   metrics(),
+                                                   manager(),
+                                                   wifi(),
+                                                   ssid,
+                                                   flimflam::kModeManaged,
+                                                   flimflam::kSecurityPsk,
+                                                   false);
+  WiFiEndpointRefPtr endpoint = MakeEndpoint("a", "00:00:00:00:00:01", 0, 0);
+  endpoint->ieee80211w_required_ = true;
+  wifi_service->AddEndpoint(endpoint);
+  Error error;
+  wifi_service->SetPassphrase("0:mumblemumblem", &error);
+  EXPECT_CALL(*wifi(),
+              ConnectTo(wifi_service.get(), WPA80211wSecurityArgs()));
+  wifi_service->Connect(NULL);
+}
+
 MATCHER(WEPSecurityArgsKeyIndex0, "") {
   return ContainsKey(arg, wpa_supplicant::kPropertyAuthAlg) &&
       ContainsKey(arg, wpa_supplicant::kPropertyWEPKey + std::string("0")) &&
@@ -1344,4 +1371,18 @@
   Mock::VerifyAndClearExpectations(&adaptor);
 }
 
+TEST_F(WiFiServiceUpdateFromEndpointsTest, Ieee80211w) {
+  EXPECT_CALL(adaptor, EmitUint16Changed(_, _)).Times(AnyNumber());
+  EXPECT_CALL(adaptor, EmitStringChanged(_, _)).Times(AnyNumber());
+  EXPECT_CALL(adaptor, EmitUint8Changed(_, _)).Times(AnyNumber());
+  EXPECT_CALL(adaptor, EmitBoolChanged(_, _)).Times(AnyNumber());
+  service->AddEndpoint(ok_endpoint);
+  EXPECT_FALSE(service->ieee80211w_required());
+  good_endpoint->ieee80211w_required_ = true;
+  service->AddEndpoint(good_endpoint);
+  EXPECT_TRUE(service->ieee80211w_required());
+  service->RemoveEndpoint(good_endpoint);
+  EXPECT_TRUE(service->ieee80211w_required());
+}
+
 }  // namespace shill