Fix TIVI-{1191,1192,2108} by implementing a connman 'Agent'. 64/13664/1 accepted/tizen/ivi/20131214.022856 submit/tizen/20131213.180923
authorOssama Othman <ossama.othman@intel.com>
Wed, 11 Dec 2013 23:43:22 +0000 (15:43 -0800)
committerOssama Othman <ossama.othman@intel.com>
Wed, 11 Dec 2013 23:44:39 +0000 (15:44 -0800)
Change-Id: Ibd0277bb3252b33b30f96b0221938aab161128a0
Signed-off-by: Ossama Othman <ossama.othman@intel.com>
33 files changed:
.gitignore
configure.ac
include/settingsd/event_callback.hpp
include/settingsd/glib_traits.hpp
include/settingsd/response_callback.hpp
include/settingsd/send_callback.hpp
lib/event_callback.cpp
lib/manager.cpp
lib/manager.hpp
lib/response_callback.cpp
lib/send_callback.cpp
packaging/settingsd.changes
packaging/settingsd.spec
plugins/connman/Makefile.am
plugins/connman/agent.cpp [new file with mode: 0644]
plugins/connman/agent.hpp [new file with mode: 0644]
plugins/connman/agent.xml
plugins/connman/clock.cpp
plugins/connman/clock.hpp
plugins/connman/connman.cpp
plugins/connman/connman.hpp
plugins/connman/connman_manager.cpp
plugins/connman/connman_manager.hpp
plugins/connman/connman_service.cpp
plugins/connman/connman_service.hpp
plugins/connman/connman_technology.cpp
plugins/connman/connman_technology.hpp
plugins/connman/registration.cpp
plugins/connman/service.cpp
plugins/connman/service.hpp
plugins/connman/settings-agent.conf.in [new file with mode: 0644]
plugins/connman/technology.cpp
plugins/connman/technology.hpp

index a1c8282..3d01d77 100644 (file)
@@ -28,6 +28,7 @@ src/settingsd
 tests/settings_test
 config.*
 !plugins/connman/config.h
+plugins/connman/settings-agent.conf
 !packaging/settingsd.socket
 *.tar.*
 doc/doxygen
index 4fb9240..89b4b2f 100644 (file)
@@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor,
 Boston, MA  02110-1301  USA
 ])
 
-AC_INIT([settingsd], [0.3], [ossama.othman@intel.com])
+AC_INIT([settingsd], [0.4], [ossama.othman@intel.com])
 AM_INIT_AUTOMAKE([1.11.1 foreign -Wall -Werror -Wno-portability silent-rules])
 LT_INIT([disable-static dlopen])
 
index 910082a..54e9013 100644 (file)
@@ -73,7 +73,7 @@ namespace ivi
        *                          formatted event data.
        */
       bool send_event(
-        std::function<void(JsonBuilder *)> event_builder);
+        std::function<void(JsonBuilder *)> event_builder) const;
 
     private:
 
@@ -84,12 +84,12 @@ namespace ivi
        * The appropriate "header" information will be prepended to the
        * event.
        */
-      unique_ptr<JsonBuilder> begin_event();
+      unique_ptr<JsonBuilder> begin_event() const;
 
       /**
        * End the JSON formatted event to the Settings app request.
        */
-      void end_event(unique_ptr<JsonBuilder> const & builder);
+      void end_event(unique_ptr<JsonBuilder> const & builder) const;
 
     private:
 
index 7fc4d9c..c2daedf 100644 (file)
@@ -53,7 +53,6 @@ namespace ivi
       };
     };
 
-
     // GVariant traits specialization.
     template<>
     struct traits<GVariant>
index 02936ef..d3f6014 100644 (file)
@@ -77,14 +77,14 @@ namespace ivi
        *                             JSON formatted response data.
        */
       bool send_response(
-        std::function<void(JsonBuilder *)> response_builder);
+        std::function<void(JsonBuilder *)> response_builder) const;
 
       /**
        * Send error response to Settings app.
        *
        * @param[in] error_message Free form error message.
        */
-      bool send_error(std::string error_message);
+      bool send_error(std::string error_message) const;
 
       /**
        * The settings type/ID associated with the request and
@@ -103,7 +103,7 @@ namespace ivi
        */
       void add_string_value(JsonBuilder * builder,
                             std::string const & name,
-                            std::string const & value);
+                            std::string const & value) const;
 
       /**
        * Begin the JSON formatted response to the Settings app
@@ -115,12 +115,12 @@ namespace ivi
        *
        * @param[in] result @c "succeeded" or @c "failed"
        */
-      unique_ptr<JsonBuilder> begin_response(char const * result);
+      unique_ptr<JsonBuilder> begin_response(char const * result) const;
 
       /**
        * End the JSON formatted response to the Settings app request.
        */
-      void end_response(unique_ptr<JsonBuilder> const & builder);
+      void end_response(unique_ptr<JsonBuilder> const & builder) const;
 
     private:
 
index e0af875..835b84d 100644 (file)
@@ -72,7 +72,7 @@ namespace ivi
        *                      pre-marshalled (in-memory) payload.
        */
       bool send_payload(char const * send_type,
-                        unique_ptr<JsonBuilder> const & builder);
+                        unique_ptr<JsonBuilder> const & builder) const;
 
       /**
        * Check if the WebSocket instance @a wsi corresponds to this
index 12cc69c..b4bf113 100644 (file)
@@ -37,7 +37,7 @@ ivi::settings::event_callback::event_callback(manager & mgr)
 
 bool
 ivi::settings::event_callback::send_event(
-  std::function<void(JsonBuilder *)> event_builder)
+  std::function<void(JsonBuilder *)> event_builder) const
 {
   unique_ptr<JsonBuilder> const builder = begin_event();
 
@@ -50,7 +50,7 @@ ivi::settings::event_callback::send_event(
 }
 
 ivi::settings::unique_ptr<JsonBuilder>
-ivi::settings::event_callback::begin_event()
+ivi::settings::event_callback::begin_event() const
 {
   // Construct JSON event string.
   unique_ptr<JsonBuilder> safe_builder(json_builder_new());
@@ -66,7 +66,7 @@ ivi::settings::event_callback::begin_event()
 
 void
 ivi::settings::event_callback::end_event(
-  ivi::settings::unique_ptr<JsonBuilder> const & builder)
+  ivi::settings::unique_ptr<JsonBuilder> const & builder) const
 {
   json_builder_end_object(builder.get());
 }
index 5ca8d2b..3f8ad7c 100644 (file)
@@ -210,7 +210,7 @@ ivi::settings::manager::unsubscribe_client(libwebsocket * wsi)
 
 bool
 ivi::settings::manager::send_event(
-  unique_ptr<JsonBuilder> const & builder)
+  unique_ptr<JsonBuilder> const & builder) const
 {
   bool success = true;
 
index aea12fd..95f9ea9 100644 (file)
@@ -103,7 +103,7 @@ namespace ivi
        *
        * @return @c true on success.
        */
