Add validation check logic to the provider side 61/175861/6
authorjusung son <jusung07.son@samsung.com>
Fri, 13 Apr 2018 04:26:06 +0000 (13:26 +0900)
committerjusung son <jusung07.son@samsung.com>
Mon, 16 Apr 2018 02:21:25 +0000 (11:21 +0900)
Related chage:
 - https://review.tizen.org/gerrit/#/c/175865/

Change-Id: Ib2ee58c0515e6abe34cfdfc9fae6a64869f446c3
Signed-off-by: jusung son <jusung07.son@samsung.com>
19 files changed:
packaging/libwatchface-complication.spec
unittest/src/test_complication_provider.cc
watchface-common/watchface-util.cc [new file with mode: 0644]
watchface-common/watchface-util.h [new file with mode: 0644]
watchface-complication-provider/CMakeLists.txt
watchface-complication-provider/complication-provider-implementation.h
watchface-complication-provider/complication-provider.cc
watchface-complication-provider/complication-provider.h
watchface-complication-provider/watchface-complication-provider.cc
watchface-complication/complication-connector-implementation.h
watchface-complication/complication-connector.h
watchface-complication/complication-implementation.h
watchface-complication/complication.cc
watchface-complication/db-manager.cc
watchface-complication/db-manager.h
watchface-complication/editables-container-implementation.h
watchface-complication/editables-container.cc
watchface-editor/editables-editor-implementation.h
watchface-editor/editables-editor.cc

index 9a7fabd..582e3c6 100644 (file)
@@ -24,6 +24,8 @@ BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(pkgmgr-info)
 BuildRequires: pkgconfig(pkgmgr-installer)
 BuildRequires: pkgconfig(capi-appfw-app-control)
+BuildRequires: pkgconfig(cynara-client)
+BuildRequires: pkgconfig(cynara-creds-gdbus)
 %if 0%{?gcov:1}
 BuildRequires: lcov
 %endif
