Add default theme feature 36/237236/4
authorSangyoon Jang <jeremy.jang@samsung.com>
Fri, 26 Jun 2020 07:06:37 +0000 (16:06 +0900)
committerSangyoon Jang <jeremy.jang@samsung.com>
Mon, 29 Jun 2020 04:26:00 +0000 (13:26 +0900)
Change-Id: Ib1c2efe434283ab2f28883e0f1b2756399b1e93b
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
src/theme_plugin/theme_metadata_plugin.cc
src/theme_plugin/theme_parser.cc
src/theme_plugin/theme_parser.h
src/theme_provider/db_manager.cc
src/theme_provider/sqlite_statement.cc
src/theme_provider/sqlite_statement.h
test/unit_tests/test_theme_parser.cc

index c97a52c..024b283 100644 (file)
@@ -23,7 +23,8 @@ using ttm::plugin::ThemeParser;
 
 namespace {
 
-const char kThemeMetadataKey[] = "http://tizen.org/metadata/theme";
+const char kDefaultThemeKey[] = "http://tizen.org/metadata/theme/default";
+const char kThemeKey[] = "http://tizen.org/metadata/theme";
 
 std::string GetThemeFilePath(const char* pkgid) {
   pkgmgrinfo_pkginfo_h handle;
@@ -45,15 +46,16 @@ std::string GetThemeFilePath(const char* pkgid) {
 }
 
 bool ParseAndCommitTheme(ThemeParser::ThemeOperation op, const std::string& id,
-    const std::string& pkgid, const std::string& path) {
+    const std::string& pkgid, const std::string& path, bool is_default) {
   uid_t uid;
   int r = pkgmgr_installer_info_get_target_uid(&uid);
   if (r < 0) {
     LOG(ERROR) << "Failed to get target uid";
     return false;
   }
+
   ThemeParser parser(path);
-  ThemeInfo theme = parser.Inflate(id, pkgid, uid);
+  ThemeInfo theme = parser.Inflate(id, pkgid, uid, is_default);
   if (!theme.IsValid()) {
     LOG(ERROR) << "Failed to parse theme";
     return false;
@@ -71,13 +73,19 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(
   if (root_path.empty())
     return -1;
 
+  bool is_default = false;
+  std::string json_file;
   for (__metadata_t* md : GListRange<__metadata_t*>(metadata)) {
-    if (!strcmp(md->key, kThemeMetadataKey)) {
-      if (!ParseAndCommitTheme(ThemeParser::ThemeOperation::ADD, appid, pkgid,
-          (root_path + md->value)))
-        return -1;
-    }
+    // Assume that there is a only json file for theme
+    if (!strcmp(md->key, kThemeKey))
+      json_file = root_path + md->value;
+    else if (!strcmp(md->key, kDefaultThemeKey))
+      is_default = true;
   }
+
+  if (!ParseAndCommitTheme(ThemeParser::ThemeOperation::ADD, appid, pkgid,
+      json_file, is_default))
+    return -1;
   return 0;
 }
 
@@ -87,13 +95,17 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(
   if (root_path.empty())
     return -1;
 
+  std::string json_file;
   for (__metadata_t* md : GListRange<__metadata_t*>(metadata)) {
-    if (!strcmp(md->key, kThemeMetadataKey)) {
-      if (!ParseAndCommitTheme(ThemeParser::ThemeOperation::UPDATE, appid,
-          pkgid, (root_path + md->value)))
-        return -1;
-    }
+    // Assume that there is a only json file for theme
+    if (!strcmp(md->key, kThemeKey))
+      json_file = root_path + md->value;
   }
+
+  // Upgrading default theme is not allowed
+  if (!ParseAndCommitTheme(ThemeParser::ThemeOperation::UPDATE, appid, pkgid,
+      json_file, false))
+    return -1;
   return 0;
 }
 
@@ -103,12 +115,16 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(
   if (root_path.empty())
     return -1;
 
+  std::string json_file;
   for (__metadata_t* md : GListRange<__metadata_t*>(metadata)) {
-    if (!strcmp(md->key, kThemeMetadataKey)) {
-      if (!ParseAndCommitTheme(ThemeParser::ThemeOperation::REMOVE, appid,
-          pkgid, (root_path + md->value)))
-        return -1;
-    }
+    // Assume that there is a only json file for theme
+    if (!strcmp(md->key, kThemeKey))
+      json_file = root_path + md->value;
   }
+
+  // Removing default theme is not allowed
+  if (!ParseAndCommitTheme(ThemeParser::ThemeOperation::REMOVE, appid, pkgid,
+      json_file, false))
+    return -1;
   return 0;
 }
index b735705..5ecd2bc 100644 (file)
@@ -20,7 +20,7 @@ namespace ttm {
 namespace plugin {
 
 loader::ThemeInfo ThemeParser::Inflate(const std::string id,
-    const std::string pkgid, uid_t uid) {
+    const std::string pkgid, uid_t uid, bool is_default) {
   Json::CharReaderBuilder rbuilder;
   rbuilder["collectComments"] = false;
 
@@ -37,6 +37,7 @@ loader::ThemeInfo ThemeParser::Inflate(const std::string id,
   ThemeInfoBuilder builder(id);
   builder.PutString("pkgid", pkgid).
       PutString("uid", std::to_string(uid)).
+      PutString("is_default", is_default ? "true" : "false").
       PutString("version", root["version"].asString()).
       PutString("tool_version", root["tool_version"].asString()).
       PutString("title", root["header"]["title"].asString()).
index 0bfbacd..65d07ac 100644 (file)
@@ -25,7 +25,7 @@ class ThemeParser {
 
   explicit ThemeParser(const std::string& path) : path_(path) {}
   loader::ThemeInfo Inflate(const std::string id, const std::string pkgid,
-      uid_t uid);
+      uid_t uid, bool is_default);
   bool Commit(ThemeOperation operation, const loader::ThemeInfo& theme);
 
  private:
index 45e860e..53873d8 100644 (file)
@@ -24,12 +24,17 @@ const char kCreateThemeTableQuery[] =
     "  description  TEXT,\n"
     "  preview      TEXT,\n"
     "  resolution   TEXT,\n"
+    "  is_default   TEXT DEFAULT 'false',\n"
     "  details      BLOB,\n"
+    "  CHECK (is_default IN ('true', 'false'))\n"
     "  PRIMARY KEY (id))";
+const char kCreateIndexQuery[] =
+    "CREATE UNIQUE INDEX IF NOT EXISTS 'is_default_INDEX' "
+    "ON theme (is_default) WHERE is_default = 'true'";
 const char kInsertQuery[] =
     "INSERT INTO theme (id, pkgid, version, tool_version, title, description,"
-    "  preview, resolution, details) "
-    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
+    "  preview, resolution, is_default, details) "
+    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
 const char kUpdateQuery[] =
     "UPDATE theme SET version = ?, tool_version = ?, title = ?,"
     "  description = ?, preview = ?, resolution = ?, details = ? "
@@ -57,6 +62,8 @@ DbManager::DbManager(const std::string& db_path) {
   conn_ = std::make_shared<SQLiteConnection>(db_path, false);
   if (!conn_->Execute(kCreateThemeTableQuery))
     LOG(ERROR) << "Failed to create theme table";
+  if (!conn_->Execute(kCreateIndexQuery))
+    LOG(ERROR) << "Failed to create unique index for theme table";
   if (!conn_->Execute(kCreateThemeSettingTableQuery))
     LOG(ERROR) << "Failed to create theme_setting table";
 }
@@ -88,6 +95,8 @@ bool DbManager::Insert(const std::string& id, const tizen_base::Bundle& info) {
     return false;
   if (!stmt->BindString(idx++, info.GetString("resolution")))
     return false;
+  if (!stmt->BindString(idx++, info.GetString("is_default")))
+    return false;
   if (!stmt->BindBlob(idx++, info.GetByte("details")))
     return false;
 
index 5f091d5..f83b660 100644 (file)
@@ -43,7 +43,20 @@ SQLiteStatement::StepResult SQLiteStatement::Step() {
   return res;
 }
 
+bool SQLiteStatement::BindNull(int pos) {
+  int r = sqlite3_bind_null(stmt_, pos);
+  if (r != SQLITE_OK) {
+    LOG(ERROR) << "sqlite3_bind_null() failed: " << GetErrorMessage();
+    sql_conn_->SetErrorCode(r);
+    return false;
+  }
+  return true;
+}
+
 bool SQLiteStatement::BindString(int pos, const std::string& val) {
+  if (val.empty())
+    return BindNull(pos);
+
   int r = sqlite3_bind_text(stmt_, pos, val.c_str(), -1, SQLITE_TRANSIENT);
   if (r != SQLITE_OK) {
     LOG(ERROR) << "sqlite3_bind_text() failed: " << GetErrorMessage();
index 4ab6d70..1772e1b 100644 (file)
@@ -29,6 +29,7 @@ class SQLiteStatement {
   enum class StepResult : int { DONE, ROW, ERROR, };
   StepResult Step();
 
+  bool BindNull(int pos);
   bool BindString(int pos, const std::string& val);
   bool BindBlob(int pos, const std::vector<unsigned char>& val);
 
index 500bab0..5417be0 100644 (file)
@@ -32,7 +32,7 @@ class ThemeParserTest : public testing::Test {
 
 TEST_F(ThemeParserTest, Inflate) {
   ttm::plugin::ThemeParser parser("test_samples/test_theme.json");
-  auto info = parser.Inflate("testid", "testpkgid", 5001);
+  auto info = parser.Inflate("testid", "testpkgid", 5001, false);
   EXPECT_EQ(info.GetId(), "testid");
   EXPECT_EQ(info.GetPkgid(), "testpkgid");
   EXPECT_EQ(info.GetUid(), 5001);