-      bool send_event(unique_ptr<JsonBuilder> const & builder);
+      bool send_event(unique_ptr<JsonBuilder> const & builder) const;
 
     private:
 
@@ -150,7 +150,7 @@ namespace ivi
       map_type settings_;
 
       /// Mutex used to synchronize access to the send_callback list.
-      std::mutex mutex_;
+      mutable std::mutex mutex_;
 
       /**
        * List of client WebSockets to be used for sending events to
index 24bf616..eb77a86 100644 (file)
@@ -50,7 +50,7 @@ ivi::settings::response_callback::response_callback(
 
 bool
 ivi::settings::response_callback::send_response(
-  std::function<void(JsonBuilder *)> response_builder)
+  std::function<void(JsonBuilder *)> response_builder) const
 {
   unique_ptr<JsonBuilder> const builder = begin_response("succeeded");
 
@@ -73,7 +73,8 @@ ivi::settings::response_callback::send_response(
 }
 
 bool
-ivi::settings::response_callback::send_error(std::string error_message)
+ivi::settings::response_callback::send_error(
+  std::string error_message) const
 {
   unique_ptr<JsonBuilder> builder = begin_response("failed");
 
@@ -98,7 +99,7 @@ void
 ivi::settings::response_callback::add_string_value(
   JsonBuilder * builder,
   std::string const & name,
-  std::string const & value)
+  std::string const & value) const
 {
   json_builder_set_member_name(builder, name.c_str());
   if (value.empty())
@@ -108,7 +109,8 @@ ivi::settings::response_callback::add_string_value(
 }
 
 ivi::settings::unique_ptr<JsonBuilder>
-ivi::settings::response_callback::begin_response(char const * result)
+ivi::settings::response_callback::begin_response(
+  char const * result) const
 {
   // Construct JSON response.
   unique_ptr<JsonBuilder> safe_builder(json_builder_new());
@@ -127,7 +129,7 @@ ivi::settings::response_callback::begin_response(char const * result)
 
 void
 ivi::settings::response_callback::end_response(
-  ivi::settings::unique_ptr<JsonBuilder> const & builder)
+  ivi::settings::unique_ptr<JsonBuilder> const & builder) const
 {
   json_builder_end_object(builder.get());
 }
index 9330f8e..c243141 100644 (file)
@@ -56,7 +56,7 @@ ivi::settings::send_callback::operator=(send_callback const & other)
 bool
 ivi::settings::send_callback::send_payload(
   char const * send_type,
-  unique_ptr<JsonBuilder> const & builder)
+  unique_ptr<JsonBuilder> const & builder) const
 {
   unique_ptr<JsonGenerator> const generator(json_generator_new());
   unique_ptr<JsonNode> const root(json_builder_get_root(builder.get()));
index 57e1c64..22029ef 100644 (file)
@@ -1,3 +1,7 @@
+* Wed Dec 11 2013 Ossama Othman <ossama.othman@intel.com> accepted/tizen/20131207.002830@9d8e1e0
+- Bump version to 0.4.
+- Fix TIVI-{1191,1192,2108} by implementing a connman 'Agent'.
+
 * Wed Dec 04 2013 Ossama Othman <ossama.othman@intel.com> accepted/tizen_ivi_stable/20131119.040308@7e5f66d
 - Bump version to 0.3.
 - Support technology PropertyChanged signal reporting again.
index 13504d6..0f5a112 100644 (file)
@@ -1,6 +1,6 @@
 Name:          settingsd
 Summary:       Tizen IVI Settings Daemon
-Version:       0.3
+Version:       0.4
 Release:       1
 Group:         Application Framework/Settings
 License:       LGPL-2.1
@@ -83,6 +83,7 @@ ln -sf ../settingsd.socket %{buildroot}/%{_unitdir_user}/sockets.target.wants/
 %{_libdir}/libsettings.so.*
 %{pkglibdir}/*.so
 %config %{_sysconfdir}/%{name}/*
+%config %{_sysconfdir}/dbus-1/system.d/settings-agent.conf
 %{_unitdir_user}/settingsd.service
 %{_unitdir_user}/settingsd.socket
 %{_unitdir_user}/sockets.target.wants/settingsd.socket
index d452e63..c883485 100644 (file)
@@ -32,17 +32,23 @@ IVI_SETTINGS_PLUGIN_CPPFLAGS = \
 
 IVI_SETTINGS_PLUGIN_LIBRARY = $(top_builddir)/lib/libsettings.la
 
-connman_la_SOURCES =           \
-       dbus_connection.cpp     \
-       connman.cpp             \
-       connman_manager.cpp     \
-       connman_service.cpp     \
-       connman_technology.cpp  \
-       service.cpp             \
-       technology.cpp          \
-       clock.cpp               \
-       registration.cpp        \
-       subscription_manager.cpp
+## The D-Bus name that will be owned by the settings daemon's connman
+## Agent.
+IVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME = \
+       "$(IVI_SETTINGS_DBUS_NAME).connman.Agent"
+
+connman_la_SOURCES =                   \
+       dbus_connection.cpp             \
+       connman.cpp                     \
+       connman_manager.cpp             \
+       connman_service.cpp             \
+       connman_technology.cpp          \
+       service.cpp                     \
+       technology.cpp                  \
+       clock.cpp                       \
+       agent.cpp                       \
+       registration.cpp                \
+       subscription_manager.cpp        \
        $(BUILT_SOURCES)
 connman_la_CXXFLAGS = \
        $(IVI_SETTINGS_PLUGIN_CXXFLAGS) \
@@ -51,7 +57,9 @@ connman_la_CXXFLAGS = \
 connman_la_CFLAGS =                    \
        $(IVI_SETTINGS_PLUGIN_CFLAGS)   \
        $(GIO_CFLAGS)
-connman_la_CPPFLAGS = $(IVI_SETTINGS_PLUGIN_CPPFLAGS) 
+connman_la_CPPFLAGS = \
+       $(IVI_SETTINGS_PLUGIN_CPPFLAGS) \
+       -DIVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME='$(IVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME)'
 connman_la_LIBADD   = $(IVI_SETTINGS_PLUGIN_LIBRARY)
 connman_la_LDFLAGS  = -no-undefined   \
                       -module         \
@@ -70,6 +78,7 @@ noinst_HEADERS =              \
        service.hpp             \
        technology.hpp          \
        clock.hpp               \
+       agent.hpp               \
        subscription_manager.hpp
 
 dbus_codegen_verbose = $(dbus_codegen_verbose_$(V))
@@ -85,9 +94,32 @@ BUILT_SOURCES = \
        agent-glue.c \
        agent-glue.h
 
-CLEANFILES = $(BUILT_SOURCES)
+dbussystemconf_DATA = settings-agent.conf
+dbussystemconfdir = $(sysconfdir)/dbus-1/system.d/
+
+## Silent mode output for settingsd config file generation.
+config_verbose = $(config_verbose_$(V))
+config_verbose_ = $(config_verbose_$(AM_DEFAULT_VERBOSITY))
+config_verbose_0 = @echo CONFGEN $@;
+
+agent_name = $(IVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME)
+
+## The configure script won't fully expand $libdir so leverage `make'
+## based variable expansion instead.
+settings-agent.conf: Makefile settings-agent.conf.in
+       $(config_verbose)rm -f $@ $@.tmp; \
+       srcdir=''; \
+               test -f ./$@.in || srcdir=$(srcdir)/; \
+               sed \
+                       -e 's,@agent_name[@],$(agent_name),g' \
+                       $${srcdir}$@.in >$@.tmp; \
+       chmod 644 $@.tmp; \
+       mv $@.tmp $@
+
+
+CLEANFILES = $(BUILT_SOURCES) settings-agent.conf
 
 dist-hook:
        cd $(distdir); rm -f $(BUILT_SOURCES)
 
-EXTRA_DIST = agent.xml
+EXTRA_DIST = agent.xml settings-agent.conf.in
diff --git a/plugins/connman/agent.cpp b/plugins/connman/agent.cpp
new file mode 100644 (file)
index 0000000..97f5a14
--- /dev/null
@@ -0,0 +1,430 @@
+/**
+ * @file agent.cpp
+ *
+ * @brief Settings daemon D-Bus connection adapter.
+ *
+ * @author Michael Leibowitz @<michael.leibowitz@@intel.com@>
+ * @author Ossama Othman @<ossama.othman@@intel.com@>
+ *
+ * @copyright @par
+ * Copyright 2013 Intel Corporation All Rights Reserved.
+ * @par
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ * @par
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * @par
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ */
+
+#include "agent.hpp"
+#include "../../lib/config.hpp"
+
+#include <settingsd/glib_traits.hpp>
+#include <settingsd/unique_ptr.hpp>
+
+#include <cstring>
+#include <string>
+#include <algorithm>
+#include <stdexcept>
+
+
+namespace
+{
+  // --------------------------------------------------------------
+  //                  D-Bus Name Acquisition
+  // --------------------------------------------------------------
+  /**
+   * @brief Callback function invoked when a D-Bus name is acquired.
+   *
+   * @param[in] connection The D-Bus connection on which the name was
+   *                       acquired.
+   * @param[in] name       The name being owned.
+   * @param[in] user_data  User-provided data.
+   */
+  void
+  on_name_acquired(GDBusConnection * /* connection */,
+                   gchar const * name,
+                   gpointer /* user_data */)
+  {
+    g_debug("Name \"%s\" acquired on D-Bus.\n", name);
+  }
+
+  /**
+   * @brief Callback function invoked when a D-Bus name is no longer
+   *        owned or the D-Bus connection has been closed.
+   *
+   * @param[in] connection The D-Bus connection on which the name was
+   *                       acquired.
+   * @param[in] name       The name being owned.
+   * @param[in] user_data  User-provided data.
+   *
+   */
+  void
+  on_name_lost(GDBusConnection * /* connection */,
+               gchar const * name,
+               gpointer /* user_data */)
+  {
+    // This can happen if the appropriate D-Bus policy is not
+    // installed, for example.
+    throw std::runtime_error(std::string("Lost name \"")
+                             + name + "\" on D-Bus!");
+  }
+
+  // --------------------------------------------------------------
+  //                   Connman Agent Handlers
+  // --------------------------------------------------------------
+  /**
+   * @class agent_operation_handler
+   *
+   * @brief Handle agent operations through given callback.
+   *
+   * This class factors out common connection data retrieval code, and
+   * performs Agent operations through the given callback.
+   */
+  class agent_operation_handler
+  {
+    typedef ivi::settings::agent agent;
+    typedef agent::user_data data_type;
+
+    // Prevent copying.
+    agent_operation_handler(agent_operation_handler const &) = delete;
+    void operator=(agent_operation_handler const &) = delete;
+
+  public:
+
+    /**
+     * Constructor
+     *
+     * @param[in] service   D-Bus object path for connman service
+     * @param[in] user_data User/connection data
+     * @param[in] callback  Callback that implements Agent operation
+     */
+    agent_operation_handler(
+      gchar const * service,
+      gpointer user_data,
+      std::function<void(ivi::settings::agent::connect_data const &)>
+        callback)
+      : data_(static_cast<data_type *>(user_data))
+      , guard_(data_->lock)
+      , iterator_(data_->info.find(service))
+    {
+      // data_ should never be null!
+
+      if (iterator_ != data_->info.end())
+        callback(iterator_->second);
+    }
+
+    /// Destructor
+    ~agent_operation_handler()
+    {
+      // Done with the connection data.  Remove it from the map.
+      if (iterator_ != data_->info.end())
+        data_->info.erase(iterator_);
+    }
+
+  private:
+    /// User/connection data.
+    data_type * const data_;
+
+    /**
+     * Synchronize access to the user/connection data map.
+     *
+     * @note This lock will be held for the life of the
+     *       @c agent_operation_handler object, i.e. for the duration
+     *       of the operation.  This is needed to synchronize the map
+     *       @c erase() operation in the destructor.  The erase()
+     *       operation is performed in the destructor to ensure
+     *       element removal occurs if an exception is thrown by the
+     *       callback.
+     */
+    std::lock_guard<std::mutex> guard_;
+
+    /// Map iterator that points to the connection data.
+    agent::user_data::map_type::iterator const iterator_;
+  };
+
+  bool
+  on_handle_release(Agent * object,
+                    GDBusMethodInvocation * invocation,
+                    gpointer /* user_data */)
+  {
+    agent_complete_release(object, invocation);
+    return true;
+  }
+
+  bool
+  on_handle_report_error(Agent * object,
+                         GDBusMethodInvocation * invocation,
+                         gchar const * service,
+                         gchar const * error,
+                         gpointer user_data)
+  {
+    using ivi::settings::agent;
+
+    agent_operation_handler(service,
+                            user_data,
+                            [error](agent::connect_data const & d){
+                              d.response.send_error(std::string(error));
+                            });
+
+    agent_complete_report_error(object, invocation);
+
+    return true;
+  }
+
+  bool
+  on_handle_request_browser(Agent * object,
+                            GDBusMethodInvocation * invocation,
+                            gchar const * /* service */,
+                            gchar const * /* url */,
+                            gpointer /* user_data */)
+  {
+    agent_complete_request_browser(object, invocation);
+    return true;
+  }
+
+  bool
+  on_handle_request_input(Agent * object,
+                          GDBusMethodInvocation * invocation,
+                          gchar const * service,
+                          GVariant * fields,
+                          gpointer user_data)
+  {
+    using ivi::settings::agent;
+
+    agent_operation_handler(
+      service,
+      user_data,
+      [object, invocation, fields](agent::connect_data const & d){
+        using ivi::settings::unique_ptr;
+
+        // Prepare to build a dictionary, i.e. an array of
+        // dictionary entries, "a{sv}".
+        GVariantBuilder builder;
+        g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+
+        bool error_occurred = false;
+        bool found_field = false;
+
+        // Extract requested mandatory and alternate fields.
+        GVariantIter * vi = nullptr;
+        g_variant_get(fields, "a{sv}", &vi);
+        unique_ptr<GVariantIter> const iter(vi);
+
+        gchar    * fname  = nullptr;
+        GVariant * fvalue = nullptr;
+
+        /**
+         * @todo Refactor this GVariant dictionary iteration code.
+         */
+        while (g_variant_iter_next(vi, "{sv}", &fname, &fvalue)) {
+          //
+          unique_ptr<gchar>    const field(fname);
+          unique_ptr<GVariant> const arguments(fvalue);
+
+          GVariantIter * ai = nullptr;
+          g_variant_get(arguments.get(), "a{sv}", &ai);
+          unique_ptr<GVariantIter> const iter(ai);
+
+          gchar    * argname  = nullptr;
+          GVariant * argvalue = nullptr;
+
+          while (g_variant_iter_next(ai, "{sv}", &argname, &argvalue)) {
+            unique_ptr<gchar>    const name(argname);
+            unique_ptr<GVariant> const value(argvalue);
+
+            // Determine which requested fields are mandatory.
+            if (strcmp(argname, "Requirement") == 0
+                && strcmp(g_variant_get_string(argvalue, nullptr),
+                          "mandatory") == 0) {
+              // Check if we were supplied the required field, and add
+              // it to the dictionary result.
+              auto const i = d.info.find(fname);
+              if (i != d.info.end()) {
+                // Note that the dictionary is of the form a{sv} so
+                // we wrap the dictionary string value in a variant.
+                g_variant_builder_add_value(
+                  &builder,
+                  g_variant_new_dict_entry(
+                    g_variant_new_string(fname),
+                    g_variant_new_variant(
+                      g_variant_new_string(i->second.c_str()))));
+
+                /**
+                 * @todo Is there any way to tell if an entry was
+                 *       added to the indefinite array being
+                 *       constructed through the glib GVariant builder
+                 *       interface?  We can't get rid of this flag if
+                 *       that is the case.
+                 */
+                found_field = true;
+              } else {
+                std::string err(
+                  std::string("Required connection field \"")
+                  + fname
+                  + "\" not supplied.");
+
+                /**
+                 * @todo This send_error() call is probably
+                 *       redundant.  Look into removing it.
+                 */
+                d.response.send_error(err);
+
+                /**
+                 * @bug Register a settingsd-specific error during
+                 *      initialization via
+                 *      @c g_dbus_error_register_error(), and use it
+                 *      in this call instead.
+                 */
+                g_dbus_method_invocation_return_dbus_error(
+                  invocation,
+                  "net.connman.Agent.Error.Canceled",
+                  err.c_str());
+
+                error_occurred = true;
+
+                return;
+              }
+            }
+          }
+        }
+
+        if (!error_occurred) {
+          GVariant * dictionary = nullptr;
+
+          // We can't call g_variant_builder_end() if no children
+          // (dictionary entries) were added to the indefinite array
+          // being constructed through the builder.
+          if (found_field)
+            dictionary = g_variant_builder_end(&builder);
+
+          // The method return value will contain a dictionary,
+          // i.e. "a{sv}", of the requested input fields.
+          agent_complete_request_input(object, invocation, dictionary);
+        }
+      });
+
+    return true;
+  }
+
+  bool
+  on_handle_cancel(Agent * object,
+                   GDBusMethodInvocation * invocation,
+                   gpointer /* user_data */)
+  {
+    agent_complete_cancel(object, invocation);
+    return true;
+  }
+}
+
+// ----------------------------------------------------------------
+
+ivi::settings::agent::agent(GDBusConnection * connection)
+  : owner_id_(
+      // The bus name will be of the form:
+      //     "org.tizen.settingsd.connman.Agent"
+      g_bus_own_name_on_connection(connection,
+                                   IVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME,
+                                   G_BUS_NAME_OWNER_FLAGS_NONE,
+                                   on_name_acquired,
+                                   on_name_lost,
+                                   nullptr, // user_data,
+                                   nullptr))
+  , interface_(agent_skeleton_new())
+  , object_path_("/" IVI_SETTINGS_DBUS_NAME "/connman/Agent")
+  , data_()
+{
+  // Construct object path of the form:
+  //     /org/tizen/settingsd/connman/Agent"
+  std::replace(object_path_.begin(), object_path_.end(), '.', '/');
+
+  // Connect the signal handlers corresponding to the Agent
+  // interface.
+  g_signal_connect(interface_,
+                   "handle-release",
+                   G_CALLBACK(on_handle_release),
+                   &data_);
+
+  g_signal_connect(interface_,
+                   "handle-report-error",
+                   G_CALLBACK(on_handle_report_error),
+                   &data_);
+
+  g_signal_connect(interface_,
+                   "handle-request-browser",
+                   G_CALLBACK(on_handle_request_browser),
+                   &data_);
+
+  g_signal_connect(interface_,
+                   "handle-request-input",
+                   G_CALLBACK(on_handle_request_input),
+                   &data_);
+
+  g_signal_connect(interface_,
+                   "handle-cancel",
+                   G_CALLBACK(on_handle_cancel),
+                   &data_);
+
+  // Export the interface on the bus.
+  GError * error = nullptr;
+  if (!g_dbus_interface_skeleton_export(
+        G_DBUS_INTERFACE_SKELETON(interface_),
+        connection,
+        object_path_.c_str(),
+        &error)) {
+    unique_ptr<GError> safe_error(error);
+    throw std::runtime_error(error->message);
+  }
+}
+
+ivi::settings::agent::~agent()
+{
+  if (interface_ != nullptr) {
+    g_dbus_interface_skeleton_unexport(
+      G_DBUS_INTERFACE_SKELETON(interface_));
+    g_object_unref(interface_);
+  }
+
+  g_bus_unown_name(owner_id_);
+}
+
+bool
+ivi::settings::agent::register_connect_data(
+  char const * service_path,
+  std::map<std::string, std::string> && info,
+  response_callback const & response)
+{
+  connect_data data(std::move(info), response);
+
+  std::lock_guard<std::mutex> guard(data_.lock);
+
+  auto const result =
+    data_.info.insert(
+      std::make_pair(service_path, std::move(data)));
+
+  return result.second;
+}
+
+bool
+ivi::settings::agent::deregister_connect_data(char const * service_path)
+{
+  std::lock_guard<std::mutex> guard(data_.lock);
+
+  return data_.info.erase(service_path) == 1;
+}
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End:
diff --git a/plugins/connman/agent.hpp b/plugins/connman/agent.hpp
new file mode 100644 (file)
index 0000000..65159f2
--- /dev/null
@@ -0,0 +1,188 @@
+/**
+ * @file agent.hpp
+ *
+ * @brief Connman agent implementation header.
+ *
+ * @author Ossama Othman @<ossama.othman@@intel.com@>
+ *
+ * @copyright @par
+ * Copyright 2013 Intel Corporation All Rights Reserved.
+ * @par
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * @par
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * @par
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ *
+ * @note This is an internal header.
+ */
+
+#ifndef IVI_SETTINGS_AGENT_HPP
+#define IVI_SETTINGS_AGENT_HPP
+
+#include "agent-glue.h"
+
+#include <settingsd/response_callback.hpp>
+
+#include <string>
+#include <map>
+#include <mutex>
+
+
+namespace ivi
+{
+  namespace settings
+  {
+    class agent
+    {
+    public:
+
+      typedef std::map<std::string, std::string> connect_info_map_type;
+
+      /**
+       * Constructor.
+       *
+       * @param[in] connection D-Bus connection on which agent will be
+       *                       exported.
+       */
+      agent(GDBusConnection *connection);
+
+      /// Destructor.
+      ~agent();
+
+      /**
+       * Register data that may be needed when handling Connman Agent
+       * method calls.
+       */
+      bool register_connect_data(char const * service_path,
+                                 connect_info_map_type && info,
+                                 response_callback const & response);
+
+      /**
+       * Deregister connectio data.
+       */
+      bool deregister_connect_data(char const * service_path);
+
+      /// Get D-Bus object path for this @c Agent.
+      char const *
+      object_path() const
+      {
+        return object_path_.c_str();
+      }
+
+      /**
+       * @struct connect_data
+       *
+       * @brief Connman Service object-specific connect data.
+       *
+       * An instance of this structure will be created each time a
+       * Connman connection operation will be performed in case
+       * Connman needs additional information, such as a passphrase,
+       * to complete a connection.
+       */
+      struct connect_data
+      {
+        /**
+         * Constructor.
+         *
+         * @param[in] info_map Map of Connman Agent API field name to
+         *                     value.
+         * @param[in] resp     Callback object through which responses
+         *                     will be sent to the caller
+         *                     (e.g. Settings app).
+         */
+        connect_data(connect_info_map_type && info_map,
+                     response_callback const & resp)
+          : info(info_map)
+          , response(resp)
+        {
+        }
+
+        /// Move constructor.
+        connect_data(connect_data && other)
+          : info(std::move(other.info))
+          , response(other.response)
+        {
+        }
+
+        /// Disallow copy construction and assignment.
+        connect_data(connect_data const &) = delete;
+        void operator=(connect_data const &) = delete;
+
+        /**
+         * Map of Connman Agent API field name to value.
+         */
+        std::map<std::string, std::string> info;
+
+        /**
+         * The response callback through errors will be sent to the
+         * caller.
+         */
+        response_callback response;
+      };
+
+      /**
+       * @struct user_data
+       *
+       * @brief Wrapper for data passed to Connman Agent method
+       *        handlers.
+       */
+      struct user_data
+      {
+        /// Synchronize access to the response/request data map.
+        std::mutex lock;
+
+        typedef std::map<std::string, connect_data> map_type;
+
+        /**
+         * Map of service D-Bus object path to request/response
+         * data.
+         */
+        map_type info;
+      };
+
+    private:
+
+      /**
+       * @name Prevent copying
+       */
+      //@{
+      agent(agent const &) = delete;
+      agent & operator=(agent const &) = delete;
+      //@}
+
+    private:
+
+      /// ID corresponding to owned name on D-Bus system bus.
+      guint const owner_id_;
+
+      /// GDBus Agent skeleton object.
+      Agent * const interface_;
+
+      /// D-Bus object path for this @c Agent.
+      std::string object_path_;
+
+      /// Service connect map, data, etc.
+      user_data data_;
+
+    };
+  }
+}
+
+#endif  /* IVI_SETTINGS_AGENT_HPP */
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End:
index 1ba7ae2..2435573 100644 (file)
@@ -49,6 +49,7 @@
     <method name="RequestInput">
       <arg name="service" direction="in" type="o"/>
       <arg name="fields" direction="in" type="a{sv}"/>
