Change behaivor of reporter_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           DBManager::GetNotificationList(facade_->GetUid(info), info.GetChannel());
371       for (auto& i : noti_list) {
372         DoDelete(info, i);
373       }
374     } else {
375       DoDelete(info, deletedItem);
376     }
377   }
378
379   void OnEvent(const IEventInfo& info,
380       list<shared_ptr<item::AbstractItem>> noti_list) override {
381     LOGI("Event received (%d) !!", (int)info.GetEventType());
382     int type = info.GetEventType();
383     if (type == IEventInfo::EventType::DeleteAll) {
384       OnDelete(info, nullptr);
385       return;
386     } else if (type == IEventInfo::EventType::Register) {
387       OnRegister(info);
388       return;
389     }
390
391     for (auto& i : noti_list) {
392       switch (type) {
393       case IEventInfo::EventType::Update:
394         OnUpdate(info, i);
395         break;
396       case IEventInfo::EventType::Delete:
397         OnDelete(info, i);
398         break;
399       default :
400         break;
401       }
402     }
403   }
404
405   list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
406     list<shared_ptr<item::AbstractItem>> item_list;
407
408     DBG("Get report !!! %s", info.GetItemId().c_str());
409     item_list = DBManager::GetNotificationList(facade_->GetUid(info),
410                 ((const IEventInfoInternal&)info).GetChannel().c_str());
411
412     facade_->shared_file_.SetPrivateSharing(item_list,
413                 facade_->receiver_group_list_);
414
415     facade_->TranslateText(item_list);
416
417     return item_list;
418   }
419
420   int OnRequestNumber(const IEventInfo& info) override {
421     DBG("Get count !!! %s", info.GetItemId().c_str());
422     return DBManager::GetNotificationList(facade_->GetUid(info)).size();
423   }
424
425   int UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
426     int ret;
427     string hide_list;
428     int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
429     DBG("try update hide app_id(%s) sender(%s) uid(%s)",
430       updatedItem->GetId().c_str(),
431       updatedItem->GetSenderAppId().c_str(), string(to_string(uid)).c_str());
432     string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
433     list<string> updated_hide_list = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
434
435     /* Check new hide app */
436     auto noti = facade_->hide_map_.find(map_key);
437     if (noti == facade_->hide_map_.end()) {
438       if (updated_hide_list.size() > 0) {
439         for (auto& i : updated_hide_list)
440           hide_list += i + ";";
441
442         ret = DBManager::UpdateHideList(updatedItem, hide_list);
443         if (ret != ERROR_NONE)
444           return ret;
445
446         facade_->hide_map_[map_key] = hide_list;
447         return ERROR_NONE;
448       } else {
449         DBG("Empty hide viewer list");
450         return ERROR_NOT_EXIST_ID;
451       }
452     }
453
454     /* Check new hide app */
455     hide_list = noti->second;
456     for (auto& i : updated_hide_list) {
457       if (hide_list.find(i + ";") == string::npos) {
458         string new_hide_list = hide_list + i + ";";
459         ret = DBManager::UpdateHideList(updatedItem, new_hide_list);
460         if (ret != ERROR_NONE)
461           return ret;
462
463         facade_->hide_map_[map_key] = new_hide_list;
464         return ERROR_NONE;
465       }
466     }
467
468     return ERROR_NOT_EXIST_ID;
469   }
470
471   void OnRegister(const IEventInfo& info) {
472     std::string receiver_group = info.GetChannel();
473     std::string appid = info.GetOwner();
474
475     std::multimap<std::string,std::string>::iterator it;
476     for(auto receiver_group_ : facade_->receiver_group_list_) {
477       if (receiver_group_.first.compare(receiver_group) == 0 &&
478           receiver_group_.second.compare(appid) == 0)
479         return;
480     }
481
482     facade_->receiver_group_list_.insert(make_pair(receiver_group, appid));
483   }
484
485  public:
486   DPMReporter(std::unique_ptr<IEventSender> sender,
487       std::unique_ptr<IEventListener> listener)
488     : Reporter(move(sender), move(listener)) {
489   }
490 };
491
492 class DPMManager : public Manager {
493  protected:
494   void UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
495     string hide_list;
496     int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
497     string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
498     list<string> updated_hide_list =
499       static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
500
501     auto noti = facade_->hide_map_.find(map_key);
502     if (noti == facade_->hide_map_.end())
503       return;
504
505     /* hide app list synchronization */
506     hide_list = noti->second;
507     istringstream stream(hide_list);
508     string hide_app_id;
509
510     while (getline(stream, hide_app_id, ';')) {
511       list<string>::iterator iter = std::find(updated_hide_list.begin(),
512                                 updated_hide_list.end(), hide_app_id);
513       if (iter == updated_hide_list.end())
514         static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->AddHideViewer(hide_app_id);
515     }
516   }
517
518   void OnAdd(const IEventInfo& info,
519       list<shared_ptr<item::AbstractItem>> addedItem) override {
520     DBG("Add !!!");
521     int ret;
522
523     ret = ValidateUid(info, addedItem);
524     if (ret != ERROR_NONE) {
525       SendError(info, static_cast<NotificationError>(ret));
526       return;
527     }
528
529     SetIndirectRequest(info, addedItem);
530
531     if (facade_->CheckAllowedToNotify(addedItem) == false)
532       return;
533
534     facade_->SetDoNoDisturbPolicy(addedItem);
535     facade_->SetPopUpPolicy(addedItem);
536
537     ret = DBManager::InsertNotification(addedItem);
538     if (ret == ERROR_NONE) {
539       facade_->shared_file_.SetPrivateSharing(addedItem,
540             facade_->receiver_group_list_);
541       facade_->TranslateText(addedItem);
542       facade_->DelegateReporterEvent(info, addedItem);
543       facade_->LaunchDefaultViewer(addedItem, NOTIFICATION_OP_INSERT);
544     } else {
545         DBG("SendError !!!");
546         SendError(info, static_cast<NotificationError>(ret));
547     }
548   }
549
550   void OnUpdate(const IEventInfo& info,
551       shared_ptr<item::AbstractItem> updatedItem) override {
552     DBG("Update !!!");
553     int ret;
554
555     ret = ValidateUid(info, updatedItem);
556     if (ret != ERROR_NONE) {
557       SendError(info, static_cast<NotificationError>(ret));
558       return;
559     }
560
561     UpdateHideApp(updatedItem);
562     SetIndirectRequest(info, updatedItem);
563
564     if (facade_->CheckAllowedToNotify(updatedItem) == false)
565       return;
566
567     facade_->SetDoNoDisturbPolicy(updatedItem);
568     facade_->SetPopUpPolicy(updatedItem);
569
570     ret = DBManager::UpdateNotification(updatedItem);
571     if (ret == ERROR_NONE) {
572       facade_->shared_file_.UpdatePrivateSharing(updatedItem,
573             facade_->receiver_group_list_);
574       facade_->TranslateText(updatedItem);
575       facade_->DelegateReporterEvent(info, updatedItem);
576       facade_->LaunchDefaultViewer(updatedItem, NOTIFICATION_OP_UPDATE);
577     } else {
578       SendError(info, static_cast<NotificationError>(ret));
579     }
580   }
581
582   int DoDelete(const IEventInfo& info,
583       shared_ptr<item::AbstractItem> deletedItem) {
584     int ret;
585
586     ret = DBManager::DeleteNotification(deletedItem);
587     if (ret == ERROR_NONE) {
588       facade_->DelegateReporterEvent(info, deletedItem);
589       facade_->shared_file_.RemovePrivateSharing(deletedItem,
590             facade_->receiver_group_list_);
591     } else {
592       SendError(info, static_cast<NotificationError>(ret));
593     }
594     return ret;
595   }
596
597   void OnDelete(const IEventInfo& info,
598       shared_ptr<item::AbstractItem> deletedItem) override {
599     DBG("Delete !!!");
600     if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
601       list<shared_ptr<item::AbstractItem>> noti_list =
602           DBManager::GetNotificationList(info.GetOwner(), facade_->GetUid(info),
603               info.GetChannel());
604       for (auto& i : noti_list) {
605         EventInfo event_info(EventInfo::Delete, info.GetOwner(), info.GetChannel());
606         DoDelete(event_info, i);
607       }
608       facade_->LaunchDefaultViewer(noti_list, NOTIFICATION_OP_DELETE);
609     } else {
610       int ret = DoDelete(info, deletedItem);
611       if (ret == ERROR_NONE)
612         facade_->LaunchDefaultViewer(deletedItem, NOTIFICATION_OP_DELETE);
613     }
614   }
615
616   list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
617     DBG("Get !!! %s", info.GetOwner().c_str());
618     list<shared_ptr<item::AbstractItem>> item_list;
619     uid_t uid = facade_->GetUid(info);
620     if (info.GetItemId().empty()) {
621       if (!info.GetChannel().empty()) {
622         /* get by channel */
623         item_list = DBManager::GetNotificationList(info.GetOwner(), uid, info.GetChannel());
624         facade_->TranslateText(item_list);
625         return item_list;
626       } else {
627         /* get all*/
628         item_list = DBManager::GetNotificationList(info.GetOwner(), uid);
629         facade_->TranslateText(item_list);
630         return item_list;
631       }
632     } else {
633       /*  FindByRootID */
634       item_list = DBManager::GetNotificationList(info.GetOwner(), info.GetItemId(), uid);
635       facade_->TranslateText(item_list);
636       return item_list;
637     }
638   }
639
640   void SetIndirectRequest(const IEventInfo& info,
641           list<shared_ptr<AbstractItem>> addedItem) {
642     for (auto& i : addedItem)
643       SetIndirectRequest(info, i);
644   }
645
646   void SetIndirectRequest(const IEventInfo& info,
647           shared_ptr<AbstractItem> addedItem) {
648     SetIndirectRequest(info, addedItem->GetAction());
649
650     if (addedItem->GetType() != AbstractItem::Type::Group)
651       return;
652
653     auto item_group = static_pointer_cast<GroupItem>(addedItem);
654     auto children_list = item_group->GetChildren();
655     for (auto& i : children_list)
656       SetIndirectRequest(info, i);
657   }
658
659   void SetIndirectRequest(const IEventInfo& info, shared_ptr<AbstractAction>action) {
660     if (action == nullptr || action->GetType() != AbstractAction::Type::AppControl)
661       return;
662
663     uid_t uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
664     if (uid < NORMAL_UID_BASE)
665       return;
666
667     string owner = static_cast<const IEventInfoInternal&>(info).GetValidatedOwner();
668     app_control_h appcontrol = static_pointer_cast<AppControlAction>(action)->GetAppControl();
669     bundle* b = nullptr;
670     app_control_export_as_bundle(appcontrol, &b);
671
672     bundle_del(b, AUL_K_REQUEST_TYPE);
673     bundle_add(b, AUL_K_REQUEST_TYPE, "indirect-request");
674
675     bundle_del(b, AUL_K_ORG_CALLER_UID);
676     bundle_add(b, AUL_K_ORG_CALLER_UID, std::to_string(uid).c_str());
677
678     bundle_del(b, AUL_K_ORG_CALLER_APPID);
679     bundle_add(b, AUL_K_ORG_CALLER_APPID, owner.c_str());
680
681     pkgmgrinfo_appinfo_h handle;
682     int r = pkgmgrinfo_appinfo_get_usr_appinfo(owner.c_str(), uid, &handle);
683     if (r == PMINFO_R_OK) {
684       char* pkgid = nullptr;
685       pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
686       if (pkgid) {
687         bundle_del(b, AUL_K_ORG_CALLER_PKGID);
688         bundle_add(b, AUL_K_ORG_CALLER_PKGID, pkgid);
689       }
690       pkgmgrinfo_appinfo_destroy_appinfo(handle);
691     }
692
693     app_control_import_from_bundle(appcontrol, b);
694     bundle_free(b);
695   }
696
697   int ValidateUid(const IEventInfo& info, list<shared_ptr<AbstractItem>> addedItem) {
698     int ret;
699     for (auto& i : addedItem) {
700       ret = ValidateUid(info, i);
701       if (ret != ERROR_NONE)
702         return ret;
703     }
704
705     return ERROR_NONE;
706   }
707
708   int ValidateUid(const IEventInfo& info, shared_ptr<AbstractItem> addedItem) {
709     uid_t validated_uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
710     uid_t item_uid = static_pointer_cast<IItemInfoInternal>
711                                   (addedItem->GetInfo())->GetUid();
712
713     if (validated_uid <= NORMAL_UID_BASE) {
714       static_pointer_cast<IItemInfoInternal>
715           (addedItem->GetInfo())->SetUid(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
716     } else if (validated_uid != item_uid) {
717       ERR("Invalid sender uid[%d] noti_uid[%d]", validated_uid, item_uid);
718       return ERROR_INVALID_PARAMETER;
719     }
720
721     return ERROR_NONE;
722   }
723
724  public:
725   DPMManager(std::unique_ptr<IEventSender> sender,
726       std::unique_ptr<IEventListener> listener)
727     : Manager(move(sender), move(listener)) {
728   }
729 };
730
731 HAPI int notification_ex_service_init(int restart_count) {
732   facade_ = new DPMFacade(
733     unique_ptr<Reporter>(
734       new DPMReporter(
735         unique_ptr<DBusSender>(new DBusSender(Manager::GetPath())),
736         unique_ptr<DBusEventListener>(new DBusEventListener(Reporter::GetPath())))),
737     unique_ptr<Manager>(
738       new DPMManager(
739         unique_ptr<DBusSender>(new DBusSender(Reporter::GetPath())),
740         unique_ptr<DBusEventListener>(new DBusEventListener(Manager::GetPath())))),
741         restart_count);
742
743   notification_init_default_viewer();
744
745   return ERROR_NONE;
746 }
747
748 HAPI int notification_ex_service_fini() {
749   delete facade_;
750   return ERROR_NONE;
751 }
752
753 HAPI GDBusConnection* notification_ex_service_get_gdbus_connection() {
754   return DBusConnectionManager::GetInst().GetConnection();
755 }