To get deleted item's info when viewer delete all
[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 #include <aul.h>
23 #include <app_control_internal.h>
24 #include <pkgmgr-info.h>
25 #include <bundle.h>
26 #include <bundle_internal.h>
27 #include <tzplatform_config.h>
28 #include <notification_setting.h>
29 #include <notification_setting_internal.h>
30 #include <notification_setting_service.h>
31
32 #include <iostream>
33 #include <sstream>
34 #include <algorithm>
35 #include <map>
36
37 #include <notification_ex_item.h>
38 #include <notification-ex/manager.h>
39 #include <notification-ex/reporter.h>
40 #include <notification-ex/dbus_sender.h>
41 #include <notification-ex/dbus_event_listener.h>
42 #include <notification-ex/dbus_connection_manager.h>
43 #include <notification-ex/db_manager.h>
44 #include <notification-ex/common.h>
45 #include <notification-ex/exception.h>
46 #include <notification-ex/item_info_internal.h>
47 #include <notification-ex/button_item.h>
48 #include <notification-ex/ex_util.h>
49 #include <notification-ex/ievent_info_internal.h>
50 #include <notification-ex/event_info_internal.h>
51 #include <notification-ex/iitem_info_internal.h>
52 #include <notification-ex/shared_file.h>
53 #include <notification-ex/group_item.h>
54 #include <notification-ex/app_control_action.h>
55
56 #include "debug.h"
57 #include "notification_ex_service.h"
58
59 #define NORMAL_UID_BASE 5000
60
61 using namespace std;
62 using namespace notification;
63 using namespace notification::item;
64
65 class DPMFacade {
66  public:
67   DPMFacade(unique_ptr<Reporter> reporter, unique_ptr<Manager> manager, int restartCount)
68       : reporter_(move(reporter)), manager_(move(manager)) {
69     DBManager::InitializeDB();
70
71     if (restartCount == 0)
72       DBManager::InitializeData();
73
74     hide_map_ = DBManager::GetHideMap();
75   }
76
77   void DelegateReporterEvent(const IEventInfo& info,
78         shared_ptr<item::AbstractItem> item) {
79     reporter_->SendEvent(info, item);
80   }
81
82   void DelegateReporterEvent(const IEventInfo& info,
83         std::list<std::shared_ptr<item::AbstractItem>> itemList) {
84     reporter_->SendEvent(info, itemList);
85   }
86
87   void DelegateManagerEvent(const IEventInfo& info,
88         shared_ptr<item::AbstractItem> noti) {
89     manager_->SendEvent(info, noti);
90   }
91
92   void LaunchDefaultViewer(list<shared_ptr<item::AbstractItem>> item,
93                                    notification_op_type_e status) {
94     int64_t priv_id;
95     if (item.size() == 0)
96       return;
97
98     if (item.size() > 1)
99       priv_id = NOTIFICATION_PRIV_ID_NONE;
100     else
101       priv_id = static_pointer_cast<IItemInfoInternal>(
102                     item.front()->GetInfo())->GetPrivateId();
103
104     LaunchDefaultViewer(priv_id, status,
105                         static_pointer_cast<IItemInfoInternal>(
106                             item.front()->GetInfo())->GetUid());
107   }
108   void LaunchDefaultViewer(shared_ptr<item::AbstractItem> item,
109               notification_op_type_e status) {
110     LaunchDefaultViewer(
111         static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetPrivateId(),
112         status,
113         static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid());
114   }
115
116   void LaunchDefaultViewer(int64_t privId, notification_op_type_e status,
117                                    uid_t uid) {
118     int ret = notification_launch_default_viewer(
119                    static_cast<int>(privId), status, uid);
120     if (ret != ERROR_NONE)
121       ERR("Failed to launch default viewer [%d]", ret);
122   }
123
124   uid_t GetUid(const IEventInfo& info) {
125     uid_t validated_uid =
126             static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
127
128     return validated_uid > NORMAL_UID_BASE ?
129                     validated_uid : tzplatform_getuid(TZ_SYS_DEFAULT_USER);
130   }
131
132   void TranslateText(list<shared_ptr<item::AbstractItem>> item) {
133     for (auto& i : item)
134       TranslateText(i);
135   }
136
137   void TranslateText(shared_ptr<item::AbstractItem> item) {
138     if (item->GetMultiLanguage() != nullptr)
139       item->GetMultiLanguage()->UpdateString();
140
141     if (item->GetType() != AbstractItem::Type::Group)
142       return;
143
144     auto item_group = static_pointer_cast<GroupItem>(item);
145     auto children_list = item_group->GetChildren();
146
147     for (auto& i : children_list)
148       TranslateText(i);
149   }
150
151   bool CheckAllowedToNotify(list<shared_ptr<item::AbstractItem>> item) {
152     auto iter = item.begin();
153
154     while (iter != item.end()) {
155       if (CheckAllowedToNotify(*iter) == false)
156         iter = item.erase(iter);
157       else
158         iter++;
159     }
160
161     if (item.size() == 0)
162       return false;
163     else
164       return true;
165   }
166
167   bool CheckAllowedToNotify(shared_ptr<item::AbstractItem> item) {
168     notification_setting_h setting;
169     int ret;
170     bool allow_to_notify, app_disabled;
171     uid_t uid = static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid();
172
173     ret = noti_setting_service_get_setting_by_app_id(item->GetSenderAppId().c_str(),
174              &setting, uid);
175     if (ret != NOTIFICATION_ERROR_NONE)
176       return true;
177
178     notification_setting_get_allow_to_notify(setting, &allow_to_notify);
179     notification_setting_get_app_disabled(setting, &app_disabled);
180     notification_setting_free_notification(setting);
181
182     if (!allow_to_notify || app_disabled) {
183       ERR("[%s] is not allowed to notify[%d,%d]", item->GetSenderAppId().c_str(),
184             allow_to_notify, app_disabled);
185       return false;
186     }
187
188     return true;
189   }
190   bool CheckDoNoDisturbStatus(uid_t uid, const string& owner) {
191     int ret;
192     bool do_not_disturb = false;
193     bool do_not_disturb_exception;
194     notification_setting_h setting = nullptr;
195     notification_system_setting_h system_setting = nullptr;
196
197     ret = noti_system_setting_load_system_setting(&system_setting, uid);
198     if (ret != NOTIFICATION_ERROR_NONE) {
199       WARN("Failed to load system setting [%d]", ret);
200       goto out;
201     }
202
203     ret = notification_system_setting_get_do_not_disturb(system_setting, &do_not_disturb);
204     if (ret != NOTIFICATION_ERROR_NONE) {
205       WARN("Failed to get do_not_disturb [%d]", ret);
206       goto out;
207     }
208
209     if (do_not_disturb) {
210       do_not_disturb = false;
211       /* Check exception option of the caller app_id */
212       ret = noti_setting_service_get_setting_by_app_id(owner.c_str(), &setting, uid);
213       if (ret != NOTIFICATION_ERROR_NONE) {
214         WARN("Failed to get setting by app_id [%d]", ret);
215         goto out;
216       }
217
218       ret = notification_setting_get_do_not_disturb_except(setting, &do_not_disturb_exception);
219       if (ret != NOTIFICATION_ERROR_NONE) {
220         WARN("Failed to get do_not_disturb_exception [%d]", ret);
221         goto out;
222       }
223
224       if (do_not_disturb_exception == false)
225         do_not_disturb = true;
226     }
227
228 out:
229     DBG("do_not_disturb [%d]", do_not_disturb);
230     if (system_setting)
231       notification_system_setting_free_system_setting(system_setting);
232
233     if (setting)
234       notification_setting_free_notification(setting);
235
236     return do_not_disturb;
237   }
238
239   void SetDoNoDisturbPolicy(list<shared_ptr<item::AbstractItem>> item) {
240     for (auto& i : item)
241       SetDoNoDisturbPolicy(i);
242   }
243
244   void SetDoNoDisturbPolicy(shared_ptr<item::AbstractItem> item) {
245     uid_t uid = static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid();
246     if (CheckDoNoDisturbStatus(uid, item->GetSenderAppId()) == false)
247       return;
248
249     item->SetSoundPath("");
250     item->SetVibrationPath("");
251     item->SetLEDInfo(nullptr);
252
253     std::list<std::string> receiver_list = item->GetReceiverList();
254     if (receiver_list.size() == 0) {
255       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_PANEL);
256       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_INDICATOR);
257     } else {
258        auto iter = receiver_list.begin();
259
260       while (iter != receiver_list.end()) {
261         if ((*iter).compare(NOTI_EX_RECEIVER_GROUP_PANEL) != 0
262               && (*iter).compare(NOTI_EX_RECEIVER_GROUP_INDICATOR) != 0)
263           iter = receiver_list.erase(iter);
264         else
265           iter++;
266       }
267     }
268   }
269
270   void SetPopUpPolicy(list<shared_ptr<item::AbstractItem>> item) {
271     for (auto& i : item)
272       SetPopUpPolicy(i);
273   }
274
275   void SetPopUpPolicy(shared_ptr<item::AbstractItem> item) {
276     notification_setting_h setting;
277     int ret;
278     bool is_pop_up;
279     uid_t uid = static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid();
280     ret = noti_setting_service_get_setting_by_app_id(item->GetSenderAppId().c_str(),
281                    &setting, uid);
282     if (ret != NOTIFICATION_ERROR_NONE) {
283       WARN("Failed get the setting for [%s] [%x]", item->GetSenderAppId().c_str(), ret);
284       return;
285     }
286
287     notification_setting_get_pop_up_notification(setting, &is_pop_up);
288     notification_setting_free_notification(setting);
289     if (is_pop_up == true)
290       return;
291
292     std::list<std::string> receiver_list = item->GetReceiverList();
293     if (receiver_list.size() == 0) {
294       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_PANEL);
295       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_TICKER);
296       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_LOCKSCREEN);
297       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_INDICATOR);
298     } else {
299        auto iter = receiver_list.begin();
300
301       while (iter != receiver_list.end()) {
302         if ((*iter).compare(NOTI_EX_RECEIVER_GROUP_POPUP) == 0)
303           iter = receiver_list.erase(iter);
304         else
305           iter++;
306       }
307     }
308   }
309   unique_ptr<Reporter> reporter_;
310   unique_ptr<Manager> manager_;
311   map<string, string> hide_map_;
312   multimap<string, string> receiver_group_list_;
313   SharedFile shared_file_;
314 };
315
316 static DPMFacade* facade_;
317
318 class DPMReporter : public Reporter {
319  protected:
320   void OnUpdate(const IEventInfo& info,
321       shared_ptr<item::AbstractItem> updatedItem) {
322     DBG("Update !!!");
323     int ret;
324
325     /* check Manager::Hide() */
326     ret = UpdateHideApp(updatedItem);
327     if (ret == ERROR_NONE)
328       return;
329
330     if (ret != ERROR_NOT_EXIST_ID) {
331       SendError(info, static_cast<NotificationError>(ret));
332       return;
333     }
334
335     ret = DBManager::UpdateNotification(updatedItem);
336     if (ret == ERROR_NONE) {
337       facade_->TranslateText(updatedItem);
338       /* noti owner */
339       facade_->DelegateManagerEvent(info, updatedItem);
340
341       /* noti to viewers */
342       facade_->DelegateReporterEvent(info, updatedItem);
343     } else {
344       SendError(info, static_cast<NotificationError>(ret));
345     }
346   }
347
348   void DoDelete(const IEventInfo& info,
349       shared_ptr<item::AbstractItem> deletedItem) {
350     int ret = DBManager::DeleteNotification(deletedItem);
351     if (ret == ERROR_NONE) {
352       /* noti owner */
353       facade_->DelegateManagerEvent(info, deletedItem);
354
355       /* noti to viewers */
356       facade_->DelegateReporterEvent(info, deletedItem);
357
358       facade_->shared_file_.RemovePrivateSharing(deletedItem,
359             facade_->receiver_group_list_);
360     } else {
361       SendError(info, static_cast<NotificationError>(ret));
362     }
363   }
364
365   void OnDelete(const IEventInfo& info,
366       shared_ptr<item::AbstractItem> deletedItem) {
367     DBG("Delete !!!");
368     if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
369       list<shared_ptr<item::AbstractItem>> noti_list;
370       if(!info.GetItemId().empty()) /* The item_id is actually an app_id. */
371         noti_list = DBManager::GetNotificationList(
372                 info.GetItemId(), facade_->GetUid(info), "");
373       else
374         noti_list = DBManager::GetNotificationList(
375                 facade_->GetUid(info), info.GetChannel());
376
377       EventInfo event_info(EventInfo::Delete, info.GetOwner(), info.GetChannel());
378       for (auto& i : noti_list)
379         DoDelete(event_info, i);
380     } else {
381       DoDelete(info, deletedItem);
382     }
383   }
384
385   void OnEvent(const IEventInfo& info,
386       list<shared_ptr<item::AbstractItem>> noti_list) override {
387     LOGI("Event received (%d) !!", (int)info.GetEventType());
388     int type = info.GetEventType();
389     if (type == IEventInfo::EventType::DeleteAll) {
390       OnDelete(info, nullptr);
391       return;
392     } else if (type == IEventInfo::EventType::Register) {
393       OnRegister(info);
394       return;
395     }
396
397     for (auto& i : noti_list) {
398       switch (type) {
399       case IEventInfo::EventType::Update:
400         OnUpdate(info, i);
401         break;
402       case IEventInfo::EventType::Delete:
403         OnDelete(info, i);
404         break;
405       default :
406         break;
407       }
408     }
409   }
410
411   list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
412     list<shared_ptr<item::AbstractItem>> item_list;
413
414     DBG("Get report !!! %s", info.GetItemId().c_str());
415     item_list = DBManager::GetNotificationList(facade_->GetUid(info),
416                 ((const IEventInfoInternal&)info).GetChannel().c_str());
417
418     facade_->shared_file_.SetPrivateSharing(item_list,
419                 facade_->receiver_group_list_);
420
421     facade_->TranslateText(item_list);
422
423     return item_list;
424   }
425
426   int OnRequestNumber(const IEventInfo& info) override {
427     DBG("Get count !!! %s", info.GetItemId().c_str());
428     return DBManager::GetNotificationList(facade_->GetUid(info)).size();
429   }
430
431   int UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
432     int ret;
433     string hide_list;
434     int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
435     DBG("try update hide app_id(%s) sender(%s) uid(%s)",
436       updatedItem->GetId().c_str(),
437       updatedItem->GetSenderAppId().c_str(), string(to_string(uid)).c_str());
438     string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
439     list<string> updated_hide_list = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
440
441     /* Check new hide app */
442     auto noti = facade_->hide_map_.find(map_key);
443     if (noti == facade_->hide_map_.end()) {
444       if (updated_hide_list.size() > 0) {
445         for (auto& i : updated_hide_list)
446           hide_list += i + ";";
447
448         ret = DBManager::UpdateHideList(updatedItem, hide_list);
449         if (ret != ERROR_NONE)
450           return ret;
451
452         facade_->hide_map_[map_key] = hide_list;
453         return ERROR_NONE;
454       } else {
455         DBG("Empty hide viewer list");
456         return ERROR_NOT_EXIST_ID;
457       }
458     }
459
460     /* Check new hide app */
461     hide_list = noti->second;
462     for (auto& i : updated_hide_list) {
463       if (hide_list.find(i + ";") == string::npos) {
464         string new_hide_list = hide_list + i + ";";
465         ret = DBManager::UpdateHideList(updatedItem, new_hide_list);
466         if (ret != ERROR_NONE)
467           return ret;
468
469         facade_->hide_map_[map_key] = new_hide_list;
470         return ERROR_NONE;
471       }
472     }
473
474     return ERROR_NOT_EXIST_ID;
475   }
476
477   void OnRegister(const IEventInfo& info) {
478     std::string receiver_group = info.GetChannel();
479     std::string appid = info.GetOwner();
480
481     std::multimap<std::string,std::string>::iterator it;
482     for(auto receiver_group_ : facade_->receiver_group_list_) {
483       if (receiver_group_.first.compare(receiver_group) == 0 &&
484           receiver_group_.second.compare(appid) == 0)
485         return;
486     }
487
488     facade_->receiver_group_list_.insert(make_pair(receiver_group, appid));
489   }
490
491  public:
492   DPMReporter(std::unique_ptr<IEventSender> sender,
493       std::unique_ptr<IEventListener> listener)
494     : Reporter(move(sender), move(listener)) {
495   }
496 };
497
498 class DPMManager : public Manager {
499  protected:
500   void UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
501     string hide_list;
502     int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
503     string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
504     list<string> updated_hide_list =
505       static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
506
507     auto noti = facade_->hide_map_.find(map_key);
508     if (noti == facade_->hide_map_.end())
509       return;
510
511     /* hide app list synchronization */
512     hide_list = noti->second;
513     istringstream stream(hide_list);
514     string hide_app_id;
515
516     while (getline(stream, hide_app_id, ';')) {
517       list<string>::iterator iter = std::find(updated_hide_list.begin(),
518                                 updated_hide_list.end(), hide_app_id);
519       if (iter == updated_hide_list.end())
520         static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->AddHideViewer(hide_app_id);
521     }
522   }
523
524   void OnAdd(const IEventInfo& info,
525       list<shared_ptr<item::AbstractItem>> addedItem) override {
526     DBG("Add !!!");
527     int ret;
528
529     ret = ValidateUid(info, addedItem);
530     if (ret != ERROR_NONE) {
531       SendError(info, static_cast<NotificationError>(ret));
532       return;
533     }
534
535     SetIndirectRequest(info, addedItem);
536
537     if (facade_->CheckAllowedToNotify(addedItem) == false)
538       return;
539
540     facade_->SetDoNoDisturbPolicy(addedItem);
541     facade_->SetPopUpPolicy(addedItem);
542
543     ret = DBManager::InsertNotification(addedItem);
544     if (ret == ERROR_NONE) {
545       facade_->shared_file_.SetPrivateSharing(addedItem,
546             facade_->receiver_group_list_);
547       facade_->TranslateText(addedItem);
548       facade_->DelegateReporterEvent(info, addedItem);
549       facade_->LaunchDefaultViewer(addedItem, NOTIFICATION_OP_INSERT);
550     } else {
551         DBG("SendError !!!");
552         SendError(info, static_cast<NotificationError>(ret));
553     }
554   }
555
556   void OnUpdate(const IEventInfo& info,
557       shared_ptr<item::AbstractItem> updatedItem) override {
558     DBG("Update !!!");
559     int ret;
560
561     ret = ValidateUid(info, updatedItem);
562     if (ret != ERROR_NONE) {
563       SendError(info, static_cast<NotificationError>(ret));
564       return;
565     }
566
567     UpdateHideApp(updatedItem);
568     SetIndirectRequest(info, updatedItem);
569
570     if (facade_->CheckAllowedToNotify(updatedItem) == false)
571       return;
572
573     facade_->SetDoNoDisturbPolicy(updatedItem);
574     facade_->SetPopUpPolicy(updatedItem);
575
576     ret = DBManager::UpdateNotification(updatedItem);
577     if (ret == ERROR_NONE) {
578       facade_->shared_file_.UpdatePrivateSharing(updatedItem,
579             facade_->receiver_group_list_);
580       facade_->TranslateText(updatedItem);
581       facade_->DelegateReporterEvent(info, updatedItem);
582       facade_->LaunchDefaultViewer(updatedItem, NOTIFICATION_OP_UPDATE);
583     } else {
584       SendError(info, static_cast<NotificationError>(ret));
585     }
586   }
587
588   int DoDelete(const IEventInfo& info,
589       shared_ptr<item::AbstractItem> deletedItem) {
590     int ret;
591
592     ret = DBManager::DeleteNotification(deletedItem);
593     if (ret == ERROR_NONE) {
594       facade_->DelegateReporterEvent(info, deletedItem);
595       facade_->shared_file_.RemovePrivateSharing(deletedItem,
596             facade_->receiver_group_list_);
597     } else {
598       SendError(info, static_cast<NotificationError>(ret));
599     }
600     return ret;
601   }
602
603   void OnDelete(const IEventInfo& info,
604       shared_ptr<item::AbstractItem> deletedItem) override {
605     DBG("Delete !!!");
606     if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
607       list<shared_ptr<item::AbstractItem>> noti_list =
608           DBManager::GetNotificationList(info.GetOwner(), facade_->GetUid(info),
609               info.GetChannel());
610       for (auto& i : noti_list) {
611         EventInfo event_info(EventInfo::Delete, info.GetOwner(), info.GetChannel());
612         DoDelete(event_info, i);
613       }
614       facade_->LaunchDefaultViewer(noti_list, NOTIFICATION_OP_DELETE);
615     } else {
616       int ret = DoDelete(info, deletedItem);
617       if (ret == ERROR_NONE)
618         facade_->LaunchDefaultViewer(deletedItem, NOTIFICATION_OP_DELETE);
619     }
620   }
621
622   list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
623     DBG("Get !!! %s", info.GetOwner().c_str());
624     list<shared_ptr<item::AbstractItem>> item_list;
625     uid_t uid = facade_->GetUid(info);
626     if (info.GetItemId().empty()) {
627       if (!info.GetChannel().empty()) {
628         /* get by channel */
629         item_list = DBManager::GetNotificationList(info.GetOwner(), uid, info.GetChannel());
630         facade_->TranslateText(item_list);
631         return item_list;
632       } else {
633         /* get all*/
634         item_list = DBManager::GetNotificationList(info.GetOwner(), uid);
635         facade_->TranslateText(item_list);
636         return item_list;
637       }
638     } else {
639       /*  FindByRootID */
640       item_list = DBManager::GetNotificationList(info.GetOwner(), info.GetItemId(), uid);
641       facade_->TranslateText(item_list);
642       return item_list;
643     }
644   }
645
646   void SetIndirectRequest(const IEventInfo& info,
647           list<shared_ptr<AbstractItem>> addedItem) {
648     for (auto& i : addedItem)
649       SetIndirectRequest(info, i);
650   }
651
652   void SetIndirectRequest(const IEventInfo& info,
653           shared_ptr<AbstractItem> addedItem) {
654     SetIndirectRequest(info, addedItem->GetAction());
655
656     if (addedItem->GetType() != AbstractItem::Type::Group)
657       return;
658
659     auto item_group = static_pointer_cast<GroupItem>(addedItem);
660     auto children_list = item_group->GetChildren();
661     for (auto& i : children_list)
662       SetIndirectRequest(info, i);
663   }
664
665   void SetIndirectRequest(const IEventInfo& info, shared_ptr<AbstractAction>action) {
666     if (action == nullptr || action->GetType() != AbstractAction::Type::AppControl)
667       return;
668
669     uid_t uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
670     if (uid < NORMAL_UID_BASE)
671       return;
672
673     string owner = static_cast<const IEventInfoInternal&>(info).GetValidatedOwner();
674     app_control_h appcontrol = static_pointer_cast<AppControlAction>(action)->GetAppControl();
675     bundle* b = nullptr;
676     app_control_export_as_bundle(appcontrol, &b);
677
678     bundle_del(b, AUL_K_REQUEST_TYPE);
679     bundle_add(b, AUL_K_REQUEST_TYPE, "indirect-request");
680
681     bundle_del(b, AUL_K_ORG_CALLER_UID);
682     bundle_add(b, AUL_K_ORG_CALLER_UID, std::to_string(uid).c_str());
683
684     bundle_del(b, AUL_K_ORG_CALLER_APPID);
685     bundle_add(b, AUL_K_ORG_CALLER_APPID, owner.c_str());
686
687     pkgmgrinfo_appinfo_h handle;
688     int r = pkgmgrinfo_appinfo_get_usr_appinfo(owner.c_str(), uid, &handle);
689     if (r == PMINFO_R_OK) {
690       char* pkgid = nullptr;
691       pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
692       if (pkgid) {
693         bundle_del(b, AUL_K_ORG_CALLER_PKGID);
694         bundle_add(b, AUL_K_ORG_CALLER_PKGID, pkgid);
695       }
696       pkgmgrinfo_appinfo_destroy_appinfo(handle);
697     }
698
699     app_control_import_from_bundle(appcontrol, b);
700     bundle_free(b);
701   }
702
703   int ValidateUid(const IEventInfo& info, list<shared_ptr<AbstractItem>> addedItem) {
704     int ret;
705     for (auto& i : addedItem) {
706       ret = ValidateUid(info, i);
707       if (ret != ERROR_NONE)
708         return ret;
709     }
710
711     return ERROR_NONE;
712   }
713
714   int ValidateUid(const IEventInfo& info, shared_ptr<AbstractItem> addedItem) {
715     uid_t validated_uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
716     uid_t item_uid = static_pointer_cast<IItemInfoInternal>
717                                   (addedItem->GetInfo())->GetUid();
718
719     if (validated_uid <= NORMAL_UID_BASE) {
720       static_pointer_cast<IItemInfoInternal>
721           (addedItem->GetInfo())->SetUid(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
722     } else if (validated_uid != item_uid) {
723       ERR("Invalid sender uid[%d] noti_uid[%d]", validated_uid, item_uid);
724       return ERROR_INVALID_PARAMETER;
725     }
726
727     return ERROR_NONE;
728   }
729
730  public:
731   DPMManager(std::unique_ptr<IEventSender> sender,
732       std::unique_ptr<IEventListener> listener)
733     : Manager(move(sender), move(listener)) {
734   }
735 };
736
737 HAPI int notification_ex_service_init(int restart_count) {
738   facade_ = new DPMFacade(
739     unique_ptr<Reporter>(
740       new DPMReporter(
741         unique_ptr<DBusSender>(new DBusSender(Manager::GetPath())),
742         unique_ptr<DBusEventListener>(new DBusEventListener(Reporter::GetPath())))),
743     unique_ptr<Manager>(
744       new DPMManager(
745         unique_ptr<DBusSender>(new DBusSender(Reporter::GetPath())),
746         unique_ptr<DBusEventListener>(new DBusEventListener(Manager::GetPath())))),
747         restart_count);
748
749   notification_init_default_viewer();
750
751   return ERROR_NONE;
752 }
753
754 HAPI int notification_ex_service_fini() {
755   delete facade_;
756   return ERROR_NONE;
757 }
758
759 HAPI GDBusConnection* notification_ex_service_get_gdbus_connection() {
760   return DBusConnectionManager::GetInst().GetConnection();
761 }