+      <arg name="response" direction="out" type="a{sv}"/>
     </method>
 
     <method name="Cancel"/>
index f0ff628..fcb8fa3 100644 (file)
@@ -30,6 +30,7 @@
 #include <settingsd/glib_traits.hpp>
 #include <settingsd/json_glib_traits.hpp>
 #include <settingsd/unique_ptr.hpp>
+#include <settingsd/dbus_signal_callback.hpp>
 
 #include <cstring>
 #include <boost/lexical_cast.hpp>
 
 ivi::settings::clock::clock(GDBusConnection * connection,
                             event_callback const & e)
-  : connman_("net.connman.Clock", "/", connection, e)
+  : connman_("net.connman.Clock", "/", connection)
+  , event_callback_(e)
+  , subscription_id_(
+    g_dbus_connection_signal_subscribe(
+      connection,
+      nullptr,
+      connman_.interface_name(),
+      "PropertyChanged",
+      connman_.object_path(),
+      nullptr,
+      G_DBUS_SIGNAL_FLAGS_NONE,
+      on_dbus_signal,
+      &event_callback_,
+      nullptr))
 {
 }
 
 ivi::settings::clock::~clock()
 {
+  g_dbus_connection_signal_unsubscribe(
+    connman_.connection(),
+    subscription_id_);
 }
 
 std::string const &
