Add default viewer launch feature for ex-noti
[platform/core/appfw/data-provider-master.git] / src / notification_ex_service.cc
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <dlog.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <notification_type.h>
21 #include <notification_viewer.h>
22
23 #include <iostream>
24 #include <sstream>
25 #include <algorithm>
26 #include <map>
27
28 #include <notification-ex/manager.h>
29 #include <notification-ex/reporter.h>
30 #include <notification-ex/dbus_sender.h>
31 #include <notification-ex/dbus_event_listener.h>
32 #include <notification-ex/dbus_connection_manager.h>
33 #include <notification-ex/db_manager.h>
34 #include <notification-ex/common.h>
35 #include <notification-ex/exception.h>
36 #include <notification-ex/item_info_internal.h>
37 #include <notification-ex/button_item.h>
38 #include <notification-ex/ex_util.h>
39 #include <notification-ex/ievent_info_internal.h>
40 #include <notification-ex/iitem_info_internal.h>
41
42 #include "debug.h"
43 #include "notification_ex_service.h"
44
45 using namespace std;
46 using namespace notification;
47 using namespace notification::item;
48
49 class DPMFacade {
50  public:
51   DPMFacade(unique_ptr<Reporter> reporter, unique_ptr<Manager> manager)
52       : reporter_(move(reporter)), manager_(move(manager)) {
53     DBManager::InitializeDB();
54     DBManager::InitializeData();
55     hide_map_ = DBManager::GetHideMap();
56   }
57
58   void DelegateReporterEvent(const IEventInfo& info, shared_ptr<item::AbstractItem> item) {
59     reporter_->SendEvent(info, item);
60   }
61
62   void DelegateReporterEvent(const IEventInfo& info,
63         std::list<std::shared_ptr<item::AbstractItem>> itemList) {
64     reporter_->SendEvent(info, itemList);
65   }
66
67   void DelegateManagerEvent(const IEventInfo& info, shared_ptr<item::AbstractItem> noti) {
68     manager_->SendEvent(info, noti);
69   }
70
71   void LaunchDefaultViewer(list<shared_ptr<item::AbstractItem>> item,
72                                    notification_op_type_e status) {
73     int64_t priv_id;
74     if (item.size() == 0)
75       return;
76
77     if (item.size() > 1)
78       priv_id = NOTIFICATION_PRIV_ID_NONE;
79     else
80       priv_id = static_pointer_cast<IItemInfoInternal>(
81                     item.front()->GetInfo())->GetPrivateId();
82
83     LaunchDefaultViewer(priv_id, status,
84                         static_pointer_cast<IItemInfoInternal>(
85                             item.front()->GetInfo())->GetUid());
86   }
87   void LaunchDefaultViewer(shared_ptr<item::AbstractItem> item,
88               notification_op_type_e status) {
89     LaunchDefaultViewer(
90         static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetPrivateId(),
91         status,
92         static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid());
93   }
94
95   void LaunchDefaultViewer(int64_t privId, notification_op_type_e status,
96                                    uid_t uid) {
97     int ret = notification_launch_default_viewer(
98                    static_cast<int>(privId), status, uid);
99     if (ret != ERROR_NONE)
100       ERR("Failed to launch default viewer [%d]", ret);
101   }
102
103   unique_ptr<Reporter> reporter_;
104   unique_ptr<Manager> manager_;
105   map<string, string> hide_map_;
106 };
107
108 static DPMFacade* facade_;
109
110 class DPMReporter : public Reporter {
111  protected:
112   void OnUpdate(const IEventInfo& info,
113       shared_ptr<item::AbstractItem> updatedItem) {
114     DBG("Update !!!");
115     int ret;
116
117     /* check Manager::Hide() */
118     ret = UpdateHideApp(updatedItem);
119     if (ret == ERROR_NONE)
120       return;
121
122     if (ret != ERROR_NOT_EXIST_ID) {
123       SendError(info, static_cast<NotificationError>(ret));
124       return;
125     }
126
127     ret = DBManager::UpdateNotification(updatedItem);
128     if (ret == ERROR_NONE) {
129       /* noti owner */
130       facade_->DelegateManagerEvent(info, updatedItem);
131
132       /* noti to viewers */
133       facade_->DelegateReporterEvent(info, updatedItem);
134     } else {
135       SendError(info, static_cast<NotificationError>(ret));
136     }
137   }
138
139   void DoDelete(const IEventInfo& info,
140       shared_ptr<item::AbstractItem> deletedItem) {
141     int ret = DBManager::DeleteNotification(deletedItem);
142     if (ret == ERROR_NONE) {
143       /* noti owner */
144       facade_->DelegateManagerEvent(info, deletedItem);
145
146       /* noti to viewers */
147       facade_->DelegateReporterEvent(info, deletedItem);
148     } else {
149       SendError(info, static_cast<NotificationError>(ret));
150     }
151   }
152
153   void OnDelete(const IEventInfo& info,
154       shared_ptr<item::AbstractItem> deletedItem) {
155     DBG("Delete !!!");
156     if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
157       list<shared_ptr<item::AbstractItem>> noti_list =
158           DBManager::GetNotificationList(((const IEventInfoInternal&)info).GetUid());
159       for (auto& i : noti_list) {
160         DoDelete(info, i);
161       }
162     } else {
163       DoDelete(info, deletedItem);
164     }
165   }
166
167   void OnEvent(const IEventInfo& info,
168       list<shared_ptr<item::AbstractItem>> noti_list) override {
169     LOGI("Event received (%d) !!", (int)info.GetEventType());
170     int type = info.GetEventType();
171     if (type == IEventInfo::EventType::DeleteAll) {
172       OnDelete(info, nullptr);
173       return;
174     }
175
176     for (auto& i : noti_list) {
177       switch (type) {
178       case IEventInfo::EventType::Update:
179         OnUpdate(info, i);
180         break;
181       case IEventInfo::EventType::Delete:
182         OnDelete(info, i);
183         break;
184       default :
185         break;
186       }
187     }
188   }
189
190   list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
191     DBG("Get report !!! %s", info.GetItemId().c_str());
192     return DBManager::GetNotificationList(
193         ((const IEventInfoInternal&)info).GetUid(),
194         ((const IEventInfoInternal&)info).GetChannel().c_str());
195   }
196
197   int OnRequestNumber(const IEventInfo& info) override {
198     DBG("Get count !!! %s", info.GetItemId().c_str());
199     return DBManager::GetNotificationList(
200         ((const IEventInfoInternal&)info).GetUid()).size();
201   }
202
203   int UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
204     int ret;
205     string hide_list;
206     int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
207     DBG("try update hide app_id(%s) sender(%s) uid(%s)",
208       updatedItem->GetId().c_str(),
209       updatedItem->GetSenderAppId().c_str(), string(to_string(uid)).c_str());
210     string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
211     list<string> updated_hide_list = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
212
213     /* Check new hide app */
214     auto noti = facade_->hide_map_.find(map_key);
215     if (noti == facade_->hide_map_.end()) {
216       if (updated_hide_list.size() > 0) {
217         for (auto& i : updated_hide_list)
218           hide_list += i + ";";
219
220         ret = DBManager::UpdateHideList(updatedItem, hide_list);
221         if (ret != ERROR_NONE)
222           return ret;
223
224         facade_->hide_map_[map_key] = hide_list;
225         return ERROR_NONE;
226       } else {
227         DBG("Empty hide viewer list");
228         return ERROR_NOT_EXIST_ID;
229       }
230     }
231
232     /* Check new hide app */
233     hide_list = noti->second;
234     for (auto& i : updated_hide_list) {
235       if (hide_list.find(i + ";") == string::npos) {
236         string new_hide_list = hide_list + i + ";";
237         ret = DBManager::UpdateHideList(updatedItem, new_hide_list);
238         if (ret != ERROR_NONE)
239           return ret;
240
241         facade_->hide_map_[map_key] = new_hide_list;
242         return ERROR_NONE;
243       }
244     }
245
246     return ERROR_NOT_EXIST_ID;
247   }
248
249  public:
250   DPMReporter(std::unique_ptr<IEventSender> sender,
251       std::unique_ptr<IEventListener> listener)
252     : Reporter(move(sender), move(listener)) {
253   }
254 };
255
256 class DPMManager : public Manager {
257  protected:
258   void UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
259     string hide_list;
260     int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
261     string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
262     list<string> updated_hide_list =
263       static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
264
265     auto noti = facade_->hide_map_.find(map_key);
266     if (noti == facade_->hide_map_.end())
267       return;
268
269     /* hide app list synchronization */
270     hide_list = noti->second;
271     istringstream stream(hide_list);
272     string hide_app_id;
273
274     while (getline(stream, hide_app_id, ';')) {
275       list<string>::iterator iter = std::find(updated_hide_list.begin(),
276                                 updated_hide_list.end(), hide_app_id);
277       if (iter == updated_hide_list.end())
278         static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->AddHideViewer(hide_app_id);
279     }
280   }
281
282   void OnAdd(const IEventInfo& info,
283       list<shared_ptr<item::AbstractItem>> addedItem) override {
284     DBG("Add !!!");
285     int ret;
286
287     ret = DBManager::InsertNotification(addedItem);
288     if (ret == ERROR_NONE) {
289       facade_->DelegateReporterEvent(info, addedItem);
290       facade_->LaunchDefaultViewer(addedItem, NOTIFICATION_OP_INSERT);
291     } else {
292         DBG("SendError !!!");
293         SendError(info, static_cast<NotificationError>(ret));
294     }
295   }
296
297   void OnUpdate(const IEventInfo& info,
298       shared_ptr<item::AbstractItem> updatedItem) override {
299     DBG("Update !!!");
300     int ret;
301
302     UpdateHideApp(updatedItem);
303
304     ret = DBManager::UpdateNotification(updatedItem);
305     if (ret == ERROR_NONE) {
306       facade_->DelegateReporterEvent(info, updatedItem);
307       facade_->LaunchDefaultViewer(updatedItem, NOTIFICATION_OP_UPDATE);
308     } else {
309       SendError(info, static_cast<NotificationError>(ret));
310     }
311   }
312
313   int DoDelete(const IEventInfo& info,
314       shared_ptr<item::AbstractItem> deletedItem) {
315     int ret = DBManager::DeleteNotification(deletedItem);
316     if (ret == ERROR_NONE) {
317       facade_->DelegateReporterEvent(info, deletedItem);
318     } else {
319       SendError(info, static_cast<NotificationError>(ret));
320     }
321     return ret;
322   }
323
324   void OnDelete(const IEventInfo& info,
325       shared_ptr<item::AbstractItem> deletedItem) override {
326     DBG("Delete !!!");
327     if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
328       list<shared_ptr<item::AbstractItem>> noti_list =
329           DBManager::GetNotificationList(info.GetOwner(),
330               ((const IEventInfoInternal&)info).GetUid());
331       for (auto& i : noti_list) {
332         DoDelete(info, i);
333       }
334       facade_->LaunchDefaultViewer(noti_list, NOTIFICATION_OP_DELETE_ALL);
335     } else {
336       int ret = DoDelete(info, deletedItem);
337       if (ret == ERROR_NONE)
338         facade_->LaunchDefaultViewer(deletedItem, NOTIFICATION_OP_DELETE);
339     }
340   }
341
342   list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
343     DBG("Get !!! %s", info.GetOwner().c_str());
344     if (info.GetItemId().empty()) {
345       /* get */
346       return DBManager::GetNotificationList(info.GetOwner(),
347                          ((const IEventInfoInternal&)info).GetUid());
348     } else {
349       /*  FindByRootID */
350       return DBManager::GetNotificationList(info.GetOwner(), info.GetItemId(),
351                          ((const IEventInfoInternal&)info).GetUid());
352     }
353   }
354
355  public:
356   DPMManager(std::unique_ptr<IEventSender> sender,
357       std::unique_ptr<IEventListener> listener)
358     : Manager(move(sender), move(listener)) {
359   }
360 };
361
362 HAPI int notification_ex_service_init() {
363   facade_ = new DPMFacade(
364     unique_ptr<Reporter>(
365       new DPMReporter(
366         unique_ptr<DBusSender>(new DBusSender(Manager::GetPath())),
367         unique_ptr<DBusEventListener>(new DBusEventListener(Reporter::GetPath())))),
368     unique_ptr<Manager>(
369       new DPMManager(
370         unique_ptr<DBusSender>(new DBusSender(Reporter::GetPath())),
371         unique_ptr<DBusEventListener>(new DBusEventListener(Manager::GetPath())))));
372
373   notification_init_default_viewer();
374
375   return ERROR_NONE;
376 }
377
378 HAPI int notification_ex_service_fini() {
379   delete facade_;
380   return ERROR_NONE;
381 }
382
383 HAPI GDBusConnection* notification_ex_service_get_gdbus_connection() {
384   return DBusConnectionManager::GetInst().GetConnection();
385 }