shill: Service: Support string arrays in Configure

Support conversion of string array parameters in
DBusAdaptor::ArgsToKeyValueStore(), so that in addition to SetProperty,
Manager functions like ConfigureService, GetService, etc, are passed
string array arguments.  In Service::Configure() and
Service::DoPropertiesMatch(), add string array properties to the
properties set / matched.

BUG=chromium:249363
TEST=Unit test.  As of https://gerrit.chromium.org/gerrit/59123,
network_VPNConnect now tests this code path (by setting CACertPEM
in the OpenVPN tests).

Change-Id: Ide3545e47c8c05b36c7ef3a41d83fbde7263404d
Reviewed-on: https://gerrit.chromium.org/gerrit/60221
Commit-Queue: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/service.cc b/service.cc
index 49c704d..54a3d55 100644
--- a/service.cc
+++ b/service.cc
@@ -486,50 +486,54 @@
 }
 
 void Service::Configure(const KeyValueStore &args, Error *error) {
-  map<string, bool>::const_iterator bool_it;
   SLOG(Service, 5) << "Configuring bool properties:";
-  for (bool_it = args.bool_properties().begin();
-       bool_it != args.bool_properties().end();
-       ++bool_it) {
-    if (ContainsKey(parameters_ignored_for_configure_, bool_it->first)) {
+  for (const auto &bool_it : args.bool_properties()) {
+    if (ContainsKey(parameters_ignored_for_configure_, bool_it.first)) {
       continue;
     }
-    SLOG(Service, 5) << "   " << bool_it->first;
+    SLOG(Service, 5) << "   " << bool_it.first;
     Error set_error;
-    store_.SetBoolProperty(bool_it->first, bool_it->second, &set_error);
-    OnPropertyChanged(bool_it->first);
-    if (error->IsSuccess() && set_error.IsFailure()) {
-      error->CopyFrom(set_error);
-    }
-  }
-  SLOG(Service, 5) << "Configuring string properties:";
-  map<string, string>::const_iterator string_it;
-  for (string_it = args.string_properties().begin();
-       string_it != args.string_properties().end();
-       ++string_it) {
-    if (ContainsKey(parameters_ignored_for_configure_, string_it->first)) {
-      continue;
-    }
-    SLOG(Service, 5) << "   " << string_it->first;
-    Error set_error;
-    store_.SetStringProperty(string_it->first, string_it->second, &set_error);
-    OnPropertyChanged(string_it->first);
+    store_.SetBoolProperty(bool_it.first, bool_it.second, &set_error);
+    OnPropertyChanged(bool_it.first);
     if (error->IsSuccess() && set_error.IsFailure()) {
       error->CopyFrom(set_error);
     }
   }
   SLOG(Service, 5) << "Configuring int32 properties:";
-  map<string, int32>::const_iterator int_it;
-  for (int_it = args.int_properties().begin();
-       int_it != args.int_properties().end();
-       ++int_it) {
-    if (ContainsKey(parameters_ignored_for_configure_, int_it->first)) {
+  for (const auto &int_it : args.int_properties()) {
+    if (ContainsKey(parameters_ignored_for_configure_, int_it.first)) {
       continue;
     }
-    SLOG(Service, 5) << "   " << int_it->first;
+    SLOG(Service, 5) << "   " << int_it.first;
     Error set_error;
-    store_.SetInt32Property(int_it->first, int_it->second, &set_error);
-    OnPropertyChanged(int_it->first);
+    store_.SetInt32Property(int_it.first, int_it.second, &set_error);
+    OnPropertyChanged(int_it.first);
+    if (error->IsSuccess() && set_error.IsFailure()) {
+      error->CopyFrom(set_error);
+    }
+  }
+  SLOG(Service, 5) << "Configuring string properties:";
+  for (const auto &string_it : args.string_properties()) {
+    if (ContainsKey(parameters_ignored_for_configure_, string_it.first)) {
+      continue;
+    }
+    SLOG(Service, 5) << "   " << string_it.first;
+    Error set_error;
+    store_.SetStringProperty(string_it.first, string_it.second, &set_error);
+    OnPropertyChanged(string_it.first);
+    if (error->IsSuccess() && set_error.IsFailure()) {
+      error->CopyFrom(set_error);
+    }
+  }
+  SLOG(Service, 5) << "Configuring string array properties:";
+  for (const auto &strings_it : args.strings_properties()) {
+    if (ContainsKey(parameters_ignored_for_configure_, strings_it.first)) {
+      continue;
+    }
+    SLOG(Service, 5) << "   " << strings_it.first;
+    Error set_error;
+    store_.SetStringsProperty(strings_it.first, strings_it.second, &set_error);
+    OnPropertyChanged(strings_it.first);
     if (error->IsSuccess() && set_error.IsFailure()) {
       error->CopyFrom(set_error);
     }
@@ -537,42 +541,43 @@
 }
 
 bool Service::DoPropertiesMatch(const KeyValueStore &args) const {
-  map<string, bool>::const_iterator bool_it;
   SLOG(Service, 5) << "Checking bool properties:";
-  for (bool_it = args.bool_properties().begin();
-       bool_it != args.bool_properties().end();
-       ++bool_it) {
-    SLOG(Service, 5) << "   " << bool_it->first;
+  for (const auto &bool_it: args.bool_properties()) {
+    SLOG(Service, 5) << "   " << bool_it.first;
     Error get_error;
     bool value;
-    if (!store_.GetBoolProperty(bool_it->first, &value, &get_error) ||
-        value != bool_it->second) {
-      return false;
-    }
-  }
-  SLOG(Service, 5) << "Checking string properties:";
-  map<string, string>::const_iterator string_it;
-  for (string_it = args.string_properties().begin();
-       string_it != args.string_properties().end();
-       ++string_it) {
-    SLOG(Service, 5) << "   " << string_it->first;
-    Error get_error;
-    string value;
-    if (!store_.GetStringProperty(string_it->first, &value, &get_error) ||
-        value != string_it->second) {
+    if (!store_.GetBoolProperty(bool_it.first, &value, &get_error) ||
+        value != bool_it.second) {
       return false;
     }
   }
   SLOG(Service, 5) << "Checking int32 properties:";
-  map<string, int32>::const_iterator int_it;
-  for (int_it = args.int_properties().begin();
-       int_it != args.int_properties().end();
-       ++int_it) {
-    SLOG(Service, 5) << "   " << int_it->first;
+  for (const auto &int_it : args.int_properties()) {
+    SLOG(Service, 5) << "   " << int_it.first;
     Error get_error;
     int32 value;
-    if (!store_.GetInt32Property(int_it->first, &value, &get_error) ||
-        value != int_it->second) {
+    if (!store_.GetInt32Property(int_it.first, &value, &get_error) ||
+        value != int_it.second) {
+      return false;
+    }
+  }
+  SLOG(Service, 5) << "Checking string properties:";
+  for (const auto &string_it : args.string_properties()) {
+    SLOG(Service, 5) << "   " << string_it.first;
+    Error get_error;
+    string value;
+    if (!store_.GetStringProperty(string_it.first, &value, &get_error) ||
+        value != string_it.second) {
+      return false;
+    }
+  }
+  SLOG(Service, 5) << "Checking string array properties:";
+  for (const auto &strings_it : args.strings_properties()) {
+    SLOG(Service, 5) << "   " << strings_it.first;
+    Error get_error;
+    vector<string> value;
+    if (!store_.GetStringsProperty(strings_it.first, &value, &get_error) ||
+        value != strings_it.second) {
       return false;
     }
   }