index 636c6b9..64a1796 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "connman.hpp"
 #include <settingsd/plugin.hpp>
+#include <settingsd/event_callback.hpp>
 
 #include <json-glib/json-glib.h>
 
@@ -119,6 +120,12 @@ namespace ivi
       /// Underlying connman proxy.
       connman connman_;
 
+      /// Callback through which events will be sent to clients.
+      event_callback event_callback_;
+
+      /// PropertyChanged signal subscription ID.
+      guint const subscription_id_;
+
     };
 
   }
index 707111b..f2b586a 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <settingsd/glib_traits.hpp>
 #include <settingsd/unique_ptr.hpp>
-#include <settingsd/dbus_signal_callback.hpp>
 
 #include <cstring>
 #include <string>
 
 ivi::settings::connman::connman(char const * interface,
                                 char const * path,
-                                GDBusConnection * connection,
-                                event_callback const & e)
+                                GDBusConnection * connection)
   : proxy_(nullptr)
-  , event_callback_(e)
-  , subscription_id_(0)
 {
   static char const name[] = "net.connman";  // Service
 
@@ -67,31 +63,12 @@ ivi::settings::connman::connman(char const * interface,
 
     throw std::runtime_error(error->message);
   }
-
-  // Listen for changes to properties.
-  subscription_id_ =
-      g_dbus_connection_signal_subscribe(
-        connection,
-        nullptr,
-        interface,
-        "PropertyChanged",
-        path,
-        nullptr,
-        G_DBUS_SIGNAL_FLAGS_NONE,
-        on_dbus_signal,
-        &event_callback_,
-        nullptr);
 }
 
 ivi::settings::connman::~connman()
 {
-  if (proxy_ != nullptr) {
-    g_dbus_connection_signal_unsubscribe(
-      g_dbus_proxy_get_connection(G_DBUS_PROXY(proxy_)),
-      subscription_id_);
-
+  if (proxy_ != nullptr)
     g_object_unref(proxy_);
-  }
 }
 
 GVariant *