index 74caaf4..ace3d3e 100644 (file)
@@ -35,7 +35,7 @@ class WCP : public ::testing::Test {
   ComplicationProvider* provider;
 
   virtual void SetUp(){
-    provider = new ComplicationProvider(providerId.c_str(), 1);
+    provider = new ComplicationProvider(providerId.c_str());
   }
   virtual void TearDown(){
     delete provider;
diff --git a/watchface-common/watchface-util.cc b/watchface-common/watchface-util.cc
new file mode 100644 (file)
index 0000000..33da075
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlog.h>
+#include <unistd.h>
+#include <aul.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <string>
+#include <cynara-client.h>
+#include <cynara-creds-gdbus.h>
+#include <cynara-session.h>
+
+#include "watchface-util.h"
+#include "watchface-complication/include/watchface-common.h"
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define MAX_PACKAGE_STR_SIZE 512
+#define SMACK_LABEL_LEN 255
+
+#define LOG_TAG "WATCHFACE_COMPLICATION"
+
+namespace watchface_complication {
+  namespace util {
+  static int __cynara_check(const char* client, const char* user, const char* privilege) {
+    int ret, cynara_ret;
+    cynara* p_cynara = NULL;
+
+    ret = cynara_initialize(&p_cynara, NULL);
+    if (ret != CYNARA_API_SUCCESS) {
+      LOGE("cannot init cynara [%d] failed!", ret);
+      return COMPLICATION_ERROR_IO_ERROR;
+    }
+
+    cynara_ret = cynara_check(p_cynara, client, "", user, privilege);
+    if (cynara_ret == CYNARA_API_ACCESS_ALLOWED) {
+      ret = COMPLICATION_ERROR_NONE;
+    } else {
+      if (cynara_ret == CYNARA_API_ACCESS_DENIED)
+        ret = COMPLICATION_ERROR_PERMISSION_DENIED;
+      else
+        ret = COMPLICATION_ERROR_IO_ERROR;
+
+      LOGE("cynara access check [%s][%d] failed!", privilege, ret);
+    }
+
+    cynara_finish(p_cynara);
+
+    return ret;
+  }
+
+  int CheckPrivilege(const char* privilege) {
+    int fd;
+    int ret;
+    char subject_label[SMACK_LABEL_LEN + 1] = "";
+    char uid[10] = {0,};
+
+    fd = open("/proc/self/attr/current", O_RDONLY);
+    if (fd == -1) {
+      LOGE("open [%d] failed!", errno);
+      return COMPLICATION_ERROR_IO_ERROR;
+    }
+
+    ret = read(fd, subject_label, SMACK_LABEL_LEN);
+    if (ret < 0) {
+      LOGE("read [%d] failed!", errno);
+      ret = COMPLICATION_ERROR_IO_ERROR;
+    } else {
+      snprintf(uid, 10, "%d", getuid());
+      ret = __cynara_check(subject_label, uid, privilege);
+    }
+
+    close(fd);
+    return ret;
+  }
+
+  int CheckPrivilege(std::string& privilege, GDBusConnection* connection,
+                       std::string& sender_name, std::string& sender_appid) {
+    int ret;
+    char *client = NULL;
+    char *user = NULL;
+
+    ret = cynara_creds_gdbus_get_client(connection, sender_name.c_str(),
+                                         CLIENT_METHOD_DEFAULT, &client);
+    if (ret != CYNARA_API_SUCCESS) {
+      LOGE("failed to get client");
+      ret = COMPLICATION_ERROR_IO_ERROR;
+      goto out;
+    }
+
+    ret = cynara_creds_gdbus_get_user(connection, sender_name.c_str(),
+                                        USER_METHOD_DEFAULT, &user);
+    if (ret != CYNARA_API_SUCCESS) {
+      LOGE("failed to get user");
+      ret = COMPLICATION_ERROR_IO_ERROR;
+      goto out;
+    }
+
+    LOGD("app_id(%s), client(%s), user(%s)", sender_appid.c_str(), client, user);
+
+    ret = __cynara_check(client, user, privilege.c_str());
+
+out:
+    if (client)
+      free(client);
+    if (user)
+      free(user);
+
+    return ret;
+  }
+
+  int GetSenderPid(GDBusConnection *conn, const std::string& sender_name) {
+    GDBusMessage *msg = NULL;
+    GDBusMessage *reply = NULL;
+    GError *err = NULL;
+    GVariant *body;
+    int pid = 0;
+
+    msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
+                    "org.freedesktop.DBus", "GetConnectionUnixProcessID");
+    if (!msg) {
+      LOGE("Can't allocate new method call");
+      goto out;
+    }
+
+    g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name.c_str()));
+    reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
+                    G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
+
+    if (!reply) {
+      if (err != NULL) {
+        LOGE("Failed to get pid [%s]", err->message);
+        g_error_free(err);
+      }
+      goto out;
+    }
+
+    body = g_dbus_message_get_body(reply);
+    g_variant_get(body, "(u)", &pid);
+
+out:
+    if (msg)
+      g_object_unref(msg);
+    if (reply)
+      g_object_unref(reply);
+
+    return pid;
+  }
+
+  bool CheckSender(const char* sender_app_id,
+                    const std::string& sender_name,
+                    GDBusConnection* conn,
+                    int* sender_pid) {
+    int ret = 0;
+    char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
+    int pid = GetSenderPid(conn, sender_name);
+
+    ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
+    if (ret != AUL_R_OK) {
+      LOGE("Failed to get the sender ID: (%s) (%d)", sender_name.c_str(), pid);
+      return false;
+    }
+
+    if (strcmp(buffer, sender_app_id) != 0) {
+      LOGE("invalid appid : (%s) (%s)", buffer, sender_app_id);
+      return false;
+    }
+    *sender_pid = pid;
+
+    return true;
+  }
+  }    /* namespace util */
+}      /*  namespace watchface_complication */
diff --git a/watchface-common/watchface-util.h b/watchface-common/watchface-util.h
new file mode 100644 (file)
index 0000000..db9ee0e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WATCHFACE_COMPLICATION_UTIL_H_
+#define WATCHFACE_COMPLICATION_UTIL_H_
+
+#include <gio/gio.h>
+#include <string>
+#include "watchface-complication/include/watchface-common.h"
+namespace watchface_complication {
+  namespace util {
+  int CheckPrivilege(const char* privilege);
+  int CheckPrivilege(std::string& privilege,
+                                     GDBusConnection *connection,
+                                     std::string& sender_name,
+                                     std::string& sender_appid);
+  int GetSenderPid(GDBusConnection *conn, const std::string& sender_name);
+  bool CheckSender(const char* sender_app_id,
+                                const std::string& sender_name,
+                                GDBusConnection* conn,
+                                int* sender_pid);
+  }
+}  /* namespace watchface_complication */
+
+#endif  /* WATCHFACE_COMPLICATION_DB_MANAGER_H_ */
\ No newline at end of file
index 61ab633..c0decd6 100644 (file)
@@ -15,6 +15,8 @@ pkg_check_modules(watchface-complication-provider REQUIRED
        dlog
        aul
        capi-appfw-app-control
+       cynara-client
+       cynara-creds-gdbus
 )
 
 FOREACH(flag ${watchface-complication-provider_CFLAGS})
@@ -26,10 +28,12 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}")
 SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
 SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
 
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../watchface-common)
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../)
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
 
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../watchface-common SOURCES)
 ADD_LIBRARY (${PROJECT_NAME} SHARED ${SOURCES})
 
 SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
index e002a9a..d3a31f1 100644 (file)
 #include <memory>
 #include <string>
 #include <list>
+#include <map>
 
 #include "watchface-complication/complication.h"
 #include "watchface-complication/complication-connector.h"
 
