-PROJECT(complication-parser C)
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(complication-parser CXX)
INCLUDE(FindPkgConfig)
pkg_check_modules(PKGS REQUIRED
)
FOREACH(FLAGS ${PKGS_CFLAGS})
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${FLAGS}")
ENDFOREACH(FLAGS)
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -g -Werror -Wall -fvisibility=hidden -fPIC")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline -std=c++11")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
ADD_LIBRARY(${PROJECT_NAME} SHARED
- complication_parser_plugin.c
- complication_parser_plugin_internal.c
- complication_parser_plugin_pkgmgr_interface.c
+ complication_parser_plugin.cc
+ complication_parser_plugin_internal.cc
+ complication_parser_plugin_pkgmgr_interface.cc
)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../watchface-common/include)
+++ /dev/null
-/*
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <libxml/tree.h>
-
-#include <dlog.h>
-
-#include <pkgmgr-info.h>
-#include <pkgmgr_installer_info.h>
-#include <bundle.h>
-
-#include "watchface-complication/include/watchface-complication.h"
-
-#include "complication_parser_plugin_internal.h"
-
-struct support_type_tag_map {
- char *name;
- watchface_complication_type_e tag;
-};
-
-static struct support_type_tag_map support_type_map[] = {
- {"short-text-type", WATCHFACE_COMPLICATION_TYPE_SHORT_TEXT},
- {"long-text-type", WATCHFACE_COMPLICATION_TYPE_LONG_TEXT},
- {"ranged-value-type", WATCHFACE_COMPLICATION_TYPE_RANGED_VALUE},
- {"time-type", WATCHFACE_COMPLICATION_TYPE_TIME},
- {"icon-type", WATCHFACE_COMPLICATION_TYPE_ICON},
- {"image-type", WATCHFACE_COMPLICATION_TYPE_IMAGE}
-};
-
-static uid_t target_uid;
-static bool target_uid_initialized;
-
-static uid_t _get_target_uid(void)
-{
- if (target_uid_initialized)
- return target_uid;
-
- pkgmgr_installer_info_get_target_uid(&target_uid);
-
- target_uid_initialized = true;
-
- return target_uid;
-}
-
-int complication_parser_plugin_init(void)
-{
- LOGD("complication_parser_plugin_init");
-
- target_uid_initialized = false;
-
- if (check_db(_get_target_uid())) {
- complication_parser_plugin_fini();
- LOGE("parser init fail");
- return -1;
- }
-
- return 0;
-}
-
-int complication_parser_plugin_fini(void)
-{
- LOGD("complication_parser_plugin_fini");
-
- target_uid_initialized = false;
-
- return 0;
-}
-
-static char *_get_attribute(xmlNode *node, const char *name)
-{
- xmlChar *val;
- char *attr = NULL;
-
- val = xmlGetProp(node, (const xmlChar *)name);
- if (val) {
- attr = strdup((char *)val);
- xmlFree(val);
- }
-
- return attr;
-}
-
-static int _get_support_type_tag(xmlNode *node)
-{
- int i;
-
- for (i = 0; i < (sizeof(support_type_map) / sizeof(struct support_type_tag_map)); i++) {
- if (!xmlStrcasecmp(node->name, (const xmlChar *)support_type_map[i].name))
- return support_type_map[i].tag;
- }
-
- return 0;
-}
-
-static int _parse_support_type(xmlNode *node, sqlite3 *db, const char *pkgid,
- const char *appid, const char *providerid, int period)
-{
- int ret;
- int idx;
- int support_type = 0;
- int result = -1;
-
- xmlNode *tmp;
- xmlNode *tmpdata;
- sqlite3_stmt *stmt = NULL;
-
- bundle *default_data = NULL;
- bundle_raw *raw = NULL;
- int len = 0;
-
- static const char query[] =
- "INSERT INTO complication_provider ( "
- "pkgid, appid, provider_id, period, "
- "support_type, default_data) "
- "VALUES (?, ?, ?, ?, ?, ?)";
-
- if (node->children == NULL)
- return -1;
-
- ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
- if (ret != SQLITE_OK) {
- LOGE("prepare error: %s", sqlite3_errmsg(db));
- goto out;
- }
-
- for (tmp = node->children; tmp; tmp = tmp->next) {
- if (tmp->children == NULL
- || tmp->children->content == NULL)
- continue;
-
- support_type = _get_support_type_tag(tmp);
- if (!support_type) {
- LOGE("not supported type");
- goto out;
- }
-
- default_data = bundle_create();
- if (default_data == NULL) {
- LOGE("bundle create error");
- goto out;
- }
-
- for (tmpdata = tmp->children; tmpdata; tmpdata = tmpdata->next) {
- if (tmpdata->children != NULL
- && tmpdata->children->content != NULL) {
-
- ret = bundle_add_str(default_data, (char *)tmpdata->name,
- (char *)tmpdata->children->content);
- if (ret != BUNDLE_ERROR_NONE) {
- LOGE("bundle add error");
- goto out;
- }
- }
- }
-
- ret = bundle_encode(default_data, &raw, &len);
- if (ret != BUNDLE_ERROR_NONE) {
- LOGE("bundle encode error");
- goto out;
- }
-
- idx = 1;
-
- sqlite3_bind_text(stmt, idx++, pkgid, -1, SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, idx++, appid, -1, SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, idx++, providerid, -1, SQLITE_TRANSIENT);
- sqlite3_bind_int(stmt, idx++, period);
- sqlite3_bind_int(stmt, idx++, support_type);
- sqlite3_bind_text(stmt, idx, (char *)raw, -1, SQLITE_TRANSIENT);
-
- ret = sqlite3_step(stmt);
- if (ret != SQLITE_DONE) {
- LOGE("step error: %s", sqlite3_errmsg(db));
- goto out;
- }
-
- sqlite3_reset(stmt);
- sqlite3_clear_bindings(stmt);
-
- if (raw) {
- free(raw);
- raw = NULL;
- }
-
- if (default_data) {
- bundle_free(default_data);
- default_data = NULL;
- }
- }
-
- result = 0;
-out:
- if (default_data)
- bundle_free(default_data);
-
- if (raw)
- free(raw);
-
- if (stmt)
- sqlite3_finalize(stmt);
-
- return result;
-}
-
-static int _parse_label(xmlNode *node, sqlite3 *db, const char *providerid)
-{
- int ret;
- int idx;
- sqlite3_stmt *stmt = NULL;
- xmlChar *lang = NULL;
-
- static const char query[] =
- "INSERT INTO provider_localized_info "
- "(provider_id, locale, provider_label) "
- "VALUES (?, ?, ?)";
-
- ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
- if (ret != SQLITE_OK) {
- LOGE("prepare error: %s", sqlite3_errmsg(db));
- goto out;
- }
-
- lang = xmlNodeGetLang(node);
-
- idx = 1;
-
- sqlite3_bind_text(stmt, idx++, providerid, -1, SQLITE_TRANSIENT);
-
- if (lang)
- sqlite3_bind_text(stmt, idx++, (char *)lang, -1, SQLITE_TRANSIENT);
- else
- sqlite3_bind_text(stmt, idx++, "No Locale", -1, SQLITE_TRANSIENT);
-
- sqlite3_bind_text(stmt, idx, (char *)node->children->content, -1, SQLITE_TRANSIENT);
-
- ret = sqlite3_step(stmt);
- if (ret != SQLITE_DONE) {
- LOGE("step error: %s", sqlite3_errmsg(db));
- goto out;
- }
-
- ret = 0;
-out:
- if (stmt)
- sqlite3_finalize(stmt);
-
- if (lang)
- xmlFree(lang);
-
- return ret;
-}
-
-static int _parse_privilege(xmlNode *node, sqlite3 *db, const char *providerid)
-{
- int ret;
- sqlite3_stmt *stmt = NULL;
- xmlNode *tmp;
-
- static const char query[] =
- "INSERT INTO provider_privilege "
- "(provider_id, privilege) "
- "VALUES (?, ?)";
-
- if (node->children == NULL)
- return -1;
-
- ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
- if (ret != SQLITE_OK) {
- LOGE("prepare error: %s", sqlite3_errmsg(db));
- goto out;
- }
-
- for (tmp = node->children; tmp; tmp = tmp->next) {
- if (!xmlStrcasecmp(tmp->name, (const xmlChar *)"privilege")) {
- sqlite3_bind_text(stmt, 1, providerid, -1, SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 2, (char *)tmp->children->content, -1, SQLITE_TRANSIENT);
-
- ret = sqlite3_step(stmt);
- if (ret != SQLITE_DONE) {
- LOGE("step error: %s", sqlite3_errmsg(db));
- goto out;
- }
-
- sqlite3_reset(stmt);
- sqlite3_clear_bindings(stmt);
- }
- }
-
- ret = 0;
-out:
- if (stmt)
- sqlite3_finalize(stmt);
-
- return ret;
-}
-
-static int _parse_setup_appid(sqlite3 *db, const char *providerid,
- const char *setup_appid)
-{
- int ret;
- sqlite3_stmt *stmt = NULL;
-
- static const char query[] =
- "INSERT INTO provider_setup_appid "
- "(provider_id, setup_appid) "
- "VALUES (?, ?)";
-
- ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
- if (ret != SQLITE_OK) {
- LOGE("prepare error: %s", sqlite3_errmsg(db));
- goto out;
- }
-
- sqlite3_bind_text(stmt, 1, providerid, -1, SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 2, setup_appid, -1, SQLITE_TRANSIENT);
-
- ret = sqlite3_step(stmt);
- if (ret != SQLITE_DONE) {
- LOGE("step error: %s", sqlite3_errmsg(db));
- goto out;
- }
-
- ret = 0;
-out:
- if (stmt)
- sqlite3_finalize(stmt);
-
- return ret;
-}
-
-static int _parse_complication(xmlNode *node, sqlite3 *db, const char *pkgid,
- const char *appid, const char *providerid, const char *setup_appid)
-{
- int period = -1;
-
- xmlNode *tmp = NULL;
- xmlNode *support_type_node = NULL;
-
- if (node->children == NULL)
- return -1;
-
- for (tmp = node->children; tmp; tmp = tmp->next) {
- if (!xmlStrcasecmp(tmp->name, (const xmlChar *)"support-type")) {
- if (tmp->children == NULL)
- return -1;
-
- support_type_node = tmp;
- } else if (!xmlStrcasecmp(tmp->name, (const xmlChar *)"period")) {
- if (tmp->children == NULL
- || tmp->children->content == NULL)
- return -1;
-
- period = atoi((char *)tmp->children->content);
- if (period < 60)
- period = 60;
- } else if (!xmlStrcasecmp(tmp->name, (const xmlChar *)"label")) {
- if (_parse_label(tmp, db, providerid)) {
- LOGE("parse label fail");
- return -1;
- }
- } else if (!xmlStrcasecmp(tmp->name, (const xmlChar *)"privileges")) {
- if (_parse_privilege(tmp, db, providerid)) {
- LOGE("parse privilege fail");
- return -1;
- }
- }
- }
-
- if (!support_type_node) {
- LOGE("complication provider doesn't have support-type");
- return -1;
- }
-
- if (setup_appid) {
- if (_parse_setup_appid(db, providerid, setup_appid)) {
- LOGE("parse setup appid fail");
- return -1;
- }
- }
-
- if (_parse_support_type(support_type_node, db, pkgid,
- appid, providerid, period)) {
- LOGE("parse support type fail");
- return -1;
- }
-
- return 0;
-}
-
-static int _parse_service_application(xmlNode *node, const char *pkgid)
-{
- int result = -1;
- char *appid;
- char *providerid;
- char *setup_appid;
- xmlNode *tmp;
- sqlite3 *db;
-
- appid = _get_attribute(node, "appid");
- if (appid == NULL)
- return -1;
-
- db = open_db(_get_target_uid());
- if (db == NULL) {
- LOGE("failed to open db");
- goto out;
- }
-
- if (sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL)) {
- LOGE("begin transaction error");
- goto out;
- }
-
- for (tmp = node->children; tmp; tmp = tmp->next) {
- if (!xmlStrcasecmp(tmp->name, (const xmlChar *)"complication")) {
- providerid = _get_attribute(tmp, "provider-id");
- if (providerid == NULL) {
- LOGE("provider-id error");
-
- sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
- goto out;
- }
-
- setup_appid = _get_attribute(tmp, "setup-appid");
-
- if (_parse_complication(tmp, db, pkgid, appid,
- providerid, setup_appid)) {
- LOGE("parse complication error");
-
- sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
-
- free(providerid);
-
- if (setup_appid)
- free(setup_appid);
-
- goto out;
- }
-
- free(providerid);
-
- if (setup_appid)
- free(setup_appid);
- }
- }
-
- if (sqlite3_exec(db, "END TRANSACTION", NULL, NULL, NULL)) {
- LOGE("end transaction error");
- goto out;
- }
-
- result = 0;
-out:
- if (db)
- sqlite3_close_v2(db);
-
- if (appid)
- free(appid);
-
- return result;
-}
-
-int complication_parser_plugin_parse_manifest(xmlDocPtr doc, const char *pkgid)
-{
- xmlNode *root;
- xmlNode *tmp;
-
- if (doc == NULL) {
- LOGE("invalid parameter");
- return -1;
- }
-
- root = xmlDocGetRootElement(doc);
- if (root == NULL) {
- LOGE("failed to get root element");
- return -1;
- }
-
- for (tmp = root->children; tmp; tmp = tmp->next) {
- if (xmlStrcasecmp(tmp->name, (const xmlChar *)"service-application"))
- continue;
-
- if (_parse_service_application(tmp, pkgid)) {
- LOGE("parse failed");
- return -1;
- }
- }
-
- return 0;
-}
-
-static int _remove_complication(sqlite3 *db, const char *pkgid)
-{
- int ret;
- int i;
- sqlite3_stmt *stmt = NULL;
-
- static const char *query[] = {
- "DELETE FROM provider_privilege WHERE provider_id IN "
- "(SELECT DISTINCT provider_id FROM complication_provider "
- "WHERE pkgid=?)",
- "DELETE FROM provider_localized_info WHERE provider_id IN "
- "(SELECT DISTINCT provider_id FROM complication_provider "
- "WHERE pkgid=?)",
- "DELETE FROM provider_setup_appid WHERE provider_id IN "
- "(SELECT DISTINCT provider_id FROM complication_provider "
- "WHERE pkgid=?)",
- "DELETE FROM complication_provider WHERE pkgid=?"
- };
-
- for (i = 0; i < (sizeof(query) / sizeof(*query)); i++) {
- ret = sqlite3_prepare_v2(db, query[i], strlen(query[i]), &stmt, NULL);
- if (ret != SQLITE_OK) {
- LOGE("prepare error: %s", sqlite3_errmsg(db));
- return -1;
- }
-
- sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT);
-
- ret = sqlite3_step(stmt);
- if (ret != SQLITE_DONE) {
- LOGE("step error: %s", sqlite3_errmsg(db));
- sqlite3_finalize(stmt);
- return -1;
- }
-
- sqlite3_finalize(stmt);
- }
-
- return 0;
-}
-
-int complication_parser_db_remove_complication(const char *pkgid)
-{
- int result = -1;
- sqlite3 *db;
-
- db = open_db(_get_target_uid());
- if (db == NULL)
- return -1;
-
- if (sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL)) {
- LOGE("begin transaction error");
- goto out;
- }
-
- if (_remove_complication(db, pkgid)) {
- LOGE("failed to remove complication provider");
-
- sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
- goto out;
- }
-
- if (sqlite3_exec(db, "END TRANSACTION", NULL, NULL, NULL)) {
- LOGE("begin transaction error");
- goto out;
- }
-
- result = 0;
-out:
- if (db)
- sqlite3_close_v2(db);
-
- return result;
-}
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <libxml/tree.h>
+
+#include <dlog.h>
+
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+#include <bundle.h>
+
+#include "watchface-complication/include/watchface-complication-internal.h"
+#include "watchface-complication/include/watchface-complication.h"
+
+#include "complication_parser_plugin_internal.h"
+
+#define DEFAULT_SHORT_TEXT "default-shorttext"
+#define DEFAULT_LONG_TEXT "default-longtext"
+#define DEFAULT_ICON "default-icon"
+#define DEFAULT_TITLE "default-title"
+#define DEFAULT_HOUR "default-hour"
+#define DEFAULT_MINUTE "default-minute"
+#define DEFAULT_SECOND "default-second"
+#define DEFAULT_CURRENT "default-current"
+#define DEFAULT_MAX "default-max"
+#define DEFAULT_MIN "default-min"
+#define DEFAULT_IMAGE "default-image"
+#define DEFAULT_EXTRA_DATA "default-extra-data"
+
+struct support_type_tag_map {
+ const char* name;
+ watchface_complication_type_e tag;
+};
+
+static struct support_type_tag_map __type_map[] = {
+ {"short-text-type", WATCHFACE_COMPLICATION_TYPE_SHORT_TEXT},
+ {"long-text-type", WATCHFACE_COMPLICATION_TYPE_LONG_TEXT},
+ {"ranged-value-type", WATCHFACE_COMPLICATION_TYPE_RANGED_VALUE},
+ {"time-type", WATCHFACE_COMPLICATION_TYPE_TIME},
+ {"icon-type", WATCHFACE_COMPLICATION_TYPE_ICON},
+ {"image-type", WATCHFACE_COMPLICATION_TYPE_IMAGE}
+};
+
+struct xml_to_bundle_key_map {
+ const char* xml_element;
+ const char* bundle_key;
+};
+
+static struct xml_to_bundle_key_map __budle_key_map[] = {
+ {DEFAULT_SHORT_TEXT, SHORT_TEXT_KEY},
+ {DEFAULT_LONG_TEXT, LONG_TEXT_KEY},
+ {DEFAULT_ICON, ICON_KEY},
+ {DEFAULT_TITLE, TITLE_KEY},
+ {DEFAULT_HOUR, TIME_KEY},
+ {DEFAULT_MINUTE, TIME_KEY},
+ {DEFAULT_SECOND, TIME_KEY},
+ {DEFAULT_CURRENT, RANGE_CUR_KEY},
+ {DEFAULT_MAX, RANGE_MAX_KEY},
+ {DEFAULT_MIN, RANGE_MIN_KEY},
+ {DEFAULT_IMAGE, IMAGE_KEY},
+ {DEFAULT_EXTRA_DATA, EXTRA_DATA_KEY}
+};
+
+static uid_t __target_uid;
+static bool __target_uid_initialized;
+
+static uid_t _get_target_uid(void) {
+ if (__target_uid_initialized)
+ return __target_uid;
+
+ pkgmgr_installer_info_get_target_uid(&__target_uid);
+
+ __target_uid_initialized = true;
+
+ return __target_uid;
+}
+
+int complication_parser_plugin_init(void) {
+ LOGD("complication_parser_plugin_init");
+
+ __target_uid_initialized = false;
+
+ if (check_db(_get_target_uid())) {
+ complication_parser_plugin_fini();
+ LOGE("parser init fail");
+ return -1;
+ }
+
+ return 0;
+}
+
+int complication_parser_plugin_fini(void) {
+ LOGD("complication_parser_plugin_fini");
+
+ __target_uid_initialized = false;
+
+ return 0;
+}
+
+static char* _get_attribute(xmlNode* node, const char* name) {
+ xmlChar* val;
+ char* attr = NULL;
+
+ val = xmlGetProp(node, (const xmlChar*)name);
+ if (val) {
+ attr = strdup((char*)val);
+ xmlFree(val);
+ }
+
+ return attr;
+}
+
+static int _get_support_type_tag(xmlNode* node) {
+ unsigned int i;
+
+ for (i = 0; i < (sizeof(__type_map) / sizeof(struct support_type_tag_map)); i++) {
+ if (!xmlStrcasecmp(node->name, (const xmlChar*)__type_map[i].name))
+ return __type_map[i].tag;
+ }
+
+ return 0;
+}
+
+static const char* _get_bundle_key(const char* xml_element) {
+ unsigned int i;
+
+ for (i = 0; i < (sizeof(__budle_key_map) / sizeof(struct xml_to_bundle_key_map)); i++) {
+ if (strcmp(xml_element, __budle_key_map[i].xml_element) == 0)
+ return __budle_key_map[i].bundle_key;
+ }
+
+ return NULL;
+}
+
+static bool _is_valid_element(int type, char* element_name) {
+ bool is_valid = true;
+ switch (type) {
+ case WATCHFACE_COMPLICATION_TYPE_SHORT_TEXT :
+ if (strcmp(element_name, DEFAULT_TITLE) != 0 &&
+ strcmp(element_name, DEFAULT_SHORT_TEXT) != 0 &&
+ strcmp(element_name, DEFAULT_ICON) != 0 &&
+ strcmp(element_name, DEFAULT_EXTRA_DATA) != 0) {
+ LOGE("type (%d) do not support (%s)", type, element_name);
+ is_valid = false;
+ }
+ break;
+ case WATCHFACE_COMPLICATION_TYPE_LONG_TEXT :
+ if (strcmp(element_name, DEFAULT_TITLE) != 0 &&
+ strcmp(element_name, DEFAULT_LONG_TEXT) != 0 &&
+ strcmp(element_name, DEFAULT_ICON) != 0 &&
+ strcmp(element_name, DEFAULT_EXTRA_DATA) != 0) {
+ LOGE("type (%d) do not support (%s)", type, element_name);
+ is_valid = false;
+ }
+ break;
+ case WATCHFACE_COMPLICATION_TYPE_RANGED_VALUE :
+ if (strcmp(element_name, DEFAULT_TITLE) != 0 &&
+ strcmp(element_name, DEFAULT_SHORT_TEXT) != 0 &&
+ strcmp(element_name, DEFAULT_ICON) != 0 &&
+ strcmp(element_name, DEFAULT_MIN) != 0 &&
+ strcmp(element_name, DEFAULT_MAX) != 0 &&
+ strcmp(element_name, DEFAULT_CURRENT) != 0 &&
+ strcmp(element_name, DEFAULT_EXTRA_DATA) != 0) {
+ LOGE("type (%d) do not support (%s)", type, element_name);
+ is_valid = false;
+ }
+ break;
+ case WATCHFACE_COMPLICATION_TYPE_ICON :
+ if (strcmp(element_name, DEFAULT_ICON) != 0 &&
+ strcmp(element_name, DEFAULT_EXTRA_DATA) != 0) {
+ LOGE("type (%d) do not support (%s)", type, element_name);
+ is_valid = false;
+ }
+ break;
+ case WATCHFACE_COMPLICATION_TYPE_IMAGE :
+ if (strcmp(element_name, DEFAULT_IMAGE) != 0 &&
+ strcmp(element_name, DEFAULT_EXTRA_DATA) != 0) {
+ LOGE("type (%d) do not support (%s)", type, element_name);
+ is_valid = false;
+ }
+ break;
+ case WATCHFACE_COMPLICATION_TYPE_TIME :
+ if (strcmp(element_name, DEFAULT_SHORT_TEXT) != 0 &&
+ strcmp(element_name, DEFAULT_HOUR) != 0 &&
+ strcmp(element_name, DEFAULT_MINUTE) != 0 &&
+ strcmp(element_name, DEFAULT_SECOND) != 0 &&
+ strcmp(element_name, DEFAULT_EXTRA_DATA) != 0) {
+ LOGE("type (%d) do not support (%s)", type, element_name);
+ is_valid = false;
+ }
+ break;
+ default :
+ break;
+ }
+
+ return is_valid;
+}
+
+static int _parse_support_type(xmlNode* node, sqlite3* db, const char* pkgid,
+ const char* appid, const char* providerid, int period) {
+ int ret;
+ int idx;
+ int support_type = 0;
+ int result = -1;
+
+ xmlNode* tmp;
+ xmlNode* tmpdata;
+ sqlite3_stmt* stmt = NULL;
+
+ bundle* default_data = NULL;
+ bundle_raw* raw = NULL;
+ int len = 0;
+ const char* bundle_key;
+
+ static const char query[] =
+ "INSERT INTO complication_provider ( "
+ "pkgid, appid, provider_id, period, "
+ "support_type, default_data) "
+ "VALUES (?, ?, ?, ?, ?, ?)";
+
+ if (node->children == NULL)
+ return -1;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare error: %s", sqlite3_errmsg(db));
+ goto out;
+ }
+
+ for (tmp = node->children; tmp; tmp = tmp->next) {
+ if (tmp->children == NULL
+ || tmp->children->content == NULL)
+ continue;
+
+ support_type = _get_support_type_tag(tmp);
+ if (!support_type) {
+ LOGE("not supported type");
+ goto out;
+ }
+
+ default_data = bundle_create();
+ if (default_data == NULL) {
+ LOGE("bundle create error");
+ goto out;
+ }
+
+ for (tmpdata = tmp->children; tmpdata; tmpdata = tmpdata->next) {
+ if (tmpdata->children != NULL
+ && tmpdata->children->content != NULL) {
+ if (!_is_valid_element(support_type, (char*)tmpdata->name))
+ goto out;
+
+ bundle_key = _get_bundle_key((const char*)tmpdata->name);
+ if (bundle_key == NULL) {
+ LOGE("wrong element name (%s)", (const char*)tmpdata->name);
+ goto out;
+ }
+
+ ret = bundle_add_str(default_data, bundle_key,
+ (char *)tmpdata->children->content);
+ if (ret != BUNDLE_ERROR_NONE) {
+ LOGE("bundle add error");
+ goto out;
+ }
+ }
+ }
+
+ ret = bundle_encode(default_data, &raw, &len);
+ if (ret != BUNDLE_ERROR_NONE) {
+ LOGE("bundle encode error");
+ goto out;
+ }
+
+ idx = 1;
+
+ sqlite3_bind_text(stmt, idx++, pkgid, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, idx++, appid, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, idx++, providerid, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_int(stmt, idx++, period);
+ sqlite3_bind_int(stmt, idx++, support_type);
+ sqlite3_bind_text(stmt, idx, (char*)raw, -1, SQLITE_TRANSIENT);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ LOGE("step error: %s", sqlite3_errmsg(db));
+ goto out;
+ }
+
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+
+ if (raw) {
+ free(raw);
+ raw = NULL;
+ }
+
+ if (default_data) {
+ bundle_free(default_data);
+ default_data = NULL;
+ }
+ }
+
+ result = 0;
+out:
+ if (default_data)
+ bundle_free(default_data);
+
+ if (raw)
+ free(raw);
+
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ return result;
+}
+
+static int _parse_label(xmlNode* node, sqlite3* db, const char* providerid) {
+ int ret;
+ int idx;
+ sqlite3_stmt* stmt = NULL;
+ xmlChar* lang = NULL;
+
+ static const char query[] =
+ "INSERT INTO provider_localized_info "
+ "(provider_id, locale, provider_label) "
+ "VALUES (?, ?, ?)";
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare error: %s", sqlite3_errmsg(db));
+ goto out;
+ }
+
+ lang = xmlNodeGetLang(node);
+
+ idx = 1;
+
+ sqlite3_bind_text(stmt, idx++, providerid, -1, SQLITE_TRANSIENT);
+
+ if (lang)
+ sqlite3_bind_text(stmt, idx++, (char*)lang, -1, SQLITE_TRANSIENT);
+ else
+ sqlite3_bind_text(stmt, idx++, "No Locale", -1, SQLITE_TRANSIENT);
+
+ sqlite3_bind_text(stmt, idx, (char*)node->children->content, -1, SQLITE_TRANSIENT);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ LOGE("step error: %s", sqlite3_errmsg(db));
+ goto out;
+ }
+
+ ret = 0;
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (lang)
+ xmlFree(lang);
+
+ return ret;
+}
+
+static int _parse_privilege(xmlNode* node, sqlite3* db, const char* providerid) {
+ int ret;
+ sqlite3_stmt* stmt = NULL;
+ xmlNode* tmp;
+
+ static const char query[] =
+ "INSERT INTO provider_privilege "
+ "(provider_id, privilege) "
+ "VALUES (?, ?)";
+
+ if (node->children == NULL)
+ return -1;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare error: %s", sqlite3_errmsg(db));
+ goto out;
+ }
+
+ for (tmp = node->children; tmp; tmp = tmp->next) {
+ if (!xmlStrcasecmp(tmp->name, (const xmlChar*)"privilege")) {
+ sqlite3_bind_text(stmt, 1, providerid, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 2, (char*)tmp->children->content, -1, SQLITE_TRANSIENT);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ LOGE("step error: %s", sqlite3_errmsg(db));
+ goto out;
+ }
+
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ }
+ }
+
+ ret = 0;
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ return ret;
+}
+
+static int _parse_setup_appid(sqlite3* db, const char* providerid,
+ const char* setup_appid) {
+ int ret;
+ sqlite3_stmt* stmt = NULL;
+
+ static const char query[] =
+ "INSERT INTO provider_setup_appid "
+ "(provider_id, setup_appid) "
+ "VALUES (?, ?)";
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare error: %s", sqlite3_errmsg(db));
+ goto out;
+ }
+
+ sqlite3_bind_text(stmt, 1, providerid, -1, SQLITE_TRANSIENT);
+ sqlite3_bind_text(stmt, 2, setup_appid, -1, SQLITE_TRANSIENT);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ LOGE("step error: %s", sqlite3_errmsg(db));
+ goto out;
+ }
+
+ ret = 0;
+out:
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ return ret;
+}
+
+static int _parse_complication(xmlNode* node, sqlite3* db, const char* pkgid,
+ const char* appid, const char* providerid, const char* setup_appid) {
+ int period = -1;
+
+ xmlNode* tmp = NULL;
+ xmlNode* support_type_node = NULL;
+
+ if (node->children == NULL)
+ return -1;
+
+ for (tmp = node->children; tmp; tmp = tmp->next) {
+ if (!xmlStrcasecmp(tmp->name, (const xmlChar*)"support-type")) {
+ if (tmp->children == NULL)
+ return -1;
+
+ support_type_node = tmp;
+ } else if (!xmlStrcasecmp(tmp->name, (const xmlChar*)"period")) {
+ if (tmp->children == NULL
+ || tmp->children->content == NULL)
+ return -1;
+
+ period = atoi((char*)tmp->children->content);
+ if (period < 60)
+ period = 60;
+ } else if (!xmlStrcasecmp(tmp->name, (const xmlChar*)"label")) {
+ if (_parse_label(tmp, db, providerid)) {
+ LOGE("parse label fail");
+ return -1;
+ }
+ } else if (!xmlStrcasecmp(tmp->name, (const xmlChar*)"privileges")) {
+ if (_parse_privilege(tmp, db, providerid)) {
+ LOGE("parse privilege fail");
+ return -1;
+ }
+ }
+ }
+
+ if (!support_type_node) {
+ LOGE("complication provider doesn't have support-type");
+ return -1;
+ }
+
+ if (setup_appid) {
+ if (_parse_setup_appid(db, providerid, setup_appid)) {
+ LOGE("parse setup appid fail");
+ return -1;
+ }
+ }
+
+ if (_parse_support_type(support_type_node, db, pkgid,
+ appid, providerid, period)) {
+ LOGE("parse support type fail");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _parse_service_application(xmlNode* node, const char* pkgid) {
+ int result = -1;
+ char* appid;
+ char* providerid;
+ char* setup_appid;
+ xmlNode* tmp;
+ sqlite3* db;
+
+ appid = _get_attribute(node, "appid");
+ if (appid == NULL)
+ return -1;
+
+ db = open_db(_get_target_uid());
+ if (db == NULL) {
+ LOGE("failed to open db");
+ goto out;
+ }
+
+ if (sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL)) {
+ LOGE("begin transaction error");
+ goto out;
+ }
+
+ for (tmp = node->children; tmp; tmp = tmp->next) {
+ if (!xmlStrcasecmp(tmp->name, (const xmlChar*)"complication")) {
+ providerid = _get_attribute(tmp, "provider-id");
+ if (providerid == NULL) {
+ LOGE("provider-id error");
+
+ sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
+ goto out;
+ }
+
+ setup_appid = _get_attribute(tmp, "setup-appid");
+
+ if (_parse_complication(tmp, db, pkgid, appid,
+ providerid, setup_appid)) {
+ LOGE("parse complication error");
+
+ sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
+
+ free(providerid);
+
+ if (setup_appid)
+ free(setup_appid);
+
+ goto out;
+ }
+
+ free(providerid);
+
+ if (setup_appid)
+ free(setup_appid);
+ }
+ }
+
+ if (sqlite3_exec(db, "END TRANSACTION", NULL, NULL, NULL)) {
+ LOGE("end transaction error");
+ goto out;
+ }
+
+ result = 0;
+out:
+ if (db)
+ sqlite3_close_v2(db);
+
+ if (appid)
+ free(appid);
+
+ return result;
+}
+
+int complication_parser_plugin_parse_manifest(xmlDocPtr doc, const char* pkgid) {
+ xmlNode* root;
+ xmlNode* tmp;
+
+ if (doc == NULL) {
+ LOGE("invalid parameter");
+ return -1;
+ }
+
+ root = xmlDocGetRootElement(doc);
+ if (root == NULL) {
+ LOGE("failed to get root element");
+ return -1;
+ }
+
+ for (tmp = root->children; tmp; tmp = tmp->next) {
+ if (xmlStrcasecmp(tmp->name, (const xmlChar*)"service-application"))
+ continue;
+
+ if (_parse_service_application(tmp, pkgid)) {
+ LOGE("parse failed");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int _remove_complication(sqlite3* db, const char* pkgid) {
+ int ret;
+ unsigned int i;
+ sqlite3_stmt* stmt = NULL;
+
+ static const char* query[] = {
+ "DELETE FROM provider_privilege WHERE provider_id IN "
+ "(SELECT DISTINCT provider_id FROM complication_provider "
+ "WHERE pkgid=?)",
+ "DELETE FROM provider_localized_info WHERE provider_id IN "
+ "(SELECT DISTINCT provider_id FROM complication_provider "
+ "WHERE pkgid=?)",
+ "DELETE FROM provider_setup_appid WHERE provider_id IN "
+ "(SELECT DISTINCT provider_id FROM complication_provider "
+ "WHERE pkgid=?)",
+ "DELETE FROM complication_provider WHERE pkgid=?"
+ };
+
+ for (i = 0; i < (sizeof(query) / sizeof(*query)); i++) {
+ ret = sqlite3_prepare_v2(db, query[i], strlen(query[i]), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare error: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ LOGE("step error: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_finalize(stmt);
+ }
+
+ return 0;
+}
+
+int complication_parser_db_remove_complication(const char* pkgid) {
+ int result = -1;
+ sqlite3* db;
+
+ db = open_db(_get_target_uid());
+ if (db == NULL)
+ return -1;
+
+ if (sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL)) {
+ LOGE("begin transaction error");
+ goto out;
+ }
+
+ if (_remove_complication(db, pkgid)) {
+ LOGE("failed to remove complication provider");
+
+ sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
+ goto out;
+ }
+
+ if (sqlite3_exec(db, "END TRANSACTION", NULL, NULL, NULL)) {
+ LOGE("begin transaction error");
+ goto out;
+ }
+
+ result = 0;
+out:
+ if (db)
+ sqlite3_close_v2(db);
+
+ return result;
+}
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <sqlite3.h>
-
-#include <dlog.h>
-#include <tzplatform_config.h>
-
-#include "complication_parser_plugin_internal.h"
-
-#define BUSY_WAITING_USEC 50000 /* 0.05 sec */
-#define BUSY_WAITING_MAX 20 /* wait for max 1 sec */
-#define ROOT_USER 0
-#define GLOBALAPP_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
-
-#define CREATE_COMPLICATION_TABLE " \
-PRAGMA user_version = 50; \
-PRAGMA journal_mode = PERSIST; \
-PRAGMA foreign_keys = ON; \
-BEGIN EXCLUSIVE TRANSACTION; \
-CREATE TABLE IF NOT EXISTS complication_provider ( \
- pkgid TEXT NOT NULL, \
- appid TEXT NOT NULL, \
- provider_id TEXT NOT NULL, \
- period INTEGER DEFAULT -1, \
- support_type INTEGER DEFAULT 0, \
- default_data TEXT NOT NULL, \
- PRIMARY KEY (provider_id, support_type) \
-); \
-CREATE TABLE IF NOT EXISTS provider_localized_info ( \
- provider_id TEXT NOT NULL, \
- locale TEXT NOT NULL DEFAULT 'No Locale', \
- provider_label TEXT, \
- PRIMARY KEY (provider_id, locale) \
-); \
-CREATE TABLE IF NOT EXISTS provider_privilege ( \
- provider_id TEXT NOT NULL, \
- privilege TEXT NOT NULL, \
- PRIMARY KEY (provider_id, privilege) \
-); \
-CREATE TABLE IF NOT EXISTS provider_setup_appid ( \
- provider_id TEXT NOT NULL, \
- setup_appid TEXT, \
- PRIMARY KEY (provider_id) \
-); \
-COMMIT TRANSACTION; "
-
-#define COMPLICATION_TBL_COUNT 4
-static char *_complication_table_list[COMPLICATION_TBL_COUNT] = {
- "complication_provider",
- "provider_localized_info",
- "provider_privilege",
- "provider_setup_appid"
-};
-
-static int _is_global(uid_t uid)
-{
- if (uid == ROOT_USER || uid == GLOBALAPP_USER)
- return 1;
- else
- return 0;
-}
-
-static const char *_get_db_path(uid_t uid)
-{
- const char *path;
-
- if (!_is_global(uid))
- tzplatform_set_user(uid);
-
- path = tzplatform_mkpath(_is_global(uid) ?
- TZ_SYS_DB : TZ_USER_DB, ".complication_provider.db");
-
- tzplatform_reset_user();
-
- return path;
-}
-
-static int _db_busy_handler(void *data, int count)
-{
- if (count < BUSY_WAITING_MAX) {
- usleep(BUSY_WAITING_USEC);
- return 1;
- }
-
- /* sqlite3_prepare_v2 will return SQLITE_BUSY */
- return 0;
-}
-
-static int _create_db(sqlite3 *db, const char *path)
-{
- int ret;
-
- if (db)
- sqlite3_close(db);
- unlink(path);
-
- ret = sqlite3_open_v2(path, &db,
- SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE,
- NULL);
- if (ret != SQLITE_OK) {
- unlink(path);
- LOGE("create db fail");
- return -1;
- }
-
- return ret;
-}
-
-static int _check_table_exist(sqlite3 *db)
-{
- int ret;
- char *val;
- int idx = 0;
- sqlite3_stmt *stmt;
- const char query[] =
- "SELECT name FROM sqlite_master WHERE type='table'"
- " ORDER BY name ASC";
-
- ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
- if (ret != SQLITE_OK) {
- LOGE("prepare error: %s", sqlite3_errmsg(db));
- return -1;
- }
-
- while (sqlite3_step(stmt) == SQLITE_ROW
- && idx < COMPLICATION_TBL_COUNT) {
- val = (char *)sqlite3_column_text(stmt, 0);
-
- if (strcmp(_complication_table_list[idx], val) != 0)
- continue;
-
- idx++;
- }
-
- if (stmt)
- sqlite3_finalize(stmt);
-
- if (idx != COMPLICATION_TBL_COUNT) {
- LOGE("table count not matched");
- return -1;
- }
-
- return 0;
-}
-
-static int _create_table(sqlite3 *db)
-{
- int ret;
- char *errmsg = NULL;
-
- ret = sqlite3_exec(db, CREATE_COMPLICATION_TABLE,
- NULL, NULL, &errmsg);
- if (ret != SQLITE_OK) {
- LOGE("create table fail : %s", errmsg);
- sqlite3_free(errmsg);
- return -1;
- }
-
- return 0;
-}
-
-int check_db(uid_t uid)
-{
- int ret;
- const char *path;
- sqlite3 *db = NULL;
-
- path = _get_db_path(uid);
- if (path == NULL)
- return -1;
-
- ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE, NULL);
- if (ret != SQLITE_OK) {
- ret = _create_db(db, path);
- if (ret != SQLITE_OK)
- return -1;
- }
-
- if (_check_table_exist(db)) {
- if (_create_table(db)) {
- if (db)
- sqlite3_close_v2(db);
-
- return -1;
- }
- }
-
- if (db)
- sqlite3_close_v2(db);
-
- return 0;
-}
-
-sqlite3 *open_db(uid_t uid)
-{
- int ret;
- sqlite3 *db;
- const char *path;
-
- path = _get_db_path(uid);
- if (access(path, F_OK) == -1) {
- LOGE("db(%s) does not exist, create one", path);
- return NULL;
- }
-
- ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE, NULL);
- if (ret != SQLITE_OK) {
- LOGE("open db(%s) error: %d", path, ret);
- return NULL;
- }
-
- ret = sqlite3_busy_handler(db, _db_busy_handler, NULL);
- if (ret != SQLITE_OK) {
- LOGE("Failed to register busy handler: %s",
- sqlite3_errmsg(db));
- sqlite3_close_v2(db);
- return NULL;
- }
-
- /* turn on foreign keys */
- if (sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, NULL)) {
- sqlite3_close_v2(db);
- return NULL;
- }
-
- return db;
-}
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <sqlite3.h>
+
+#include <dlog.h>
+#include <tzplatform_config.h>
+
+#include "complication_parser_plugin_internal.h"
+
+#define BUSY_WAITING_USEC 50000 /* 0.05 sec */
+#define BUSY_WAITING_MAX 20 /* wait for max 1 sec */
+#define ROOT_USER 0
+#define GLOBALAPP_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
+
+#define CREATE_COMPLICATION_TABLE " \
+PRAGMA user_version = 50; \
+PRAGMA journal_mode = PERSIST; \
+PRAGMA foreign_keys = ON; \
+BEGIN EXCLUSIVE TRANSACTION; \
+CREATE TABLE IF NOT EXISTS complication_provider ( \
+ pkgid TEXT NOT NULL, \
+ appid TEXT NOT NULL, \
+ provider_id TEXT NOT NULL, \
+ period INTEGER DEFAULT -1, \
+ support_type INTEGER DEFAULT 0, \
+ default_data TEXT NOT NULL, \
+ PRIMARY KEY (provider_id, support_type) \
+); \
+CREATE TABLE IF NOT EXISTS provider_localized_info ( \
+ provider_id TEXT NOT NULL, \
+ locale TEXT NOT NULL DEFAULT 'No Locale', \
+ provider_label TEXT, \
+ PRIMARY KEY (provider_id, locale) \
+); \
+CREATE TABLE IF NOT EXISTS provider_privilege ( \
+ provider_id TEXT NOT NULL, \
+ privilege TEXT NOT NULL, \
+ PRIMARY KEY (provider_id, privilege) \
+); \
+CREATE TABLE IF NOT EXISTS provider_setup_appid ( \
+ provider_id TEXT NOT NULL, \
+ setup_appid TEXT, \
+ PRIMARY KEY (provider_id) \
+); \
+COMMIT TRANSACTION; "
+
+#define COMPLICATION_TBL_COUNT 4
+static const char* _complication_table_list[COMPLICATION_TBL_COUNT] = {
+ "complication_provider",
+ "provider_localized_info",
+ "provider_privilege",
+ "provider_setup_appid"
+};
+
+static int _is_global(uid_t uid) {
+ if (uid == ROOT_USER || uid == GLOBALAPP_USER)
+ return 1;
+ else
+ return 0;
+}
+
+static const char* _get_db_path(uid_t uid) {
+ const char* path;
+
+ if (!_is_global(uid))
+ tzplatform_set_user(uid);
+
+ path = tzplatform_mkpath(_is_global(uid) ?
+ TZ_SYS_DB : TZ_USER_DB, ".complication_provider.db");
+
+ tzplatform_reset_user();
+
+ return path;
+}
+
+static int _db_busy_handler(void* data, int count) {
+ if (count < BUSY_WAITING_MAX) {
+ usleep(BUSY_WAITING_USEC);
+ return 1;
+ }
+
+ /* sqlite3_prepare_v2 will return SQLITE_BUSY */
+ return 0;
+}
+
+static int _create_db(sqlite3* db, const char* path) {
+ int ret;
+
+ if (db)
+ sqlite3_close(db);
+ unlink(path);
+
+ ret = sqlite3_open_v2(path, &db,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE,
+ NULL);
+ if (ret != SQLITE_OK) {
+ unlink(path);
+ LOGE("create db fail");
+ return -1;
+ }
+
+ return ret;
+}
+
+static int _check_table_exist(sqlite3* db) {
+ int ret;
+ char* val;
+ int idx = 0;
+ sqlite3_stmt* stmt;
+ const char query[] =
+ "SELECT name FROM sqlite_master WHERE type='table'"
+ " ORDER BY name ASC";
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare error: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW
+ && idx < COMPLICATION_TBL_COUNT) {
+ val = (char*)sqlite3_column_text(stmt, 0);
+
+ if (strcmp(_complication_table_list[idx], val) != 0)
+ continue;
+
+ idx++;
+ }
+
+ if (stmt)
+ sqlite3_finalize(stmt);
+
+ if (idx != COMPLICATION_TBL_COUNT) {
+ LOGE("table count not matched");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _create_table(sqlite3* db) {
+ int ret;
+ char* errmsg = NULL;
+
+ ret = sqlite3_exec(db, CREATE_COMPLICATION_TABLE,
+ NULL, NULL, &errmsg);
+ if (ret != SQLITE_OK) {
+ LOGE("create table fail : %s", errmsg);
+ sqlite3_free(errmsg);
+ return -1;
+ }
+
+ return 0;
+}
+
+int check_db(uid_t uid) {
+ int ret;
+ const char* path;
+ sqlite3* db = NULL;
+
+ path = _get_db_path(uid);
+ if (path == NULL)
+ return -1;
+
+ ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE, NULL);
+ if (ret != SQLITE_OK) {
+ ret = _create_db(db, path);
+ if (ret != SQLITE_OK)
+ return -1;
+ }
+
+ if (_check_table_exist(db)) {
+ if (_create_table(db)) {
+ if (db)
+ sqlite3_close_v2(db);
+
+ return -1;
+ }
+ }
+
+ if (db)
+ sqlite3_close_v2(db);
+
+ return 0;
+}
+
+sqlite3* open_db(uid_t uid) {
+ int ret;
+ sqlite3* db;
+ const char* path;
+
+ path = _get_db_path(uid);
+ if (access(path, F_OK) == -1) {
+ LOGE("db(%s) does not exist, create one", path);
+ return NULL;
+ }
+
+ ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("open db(%s) error: %d", path, ret);
+ return NULL;
+ }
+
+ ret = sqlite3_busy_handler(db, _db_busy_handler, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("Failed to register busy handler: %s",
+ sqlite3_errmsg(db));
+ sqlite3_close_v2(db);
+ return NULL;
+ }
+
+ /* turn on foreign keys */
+ if (sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, NULL)) {
+ sqlite3_close_v2(db);
+ return NULL;
+ }
+
+ return db;
+}
#include <libxml/tree.h>
#include <sqlite3.h>
-#ifndef API
-#define API __attribute__ ((visibility("default")))
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
#endif
#ifdef LOG_TAG
+++ /dev/null
-/*
- * 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 <libxml/tree.h>
-
-#include <dlog.h>
-
-#include "complication_parser_plugin_internal.h"
-
-API int PKGMGR_PARSER_PLUGIN_PRE_INSTALL(const char *pkgid)
-{
- return complication_parser_plugin_init();
-}
-
-API int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc, const char *pkgid)
-{
- if (complication_parser_plugin_parse_manifest(doc, pkgid)) {
- LOGE("parse failed");
- return -1;
- }
-
- return 0;
-}
-
-API int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char *pkgid)
-{
- return complication_parser_plugin_fini();
-}
-
-API int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE(const char *pkgid)
-{
- return complication_parser_plugin_init();
-}
-
-API int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr doc, const char *pkgid)
-{
- if (complication_parser_db_remove_complication(pkgid)) {
- LOGE("remove db fail");
- return -1;
- }
-
- if (complication_parser_plugin_parse_manifest(doc, pkgid)) {
- LOGE("parse failed");
- return -1;
- }
-
- return 0;
-}
-
-API int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char *pkgid)
-{
- return complication_parser_plugin_fini();
-}
-
-API int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL(const char *pkgid)
-{
- return complication_parser_plugin_init();
-}
-
-API int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr doc, const char *pkgid)
-{
- return complication_parser_db_remove_complication(pkgid);
-}
-
-API int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL(const char *pkgid)
-{
- return complication_parser_plugin_fini();
-}
--- /dev/null
+/*
+ * 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 <libxml/tree.h>
+
+#include <dlog.h>
+
+#include "complication_parser_plugin_internal.h"
+
+extern "C" EXPORT_API int PKGMGR_PARSER_PLUGIN_PRE_INSTALL(const char* pkgid) {
+ return complication_parser_plugin_init();
+}
+
+extern "C" EXPORT_API int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc, const char* pkgid) {
+ if (complication_parser_plugin_parse_manifest(doc, pkgid)) {
+ LOGE("parse failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+extern "C" EXPORT_API int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char* pkgid) {
+ return complication_parser_plugin_fini();
+}
+
+extern "C" EXPORT_API int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE(const char* pkgid) {
+ return complication_parser_plugin_init();
+}
+
+extern "C" EXPORT_API int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr doc, const char* pkgid) {
+ if (complication_parser_db_remove_complication(pkgid)) {
+ LOGE("remove db fail");
+ return -1;
+ }
+
+ if (complication_parser_plugin_parse_manifest(doc, pkgid)) {
+ LOGE("parse failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+extern "C" EXPORT_API int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char* pkgid) {
+ return complication_parser_plugin_fini();
+}
+
+extern "C" EXPORT_API int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL(const char* pkgid) {
+ return complication_parser_plugin_init();
+}
+
+extern "C" EXPORT_API int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr doc, const char* pkgid) {
+ return complication_parser_db_remove_complication(pkgid);
+}
+
+extern "C" EXPORT_API int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL(const char* pkgid) {
+ return complication_parser_plugin_fini();
+}