index de4a7b4..e722c99 100644 (file)
@@ -28,8 +28,6 @@
 #ifndef IVI_SETTINGS_CONNMAN_HPP
 #define IVI_SETTINGS_CONNMAN_HPP
 
-#include <settingsd/event_callback.hpp>
-
 #include <gio/gio.h>
 
 
@@ -55,13 +53,10 @@ namespace ivi
        * @param[in] interface  Connman D-Bus interface.
        * @param[in] path       Connman D-Bus object path.
        * @param[in] connection Underlying D-Bus connection.
-       * @param[in] e          Callback through which events will be
-       *                       sent to clients.
        */
       connman(char const * interface,
               char const * path,
-              GDBusConnection * connection,
-              event_callback const & e);
+              GDBusConnection * connection);
 
       /// Destructor.
       ~connman();
@@ -112,12 +107,6 @@ namespace ivi
       /// The proxy used to access the Connman D-Bus API.
       GDBusProxy * proxy_;
 
-      /// Callback through which events will be sent to clients.
-      event_callback event_callback_;
-
-      /// PropertyChanged signal subscription ID.
-      guint subscription_id_;
-
     };
 
   }
index 79a70eb..dae076a 100644 (file)
@@ -32,6 +32,7 @@
 #include <settingsd/unique_ptr.hpp>
 
 #include <cstring>