+enum provider_cynara_result {
+  COMPLICATION_CYNARA_UNKNOWN,
+  COMPLICATION_CYNARA_ALLOWED,
+  COMPLICATION_CYNARA_DENIED,
+};
+
 namespace watchface_complication {
 
 class ComplicationProvider::Impl : ComplicationConnector::IEventListener {
@@ -35,15 +42,35 @@ class ComplicationProvider::Impl : ComplicationConnector::IEventListener {
  private:
   friend class ComplicationProvider;
 
-  void OnSignal(const std::string& sender_name,
+  void OnSignal(GDBusConnection* connection,
+                const std::string& sender_name,
                 const std::string& object_path,
                 const std::string& interface_name,
                 const std::string& signal_name,
                 GVariant* parameters) override;
   void OnVanish(const std::string& name) override;
   void OnAppear(const std::string& name, const std::string& name_owner) override;
-  Impl(ComplicationProvider* parent, const std::string& provider_id,
-       int support_types);
+  std::list<std::string>& GetRequiredPrivileges();
+  Impl(ComplicationProvider* parent, const std::string& provider_id);
+  class SenderInfo {
+    public:
+      SenderInfo(const std::string& sender_name, const char* sender_app_id,
+                      int watcher_id, int pid);
+      int CheckPrivilege(std::list<std::string>& required_privileges, GDBusConnection* connection);
+      bool CheckAppid(const std::string& Appid);
+      int GetWatcherID();
+      int GetPID();
+      provider_cynara_result GetPrivilegeResult();
+      void SetPrivilegeResult(provider_cynara_result result);
+
+    private:
+      std::string sender_name_;
+      std::string sender_app_id_;
+      int watcher_id_;
+      int pid_;
+      std::list<std::string> sender_privileges_;
+      provider_cynara_result privilege_result_;
+  };
 
  private:
   ComplicationProvider* parent_;
@@ -51,6 +78,8 @@ class ComplicationProvider::Impl : ComplicationConnector::IEventListener {
   std::string provider_id_;
   std::string setup_appid_;
   int support_types_;
+  std::map<std::string, SenderInfo*> sender_info_;
+  std::list<std::string> required_privileges_;
 };
 
 }  // namespace watchface_complication
index b01f036..1d125da 100644 (file)
 #include <glib.h>
 #include <unistd.h>
 
-#include "watchface-complication-provider/complication-provider.h"
-#include "watchface-complication-provider/complication-provider-implementation.h"
+#include "watchface-util.h"
+#include "complication-provider.h"
+#include "complication-provider-implementation.h"
 
 #ifdef LOG_TAG
 #undef LOG_TAG
 #endif
 
 #define LOG_TAG "WATCHFACE_COMPLICATION"
+#define PRIVILEGE_DATASHARING "http://tizen.org/privilege/datasharing"
 
 namespace watchface_complication {
 
-ComplicationProvider::ComplicationProvider(const std::string& provider_id,
-    int support_types) : impl_(new Impl(this, provider_id, support_types)) {
+ComplicationProvider::ComplicationProvider(const std::string& provider_id)
+                                       : impl_(new Impl(this, provider_id)) {
 }
 
 ComplicationProvider::~ComplicationProvider() = default;
+
 ComplicationProvider::Impl::Impl(ComplicationProvider* parent,
-                                 const std::string& provider_id,
-                                 int support_types)
-  : parent_(parent), provider_id_(provider_id), support_types_(support_types) {
+                                 const std::string& provider_id)
+  : parent_(parent), provider_id_(provider_id) {
   subscribe_id_ = ComplicationConnector::GetInst().SubscribeSignal(
     ComplicationConnector::Complication, provider_id_, -1, this);
+
+  std::list<std::string> privlege_list;
+  required_privileges_.push_back(std::string(PRIVILEGE_DATASHARING));
+
+  DBManager::GetSupportTypes(provider_id_, &support_types_);
+
+  privlege_list = DBManager::GetRequiredPrivlegeList(provider_id_);
+  for (auto& i : privlege_list) {
+    required_privileges_.push_back(i);
+    LOGI("required_privileges %s", i.c_str());
+  }
+
   LOGI("subscribe signal %d", subscribe_id_);
 }
 
+ComplicationProvider::Impl::SenderInfo::SenderInfo(const std::string& sender_name,
+                                                       const char* sender_app_id,
+                                                       int watcher_id,
+                                                       int pid)
+   : sender_name_(sender_name), sender_app_id_(sender_app_id),
+     watcher_id_(watcher_id), pid_(pid), privilege_result_(COMPLICATION_CYNARA_UNKNOWN) {
+}
+
+int ComplicationProvider::Impl::SenderInfo::CheckPrivilege(std::list<std::string>& required_privileges,
+                                                                  GDBusConnection* connection) {
+  bool ret;
+  int privilege_result;
+
+  for (auto& i : required_privileges) {
+    ret = false;
+    for (auto& j : sender_privileges_) {
+      if (i.compare(j) == 0) {
+        ret = true;
+        break;
+      }
+    }
+
+    if (ret == false) {
+      privilege_result = watchface_complication::util::CheckPrivilege(i,
+                                       connection, sender_name_, sender_app_id_);
+      if (privilege_result == COMPLICATION_ERROR_NONE)
+        sender_privileges_.push_back(i);
+      else
+        return privilege_result;
+    }
+  }
+  return COMPLICATION_ERROR_NONE;
+}
+
+bool ComplicationProvider::Impl::SenderInfo::CheckAppid(const std::string& Appid) {
+  if (sender_app_id_.compare(Appid) == 0)
+    return true;
+  return false;
+ }
+
+int ComplicationProvider::Impl::SenderInfo::GetWatcherID() {
+   return watcher_id_;
+}
+
+int ComplicationProvider::Impl::SenderInfo::GetPID() {
+   return pid_;
+}
+
+provider_cynara_result ComplicationProvider::Impl::SenderInfo::GetPrivilegeResult() {
+   return privilege_result_;
+}
+
+void ComplicationProvider::Impl::SenderInfo::SetPrivilegeResult(provider_cynara_result result) {
+   privilege_result_ = result;
+}
+
+std::list<std::string>& ComplicationProvider::Impl::GetRequiredPrivileges() {
+  return required_privileges_;
+}
+
 void ComplicationProvider::Impl::OnVanish(const std::string& name) {
+  auto sender_info = sender_info_.find(name);
+  auto si = sender_info->second;
 
+  if (sender_info == sender_info_.end())
+    return;
+
+  ComplicationConnector::GetInst().UnWatch(si->GetWatcherID());
+  sender_info_.erase(name);
+  delete si;
 }
 
 void ComplicationProvider::Impl::OnAppear(const std::string& name,
@@ -51,7 +133,8 @@ void ComplicationProvider::Impl::OnAppear(const std::string& name,
 
 }
 
-void ComplicationProvider::Impl::OnSignal(const std::string& sender_name,
+void ComplicationProvider::Impl::OnSignal(GDBusConnection* connection,
+    const std::string& sender_name,
     const std::string& object_path,
     const std::string& interface_name,
     const std::string& signal_name,
@@ -61,20 +144,77 @@ void ComplicationProvider::Impl::OnSignal(const std::string& sender_name,
   int complication_id;
   char *context_raw = NULL;
   int type;
-  Bundle* shared_data = new Bundle();
 
-  LOGI("signal_name: %s", signal_name.c_str());
+  auto sender_info = sender_info_.find(sender_name);
+  auto si = sender_info->second;
+
+  if (sender_info == sender_info_.end()) {
+    char* sender_app_id = NULL;
+    int watcher_id;
+    int pid;
+    g_variant_get_child(parameters, 0, "&s", &sender_app_id);
+
+    if (sender_app_id == NULL  ||
+        !util::CheckSender(sender_app_id, sender_name, connection, &pid)) {
+      LOGE("sender_app_id %s", sender_app_id);
+      return;
+    }
+
+    watcher_id = ComplicationConnector::GetInst().Watch(
+                                      std::string(sender_app_id), this);
+
+    si = new SenderInfo(sender_name, sender_app_id, watcher_id, pid);
+    sender_info_[sender_name] = si;
+    LOGI("create new sender_info_ ");
+  }
+
+  if (si->GetPrivilegeResult() == COMPLICATION_CYNARA_DENIED) {
+    /* For performance, the senderInfo does not delete
+       Probably the sender will connect again
+       When the sender is terminated, It is deleted on OnVanish */
+    LOGE("Permission denied");
+    return;
+  }
+
+  if (si->GetPrivilegeResult() == COMPLICATION_CYNARA_UNKNOWN) {
+    int ret = si->CheckPrivilege(GetRequiredPrivileges(), connection);
+
+    if (ret != COMPLICATION_ERROR_NONE) {
+      if (ret == COMPLICATION_ERROR_PERMISSION_DENIED)
+        si->SetPrivilegeResult(COMPLICATION_CYNARA_DENIED);
+
+       LOGE("Permission denied [%d]", ret);
+       return;
+    }
+
+    si->SetPrivilegeResult(COMPLICATION_CYNARA_ALLOWED);
+  }
+
   if (signal_name.compare(
       ComplicationConnector::GetInst().GetCmdStr(
           ComplicationConnector::CompUpdateRequest)) == 0) {
     g_variant_get(parameters, "(&sii&s)", &sender_app_id,
                   &complication_id, &type, &context_raw);
+
+    if (si->CheckAppid(sender_app_id) == false) {
+      LOGE("invaild app id [%s]", sender_app_id);
+      return;
+    }
+
+    if ((support_types_ & type) == 0) {
+      LOGE("Not supported type [%d][%d]", support_types_, type);
+      return;
+    }
+
     LOGI("get : %s, %d, %d", sender_app_id, complication_id, type);
+
     Bundle* context_data = new Bundle(std::string(context_raw));
+    Bundle* shared_data = new Bundle();
 
     /* Call update request callback and fill shared data */
     parent_->OnDataUpdateRequest(sender_app_id, (ComplicationType)type,
                                 context_data, shared_data);
+    delete context_data;
     ComplicationConnector::GetInst().EmitSignal(
       ComplicationConnector::Complication,
       std::string(sender_app_id),
@@ -86,6 +226,7 @@ void ComplicationProvider::Impl::OnSignal(const std::string& sender_name,
                     type,
                     complication_id,
                     shared_data->ToString()));
+    delete shared_data;
   }
 }
 
@@ -97,15 +238,42 @@ const std::string& ComplicationProvider::GetProviderId() const {
   return impl_->provider_id_;
 }
 
-void ComplicationProvider::NotifyDataUpdate() {
-    LOGI("notify %s", impl_->provider_id_.c_str());
-    ComplicationConnector::GetInst().EmitSignal(
-      ComplicationConnector::Complication,
-      "",
-      impl_->provider_id_, -1,
-      ComplicationConnector::GetInst().GetCmdStr(
-          ComplicationConnector::CompNotifyDataUpdate),
-      NULL);
+int ComplicationProvider::NotifyDataUpdate() {
+  LOGI("notify %s", impl_->provider_id_.c_str());
+
+  static provider_cynara_result pcr = COMPLICATION_CYNARA_UNKNOWN;
+
+  int ret = COMPLICATION_ERROR_NONE;
+  bool emit_ret;
+
+  if (pcr == COMPLICATION_CYNARA_DENIED) {
+    LOGE("Permission denied");
+    return COMPLICATION_ERROR_PERMISSION_DENIED;
+
+  } else if (pcr == COMPLICATION_CYNARA_UNKNOWN) {
+    ret = util::CheckPrivilege(PRIVILEGE_DATASHARING);
+    if (ret == COMPLICATION_ERROR_NONE) {
+      pcr = COMPLICATION_CYNARA_ALLOWED;
+    } else if (ret == COMPLICATION_ERROR_PERMISSION_DENIED) {
+      pcr = COMPLICATION_CYNARA_DENIED;
+      return ret;
+    } else {
+      return ret;
+    }
+  }
+
+  emit_ret = ComplicationConnector::GetInst().EmitSignal(
+                            ComplicationConnector::Complication,
+                            "",
+                            impl_->provider_id_, -1,
+                            ComplicationConnector::GetInst().GetCmdStr(
+                                 ComplicationConnector::CompNotifyDataUpdate),
+                            NULL);
+
+  if (emit_ret == false)
+    ret = COMPLICATION_ERROR_IO_ERROR;
+
+  return ret;
 }
 
 }  // namespace watchface_complication
index a7448be..e24b675 100644 (file)
 #include "watchface-complication/complication-event-interface.h"
 #include "watchface-complication/complication-connector.h"
 
+#define PRIVILEGE_DATASHARING "http://tizen.org/privilege/datasharing"
+
 namespace watchface_complication {
 
 class EXPORT_API ComplicationProvider : public IComplicationEvent {
  public:
-  ComplicationProvider(const std::string& provider_id, int support_types);
+  ComplicationProvider(const std::string& provider_id);
   virtual ~ComplicationProvider();
 
  public:
@@ -37,7 +39,7 @@ class EXPORT_API ComplicationProvider : public IComplicationEvent {
                            const Bundle* context,
                            Bundle* shared_data) override;
 
-  void NotifyDataUpdate();
+  int NotifyDataUpdate();
   const std::string& GetProviderId() const;
 
  private:
index 567ecd8..7b2b6d2 100644 (file)
 #include <math.h>
 #include <gio/gio.h>
 #include <aul.h>
+#include <aul_complication.h>
+#include <app_control_internal.h>
 #include <dlog.h>
+#include <bundle.h>
 #include <map>
 #include <list>
 
-#include "watchface-complication-provider/complication-provider.h"
-#include "watchface-complication-provider/include/watchface-complication-provider.h"
+#include "watchface-util.h"
+#include "complication-provider.h"
+#include "include/watchface-complication-provider.h"
+#include "watchface-complication/db-manager.h"
 #include "watchface-complication/include/watchface-complication-internal.h"
 
 #ifdef LOG_TAG
@@ -51,6 +56,10 @@ class CallbackInfo {
         shared_data->GetRaw(), user_data_);
   }
 
+  on_update_request_cb GetCallback() {
+    return cb_;
+  }
+
  private:
   on_update_request_cb cb_;
   void* user_data_;
@@ -58,10 +67,8 @@ class CallbackInfo {
 
 class WatchComplicationProviderStub : public ComplicationProvider {
  public:
-  WatchComplicationProviderStub(const std::string& provider_id,
-                                int support_types)
-    : ComplicationProvider(provider_id,
-                           support_types) {
+  WatchComplicationProviderStub(const std::string& provider_id)
+    : ComplicationProvider(provider_id) {
   }
 
   virtual ~WatchComplicationProviderStub() = default;
@@ -74,17 +81,25 @@ class WatchComplicationProviderStub : public ComplicationProvider {
          sender_appid.c_str());
   }
 
-  void AddCallbackInfo(CallbackInfo* ci) {
+  int AddCallbackInfo(CallbackInfo* ci) {
+   for (auto& i : cb_list_) {
+      if (i.get()->GetCallback() == ci->GetCallback()) {
+        LOGI("already registered callback");
+        return COMPLICATION_ERROR_INVALID_PARAMETER;
+      }
+    }
     cb_list_.emplace_back(ci);
+    return COMPLICATION_ERROR_NONE;
   }
 
-  void RemoveCallbackInfo(CallbackInfo* ci) {
+  int RemoveCallbackInfo(on_update_request_cb ci) {
     for (auto& i : cb_list_) {
-      if (i.get() == ci) {
+      if (i.get()->GetCallback() == ci) {
         cb_list_.remove(i);
-        break;
+        return COMPLICATION_ERROR_NONE;
       }
     }
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
   }
 
  private:
@@ -98,22 +113,28 @@ extern "C" EXPORT_API int watchface_complication_provider_update_request_cb_add(
   if (provider_id == NULL || cb == NULL)
     return COMPLICATION_ERROR_INVALID_PARAMETER;
 
-  // TODO(?): Provider ID validation
-  // TODO(?): Get provider's support type from storage
-  int support_types = ShortText | Image;
+  std::string appid = DBManager::GetProviderAppId(provider_id);
+  if (appid.compare(ComplicationConnector::GetInst().GetAppId()) != 0) {
+    LOGE("Invalid provider id : %s", provider_id);
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  int ret = COMPLICATION_ERROR_NONE;
   auto cp = __providers.find(provider_id);
   auto ws = cp->second;
 
   if (cp == __providers.end()) {
-    ws = new WatchComplicationProviderStub(provider_id, support_types);
+    ws = new WatchComplicationProviderStub(provider_id);
     __providers[provider_id] = ws;
     LOGI("create new provider : %s", provider_id);
   }
 
   auto ci = new CallbackInfo(cb, user_data);
-  ws->AddCallbackInfo(ci);
+  ret = ws->AddCallbackInfo(ci);
+  if (ret != COMPLICATION_ERROR_NONE)
+    delete ci;
 
-  return 0;
+  return ret;
 }
 
 extern "C" EXPORT_API int watchface_complication_provider_update_request_cb_del(
@@ -121,7 +142,14 @@ extern "C" EXPORT_API int watchface_complication_provider_update_request_cb_del(
   if (provider_id == NULL || cb == NULL)
     return COMPLICATION_ERROR_INVALID_PARAMETER;
 
-  return 0;
+  auto cp = __providers.find(provider_id);
+  auto ws = cp->second;
+
+  if (cp == __providers.end()) {
+     return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  return ws->RemoveCallbackInfo(cb);
 }
 
 extern "C" EXPORT_API int watchface_complication_provider_get_support_types(
@@ -134,6 +162,9 @@ extern "C" EXPORT_API int watchface_complication_provider_get_support_types(
 
 extern "C" EXPORT_API int watchface_complication_provider_notify_update(
     const char *updated_provider_id) {
+  if (updated_provider_id == NULL)
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+
   auto cp = __providers.find(updated_provider_id);
 
   if (cp == __providers.end()) {
@@ -142,18 +173,8 @@ extern "C" EXPORT_API int watchface_complication_provider_notify_update(
   }
 
   auto ws = cp->second;
-  // TODO(?): Get provider's support type from storage
-  int support_types = ShortText | Image;
-
-  if (cp == __providers.end()) {
-    LOGI("create new provider : %s", updated_provider_id);
-    ws = new WatchComplicationProviderStub(updated_provider_id, support_types);
-    __providers[updated_provider_id] = ws;
-  }
-
-  ws->NotifyDataUpdate();
 
-  return COMPLICATION_ERROR_NONE;
+  return ws->NotifyDataUpdate();
 }
 
 extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor(
@@ -164,6 +185,7 @@ extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor(
   int ret;
   int str_len = 0;
   bundle_raw* raw_data = NULL;
+  bool emit_signal_ret;
 
   ret = app_control_get_extra_data(handle, SETUP_EDITOR_APPID_KEY, &editor_appid);
   if (ret != 0) {
@@ -173,6 +195,8 @@ extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor(
 
   ret = app_control_get_extra_data(handle, SETUP_EDITABLE_ID_KEY, &editable_id);
   if (ret != APP_CONTROL_ERROR_NONE) {
+    free(editor_appid);
+
     if (ret == APP_CONTROL_ERROR_OUT_OF_MEMORY) {
       LOGE("Fail to get context data");
       return COMPLICATION_ERROR_OUT_OF_MEMORY;
@@ -191,7 +215,7 @@ extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor(
     }
   }
 
-  ComplicationConnector::GetInst().EmitSignal(
+  emit_signal_ret = ComplicationConnector::GetInst().EmitSignal(
       ComplicationConnector::Editable,
       std::string(editor_appid),
       std::string(editor_appid), -1,
@@ -204,6 +228,9 @@ extern "C" EXPORT_API int watchface_complication_provider_setup_reply_to_editor(
   free(editable_id);
   free(raw_data);
 
+  if (emit_signal_ret == false)
+    return COMPLICATION_ERROR_IO_ERROR;
+
   return COMPLICATION_ERROR_NONE;
 }
 
@@ -530,23 +557,32 @@ extern "C" EXPORT_API int watchface_complication_provider_is_touch_launch(
     app_control_h handle, bool* is_touch_launch) {
   int ret;
   char* value = NULL;
+  bundle *data;
 
   if (handle == NULL || is_touch_launch == NULL) {
     LOGE("Invalid param");
     return COMPLICATION_ERROR_INVALID_PARAMETER;
   }
 
-  ret = app_control_get_extra_data(handle, TOUCH_LAUNCH_DATA_KEY, &value);
-  free(value);
-  if (ret == APP_CONTROL_ERROR_OUT_OF_MEMORY) {
-    LOGE("Out of memory");
-    return COMPLICATION_ERROR_OUT_OF_MEMORY;
-  } else if (ret == APP_CONTROL_ERROR_NONE) {
-    *is_touch_launch = true;
-  } else {
+  ret = app_control_to_bundle(handle, &data);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LOGE("Invalid param");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  ret = bundle_get_str(data, AUL_K_COMPLICATION_MODE, &value);
+  if (ret != BUNDLE_ERROR_NONE) {
     *is_touch_launch = false;
-    return COMPLICATION_ERROR_IO_ERROR;
+    return COMPLICATION_ERROR_NONE;
   }
+
+  ret = bundle_get_str(data, TOUCH_LAUNCH_DATA_KEY, &value);
+  if (ret != BUNDLE_ERROR_NONE) {
+   *is_touch_launch = false;
+    return COMPLICATION_ERROR_NONE;
+  }
+
+  *is_touch_launch = true;
   return COMPLICATION_ERROR_NONE;
 }
 
index c2980a7..25c501c 100644 (file)
@@ -45,7 +45,7 @@ class ComplicationConnector::Impl {
                       void* user_data) {
     IEventListener* rs = static_cast<IEventListener*>(user_data);
 
-    rs->OnSignal(sender_name, object_path, interface_name,
+    rs->OnSignal(connection, sender_name, object_path, interface_name,
                  signal_name, parameters);
   }
 
index d6ad162..587d74d 100644 (file)
@@ -46,7 +46,8 @@ class EXPORT_API ComplicationConnector {
 
   class IEventListener {
    public:
-    virtual void OnSignal(const std::string& sender_name,
+    virtual void OnSignal(GDBusConnection* connection,
+                          const std::string& sender_name,
                           const std::string& object_path,
                           const std::string& interface_name,
                           const std::string& signal_name,
index 56479e5..742ce0d 100644 (file)
@@ -37,7 +37,8 @@ namespace watchface_complication {
 
 class Complication::Impl : ComplicationConnector::IEventListener {
  public:
-  void OnSignal(const std::string& sender_name,
+  void OnSignal(GDBusConnection* connection,
+                const std::string& sender_name,
                 const std::string& object_path,
                 const std::string& interface_name,
                 const std::string& signal_name,
index 07a8c9d..d5cce6c 100644 (file)
@@ -90,7 +90,8 @@ void Complication::Impl::OnAppear(const std::string& name,
 
 }
 
-void Complication::Impl::OnSignal(const std::string& sender_name,
+void Complication::Impl::OnSignal(GDBusConnection* connection,
+                                  const std::string& sender_name,
                                   const std::string& object_path,
                                   const std::string& interface_name,
                                   const std::string& signal_name,
@@ -227,7 +228,7 @@ int Complication::Impl::StoreSetting(int comp_id, std::string& provider_id,
 }
 
 std::string Complication::Impl::GetProviderAppId() {
-  return DBManager::GetProviderAppId(cur_provider_id_);
+  return DBManager::GetProviderAppId(cur_provider_id_.c_str());
 }
 
 int Complication::GetComplicationId() {
index 10db708..75410fb 100644 (file)
@@ -69,7 +69,7 @@ std::unique_ptr<Bundle> DBManager::GetDefaultData(const char* provider_id,
   std::unique_ptr<Bundle> default_data = nullptr;
   const char* raw_data;
   sqlite3_stmt* stmt;
-  sqlite3* db = NULL;
+  sqlite3* db;
   int ret;
 
   static const char query[] =
@@ -98,19 +98,17 @@ std::unique_ptr<Bundle> DBManager::GetDefaultData(const char* provider_id,
     default_data = std::unique_ptr<Bundle>(new Bundle(std::string(raw_data)));
   }
 
-  if (stmt)
-    sqlite3_finalize(stmt);
-
+  sqlite3_finalize(stmt);
   CloseDB(db);
 
   return std::move(default_data);
 }
 
-std::string DBManager::GetProviderAppId(std::string& provider_id) {
+std::string DBManager::GetProviderAppId(const char* provider_id) {
   int ret;
   std::string appid;
   sqlite3_stmt *stmt = NULL;
-  sqlite3* db = NULL;
+  sqlite3* db;
 
   static const char query[] =
     "SELECT DISTINCT appid FROM complication_provider "
@@ -130,15 +128,13 @@ std::string DBManager::GetProviderAppId(std::string& provider_id) {
     return NULL;
   }
 
-  sqlite3_bind_text(stmt, 1, provider_id.c_str(), -1, SQLITE_TRANSIENT);
+  sqlite3_bind_text(stmt, 1, provider_id, -1, SQLITE_TRANSIENT);
 
   if (sqlite3_step(stmt) == SQLITE_ROW) {
     appid = std::string((char *)sqlite3_column_text(stmt, 0));
   }
 
-  if (stmt)
-    sqlite3_finalize(stmt);
-
+  sqlite3_finalize(stmt);
   CloseDB(db);
 
   return appid;
@@ -148,7 +144,7 @@ std::list<std::string> DBManager::GetProviderList(int support_type) {
   int ret;
   char *provider_id = NULL;
   sqlite3_stmt* stmt;
-  sqlite3* db = NULL;
+  sqlite3* db;
   std::list<std::string> provider_list;
 
   static const char query[] =
@@ -176,14 +172,87 @@ std::list<std::string> DBManager::GetProviderList(int support_type) {
     provider_list.push_back(std::string(provider_id));
   }
 
-  if (stmt)
-    sqlite3_finalize(stmt);
-
+  sqlite3_finalize(stmt);
   CloseDB(db);
 
   return provider_list;
 }
 
+int DBManager::GetSupportTypes(std::string& provider_id, int* types) {
+  int ret;
+  int support_types = 0;
+  sqlite3_stmt* stmt;
+  sqlite3* db;
+
+  static const char query[] =
+      "SELECT SUM(support_type) FROM complication_provider "
+      "WHERE provider_id = ?";
+
+  db = OpenDB();
+  if (db == NULL) {
+    LOGE("parser db not exist");
+    return COMPLICATION_ERROR_DB;
+  }
+
+  ret = sqlite3_prepare_v2(db, query, strlen(query),
+                        &stmt, NULL);
+  if (ret != SQLITE_OK) {
+    LOGE("prepare error: %s", sqlite3_errmsg(db));
+    CloseDB(db);
+    return COMPLICATION_ERROR_DB;
+  }
+
+  sqlite3_bind_text(stmt, 1, provider_id.c_str(), -1, SQLITE_TRANSIENT);
+
+  while (sqlite3_step(stmt) == SQLITE_ROW)
+    support_types = sqlite3_column_int(stmt, 0);
+
+  sqlite3_finalize(stmt);
+  CloseDB(db);
+
+  *types = support_types;
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+std::list<std::string> DBManager::GetRequiredPrivlegeList(std::string& provider_id) {
+  int ret;
+  char *privlege = NULL;
+  sqlite3_stmt* stmt;
+  sqlite3* db;
+  std::list<std::string> privlege_list;
+
+  static const char query[] =
+    "SELECT DISTINCT privilege FROM provider_privilege "
+    "WHERE provider_id=?";
+
+  db = OpenDB();
+  if (db == NULL) {
+    LOGE("parser db not exist");
+    return privlege_list;
+  }
+
+  ret = sqlite3_prepare_v2(db, query, strlen(query),
+                        &stmt, NULL);
+  if (ret != SQLITE_OK) {
+    LOGE("prepare error: %s", sqlite3_errmsg(db));
+    CloseDB(db);
+    return privlege_list;
+  }
+
+  sqlite3_bind_text(stmt, 1, provider_id.c_str(), -1, SQLITE_TRANSIENT);
+
+  while (sqlite3_step(stmt) == SQLITE_ROW) {
+    privlege = (char *)sqlite3_column_text(stmt, 0);
+    privlege_list.push_back(std::string(privlege));
+  }
+
+  sqlite3_finalize(stmt);
+  CloseDB(db);
+
+  return privlege_list;
+}
+
 const char* DBManager::GetParserDataPath() {
   uid_t target_uid;
   const char *path;
index 3c4c67e..e636a92 100644 (file)
@@ -32,8 +32,10 @@ class EXPORT_API DBManager {
  public:
   static std::unique_ptr<Bundle> GetDefaultData(const char* provider_id,
                                         int support_type);
-  static std::string GetProviderAppId(std::string& provider_id);
+  static std::string GetProviderAppId(const char* provider_id);
   static std::list<std::string> GetProviderList(int support_type);
+  static std::list<std::string> GetRequiredPrivlegeList(std::string& provider_id);
+  static int GetSupportTypes(std::string& provider_id, int* types);
 
  private:
   DBManager();
index e9c9df8..f1c5b4d 100644 (file)
@@ -35,7 +35,8 @@ class EditablesContainer::Impl : ComplicationConnector::IEventListener {
  private:
   friend class EditablesContainer;
 
-  void OnSignal(const std::string& sender_name,
+  void OnSignal(GDBusConnection* connection,
+                const std::string& sender_name,
                 const std::string& object_path,
                 const std::string& interface_name,
                 const std::string& signal_name,
index 762ecd4..be50d21 100644 (file)
@@ -45,7 +45,8 @@ EditablesContainer::Impl::Impl(EditablesContainer* parent)
   LOGI("subscribe signal %d", subscribe_id_);
 }
 
-void EditablesContainer::Impl::OnSignal(const std::string& sender_name,
+void EditablesContainer::Impl::OnSignal(GDBusConnection* connection,
+                                        const std::string& sender_name,
                                         const std::string& object_path,
                                         const std::string& interface_name,
                                         const std::string& signal_name,
index 20bf6e9..8d6b76f 100644 (file)
@@ -35,7 +35,8 @@ class EditablesEditor::Impl : ComplicationConnector::IEventListener {
  private:
   friend class EditablesEditor;
 
-  void OnSignal(const std::string& sender_name,
+  void OnSignal(GDBusConnection* connection,
+                const std::string& sender_name,
                 const std::string& object_path,
                 const std::string& interface_name,
                 const std::string& signal_name,
index b6662bf..59fb0cc 100644 (file)
@@ -53,7 +53,8 @@ void EditablesEditor::Impl::OnAppear(const std::string& name,
 
 }
 
-void EditablesEditor::Impl::OnSignal(const std::string& sender_name,
+void EditablesEditor::Impl::OnSignal(GDBusConnection* connection,
+                                     const std::string& sender_name,
                                      const std::string& object_path,
                                      const std::string& interface_name,
                                      const std::string& signal_name,