Add funcs about shared_file 54/206754/41
authormk5004.lee <mk5004.lee@samsung.com>
Tue, 2 Apr 2019 05:10:58 +0000 (14:10 +0900)
committermk5004.lee <mk5004.lee@samsung.com>
Tue, 8 Oct 2019 05:58:52 +0000 (14:58 +0900)
Change-Id: If6ddcf8d962d540b35d4ee4fd80bc3380c543b25
Signed-off-by: mk5004.lee <mk5004.lee@samsung.com>
26 files changed:
notification-ex/CMakeLists.txt
notification-ex/abstract_item.cc
notification-ex/abstract_item.h
notification-ex/chat_message_item.cc
notification-ex/common.h
notification-ex/dbus_event_listener.cc
notification-ex/dbus_sender.cc
notification-ex/event_info.cc
notification-ex/group_item.cc
notification-ex/group_item.h
notification-ex/ievent_info.h
notification-ex/image_item.cc
notification-ex/image_item.h
notification-ex/image_item_implementation.h
notification-ex/manager.cc
notification-ex/reporter.cc
notification-ex/reporter.h
notification-ex/shared_file.cc [new file with mode: 0644]
notification-ex/shared_file.h [new file with mode: 0644]
unittest/CMakeLists.txt
unittest/mock/gio_mock.h [new file with mode: 0644]
unittest/mock/mock.cc
unittest/mock/security_manager_mock.h [new file with mode: 0644]
unittest/mock/smack_mock.h [new file with mode: 0644]
unittest/mock/tzplatform_config_mock.h [new file with mode: 0644]
unittest/src/test_shared_file.cc [new file with mode: 0644]

index 0d8cc10..bf61938 100644 (file)
@@ -20,6 +20,9 @@ pkg_check_modules(notification-ex REQUIRED
        pkgmgr-info
        aul
        uuid
+       libsmack
+       libtzplatform-config
+       security-manager
 )
 
 FOREACH(flag ${notification-ex_CFLAGS})
index 5ab91e9..b4e3e15 100644 (file)
@@ -21,6 +21,7 @@
 #include <memory>
 #include <algorithm>
 #include <vector>
+#include <map>
 
 #include "notification-ex/exception.h"
 #include "notification-ex/abstract_item.h"
@@ -424,6 +425,13 @@ std::list<std::string> AbstractItem::GetSharedPath() const {
   return {};
 }
 
+void AbstractItem::SetSharedPath() {
+}
+
+std::list<std::map<std::string, std::string>> AbstractItem::GetPathMapList() const {
+  return {};
+}
+
 shared_ptr<AbstractAction> AbstractItem::GetAction() const {
   return impl_->action_;
 }
index 8c80bb6..fd46375 100644 (file)
@@ -24,6 +24,7 @@
 #include <string>
 #include <list>
 #include <vector>
+#include <map>
 
 #include "notification-ex/abstract_action.h"
 #include "notification-ex/multi_language.h"