+#include <stdexcept>
 
 // ----------------------------------------------------------------------
 
@@ -107,8 +108,7 @@ ivi::settings::connman_manager::connman_manager(
   event_callback const & e)
   : connman_("net.connman.Manager",     // Interface
              "/",                       // Object path
-             connection,
-             e)
+             connection)
   , data_(connection, e)
   , technology_added_id_(subscribe_to_signal(connection,
                                              "TechnologyAdded",
@@ -122,6 +122,7 @@ ivi::settings::connman_manager::connman_manager(
                                              "ServicesChanged",
                                              on_dbus_signal,
                                              &data_.callback))
+  , agent_(connection)
 {
   // The ServicesChanged signal parameters are:
   //
@@ -137,17 +138,13 @@ ivi::settings::connman_manager::connman_manager(
    *       method.
    */
   // Subscribe to PropertyChanged signal for all technologies.
-  constexpr gint const timeout = 5000;  // milliseconds
   GError * error = nullptr;
 
   unique_ptr<GVariant> const dictionary(
-    g_dbus_proxy_call_sync(connman_.proxy(),
-                           "GetTechnologies",
-                           nullptr,  // No parameters
-                           G_DBUS_CALL_FLAGS_NONE,
-                           timeout,
-                           nullptr,  // Not cancellable
-                           &error));
+    call_method("GetTechnologies",
+                nullptr,  // No parameters,
+                error));
+
   unique_ptr<GError> safe_error(error);
 
   if (dictionary != nullptr) {
@@ -171,10 +168,50 @@ ivi::settings::connman_manager::connman_manager(
                                     tech_path);
     }
   }
+
+  // Register the Agent implementation responsible for handling input
+  // requests for secure and hidden networks.
+  if (!g_variant_is_object_path(agent_.object_path())) {
+    throw std::runtime_error(std::string("Invalid Agent object path: ")
+                             + agent_.object_path());
+  }
+
+  error = nullptr;
+  unique_ptr<GVariant> const ret(
+    call_method("RegisterAgent",
+                g_variant_new("(o)",
+                              agent_.object_path()),
+                error));
+
+  if (ret == nullptr) {
+    safe_error.reset(error);
+
+     throw std::runtime_error(
+       std::string("Unable to register agent: ") + error->message);
+  }
 }
 
 ivi::settings::connman_manager::~connman_manager()
 {
+  // Unregister agent.
+  if (g_variant_is_object_path(agent_.object_path())) {
+    GError * error = nullptr;
+
+    unique_ptr<GVariant> const ret(
+      call_method("UnregisterAgent",
+                  g_variant_new("(o)",
+                                agent_.object_path()),
+                  error));
+
+    if (ret == nullptr) {
+      unique_ptr<GError> const safe_error(error);
+
+      g_warning("Unable to unregister agent: %s\n", error->message);
+    }
+  }
+
+  // Unsubscribe from ServicesChanged, TechnologyRemoved and
+  // TechnologyAdded signals.
   g_dbus_connection_signal_unsubscribe(connman_.connection(),
                                        services_changed_id_);
   g_dbus_connection_signal_unsubscribe(connman_.connection(),
@@ -226,21 +263,33 @@ ivi::settings::connman_manager::handle_request(
   }
 }
 
+bool
+ivi::settings::connman_manager::register_connect_data(
+  char const * service_path,
+  std::map<std::string, std::string> && info,
+  response_callback const & response)
+{
+  return agent_.register_connect_data(service_path,
+                                      std::move(info),
+                                      response);
+}
+
+bool
+ivi::settings::connman_manager::deregister_connect_data(
+  char const * service_path)
+{
+  return agent_.deregister_connect_data(service_path);
+}
+
 GVariant *
 ivi::settings::connman_manager::get_properties(
   std::string const & technology,
   GError *& error) const
 {
-  constexpr gint const timeout = 5000;  // milliseconds
-
   unique_ptr<GVariant> const dictionary(
-    g_dbus_proxy_call_sync(connman_.proxy(),
-                           "GetTechnologies",
-                           nullptr,  // No parameters
-                           G_DBUS_CALL_FLAGS_NONE,
-                           timeout,
-                           nullptr,  // Not cancellable
-                           &error));
+    call_method("GetTechnologies",
+                nullptr,  // No parameters,
+                error));
 
   if (dictionary != nullptr) {
     GVariantIter * i = nullptr;
@@ -255,7 +304,7 @@ ivi::settings::connman_manager::get_properties(
       unique_ptr<GVariant> const tmp(
         g_variant_get_child_value(child.get(), 0));
 
-      char const * object =
+      char const * const object =
         g_variant_get_string(tmp.get(), nullptr);
 
       // The technology is found at end the object path,
@@ -280,44 +329,68 @@ void
 ivi::settings::connman_manager::get_services(
   response_callback & response) const
 {
-  call_method("GetServices", response);
+  constexpr char name[] = "GetServices";
+  GError * error = nullptr;
+
+  unique_ptr<GVariant> ret(call_method(name,
+                                       nullptr,  // No parameters
+                                       error));
+
+  unique_ptr<GError> safe_error(error);
+
+  handle_return_value(name, ret.get(), error, response);
 }
 
 void
 ivi::settings::connman_manager::get_technologies(
   response_callback & response) const
 {
-  call_method("GetTechnologies", response);
+  constexpr char name[] = "GetTechnologies";
+  GError * error = nullptr;
+
+  unique_ptr<GVariant> ret(call_method(name,
+                                       nullptr,  // No parameters
+                                       error));
+
+  unique_ptr<GError> safe_error(error);
+
+  handle_return_value(name, ret.get(), error, response);
 }
 
-void
+GVariant *
 ivi::settings::connman_manager::call_method(
   char const * name,
-  response_callback & response) const
+  GVariant * parameters,
+  GError *& error) const
 {
   constexpr gint const timeout = 5000;  // milliseconds
-  GError * error = nullptr;
 
-  unique_ptr<GVariant> ret(
+  return
     g_dbus_proxy_call_sync(connman_.proxy(),
                            name,
-                           nullptr,  // No parameters
+                           parameters,
                            G_DBUS_CALL_FLAGS_NONE,
                            timeout,
                            nullptr,  // Not cancellable
-                           &error));
-
-  unique_ptr<GError> safe_error(error);
+                           &error);
+}
 
+void
+ivi::settings::connman_manager::handle_return_value(
+  char const * name,
+  GVariant * ret,
+  GError * error,
+  response_callback & response) const
+{
   if (ret != nullptr) {
     response.send_response(
-      [&ret](JsonBuilder * builder)
+      [ret](JsonBuilder * builder)
       {
         /**
          * @todo Can @c json_gvariant_serialize() ever return a nullptr?
          */
         JsonNode * const value =
-          json_gvariant_serialize(ret.get());
+          json_gvariant_serialize(ret);
 
         json_builder_set_member_name(builder, "value");
         json_builder_add_value(builder, value);
@@ -350,7 +423,6 @@ ivi::settings::connman_manager::subscribe_to_signal(
                                        nullptr);
 }
 
-
 // Local Variables:
 // mode:c++
 // c-basic-offset:2
index e96542d..8d06494 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "connman.hpp"
 #include "subscription_manager.hpp"
+#include "agent.hpp"
 
 #include <settingsd/plugin.hpp>
 #include <settingsd/event_callback.hpp>
@@ -76,6 +77,19 @@ namespace ivi
       //@}
 
       /**
+       * Register data that may be needed when handling Connman Agent
+       * method calls.
+       */
+      bool register_connect_data(char const * service_path,
+                                 std::map<std::string, std::string> && info,
+                                 response_callback const & response);
+
+      /**
+       * Deregister connection data.
+       */
+      bool deregister_connect_data(char const * service_path);
+
+      /**
        * Get the properties for a specific technology.
        *
        * @param[in] technology Connman technology for which properties
@@ -125,17 +139,31 @@ namespace ivi
       void get_technologies(response_callback & response) const;
 
       /**
-       * Call the method @a name on the connman Manager object.  This
-       * method is meant to be used for @c GetServices and
-       * @c GetTechnologies requests.
+       * Call the method @a name on the connman Manager object.
+       *
+       * @param[in]    name       The connman Manager object method
+       *                          name.
+       * @param[in]    parameters Method parameters.
+       * @param[inout] error      Pointer to error object containing
+       *                          failure related information.  Caller
+       *                          must deallocate if it is not null.
        *
-       * @param[in]    name     The connman Manager object method
-       *                        name.
-       * @param[inout] response Callback used to inform the caller of
-       *                        the results.
+       * @return Variant containing result of underlying Connman
+       *         Manager D-Bus call.  The caller must release the
+       *         returned @c GVariant.
        */
-      void call_method(char const * name,
-                       response_callback & response) const;
+      GVariant * call_method(char const * name,
+                             GVariant * parameters,
+                             GError *& error) const;
+
+
+      /**
+       * Send response or error to client that initiated the request.
+       */
+      void handle_return_value(char const * name,
+                               GVariant * ret,
+                               GError * error,
+                               response_callback & response) const;
 
       typedef void (*ivi_signal_callback)(GDBusConnection * connection,
                                           char const * sender_name,
@@ -168,6 +196,12 @@ namespace ivi
       /// ServicesChanged signal subscription ID.
       guint const services_changed_id_;
 
+      /**
+       * The connman Agent implemention that handles secure and
+       * hidden network related requests.
+       */
+      agent agent_;
+
     };
 
   }
index 143087d..5c3714d 100644 (file)
@@ -45,9 +45,9 @@ namespace
 
 ivi::settings::connman_service::connman_service(
   GDBusConnection * connection,
-  event_callback const & e)
+  connman_manager & manager)
   : connection_(connection)
-  , event_callback_(e)
+  , manager_(manager)
 {
 }
 
@@ -90,8 +90,8 @@ ivi::settings::connman_service::handle_request(
       json_reader_end_element(reader);
 
       if (path != nullptr) {
-        service s(path, connection_, event_callback_);
-        s.handle_request(name, reader, response);
+        service s(path, connection_);
+        s.handle_request(name, reader, manager_, response);
       }
     }
     json_reader_end_member(reader);
index c76902c..bbd9dcd 100644 (file)
@@ -30,7 +30,6 @@
 #include "connman.hpp"
 
 #include <settingsd/plugin.hpp>
-#include <settingsd/event_callback.hpp>
 
 #include <gio/gio.h>
 
@@ -57,7 +56,7 @@ namespace ivi
 
       /// Constructor.
       connman_service(GDBusConnection * connection,
-                      event_callback const & e);
+                      connman_manager & manager);
 
       /// Destructor.
       ~connman_service();
@@ -81,8 +80,11 @@ namespace ivi
       /// The underlying D-Bus connection.
       GDBusConnection * const connection_;
 
-      /// Callback through which events will be sent to clients.
-      event_callback event_callback_;
+      /**
+       * The object used to register connection information for use
+       * by the Connman Agent.
+       */
+      connman_manager & manager_;
 
     };
 
index b44d59e..89033a9 100644 (file)
@@ -45,14 +45,11 @@ namespace
 
 ivi::settings::connman_technology::connman_technology(
   GDBusConnection * connection,
-  connman_manager & manager,
-  event_callback const & e)
+  connman_manager & manager)
   : connman_("net.connman.Technology",     // Interface
              "/",                       // Object path
-             connection,
-             e)
+             connection)
   , manager_(manager)
-  , event_callback_(e)
 {
 }
 
@@ -95,10 +92,7 @@ ivi::settings::connman_technology::handle_request(
       json_reader_end_element(reader);
 
       if (path != nullptr) {
-        technology t(path,
-                     connman_.connection(),
-                     manager_,
-                     event_callback_);
+        technology t(path, connman_.connection(), manager_);
         t.handle_request(name, reader, response);
       }
     }
index ad8b78c..09e30f9 100644 (file)
@@ -30,7 +30,6 @@
 #include "connman.hpp"
 
 #include <settingsd/plugin.hpp>
-#include <settingsd/event_callback.hpp>
 
 #include <gio/gio.h>
 
@@ -57,8 +56,7 @@ namespace ivi
 
       /// Constructor.
       connman_technology(GDBusConnection * connection,
-                         connman_manager & manager,
-                         event_callback const & e);
+                         connman_manager & manager);
 
       /// Destructor.
       ~connman_technology();