@@ -823,6 +824,18 @@ class EXPORT_API AbstractItem {
   virtual std::list<std::string> GetSharedPath() const;
 
   /**
+   * @brief Sets the shared file path to original file path.
+   */
+  virtual void SetSharedPath();
+
+  /**
+   * @brief
+   * @since_tizen 5.5
+   * @return
+   */
+  virtual std::list<std::map<std::string, std::string>> GetPathMapList() const;
+
+  /**
    * @brief Gets the notification item id.
    * @since_tizen 5.5
    * @return The notification item id.
index 11ac30b..ea95e39 100644 (file)
@@ -57,33 +57,6 @@ int ChatMessageItem::GetType() const {
   return AbstractItem::ChatMessage;
 }
 
-std::list<std::string> ChatMessageItem::GetSharedPath() const {
-  std::list<std::string> ret;
-
-  auto name = impl_->name_->GetSharedPath();
-  auto text = impl_->text_->GetSharedPath();
-  auto image = impl_->image_->GetSharedPath();
-  auto time = impl_->time_->GetSharedPath();
-
-  for (auto& i : name) {
-    ret.push_back(std::move(i));
-  }
-
-  for (auto& i : text) {
-    ret.push_back(std::move(i));
-  }
-
-  for (auto& i : image) {
-    ret.push_back(std::move(i));
-  }
-
-  for (auto& i : time) {
-    ret.push_back(std::move(i));
-  }
-
-  return ret;
-}
-
 Bundle ChatMessageItem::Serialize() const {
   Bundle b;
   b = AbstractItem::Serialize();
@@ -170,6 +143,17 @@ bool ChatMessageItem::IsItemTypeExist(int type) {
   return false;
 }
 
+std::list<std::string> ChatMessageItem::GetSharedPath() const {
+  std::list<std::string> ret;
+
+  auto image = impl_->image_->GetSharedPath();
+  for (auto& i : image) {
+    ret.push_back(std::move(i));
+  }
+
+  return ret;
+}
+
 TextItem& ChatMessageItem::GetNameItem() const {
   return *(impl_->name_);
 }
index 74cebbd..fea66fd 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <tizen.h>
 
+#define REGULAR_UID_MIN 5000
+
 namespace notification {
 
 enum NotificationError {
index 13de3e4..2686bca 100644 (file)
@@ -53,7 +53,7 @@ DBusEventListener::Impl::~Impl() = default;
 
 DBusEventListener::Impl::Impl(DBusEventListener* parent, string path)
     : subscribe_id_(0), registration_id_(0), path_(path), parent_(parent) {
-  LOGI("ButtonItem impl created");
+  LOGI("Dbus_event_listener impl created");
 }
 
 void DBusEventListener::Impl::SignalCb(GDBusConnection* connection,
index 22d6b98..cb42df3 100644 (file)
@@ -46,7 +46,7 @@ DBusSender::Impl::~Impl() = default;
 
 DBusSender::Impl::Impl(DBusSender* parent, string path)
     : path_(path), parent_(parent) {
-  LOGI("ButtonItem impl created");
+  LOGI("Dbus_sender impl created");
 }
 
 DBusSender::~DBusSender() {
index 18e5728..a354fab 100644 (file)
@@ -90,6 +90,10 @@ string EventInfo::GetString(int type) {
       return "Count";
     case DeleteAll:
       return "DeleteAll";
+    case Register:
+      return "Register";
+    case Unregister:
+      return "Unregister";
     default:
       return "Custom" + std::to_string(Custom);
   }
index f03cc88..1488835 100644 (file)
@@ -155,6 +155,24 @@ list<string> GroupItem::GetSharedPath() const {
   return ret;
 }
 
+void GroupItem::SetSharedPath() {
+  for (auto& i : impl_->children_list_)
+    i->SetSharedPath();
+}
+
+list<map<string, string>> GroupItem::GetPathMapList() const {
+  list<map<string, string>> path_map_list;
+
+  for (auto& i : impl_->children_list_) {
+    auto path_map_list_ = i->GetPathMapList();
+    for (auto& path_map : path_map_list_) {
+      path_map_list.push_back(move(path_map));
+    }
+  }
+
+  return path_map_list;
+}
+
 void GroupItem::AddChild(shared_ptr<AbstractItem> child) {
   impl_->children_list_.emplace_back(child);
 }
index 39b6ab6..dd29fbb 100644 (file)
@@ -20,6 +20,7 @@
 #include <string>
 #include <memory>
 #include <list>
+#include <map>
 
 #include "notification-ex/abstract_item.h"
 
@@ -109,6 +110,19 @@ class EXPORT_API GroupItem : public AbstractItem {
   std::list<std::string> GetSharedPath() const override;
 
   /**
+   * @brief Sets the shared file path to original file path.
+   * @since_tizen 5.5
+   */
+  void SetSharedPath() override;
+
+  /**
+   * @brief Gets the paths of shared file location.
+   * @since_tizen 5.5
+   * @return The list of private path and original path.
+   */
+  std::list<std::map<std::string, std::string>> GetPathMapList() const override;
+
+  /**
    * @brief Sets the vertical state.
    * @details The vertical state is true, the children of GroupItem are associated vertically.
    *          And if it is false, the children are associated horizontally.
index d0c746c..e90dbaa 100644 (file)
@@ -37,6 +37,8 @@ class EXPORT_API IEventInfo {
     Error,
     Count,
     DeleteAll,
+    Register,
+    Unregister,
     Custom = 100
   };
   virtual ~IEventInfo() = default;
index 788354e..ee8087c 100644 (file)
  * limitations under the License.
  */
 
+#include <unistd.h>
+#include <sys/types.h>
 #include <dlog.h>
 
+#include <map>
+#include <string>
+#include <list>
+#include <utility>
+
 #include "notification-ex/image_item.h"
 #include "notification-ex/image_item_implementation.h"
 #include "notification-ex/factory_manager.h"
 #include "notification-ex/exception.h"
+#include "notification-ex/shared_file.h"
+#include "notification-ex/item_info_internal.h"
+#include "notification-ex/ex_util.h"
 
 #ifdef LOG_TAG
 #undef LOG_TAG
 
 #define LOG_TAG "NOTIFICATION_EX"
 #define IMAGE_PATH_KEY "__IMAGE_PATH_KEY__"
+#define PRIV_IMAGE_PATH_KEY "__PRIV_IMAGE_PATH_KEY__"
 
 using namespace tizen_base;
 
 namespace notification {
 namespace item {
-
 ImageItem::ImageItem(std::string image_path,
     std::shared_ptr<AbstractAction> action)
     : AbstractItem(action), impl_(new Impl(this, image_path)) {
+  UpdatePrivatePath();
 }
 
 ImageItem::ImageItem(std::string id, std::string image_path,
     std::shared_ptr<AbstractAction> action)
     : AbstractItem(id, action), impl_(new Impl(this, image_path)) {
+  UpdatePrivatePath();
 }
 
 ImageItem::Impl::Impl(ImageItem* parent, std::string image_path)
@@ -57,12 +69,16 @@ Bundle ImageItem::Serialize() const {
   b = AbstractItem::Serialize();
   b.Add(IMAGE_PATH_KEY, impl_->image_path_);
 
+  if (!impl_->priv_image_path_.empty())
+    b.Add(PRIV_IMAGE_PATH_KEY, impl_->priv_image_path_);
+
   return b;
 }
 
 void ImageItem::Deserialize(Bundle b) {
   AbstractItem::Deserialize(b);
   impl_->image_path_ = b.GetString(IMAGE_PATH_KEY);
+  impl_->priv_image_path_ = b.GetString(PRIV_IMAGE_PATH_KEY);
 }
 
 bool ImageItem::IsItemTypeExist(int type) {
@@ -75,6 +91,50 @@ std::string ImageItem::GetImagePath() const {
   return impl_->image_path_;
 }
 
+std::list<std::string> ImageItem::GetSharedPath() const {
+  std::list<std::string> ret;
+
+  if (!impl_->priv_image_path_.empty())
+    ret.push_back(impl_->priv_image_path_);
+
+  return ret;
+}
+
+void ImageItem::SetSharedPath() {
+  if (!impl_->priv_image_path_.empty())
+    impl_->image_path_ = impl_->priv_image_path_;
+}
+
+std::list<std::map<std::string, std::string>> ImageItem::GetPathMapList() const {
+  std::list<std::map<std::string, std::string>> path_map_list;
+  std::map<std::string, std::string> path_map;
+
+  if (!impl_->priv_image_path_.empty()) {
+    path_map.insert(std::pair<std::string, std::string>(impl_->image_path_,
+        impl_->priv_image_path_));
+    path_map_list.push_back(path_map);
+  }
+
+  return path_map_list;
+}
+
+void ImageItem::UpdatePrivatePath() {
+  std::string path;
+
+  SharedFile* shared_file = new SharedFile();
+  if (!shared_file->IsPrivatePath(impl_->image_path_)) {
+    delete(shared_file);
+    return;
+  }
+
+  path = shared_file->GetDataPath(AbstractItem::GetSenderAppId(),
+            impl_->image_path_);
+  if (!path.empty())
+    impl_->priv_image_path_ = path;
+
+  delete(shared_file);
+}
+
 ImageItem::~ImageItem() = default;
 ImageItem::Impl::~Impl() = default;
 
index 490e329..d8bdcf0 100644 (file)
@@ -20,6 +20,7 @@
 #include <string>
 #include <memory>
 #include <list>
+#include <map>
 
 #include "notification-ex/abstract_item.h"
 
@@ -94,10 +95,26 @@ class EXPORT_API ImageItem : public AbstractItem {
    */
   std::string GetImagePath() const;
 
+  /**
+   * @brief Gets the path of shared file location.
+   * @since_tizen 5.5
+   * @return The list of shared path.
+   */
+  std::list<std::string> GetSharedPath() const override;
+
+  /**
+   * @brief Sets the shared file path to original file path.
+   * @since_tizen 5.5
+   */
+  void SetSharedPath() override;
+
+  std::list<std::map<std::string, std::string>> GetPathMapList(void) const override;
+
  private:
   class Impl;
   std::unique_ptr<Impl> impl_;
-};  // class ImageItem
+  void UpdatePrivatePath();
+};  //class ImageItem
 
 }  // namespace item
 }  // namespace notification
index 5c09b92..c555a62 100644 (file)
@@ -37,6 +37,7 @@ class ImageItem::Impl {
  private:
   ImageItem* parent_;
   std::string image_path_;
+  std::string priv_image_path_;
 };
 
 }  // namespace item