@@ -85,9 +83,6 @@ namespace ivi
       /// The proxy used to access the connman Manager D-Bus API.
       connman_manager & manager_;
 
-      /// Callback through which events will be sent to clients.
-      event_callback event_callback_;
-
     };
 
   }
index 51f4aaa..edc4fe5 100644 (file)
@@ -59,10 +59,10 @@ register_settings(ivi::settings::registrar & r,
   std::unique_ptr<ivi::settings::plugin> manager(mgr);
 
   std::unique_ptr<ivi::settings::plugin> service(
-    new ivi::settings::connman_service(connection, e));
+    new ivi::settings::connman_service(connection, *mgr));
 
   std::unique_ptr<ivi::settings::plugin> technology(
-    new ivi::settings::connman_technology(connection, *mgr, e));
+    new ivi::settings::connman_technology(connection, *mgr));
 
   std::unique_ptr<ivi::settings::plugin> clk(
     new ivi::settings::clock(connection, e));
index 8d25157..c956cb6 100644 (file)
 
 
 ivi::settings::service::service(std::string service_path,
-                                GDBusConnection * connection,
-                                event_callback const & e)
+                                GDBusConnection * connection)
   : connman_("net.connman.Service",     // Interface
              service_path.c_str(),      // Object path
-             connection,
-             e)
+             connection)
 {
 }
 
 void
 ivi::settings::service::handle_request(char const * name,
                                        JsonReader * reader,
+                                       connman_manager & manager,
                                        response_callback & response)
 {
   if (name != nullptr) {
     if (strcmp(name, "connect") == 0)
-      connect(reader, response);
+      connect(reader, manager, response);
     else if (strcmp(name, "disconnect") == 0)
-      disconnect(reader, response);
+      disconnect(reader, manager, response);
     else {
       response.send_error(
         std::string("Unrecognized connman service request name: ")
@@ -62,14 +61,56 @@ ivi::settings::service::handle_request(char const * name,
 }
 
 void
-ivi::settings::service::connect(JsonReader * /* reader */,
+ivi::settings::service::connect(JsonReader * reader,
+                                connman_manager & manager,
                                 response_callback response)
 {
+  bool successful_parse = false;
+
+  typedef agent::connect_info_map_type map_type;
+  map_type info;
+
+  // The service connection information is found in the second array
+  // element.
+  if (json_reader_read_element(reader, 1)
+      && json_reader_is_object(reader)) {
+    gint const count = json_reader_count_members(reader);
+    for (gint i = 0; i < count; ++i) {
+      if (json_reader_read_element(reader, i)) {
+        char const * const name  = json_reader_get_member_name(reader);
+        char const * const value = json_reader_get_string_value(reader);
+
+        if (name != nullptr && value != nullptr)
+          info.insert(std::make_pair(name, value));
+      }
+      json_reader_end_element(reader);
+    }
+
+    // This cast is safe.
+    if (static_cast<gint>(info.size()) == count) {
+      successful_parse = true;
+    }
+  }
+  json_reader_end_element(reader);
+
+  if (!successful_parse) {
+    response.send_error("Unable to parse service connection information.");
+    return;
+  }
+
+  if (!manager.register_connect_data(connman_.object_path(),
+                                     std::move(info),
+                                     response)) {
+    response.send_error("Unable to register connection information.");
+    return;
+  }
+
   call_method("Connect", response);
 }
 
 void
 ivi::settings::service::disconnect(JsonReader * reader,
+                                   connman_manager & manager,
                                    response_callback response)
 {
   bool null = false;
@@ -86,13 +127,15 @@ ivi::settings::service::disconnect(JsonReader * reader,
   }
 
   call_method("Disconnect", response);
+
+  manager.deregister_connect_data(connman_.object_path());
 }
 
 void
 ivi::settings::service::call_method(char const * name,
                                     response_callback response)
 {
-  constexpr gint const timeout = 10000;  // milliseconds
+  constexpr gint const timeout = 15000;  // milliseconds
   GError * error = nullptr;
 
   unique_ptr<GVariant> const ret(
index 56c9b62..f5c33b5 100644 (file)
@@ -59,8 +59,7 @@ namespace ivi
        *                         sent to clients.
        */
       service(std::string service_path,
-              GDBusConnection * connection,
-              event_callback const & e);
+              GDBusConnection * connection);
 
       /**
        * Handle connman Service object request.
@@ -74,16 +73,19 @@ namespace ivi
        */
       void handle_request(char const * name,
                           JsonReader * reader,
+                          connman_manager & manager,
                           response_callback & response);
 
     private:
 
       /// Connect to the service.
       void connect(JsonReader * reader,
+                   connman_manager & manager,
                    response_callback response);
 
       /// Disconnect from the service.
       void disconnect(JsonReader * reader,
+                      connman_manager & manager,
                       response_callback response);
 
       /**
diff --git a/plugins/connman/settings-agent.conf.in b/plugins/connman/settings-agent.conf.in
new file mode 100644 (file)
index 0000000..cf8651d
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<!-- D-Bus policy for settingsd connman Agent implementation. -->
+<busconfig>
+  <policy context="default">
+    <allow own=@agent_name@/>
+    <allow send_destination=@agent_name@/>
+    <allow send_destination="net.connman"
+          send_interface="net.connman.Manager"/>
+  </policy>
+</busconfig>
index 15c0f1f..e8e3d14 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "technology.hpp"
 #include "connman_manager.hpp"
-#include "service.hpp"
 
 #include <settingsd/response_callback.hpp>
 #include <settingsd/glib_traits.hpp>
 
 ivi::settings::technology::technology(char const * path,
                                       GDBusConnection * connection,
-                                      connman_manager & manager,
-                                      event_callback const & e)
+                                      connman_manager & manager)
   : connman_("net.connman.Technology",     // Interface
              path,                         // Object path
-             connection,
-             e)
+             connection)
   , manager_(manager)
-  , event_callback_(e)
 {
 }
 
index fde6737..5008eb5 100644 (file)
@@ -59,14 +59,10 @@ namespace ivi
        * @param[in] path       The connman technology object path.
        * @param[in] connection Underlying D-Bus connection.
        * @param[in] manager    Connman manager proxy.
-       * @param[in] e          Callback through which events will be
-       *                       sent to clients.
        */
       technology(char const * path,
                  GDBusConnection * connection,
-                 connman_manager & manager,
-                 event_callback const & e);
-
+                 connman_manager & manager);
 
       /**
        * Handle connman technology-specific request.
@@ -122,9 +118,6 @@ namespace ivi
       /// The proxy used to access the connman Manager D-Bus API.
       connman_manager & manager_;
 
-      /// Callback through which events will be sent to clients.
-      event_callback event_callback_;
-
     };
 
   }