index 86d7b09..a66703c 100644 (file)
@@ -37,6 +37,7 @@
 
 #define MAX_PACKAGE_STR_SIZE 512
 #define NOTIFICATION_EX_MANAGER_OBJECT_PATH "/org/tizen/notification_ex_manager"
+#define DATA_PROVIDER_MASTER_ID "data-provider-master"
 
 using namespace std;
 using namespace tizen_base;
@@ -51,6 +52,10 @@ Manager::~Manager() = default;
 
 Manager::Impl::~Impl() {
   listener_->UnRegisterObserver(parent_);
+
+  list<Bundle> dummy_list {};
+  EventInfo info(EventInfo::Unregister, util::GetAppId(), "", "");
+  sender_->Notify(info, dummy_list, DATA_PROVIDER_MASTER_ID);
 }
 Manager::Impl::Impl(Manager* parent,
     unique_ptr<IEventSender> sender,
@@ -60,6 +65,10 @@ Manager::Impl::Impl(Manager* parent,
     parent_(parent) {
   LOGI("impl created");
   listener_->RegisterObserver(parent_);
+
+  list<Bundle> serialized_list {};
+  EventInfo info(EventInfo::Register, util::GetAppId(), receiver_group, "");
+  sender_->Notify(info, serialized_list, DATA_PROVIDER_MASTER_ID);
 }
 
 int Manager::Impl::SendNotify(shared_ptr<item::AbstractItem> noti,
index f7041d7..67060db 100644 (file)
@@ -27,6 +27,7 @@
 #include "notification-ex/dbus_connection_manager.h"
 #include "notification-ex/ex_util.h"
 #include "notification-ex/item_info_internal.h"
+#include "notification-ex/shared_file.h"
 
 #ifdef LOG_TAG
 #undef LOG_TAG
@@ -77,6 +78,10 @@ void Reporter::SendError(const IEventInfo& info, NotificationError error) {
 int Reporter::Post(std::shared_ptr<item::AbstractItem> noti) {
   LOGI("Post noti");
   static_pointer_cast<IItemInfoInternal>(noti->GetInfo())->SetTime(time(NULL));
+  SharedFile* shared_file = new SharedFile();
+  shared_file->CopyPrivateFile(noti);
+  delete shared_file;
+
   return impl_->SendNotify(noti, EventInfo::Post);
 }
 
@@ -87,6 +92,10 @@ int Reporter::Post(std::list<std::shared_ptr<AbstractItem>> notiList) {
     static_pointer_cast<IItemInfoInternal>(i->GetInfo())->SetTime(time(NULL));
     Bundle b = i->Serialize();
     serialized_list.push_back(b);
+
+    SharedFile* shared_file = new SharedFile();
+    shared_file->CopyPrivateFile(i);
+    delete shared_file;
   }
   impl_->sender_->Notify(info, serialized_list);
   return info.GetRequestId();
@@ -94,6 +103,10 @@ int Reporter::Post(std::list<std::shared_ptr<AbstractItem>> notiList) {
 
 int Reporter::Update(std::shared_ptr<AbstractItem> noti) {
   static_pointer_cast<IItemInfoInternal>(noti->GetInfo())->SetTime(time(NULL));
+  SharedFile* shared_file = new SharedFile();
+  shared_file->CopyPrivateFile(noti);
+  delete shared_file;
+
   return impl_->SendNotify(noti, EventInfo::Update);
 }
 
@@ -188,4 +201,7 @@ string Reporter::GetPath() {
   return NOTIFICATION_EX_REPORTER_OBJECT_PATH;
 }
 
+void Reporter::OnRegister(const IEventInfo& info) {
+}
+
 }  // namespace notification
index d5ca8a4..e3dd3c1 100644 (file)
@@ -60,6 +60,7 @@ class EXPORT_API Reporter : public IEventObserver {
   std::list<tizen_base::Bundle> OnRequest(const IEventInfo& info) override;
   int OnRequestNumber(const IEventInfo& info) override;
   static std::string GetPath();
+  virtual void OnRegister(const IEventInfo& info);
 
  private:
   class Impl;
diff --git a/notification-ex/shared_file.cc b/notification-ex/shared_file.cc
new file mode 100644 (file)
index 0000000..9ed7eff
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ * Copyright (c) 2019 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 <unistd.h>
+#include <dlog.h>
+#include <linux/xattr.h>
+#include <sys/smack.h>
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+#include <utime.h>
+#include <tzplatform_config.h>
+#include <security-manager.h>
+
+#include <string>
+#include <list>
+#include <map>
+#include <algorithm>
+#include <vector>
+
+#include "notification-ex/common.h"
+#include "notification-ex/shared_file.h"
+#include "notification-ex/group_item.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define CHECK_LABEL "::RO"
+#define NOTI_PRIV_DATA_DIR "data/.notification_ex"
+
+using namespace std;
+
+namespace notification {
+namespace item {
+SharedFile::SharedFile() = default;
+SharedFile::~SharedFile() = default;
+SharedFile::SharingData::SharingData() = default;
+SharedFile::SharingData::~SharingData() = default;
+SharedFile::SharingTarget::SharingTarget() = default;
+SharedFile::SharingTarget::~SharingTarget() = default;
+
+const char* SharedFile::GetLastIndex(const char* path, const char* search) const {
+  int i;
+  int search_len;
+  const char* index;
+
+  if (path == nullptr || search == nullptr)
+    return nullptr;
+
+  search_len = strlen(search);
+  index = path + strlen(path) - search_len;
+
+  while (index >= path) {
+    for (i = 0; i < search_len; i++) {
+      if (index[i] != search[i])
+        break;
+    }
+
+    if (i == search_len)
+      return index;
+
+    index--;
+  }
+
+  return nullptr;
+}
+
+bool SharedFile::MakeDir(const char* path) {
+  if (access(path, R_OK) == 0)
+    return true;
+
+  auto noti_dir = unique_ptr<GFile, decltype(&g_object_unref)>(
+                        g_file_new_for_path(path), g_object_unref);
+  if (noti_dir == nullptr)
+    return false;
+
+  GError* g_err = nullptr;
+  if (!g_file_make_directory(noti_dir.get(), nullptr, &g_err)) {
+    if (g_err) {
+      LOGE("Failed to make sharing dir[%s]", g_err->message);
+      g_error_free(g_err);
+    }
+    return false;
+  }
+
+  return true;
+}
+
+string SharedFile::GetDir(string path) {
+  int dir_len;
+  const char* index;
+  string dir;
+
+  if (path.empty())
+    return "";
+
+  index = GetLastIndex(path.c_str(), "/");
+  if (index == nullptr) {
+    LOGE("Failed to find directory separator");
+    return "";
+  }
+
+  dir_len = index - path.c_str() + 1;
+  if (dir_len <= 0 || dir_len > PATH_MAX)
+    return "";
+
+  dir.reserve(PATH_MAX);
+  snprintf(&dir[0], dir_len, "%s", path.c_str());
+
+  return dir;
+}
+
+int SharedFile::CopyFile(const char* source, const char* dest) {
+  GError* g_err = nullptr;
+  struct utimbuf ut = {0, };
+
+  if (source == nullptr || dest == nullptr) {
+    LOGE("Invalid parameter");
+    return ERROR_INVALID_PARAMETER;
+  }
+
+  auto dst = unique_ptr<GFile, decltype(&g_object_unref)>(
+                g_file_new_for_path(dest), g_object_unref);
+  if (dst == nullptr) {
+    LOGE("dest path is wrong [%s]", dest);
+    return ERROR_IO_ERROR;
+  }
+
+  if (g_file_query_exists(dst.get(), nullptr)) {
+    LOGD("dst path already existed [%s]", dest);
+    return  ERROR_ALREADY_EXIST_ID;
+  }
+
+  auto src = unique_ptr<GFile, decltype(&g_object_unref)>(
+                g_file_new_for_path(source), g_object_unref);
+  if (src == nullptr) {
+    LOGE("src path is wrong [%s]", source);
+    return ERROR_IO_ERROR;
+  }
+
+  if (!g_file_copy(src.get(), dst.get(), G_FILE_COPY_NOFOLLOW_SYMLINKS, nullptr,
+                nullptr, nullptr, &g_err)) {
+    if (g_err) {
+      LOGE("Copying file from [%s] to [%s] is failed [%s]", source, dest,
+          g_err->message);
+      g_error_free(g_err);
+    }
+    return ERROR_IO_ERROR;
+  }
+
+  ut.modtime = time(nullptr);
+  if (g_utime(dest, &ut) != 0)
+    LOGD("Failed to set g_utime %d ", errno);
+
+  return ERROR_NONE;
+}
+
+vector<char*> SharedFile::ConvertListToArray(const list<string>& data) {
+  vector<char*> v;
+
+  if (data.empty())
+    return {};
+
+  for (const auto& i : data)
+    v.push_back(const_cast<char*>(i.c_str()));
+
+  return v;
+}
+
+bool SharedFile::IsPrivatePath(string path) const {
+  char* smack_label = nullptr;
+  bool ret = false;
+
+  if (path.empty()) {
+    LOGE("Invalid parameter");
+    return false;
+  }
+
+  if (smack_new_label_from_path(path.c_str(), XATTR_NAME_SMACK, 1, &smack_label)
+        <= 0) {
+    LOGE("smack_new_label_from_path failed");
+    return false;
+  }
+
+  if (GetLastIndex(smack_label, CHECK_LABEL) != nullptr)
+    ret = true;
+
+  free(smack_label);
+  return ret;
+}
+
+string SharedFile::GetDataPath(string app_id, string path) const {
+  string user_app;
+  string dir;
+
+  if (app_id.empty() || path.empty()) {
+    LOGE("Invalid parameter");
+    return nullptr;
+  }
+
+  tzplatform_set_user(getuid());
+  user_app = tzplatform_getenv(TZ_USER_APP);
+  tzplatform_reset_user();
+
+  dir = user_app + "/" + app_id + "/" + NOTI_PRIV_DATA_DIR + "/";
+  dir += string(GetLastIndex(path.c_str(), "/") + 1);
+
+  return dir;
+}
+
+int SharedFile::SetSharingData(SharingData sharing_data,
+    list<string> new_shared_file_list, list<string> new_receiver_group_list,
+    multimap<string, string> receiver_group_map) {
+  private_sharing_req* handle = nullptr;
+  vector<char*> path_array;
+  vector<char*> target_array;
+  const char* appid = nullptr;
+  int ret;
+
+  if (new_shared_file_list.empty() || new_receiver_group_list.empty()) {
+    LOGE("Invalid parameter");
+    return ERROR_INVALID_PARAMETER;
+  }
+
+  ret = security_manager_private_sharing_req_new(&handle);
+  if (ret != SECURITY_MANAGER_SUCCESS) {
+    LOGE("Failed to create private sharing request handle[%d]", ret);
+    return ERROR_IO_ERROR;
+  }
+
+  auto req = unique_ptr<private_sharing_req,
+                decltype(&security_manager_private_sharing_req_free)>(
+                handle, security_manager_private_sharing_req_free);
+  if (req == nullptr)
+    return ERROR_IO_ERROR;
+
+  appid = strdup(sharing_data.app_id.c_str());
+  if (appid == nullptr) {
+    LOGE("Failed to get Sender appid");
+    return ERROR_OUT_OF_MEMORY;
+  }
+
+  ret = security_manager_private_sharing_req_set_owner_appid(req.get(), appid);
+  if (ret != SECURITY_MANAGER_SUCCESS) {
+    LOGE("Failed to set owner appid[%s][%d]", appid, ret);
+    return ERROR_IO_ERROR;
+  }
+
+  path_array = ConvertListToArray(new_shared_file_list);
+  if (path_array.empty()) {
+    LOGE("path_array is null");
+    return ERROR_IO_ERROR;
+  }
+
+  ret = security_manager_private_sharing_req_add_paths(req.get(),
+            const_cast<const char**>(path_array.data()), path_array.size());
+  if (ret != SECURITY_MANAGER_SUCCESS) {
+    LOGE("Failed to add paths [%d]", ret);
+    return ERROR_IO_ERROR;
+  }
+
+  target_array = ConvertListToArray(new_receiver_group_list);
+  if (target_array.empty()) {
+    LOGE("target_array is null");
+    return ERROR_IO_ERROR;
+  }
+
+  for (int i = 0; i < static_cast<int>(target_array.size()); i++) {
+    multimap<string, string>::iterator it;
+    for (it = receiver_group_map.begin(); it != receiver_group_map.end(); it++) {
+      if (it->first.compare(target_array[i]) == 0) {
+        ret = security_manager_private_sharing_req_set_target_appid(req.get(),
+                it->second.c_str());
+        if (ret != SECURITY_MANAGER_SUCCESS) {
+          LOGE("Failed to set target appid [%s]", appid);
+          return ERROR_IO_ERROR;
+        }
+
+        ret = security_manager_private_sharing_apply(req.get());
+        if (ret != SECURITY_MANAGER_SUCCESS) {
+          LOGE("Failed to apply private sharing [%d]", ret);
+          return ERROR_IO_ERROR;
+        }
+      }
+    }
+  }
+
+  return ERROR_NONE;
+}
+
+int SharedFile::UnsetSharingData(SharingData sharing_data,
+    multimap<string, string> receiver_group_map) {
+  private_sharing_req* handle = nullptr;
+  vector<char*> path_array;
+  vector<char*> target_array;
+  const char* appid = nullptr;
+  int ret;
+
+  if (receiver_group_map.empty()) {
+    LOGE("Invalid parameter");
+    return ERROR_INVALID_PARAMETER;
+  }
+
+  ret = security_manager_private_sharing_req_new(&handle);
+  if (ret != SECURITY_MANAGER_SUCCESS) {
+    LOGE("Failed to create private sharing request handle[%d]", ret);
+    return ERROR_IO_ERROR;
+  }
+
+  auto req = unique_ptr<private_sharing_req,
+                decltype(&security_manager_private_sharing_req_free)>(
+                handle, security_manager_private_sharing_req_free);
+  if (req == nullptr)
+    return ERROR_IO_ERROR;
+
+  appid = strdup(sharing_data.app_id.c_str());
+  if (appid == nullptr) {
+    LOGE("Failed to get Sender appid");
+    return ERROR_OUT_OF_MEMORY;
+  }
+
+  ret = security_manager_private_sharing_req_set_owner_appid(req.get(), appid);
+  if (ret != SECURITY_MANAGER_SUCCESS) {
+    LOGE("Failed to set owner appid[%s][%d]", appid, ret);
+    return ERROR_IO_ERROR;
+  }
+
+  path_array = ConvertListToArray(sharing_data.shared_file_list);
+  if (path_array.empty()) {
+    LOGE("path_array is null");
+    return ERROR_IO_ERROR;
+  }
+
+  ret = security_manager_private_sharing_req_add_paths(req.get(),
+            const_cast<const char**>(path_array.data()), path_array.size());
+  if (ret != SECURITY_MANAGER_SUCCESS) {
+    LOGE("Failed to add paths [%d]", ret);
+    return ERROR_IO_ERROR;
+  }
+
+  target_array = ConvertListToArray(sharing_data.receiver_group_list);
+  if (target_array.empty()) {
+    LOGE("target_array is null");
+    return ERROR_IO_ERROR;
+  }
+
+  for (int i = 0; i < static_cast<int>(target_array.size()); i++) {
+    multimap<string, string>::iterator it;
+    for (it = receiver_group_map.begin(); it != receiver_group_map.end(); it++) {
+      if (it->first.compare(target_array[i]) == 0) {
+        ret = security_manager_private_sharing_req_set_target_appid(req.get(),
+                it->second.c_str());
+        if (ret != SECURITY_MANAGER_SUCCESS) {
+          LOGE("Failed to set target appid [%s]", appid);
+          return ERROR_IO_ERROR;
+        }
+
+        ret = security_manager_private_sharing_drop(req.get());
+        if (ret != SECURITY_MANAGER_SUCCESS) {
+          LOGE("Failed to drop private sharing [%d]", ret);
+          return ERROR_IO_ERROR;
+        }
+      }
+    }
+  }
+
+  return ERROR_NONE;
+}
+
+SharedFile::SharingData SharedFile::FindSharingData(string appid) {
+  if (sharing_data_list_.size() == 0 || appid.empty())
+    return {};
+
+  for (auto sharing_data : sharing_data_list_) {
+    if (sharing_data.app_id.compare(appid) == 0)
+      return sharing_data;
+  }
+
+  return {};
+}
+
+int SharedFile::SetPrivateSharing(list<shared_ptr<AbstractItem>> item,
+    multimap<string, string> receiver_group_map) {
+  int ret;
+
+  if (item.empty() || receiver_group_map.empty()) {
+    LOGE("Invalid parameter");
+    return ERROR_INVALID_PARAMETER;
+  }
+
+  for (auto& i : item) {
+    SharingData sharing_data;
+    list<string> new_shared_file_list;
+    list<string> new_receiver_group_list;
+
+    list<string> shared_path_list = i->GetSharedPath();
+    if (shared_path_list.empty())
+      continue;
+
+    string appid = i->GetSenderAppId();
+    if (appid.empty())
+      continue;
+
+    sharing_data = FindSharingData(appid);
+    if (!sharing_data.app_id.empty()) {
+      string noti_id = i->GetId();
+      list<string>::iterator it;
+      it = find_if(sharing_data.noti_id_list.begin(),
+                    sharing_data.noti_id_list.end(),
+                    [&noti_id](std::string id){
+                      return id.compare(noti_id) == 0;
+                    });
+      if (it == sharing_data.noti_id_list.end())
+        sharing_data.noti_id_list.push_back(noti_id);
+
+      for (auto& shared_path : shared_path_list) {
+        list<string>::iterator it;
+        it = find_if(sharing_data.shared_file_list.begin(),
+                    sharing_data.shared_file_list.end(),
+                    [&shared_path](std::string shared_file){
+                      return shared_file.compare(shared_path) == 0;
+                    });
+        if (it == sharing_data.shared_file_list.end()) {
+          sharing_data.shared_file_list.push_back(shared_path);
+          new_shared_file_list.push_back(shared_path);
+        }
+      }
+
+      list<string> receiver_list = i->GetReceiverList();
+      for (auto& receiver : receiver_list) {
+        list<string>::iterator it;
+        it = find_if(sharing_data.receiver_group_list.begin(),
+                    sharing_data.receiver_group_list.end(),
+                    [&receiver](std::string receiver_group){
+                      return receiver_group.compare(receiver) == 0;
+                    });
+        if (it == sharing_data.receiver_group_list.end()) {
+          sharing_data.receiver_group_list.push_back(receiver);
+          new_receiver_group_list.push_back(receiver);
+        }
+      }
+    } else {
+      sharing_data.app_id = appid;
+      sharing_data.dir = GetDir(*(shared_path_list.begin()));
+      sharing_data.noti_id_list.emplace_back(i->GetId());
+      sharing_data.shared_file_list = shared_path_list;
+      sharing_data.receiver_group_list = i->GetReceiverList();
+      sharing_data_list_.emplace_back(sharing_data);
+
+      new_shared_file_list = shared_path_list;
+      new_receiver_group_list = i->GetReceiverList();
+    }
+
+    ret = SetSharingData(sharing_data, new_shared_file_list,
+                new_receiver_group_list, receiver_group_map);
+    if (ret == ERROR_NONE)
+      i->SetSharedPath();
+  }
+
+  LOGD("SetPrivateSharing");
+  return ERROR_NONE;
+}
+
+int SharedFile::UpdatePrivateSharing(shared_ptr<AbstractItem> item,
+    multimap<string, string> receiver_group_map) {
+  list<string> new_shared_file_list;
+  list<string> new_receiver_group_list;
+  int ret;
+
+  if (item == nullptr || receiver_group_map.empty()) {
+    LOGE("Invalid parameter");
+    return ERROR_INVALID_PARAMETER;
+  }
+
+  list<string> shared_path_list = item->GetSharedPath();
+  if (shared_path_list.empty())
+    return ERROR_NONE;
+
+  string appid = item->GetSenderAppId();
+  SharingData sharing_data = FindSharingData(appid);
+  if (appid.empty() || sharing_data.app_id.empty())
+    return ERROR_IO_ERROR;
+
+  for (auto& shared_path : shared_path_list) {
+    std::list<std::string>::iterator it;
+    it = std::find_if(sharing_data.shared_file_list.begin(),
+                    sharing_data.shared_file_list.end(),
+                    [&shared_path](std::string shared_file){
+                      return shared_file.compare(shared_path) == 0;
+                    });
+    if (it == sharing_data.shared_file_list.end()) {
+      sharing_data.shared_file_list.push_back(shared_path);
+      new_shared_file_list.push_back(shared_path);
+    }
+  }
+
+  new_receiver_group_list = item->GetReceiverList();
+  ret = SetSharingData(sharing_data, new_shared_file_list,
+            new_receiver_group_list, receiver_group_map);
+  if (ret == ERROR_NONE)
+    item->SetSharedPath();
+
+  LOGD("UpdatePrivateSharing");
+  return ERROR_NONE;
+}
+
+int SharedFile::RemovePrivateSharing(shared_ptr<AbstractItem> item,
+    multimap<string, string> receiver_group_map) {
+  if (item == nullptr || receiver_group_map.empty()) {
+    LOGE("Invalid parameter");
+    return ERROR_INVALID_PARAMETER;
+  }
+
+  string appid = item->GetSenderAppId();
+  if (appid.empty())
+    return ERROR_IO_ERROR;
+
+  SharingData sharing_data = FindSharingData(appid);
+  if (sharing_data.app_id.empty())
+    return ERROR_NONE;
+
+  sharing_data.noti_id_list.remove(item->GetId());
+  if (sharing_data.noti_id_list.size() == 0) {
+    UnsetSharingData(sharing_data, receiver_group_map);
+
+    vector<char*> path_array = ConvertListToArray(sharing_data.shared_file_list);
+    if (!path_array.empty()) {
+      for (int i = 0; i < static_cast<int>(path_array.size()); i++) {
+        if (g_remove(path_array[i]) == -1)
+          LOGE("Failed to remove shared_file(%s)", path_array[i]);
+      }
+    }
+    g_rmdir(sharing_data.dir.c_str());
+  }
+
+  LOGD("RemovePrivateSharing");
+  return ERROR_NONE;
+}
+
+int SharedFile::CopyPrivateFile(shared_ptr<item::AbstractItem> item) {
+  if (item == nullptr) {
+    LOGE("Invalid paramenter");
+    return ERROR_INVALID_PARAMETER;
+  }
+
+  list<map<string, string>> path_map_list = item->GetPathMapList();
+  if (path_map_list.empty())
+    return ERROR_NONE;
+
+  if (!MakeDir(GetDir((*(path_map_list.begin())).begin()->second).c_str()))
+    return ERROR_IO_ERROR;
+
+  list<map<string, string>>::iterator list_it;
+  for (list_it = path_map_list.begin(); list_it != path_map_list.end(); ++list_it) {
+    map<string, string>::iterator map_it;
+    for (map_it = (*list_it).begin(); map_it != (*list_it).end(); map_it++) {
+      CopyFile((map_it->first).c_str(), (map_it->second).c_str());
+    }
+  }
+
+  return ERROR_NONE;
+}
+
+}  // namespace item
+}  // namespace notification
diff --git a/notification-ex/shared_file.h b/notification-ex/shared_file.h
new file mode 100644 (file)
index 0000000..acf9fab
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019 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 NOTIFICATION_EX_SHARED_FILE_H_
+#define NOTIFICATION_EX_SHARED_FILE_H_
+
+#include <security-manager.h>
+
+#include <string>
+#include <memory>
+#include <list>
+#include <map>
+#include <vector>
+
+#include "notification-ex/abstract_item.h"
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+namespace item {
+
+class EXPORT_API SharedFile {
+ public:
+  SharedFile();
+  virtual ~SharedFile();
+
+  bool IsPrivatePath(std::string path) const;
+  std::string GetDataPath(std::string app_id, std::string path) const;
+  int SetPrivateSharing(std::list<std::shared_ptr<AbstractItem>> item,
+          std::multimap<std::string, std::string> receiver_group_map);
+  int UpdatePrivateSharing(std::shared_ptr<AbstractItem>item,
+          std::multimap<std::string, std::string> receiver_group_map);
+  int RemovePrivateSharing(std::shared_ptr<AbstractItem>item,
+          std::multimap<std::string, std::string> receiver_group_map);
+  int CopyPrivateFile(std::shared_ptr<item::AbstractItem>added_item);
+
+ private:
+  class SharingData {
+   public:
+    SharingData();
+    ~SharingData();
+    std::string app_id;
+    std::string dir;
+    std::list<std::string> noti_id_list;
+    std::list<std::string> shared_file_list;
+    std::list<std::string> receiver_group_list;
+  };
+  class SharingTarget {
+   public:
+    SharingTarget();
+    ~SharingTarget();
+    std::string target_id;
+  };
+  const char* GetLastIndex(const char* path, const char* search) const;
+  bool MakeDir(const char* path);
+  std::string GetDir(std::string path);
+  int CopyFile(const char* source, const char* dest);
+  std::vector<char*> ConvertListToArray(const std::list<std::string>& data);
+  SharingData FindSharingData(std::string appid);
+  int SetSharingData(SharingData sharing_data,
+          std::list<std::string> new_shared_file_list,
+          std::list<std::string> new_receiver_group_list,
+          std::multimap<std::string, std::string> receiver_group_map);
+  int UnsetSharingData(SharingData sharing_data,
+          std::multimap<std::string, std::string> receiver_group_map);
+
+  std::list<SharingData> sharing_data_list_;
+  std::list<SharingTarget> sharing_target_list_;
+};  // class SharedFile
+
+}  // namespace item
+}  // namespace notification
+
+#endif  // NOTIFICATION_EX_SHARED_FILE_H_
index bb59627..ea7eba3 100644 (file)
@@ -8,6 +8,8 @@ pkg_check_modules(notification-ex_unittests REQUIRED
     capi-appfw-app-control
     glib-2.0
     aul
+    security-manager
+    libtzplatform-config
 )
 
 FOREACH(flag ${notification-ex_unittests_CFLAGS})
diff --git a/unittest/mock/gio_mock.h b/unittest/mock/gio_mock.h
new file mode 100644 (file)
index 0000000..936ec9e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019 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 MOCK_GIO_H_
+#define MOCK_GIO_H_
+
+#include "mock.h"
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _GFile GFile;
+typedef struct _GError GError;
+typedef void GDBusConnection;
+typedef void GCancellable;
+typedef void* gpointer;
+typedef int gboolean;
+
+typedef enum {
+  G_FILE_COPY_NONE                 = 0,
+  G_FILE_COPY_OVERWRITE            = (1 << 0),
+  G_FILE_COPY_BACKUP               = (1 << 1),
+  G_FILE_COPY_NOFOLLOW_SYMLINKS    = (1 << 2),
+  G_FILE_COPY_ALL_METADATA         = (1 << 3),
+  G_FILE_COPY_NO_FALLBACK_FOR_MOVE = (1 << 4),
+  G_FILE_COPY_TARGET_DEFAULT_PERMS = (1 << 5)
+} GFileCopyFlags;
+
+
+typedef void (*GFileProgressCallback) (goffset current_num_bytes,
+    goffset total_num_bytes, gpointer user_data);
+
+DECLARE_FAKE_VALUE_FUNC(GFile*, g_file_new_for_path, const char*);
+DECLARE_FAKE_VALUE_FUNC(gboolean, g_file_query_exists, GFile*, GCancellable*);
+DECLARE_FAKE_VALUE_FUNC(gboolean, g_file_copy, GFile*, GFile*, GFileCopyFlags,
+    GCancellable*, GFileProgressCallback, gpointer, GError**);
+DECLARE_FAKE_VALUE_FUNC(gboolean, g_file_make_directory, GFile*, GCancellable*,
+    GError**);
+DECLARE_FAKE_VALUE_FUNC(int, access, const char*, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MOCK_GIO_H_ */
index e2addda..4ccd8ae 100644 (file)
  * limitations under the License.
  */
 
-#include "app_common.h"
+#include <sys/types.h>
+
 #include "mock.h"
+#include "app_common.h"
+#include "gio_mock.h"
+#include "smack_mock.h"
+#include "tzplatform_config_mock.h"
+#include "security_manager_mock.h"
 
 DEFINE_FFF_GLOBALS;
 
-DEFINE_FAKE_VALUE_FUNC(int, app_get_name, char**);
\ No newline at end of file
+DEFINE_FAKE_VALUE_FUNC(int, app_get_name, char**);
+
+/* gio */
+DEFINE_FAKE_VALUE_FUNC(GFile*, g_file_new_for_path, const char*);
+DEFINE_FAKE_VALUE_FUNC(gboolean, g_file_query_exists, GFile*, GCancellable*);
+DEFINE_FAKE_VALUE_FUNC(gboolean, g_file_copy, GFile*, GFile*, GFileCopyFlags,
+    GCancellable*, GFileProgressCallback, gpointer, GError**);
+DEFINE_FAKE_VALUE_FUNC(gboolean, g_file_make_directory, GFile*, GCancellable*,
+    GError**);
+DEFINE_FAKE_VALUE_FUNC(int, access, const char*, int);
+
+/* smack */
+DEFINE_FAKE_VALUE_FUNC(ssize_t, smack_new_label_from_path, const char*,
+    const char*, int, char**);
+
+/* tzplatform */
+DEFINE_FAKE_VALUE_FUNC(const char*, tzplatform_getenv, enum tzplatform_variable);
+
+/* security-manager */
+DEFINE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_req_new,
+    private_sharing_req**);
+DEFINE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_req_add_paths,
+    private_sharing_req*, const char**, size_t);
+DEFINE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_req_set_target_appid,
+    private_sharing_req*, const char*);
+DEFINE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_apply,
+    const private_sharing_req*);
+DEFINE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_drop,
+    const private_sharing_req*);
diff --git a/unittest/mock/security_manager_mock.h b/unittest/mock/security_manager_mock.h
new file mode 100644 (file)
index 0000000..6efd9b6
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019 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 MOCK_SECURITY_MANAGER_H
+#define MOCK_SECURITY_MANAGER_H
+
+#include "mock.h"
+
+#include <string>
+#include <vector>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct private_sharing_req {
+    std::string ownerAppName;
+    std::string targetAppName;
+    std::vector<std::string> paths;
+};
+
+DECLARE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_req_new,
+    private_sharing_req**);
+DECLARE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_req_add_paths,
+    private_sharing_req*, const char**, size_t);
+DECLARE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_req_set_target_appid,
+    private_sharing_req*, const char*);
+DECLARE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_apply,
+    const private_sharing_req*);
+DECLARE_FAKE_VALUE_FUNC(int, security_manager_private_sharing_drop,
+    const private_sharing_req*);
+
+#ifdef __cplusplus
+}
+#endif
+#endif  /* MOCK_SECURITY_MANAGER_H */
diff --git a/unittest/mock/smack_mock.h b/unittest/mock/smack_mock.h
new file mode 100644 (file)
index 0000000..c548e05
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019 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 MOCK_SMACK_H
+#define MOCK_SMACK_H
+
+#include "mock.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DECLARE_FAKE_VALUE_FUNC(ssize_t, smack_new_label_from_path, const char*,
+    const char*, int, char**);
+
+#ifdef __cplusplus
+}
+#endif
+#endif  /* MOCK_SMACK_H */
+
diff --git a/unittest/mock/tzplatform_config_mock.h b/unittest/mock/tzplatform_config_mock.h
new file mode 100644 (file)
index 0000000..a24c49a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 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 MOCK_TZPLATFORM_CONFIG_H_
+#define MOCK_TZPLATFORM_CONFIG_H_
+
+#include "mock.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tzplatform_variable {
+       USER = 0,
+       SYSTEM = 1,
+};
+
+DECLARE_FAKE_VALUE_FUNC(const char*, tzplatform_getenv, enum tzplatform_variable);
+
+#ifdef __cplusplus
+}
+#endif
+#endif  /* MOCK_TZPLATFORM_CONFIG_H_ */
diff --git a/unittest/src/test_shared_file.cc b/unittest/src/test_shared_file.cc
new file mode 100644 (file)
index 0000000..582d322
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2019 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <app_common.h>
+
+#include "notification-ex/shared_file.h"
+#include "notification-ex/image_item.h"
+#include "notification-ex/common.h"
+
+#include "unittest/mock/gio_mock.h"
+#include "unittest/mock/smack_mock.h"
+#include "unittest/mock/tzplatform_config_mock.h"
+#include "unittest/mock/security_manager_mock.h"
+
+
+using namespace notification;
+using namespace notification::item;
+using namespace std;
+
+namespace {
+
+GFile* __fake_g_file_new_for_path(const char* path) {
+  GFile* noti_dir = {};
+  return noti_dir;
+}
+
+gboolean __fake_g_file_query_exists(GFile* file, GCancellable* cancellable) {
+  return false;
+}
+
+gboolean __fake_g_file_make_directory(GFile* file, GCancellable* cancellable,
+    GError** error) {
+  return true;
+}
+
+gboolean __fake_g_file_copy(GFile* source, GFile* dest, GFileCopyFlags flags,
+    GCancellable* cancellable, GFileProgressCallback callback,
+    gpointer data, GError** error) {
+  return false;
+}
+
+int __fake_access(const char* path, int mode) {
+  return 0;
+}
+
+// smack
+ssize_t __fake_smack_new_label_from_path(const char* path, const char* xattr,
+    int follow, char** label) {
+  *label = strdup("User::Pkg::unittest::RO");
+  return 1;
+}
+
+// tzplatform
+const char* __fake_tzplatform_getenv(enum tzplatform_variable id) {
+  return "/opt/usr/home/owner/apps_rw";
+}
+
+// security-manager
+int __fake_security_manager_private_sharing_req_new(private_sharing_req** pp_req) {
+  return 0;
+}
+
+int __fake_security_manager_private_sharing_req_add_paths(
+    private_sharing_req* p_req, const char** pp_paths, size_t count) {
+  return 0;
+}
+
+int __fake_security_manager_private_sharing_req_set_target_appid(
+    private_sharing_req* p_req, const char* appid) {
+  return 0;
+}
+
+int __fake_security_manager_private_sharing_apply(const private_sharing_req* p_req) {
+  return 0;
+}
+
+int __fake_security_manager_private_sharing_drop(const private_sharing_req* p_req) {
+  return 0;
+}
+
+class SharedFileTest  : public ::testing::Test {
+ public:
+  std::shared_ptr<ImageItem> item;
+  std::string id = "image_id";
+  std::string image_path = "res/image.png";
+
+  SharedFile* shared_file;
+
+  virtual void SetUp() {
+    smack_new_label_from_path_fake.custom_fake = __fake_smack_new_label_from_path;
+    tzplatform_getenv_fake.custom_fake = __fake_tzplatform_getenv;
+    g_file_new_for_path_fake.custom_fake = __fake_g_file_new_for_path;
+    g_file_query_exists_fake.custom_fake = __fake_g_file_query_exists;
+    g_file_make_directory_fake.custom_fake = __fake_g_file_make_directory;
+    g_file_copy_fake.custom_fake = __fake_g_file_copy;
+    access_fake.custom_fake = __fake_access;
+    security_manager_private_sharing_req_new_fake.custom_fake =
+      __fake_security_manager_private_sharing_req_new;
+    security_manager_private_sharing_req_add_paths_fake.custom_fake =
+      __fake_security_manager_private_sharing_req_add_paths;
+    security_manager_private_sharing_req_set_target_appid_fake.custom_fake =
+      __fake_security_manager_private_sharing_req_set_target_appid;
+    security_manager_private_sharing_apply_fake.custom_fake =
+      __fake_security_manager_private_sharing_apply;
+    security_manager_private_sharing_drop_fake.custom_fake =
+      __fake_security_manager_private_sharing_drop;
+
+    item = make_shared<ImageItem>(id, image_path);
+    shared_file = new SharedFile();
+  }
+
+  virtual void TearDown() {
+  }
+};
+
+TEST_F(SharedFileTest, IsPrivatePath) {
+  ASSERT_TRUE(shared_file->IsPrivatePath(SharedFileTest::image_path));
+}
+
+TEST_F(SharedFileTest, GetDataPath) {
+  ASSERT_EQ(shared_file->GetDataPath(item->GetSenderAppId(), SharedFileTest::image_path),
+    "/opt/usr/home/owner/apps_rw/notification-ex_unittests/data/.notification_ex/image.png");
+}
+
+TEST_F(SharedFileTest, SetPrivateSharing) {
+  list<shared_ptr<item::AbstractItem>> notiList;
+  notiList.push_back(SharedFileTest::item);
+
+  std::multimap<std::string, std::string> map_;
+  map_.insert(make_pair("tizen.org/receiver/popup", "test_appid"));
+
+  ASSERT_EQ(shared_file->SetPrivateSharing(notiList, map_), ERROR_NONE);
+}
+
+TEST_F(SharedFileTest, RemovePrivateSharing) {
+  std::multimap<std::string, std::string> map_;
+  map_.insert(make_pair("tizen.org/receiver/popup", "test_appid"));
+
+  ASSERT_EQ(shared_file->RemovePrivateSharing(SharedFileTest::item, map_), ERROR_NONE);
+}
+
+}  // namespace