[Application] Add check for user_data availability in AppControl callback
[platform/core/api/webapi-plugins.git] / src / application / application_manager.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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 "application_manager.h"
18
19 #include <glib.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <thread>
23 #include <type_traits>
24
25 #include <app_control_internal.h>
26 #include <app_info.h>
27 #include <app_manager_extension.h>
28 #include <appsvc.h>
29 #include <aul.h>
30 #include <bundle.h>
31 #include <bundle_internal.h>
32 #include <package_manager.h>
33 #include <pkgmgr-info.h>
34 #include <pkgmgr_installer.h>
35
36 #include "common/current_application.h"
37 #include "common/logger.h"
38 #include "common/platform_result.h"
39 #include "common/scope_exit.h"
40 #include "common/task-queue.h"
41 #include "common/tools.h"
42
43 #include "application/application_instance.h"
44 #include "application/application_utils.h"
45
46 using namespace common;
47 using namespace tools;
48
49 namespace extension {
50 namespace application {
51
52 namespace {
53 const std::string kTizenApisFileScheme = "file://";
54 const std::string kTizenApisAppSlash = "/";
55 const std::string kTizenApisAppShared = "shared";
56
57 const char* kStartKey = PKGMGR_INSTALLER_START_KEY_STR;
58 const char* kEndKey = PKGMGR_INSTALLER_END_KEY_STR;
59 const char* kOkValue = PKGMGR_INSTALLER_OK_EVENT_STR;
60 const char* kInstallEvent = PKGMGR_INSTALLER_INSTALL_EVENT_STR;
61 const char* kUpdateEvent = PKGMGR_INSTALLER_UPGRADE_EVENT_STR;
62 const char* kUninstallEvent = PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
63
64 const char* kAppidKey = "appid";
65
66 const std::string kAction = "action";
67 const std::string kCallbackId = "callbackId";
68 const std::string kOnInstalled = "oninstalled";
69 const std::string kOnUpdated = "onupdated";
70 const std::string kOnUninstalled = "onuninstalled";
71 const std::string kData = "data";
72 const std::string kStatusType = "statusType";
73 const std::string kAppId = "appId";
74 const std::string kListenerId = "listenerId";
75 const std::string kAppStatusChangeListener = "AppStatusChangeListener";
76 const std::string kAppUsageModeFrequently = "FREQUENTLY";
77 const std::string kAppUsageModeRecently = "RECENTLY";
78
79 const std::map<std::string, std::string> event_map_ = {
80     {SYSTEM_EVENT_BATTERY_CHARGER_STATUS, EVENT_KEY_BATTERY_CHARGER_STATUS},
81     {SYSTEM_EVENT_BATTERY_LEVEL_STATUS, EVENT_KEY_BATTERY_LEVEL_STATUS},
82     {SYSTEM_EVENT_USB_STATUS, EVENT_KEY_USB_STATUS},
83     {SYSTEM_EVENT_EARJACK_STATUS, EVENT_KEY_EARJACK_STATUS},
84     {SYSTEM_EVENT_DISPLAY_STATE, EVENT_KEY_DISPLAY_STATE},
85     {SYSTEM_EVENT_LOW_MEMORY, EVENT_KEY_LOW_MEMORY},
86     {SYSTEM_EVENT_WIFI_STATE, EVENT_KEY_WIFI_STATE},
87     {SYSTEM_EVENT_BT_STATE, EVENT_KEY_BT_STATE},
88     {SYSTEM_EVENT_LOCATION_ENABLE_STATE, EVENT_KEY_LOCATION_ENABLE_STATE},
89     {SYSTEM_EVENT_GPS_ENABLE_STATE, EVENT_KEY_GPS_ENABLE_STATE},
90     {SYSTEM_EVENT_NPS_ENABLE_STATE, EVENT_KEY_NPS_ENABLE_STATE},
91     {SYSTEM_EVENT_INCOMING_MSG, EVENT_KEY_MSG_TYPE},
92     {SYSTEM_EVENT_TIME_ZONE, EVENT_KEY_TIME_ZONE},
93     {SYSTEM_EVENT_HOUR_FORMAT, EVENT_KEY_HOUR_FORMAT},
94     {SYSTEM_EVENT_LANGUAGE_SET, EVENT_KEY_LANGUAGE_SET},
95     {SYSTEM_EVENT_REGION_FORMAT, EVENT_KEY_REGION_FORMAT},
96     {SYSTEM_EVENT_SILENT_MODE, EVENT_KEY_SILENT_MODE},
97     {SYSTEM_EVENT_VIBRATION_STATE, EVENT_KEY_VIBRATION_STATE},
98     {SYSTEM_EVENT_SCREEN_AUTOROTATE_STATE, EVENT_KEY_SCREEN_AUTOROTATE_STATE},
99     {SYSTEM_EVENT_MOBILE_DATA_STATE, EVENT_KEY_MOBILE_DATA_STATE},
100     {SYSTEM_EVENT_DATA_ROAMING_STATE, EVENT_KEY_DATA_ROAMING_STATE},
101     {SYSTEM_EVENT_FONT_SET, EVENT_KEY_FONT_SET}};
102
103 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
104 const int kMaximumBatteryRetrievedObjects = 30;
105 const int kMaximumAppsRetrievedObjects = 10;
106 const int kDefaultPeriodOfTime = 30;
107 #endif
108 }
109
110 std::set<LaunchAppControlCallbackData*> ApplicationManager::launch_app_control_set_global_{};
111 std::mutex ApplicationManager::launch_app_control_set_mutex_{};
112
113 ApplicationManager::ApplicationManager(ApplicationInstance& instance)
114     : pkgmgr_client_handle_(nullptr),
115       pkgmgr_client_uninstall_handle_(nullptr),
116       instance_(instance),
117       app_status_handle_(nullptr) {
118   ScopeLogger();
119 }
120
121 ApplicationManager::~ApplicationManager() {
122   ScopeLogger();
123   StopAppInfoEventListener();
124   StopStatusChangeListener();
125
126   for (auto it = event_handler_map_.begin(); it != event_handler_map_.end();) {
127     int ret = event_remove_event_handler(it->second);
128     if (EVENT_ERROR_NONE != ret) {
129       LoggerE("event_remove_event_handler failed, error: %d (%s)", ret, get_error_message(ret));
130     }
131     it = event_handler_map_.erase(it);
132   }
133
134   if (app_status_handle_) {
135     int ret = app_manager_event_destroy(app_status_handle_);
136     if (APP_MANAGER_ERROR_NONE != ret) {
137       LoggerE("app_manager_event_destroy failed, error: %d", ret);
138     }
139   }
140
141   // Calling order of reply_callback and result_callback of launchAppControl
142   // cannot be determined, reply_callback depends on application scenario, which
143   // cannot be predicted. Moreover reply_callback is optional and can be called or not,
144   // thus callback_data is relesed here at the end of application lifetime.
145   std::lock_guard<std::mutex> lock(launch_app_control_set_mutex_);
146   std::for_each(launch_app_control_set_.begin(), launch_app_control_set_.end(),
147                 [](LaunchAppControlCallbackData* const& data) {
148                   LoggerD("Releasing callback data: %p", data);
149                   delete data;
150                   launch_app_control_set_global_.erase(data);
151                 });
152 }
153
154 void ApplicationManager::GetCurrentApplication(const std::string& app_id, picojson::object* out) {
155   ScopeLogger();
156
157   // obtain handle to application info
158   pkgmgrinfo_appinfo_h handle;
159   int ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle);
160   if (PMINFO_R_OK != ret) {
161     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get app info."), out,
162                       ("Failed to get app info: %d (%s)", ret, get_error_message(ret)));
163     return;
164   }
165
166   picojson::value app_info = picojson::value(picojson::object());
167   picojson::object& app_info_obj = app_info.get<picojson::object>();
168
169   utils::CreateApplicationInformation(handle, &app_info_obj);
170   pkgmgrinfo_appinfo_destroy_appinfo(handle);
171
172   picojson::value result = picojson::value(picojson::object());
173   picojson::object& result_obj = result.get<picojson::object>();
174
175   result_obj.insert(std::make_pair(
176       "contextId",
177       picojson::value(std::to_string(CurrentApplication::GetInstance().GetProcessId()))));
178   result_obj.insert(std::make_pair("appInfo", app_info));
179
180   ReportSuccess(result, *out);
181 }
182
183 class TerminateHandler {
184  public:
185   TerminateHandler(int callback_id, ApplicationInstance* app_instance)
186       : callback_handle_(callback_id), pid_(-1), timeout_id_(0), app_instance_(app_instance) {
187   }
188
189   void set_pid(pid_t pid) {
190     pid_ = pid;
191   }
192
193   pid_t pid() const {
194     return pid_;
195   }
196
197   void Invoke(const std::shared_ptr<picojson::value>& response) {
198     ScopeLogger();
199
200     if (timeout_id_ > 0) {
201       // cancel terminate callback
202       g_source_remove(timeout_id_);
203       timeout_id_ = 0;
204     }
205
206     ApplicationInstance* app_instance = this->app_instance_;
207     int callback_id = this->callback_handle_;
208     TaskQueue::GetInstance().Async<picojson::value>(
209         [callback_id, app_instance](const std::shared_ptr<picojson::value>& response) {
210           picojson::object& obj = response->get<picojson::object>();
211           obj.insert(
212               std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
213           Instance::PostMessage(app_instance, response->serialize().c_str());
214         },
215         response);
216   }
217
218  private:
219   int callback_handle_;
220   pid_t pid_;
221   guint timeout_id_;
222   ApplicationInstance* app_instance_;
223 };
224
225 #define CHECK_RESULT(result, response, handler)                    \
226   if (result.IsError()) {                                          \
227     LogAndReportError(result, &response->get<picojson::object>()); \
228     handler->Invoke(response);                                     \
229     delete handler;                                                \
230     return;                                                        \
231   }
232
233 void ApplicationManager::AsyncResponse(const PlatformResult& result,
234                                        std::shared_ptr<picojson::value>* response) {
235   ScopeLogger();
236   LogAndReportError(result, &(*response)->get<picojson::object>());
237
238   TaskQueue::GetInstance().Async<picojson::value>(
239       [this](const std::shared_ptr<picojson::value>& response) {
240         Instance::PostMessage(&this->instance_, response->serialize().c_str());
241       },
242       *response);
243 }
244
245 void ApplicationManager::Kill(const picojson::value& args) {
246   ScopeLogger();
247
248   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
249
250   int callback_id = -1;
251   const auto& callback = args.get(kCallbackId);
252   if (callback.is<double>()) {
253     callback_id = static_cast<int>(callback.get<double>());
254   }
255
256   const auto& context = args.get("contextId");
257   if (!context.is<std::string>()) {
258     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
259   }
260
261   const std::string& context_id = context.get<std::string>();
262
263   if (context_id.empty() && result.IsSuccess()) {
264     result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Context ID is empty.");
265   }
266
267   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
268   picojson::object& obj = response->get<picojson::object>();
269   obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
270
271   if (result.IsError()) {
272     LoggerE("Failed args.get");
273     AsyncResponse(result, &response);
274     return;
275   }
276
277   auto kill = [this, callback_id, context_id]() -> void {
278     ScopeLogger("Kill");
279
280     std::shared_ptr<picojson::value> response =
281         std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
282
283     TerminateHandler* handler = new TerminateHandler(callback_id, &this->instance_);
284     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
285
286     pid_t pid = -1;
287     try {
288       pid = std::stoi(context_id);
289     } catch (...) {
290       result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert string to int.");
291       CHECK_RESULT(result, response, handler)
292     }
293
294     if (pid <= 0) {
295       result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Context ID cannot be negative value.");
296       CHECK_RESULT(result, response, handler)
297     }
298
299     // if kill request comes for current context, throw InvalidValuesException
300     if (CurrentApplication::GetInstance().GetProcessId() == pid) {
301       result =
302           LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Cannot kill current application.");
303       CHECK_RESULT(result, response, handler)
304     }
305
306     LoggerD("Kill, pid: %d", pid);
307
308     char* app_id = nullptr;
309     int ret = app_manager_get_app_id(pid, &app_id);
310     // automatically release the memory
311     std::unique_ptr<char, void (*)(void*)> app_id_ptr(app_id, &std::free);
312
313     if (APP_MANAGER_ERROR_NONE != ret) {
314       result = LogAndCreateResult(
315           ErrorCode::NOT_FOUND_ERR, "Failed to get application ID.",
316           ("Failed to get application ID, error: %d (%s)", ret, get_error_message(ret)));
317       CHECK_RESULT(result, response, handler)
318     }
319
320     LoggerD("Kill, app ID: %s", app_id);
321
322     // acquire application context
323     app_context_h app_context = nullptr;
324
325     ret = app_manager_get_app_context(app_id, &app_context);
326     std::unique_ptr<std::remove_pointer<app_context_h>::type, int (*)(app_context_h)>
327         app_context_ptr(app_context, &app_context_destroy);  // automatically release the memory
328
329     if (APP_MANAGER_ERROR_NONE != ret) {
330       result = LogAndCreateResult(
331           ErrorCode::NOT_FOUND_ERR, "Failed to get application ID.",
332           ("Failed to get application context handle: %d (%s)", ret, get_error_message(ret)));
333       CHECK_RESULT(result, response, handler)
334     }
335
336     auto terminate_callback = [](app_context_h app_context, app_context_event_e event,
337                                  void* user_data) {
338       LoggerD("terminate_callback: %d", event);
339
340       if (APP_CONTEXT_EVENT_TERMINATED != event) {
341         LoggerD("ignoring event");
342         return;
343       }
344
345       int pid = 0;
346       int ret = app_context_get_pid(app_context, &pid);
347
348       if (APP_MANAGER_ERROR_NONE != ret) {
349         LoggerE("Failed to get pid of terminated app: %d (%s)", ret, get_error_message(ret));
350         return;
351       }
352
353       TerminateHandler* handler = static_cast<TerminateHandler*>(user_data);
354
355       LoggerD("Expected PID: %d, got: %d", handler->pid(), pid);
356
357       if (handler->pid() == pid) {
358         std::shared_ptr<picojson::value> response =
359             std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
360         ReportSuccess(response->get<picojson::object>());
361         handler->Invoke(response);
362         delete handler;
363       }
364     };
365
366     LoggerD("Kill, setting callback");
367     handler->set_pid(pid);
368     ret = app_manager_set_app_context_event_cb(terminate_callback, handler);
369
370     if (APP_MANAGER_ERROR_NONE != ret) {
371       result = LogAndCreateResult(
372           ErrorCode::UNKNOWN_ERR, "Failed to register termination callback.",
373           ("Error while registering app context event: %d (%s)", ret, get_error_message(ret)));
374       CHECK_RESULT(result, response, handler)
375     }
376
377     LoggerD("Kill, calling native function");
378
379     // terminate application
380     ret = app_manager_terminate_app(app_context);
381
382     if (APP_MANAGER_ERROR_NONE != ret) {
383       result = LogAndCreateResult(
384           ErrorCode::UNKNOWN_ERR, "Failed to terminate application.",
385           ("Failed to terminate application: %d (%s)", ret, get_error_message(ret)));
386       CHECK_RESULT(result, response, handler)
387     }
388
389     LoggerD("Kill, end, waiting for notification");
390   };
391
392   kill();
393 }
394
395 namespace {
396
397 PlatformResult PrepareAppControlForLaunchAppControl(const picojson::value& args,
398                                                     app_control_h* app_control) {
399   ScopeLogger();
400
401   const auto& control = args.get("appControl");
402   if (!control.is<picojson::object>()) {
403     return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
404   }
405   const picojson::object& app_control_obj = control.get<picojson::object>();
406
407   app_control_h tmp_app_control = nullptr;
408   auto result = utils::ApplicationControlToService(app_control_obj, &tmp_app_control);
409   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
410       app_control_ptr(tmp_app_control, &app_control_destroy);
411
412   if (result.IsError()) {
413     LoggerE("Application control to service failed.");
414     return result;
415   }
416
417   std::string app_id;
418   const auto& id = args.get("id");
419   if (id.is<std::string>()) {
420     app_id = id.get<std::string>();
421   }
422
423   if (!app_id.empty()) {
424     LoggerD("app_id: %s", app_id.c_str());
425
426     int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
427
428     if (APP_CONTROL_ERROR_NONE != ret) {
429       LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
430       return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
431     }
432   }
433
434   *app_control = app_control_ptr.release();
435
436   return PlatformResult(ErrorCode::NO_ERROR);
437 }
438
439 }  // namespace
440
441 void ApplicationManager::LaunchAppControl(const picojson::value& args) {
442   ScopeLogger();
443
444   int callback_id = -1;
445   const auto& callback = args.get(kCallbackId);
446   if (callback.is<double>()) {
447     callback_id = static_cast<int>(callback.get<double>());
448   }
449
450   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
451   picojson::object& response_obj = response->get<picojson::object>();
452   response_obj.insert(
453       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
454
455   app_control_h app_control = nullptr;
456   auto prepare_app_control_result = PrepareAppControlForLaunchAppControl(args, &app_control);
457   if (prepare_app_control_result.IsError()) {
458     AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
459     return;
460   }
461
462   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
463       app_control_ptr(app_control, &app_control_destroy);
464
465   std::string reply_callback_id;
466   const auto& reply = args.get("replyCallback");
467   if (reply.is<std::string>()) {
468     reply_callback_id = reply.get<std::string>();
469   }
470
471   LaunchAppControlCallbackData* launch_app_user_data = new (std::nothrow)
472       LaunchAppControlCallbackData{&this->instance_, response, reply_callback_id};
473
474   if (!launch_app_user_data) {
475     LoggerE("Memory allocation fail!");
476     AsyncResponse(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response);
477     return;
478   }
479
480   app_control_reply_cb reply_callback = nullptr;
481   if (!reply_callback_id.empty()) {
482     launch_app_user_data->reply_callback_id = reply_callback_id;
483
484     reply_callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
485                         void* user_data) {
486       ScopeLogger("reply_callback");
487
488       LaunchAppControlCallbackData* callback_data =
489           static_cast<LaunchAppControlCallbackData*>(user_data);
490
491       std::lock_guard<std::mutex> lock(launch_app_control_set_mutex_);
492       if (!launch_app_control_set_global_.count(callback_data)) {
493         LoggerE("Invalid callback_data: %p", callback_data);
494         return;
495       }
496
497       picojson::value return_value = picojson::value(picojson::object());
498       picojson::object& return_value_obj = return_value.get<picojson::object>();
499       return_value_obj.insert(
500           std::make_pair(kListenerId, picojson::value(callback_data->reply_callback_id)));
501
502       if (APP_CONTROL_RESULT_SUCCEEDED == result) {
503         LoggerD("App started");
504         return_value_obj.insert(std::make_pair("data", picojson::value(picojson::array())));
505         if (!utils::ServiceToApplicationControlDataArray(
506                 reply, &return_value_obj.find("data")->second.get<picojson::array>())) {
507           return_value_obj.erase("data");
508         }
509         ReportSuccess(return_value_obj);
510       } else {
511         ReportError(return_value_obj);
512       }
513
514       Instance::PostMessage(callback_data->instance, return_value.serialize().c_str());
515       // Calling order of reply_callback and result_callback cannot be determined,
516       // thus callback_data is not released here, but stored for release in destructor of
517       // ApplicationManager
518     };
519   }
520
521   app_control_result_cb result_callback = [](app_control_h launch_request,
522                                              app_control_error_e launch_result, void* user_data) {
523     ScopeLogger("LaunchAppControl result_callback");
524
525     LaunchAppControlCallbackData* callback_data =
526         static_cast<LaunchAppControlCallbackData*>(user_data);
527
528     std::lock_guard<std::mutex> lock(launch_app_control_set_mutex_);
529     if (!launch_app_control_set_global_.count(callback_data)) {
530       LoggerE("Invalid callback_data: %p", callback_data);
531       return;
532     }
533
534     auto result = utils::TranslateAppControlError(launch_result);
535
536     if (result.IsError()) {
537       LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
538     } else {
539       ReportSuccess(callback_data->response->get<picojson::object>());
540     }
541
542     Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
543
544     // Calling order of reply_callback and result_callback cannot be determined,
545     // thus callback_data is not released here, but stored for release in destructor of
546     // ApplicationManager
547   };
548
549   /*
550    * TODO: Observe how often app_control_send_launch_request_async tries to launch the application.
551    * Previous implementation, using synchronous app_control_send_launch_request,
552    * tries to launch the application 3 times, before reporting an error.
553    * New implementation, using app_control_send_launch_request_async makes only one attempt.
554    * If problems, such as failed application start occur, multiple attempts may solve the problem.
555    */
556   auto launch_result = utils::TranslateAppControlError(
557       static_cast<app_control_error_e>(app_control_send_launch_request_async(
558           app_control_ptr.get(), result_callback, reply_callback, launch_app_user_data)));
559
560   if (launch_result.IsError()) {
561     delete launch_app_user_data;
562     AsyncResponse(launch_result, &response);
563   } else {
564     // Calling order of reply_callback and result_callback cannot be determined,
565     // reply_callback depends on application scenario, which cannot be predicted.
566     // Moreover reply_callback is optional and can be called or not,
567     // thus callback_data is stored for releasing in destructor of ApplicationManager
568     // at the end of application lifetime.
569     // We can not be sure whether callbach will not fire after instance destruction,
570     // we store all user_data pointers in static launch_app_control_set_global_ to check
571     // if they are still valid.
572     std::lock_guard<std::mutex> lock(launch_app_control_set_mutex_);
573     launch_app_control_set_.insert(launch_app_user_data);
574     launch_app_control_set_global_.insert(launch_app_user_data);
575     LoggerD("App launched, data %p stored for later release", launch_app_user_data);
576   }
577 }
578 namespace {
579
580 PlatformResult TranslateLaunchError(app_control_error_e return_code) {
581   ScopeLogger();
582
583   auto result = utils::TranslateAppControlError(return_code);
584   if (ErrorCode::SECURITY_ERR == result.error_code()) {
585     result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
586   }
587
588   return result;
589 }
590
591 PlatformResult PrepareAppControlForLaunch(const picojson::value& args, app_control_h* app_control) {
592   ScopeLogger();
593
594   const auto& app_id = args.get("id");
595   if (!app_id.is<std::string>()) {
596     return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
597   }
598   const auto app_id_str = app_id.get<std::string>();
599
600   app_control_h tmp_app_control = nullptr;
601   int result = app_control_create(&tmp_app_control);
602   if (APP_CONTROL_ERROR_NONE != result) {
603     LoggerD("app_control_create() failed: %d (%s)", result, get_error_message(result));
604     return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
605   }
606
607   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
608       app_control_ptr(tmp_app_control, &app_control_destroy);
609
610   if (!app_id_str.empty()) {
611     LoggerD("app_id: %s", app_id_str.c_str());
612
613     int ret = app_control_set_app_id(app_control_ptr.get(), app_id_str.c_str());
614
615     if (APP_CONTROL_ERROR_NONE != ret) {
616       LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
617       return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
618     }
619   }
620
621   *app_control = app_control_ptr.release();
622
623   return PlatformResult(ErrorCode::NO_ERROR);
624 }
625
626 }  // namespace
627 void ApplicationManager::Launch(const picojson::value& args) {
628   ScopeLogger();
629
630   int callback_id = -1;
631   const auto& callback = args.get(kCallbackId);
632   if (callback.is<double>()) {
633     callback_id = static_cast<int>(callback.get<double>());
634   }
635
636   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
637   picojson::object& response_obj = response->get<picojson::object>();
638   response_obj.insert(
639       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
640
641   app_control_h app_control = nullptr;
642   auto prepare_app_control_result = PrepareAppControlForLaunch(args, &app_control);
643   if (prepare_app_control_result.IsError()) {
644     AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response);
645     return;
646   }
647
648   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)>
649       app_control_ptr(app_control, &app_control_destroy);
650
651   struct LaunchCallbackData {
652     ApplicationInstance* instance;
653     std::shared_ptr<picojson::value> response;
654   }* launch_user_data = new (std::nothrow) LaunchCallbackData{&this->instance_, response};
655
656   app_control_result_cb result_callback = [](app_control_h launch_request,
657                                              app_control_error_e launch_result, void* user_data) {
658     ScopeLogger("Launch result_callback");
659
660     LaunchCallbackData* callback_data = static_cast<LaunchCallbackData*>(user_data);
661
662     auto result = TranslateLaunchError(launch_result);
663
664     if (result.IsError()) {
665       LogAndReportError(result, &(callback_data->response->get<picojson::object>()));
666     } else {
667       ReportSuccess(callback_data->response->get<picojson::object>());
668     }
669
670     Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
671
672     delete callback_data;
673   };
674
675   /*
676    * TODO: Observe how often app_control_send_resume_request tries to launch the application.
677    * Previous implementation, using synchronous app_control_send_launch_request,
678    * tries to launch the application 3 times, before reporting an error.
679    * New implementation, using app_control_send_resume_request makes only one attempt.
680    * If problems, such as failed application start occur, multiple attempts may solve the problem.
681    */
682   auto launch_result = TranslateLaunchError(static_cast<app_control_error_e>(
683       app_control_send_resume_request(app_control_ptr.get(), result_callback, launch_user_data)));
684
685   if (launch_result.IsError()) {
686     delete launch_user_data;
687     AsyncResponse(launch_result, &response);
688   } else {
689     LoggerD("App launched");
690   }
691 }
692
693 // internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND
694 // public CAPI did not handling APP_CONTROL_ERROR_APP_NOT_FOUND
695 int app_control_foreach_app_matched_internal(app_control_h app_control,
696                                              app_control_app_matched_cb callback, void* user_data) {
697   ScopeLogger();
698   typedef struct {
699     app_control_h app_control;
700     app_control_app_matched_cb callback;
701     void* user_data;
702     bool foreach_break;
703   } foreach_context_launchable_app_t_internal;
704
705   // internal impl of app_control_cb_broker_foreach_app_matched()
706   auto app_control_cb_broker_foreach_app_matched_internal = [](const char* package,
707                                                                void* data) -> int {
708     ScopeLogger(
709         "Entered into asynchronous function, app_control_cb_broker_foreach_app_matched_internal's "
710         "argument");
711     foreach_context_launchable_app_t_internal* foreach_context;
712     app_control_app_matched_cb app_matched_cb;
713
714     if (package == NULL || data == NULL) {
715       LoggerE("APP_CONTROL_ERROR_INVALID_PARAMETER");
716       return -1;
717     }
718
719     foreach_context = (foreach_context_launchable_app_t_internal*)data;
720     if (foreach_context->foreach_break == true) return -1;
721
722     app_matched_cb = foreach_context->callback;
723     if (app_matched_cb != NULL) {
724       bool stop_foreach = false;
725
726       stop_foreach =
727           !app_matched_cb(foreach_context->app_control, package, foreach_context->user_data);
728
729       foreach_context->foreach_break = stop_foreach;
730     }
731
732     return 0;
733   };
734
735   foreach_context_launchable_app_t_internal foreach_context = {.app_control = app_control,
736                                                                .callback = callback,
737                                                                .user_data = user_data,
738                                                                .foreach_break = false};
739
740   bundle* bundle_data = NULL;
741   app_control_to_bundle(app_control, &bundle_data);
742
743   int ret = appsvc_usr_get_list(bundle_data, app_control_cb_broker_foreach_app_matched_internal,
744                                 &foreach_context, getuid());
745
746   if (ret < 0) {
747     switch (ret) {
748       case APPSVC_RET_EINVAL:
749         return APP_CONTROL_ERROR_INVALID_PARAMETER;
750
751       case APPSVC_RET_ENOMATCH:
752         return APP_CONTROL_ERROR_APP_NOT_FOUND;
753
754       default:
755         return APP_CONTROL_ERROR_LAUNCH_FAILED;
756     }
757   }
758
759   return APP_CONTROL_ERROR_NONE;
760 }
761
762 void ApplicationManager::FindAppControl(const picojson::value& args) {
763   ScopeLogger();
764
765   int callback_id = -1;
766   const auto& callback = args.get(kCallbackId);
767   if (callback.is<double>()) {
768     callback_id = static_cast<int>(callback.get<double>());
769   }
770
771   std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
772   picojson::object& response_obj = response->get<picojson::object>();
773   response_obj.insert(
774       std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
775
776   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
777   const auto& control = args.get("appControl");
778   if (!control.is<picojson::object>()) {
779     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
780     AsyncResponse(result, &response);
781     return;
782   }
783
784   const picojson::object& app_control_obj = control.get<picojson::object>();
785
786   app_control_h app_control = nullptr;
787   result = utils::ApplicationControlToService(app_control_obj, &app_control);
788   std::shared_ptr<std::remove_pointer<app_control_h>::type> app_control_ptr(
789       app_control, &app_control_destroy);  // automatically release the memory
790
791   if (result.IsError()) {
792     LoggerE("Application control to service failed.");
793     AsyncResponse(result, &response);
794     return;
795   }
796
797   auto find = [app_control_ptr](const std::shared_ptr<picojson::value>& response) -> void {
798     ScopeLogger("Entered into asynchronous function, find");
799     auto app_control_matched = [](app_control_h app_control, const char* appid,
800                                   void* user_data) -> bool {
801       ScopeLogger("Entered into asynchronous function, app_control_matched");
802       if (nullptr == appid) {
803         LoggerD("appid is NULL");
804         return false;
805       }
806
807       pkgmgrinfo_appinfo_h handle;
808       int ret = pkgmgrinfo_appinfo_get_usr_appinfo(appid, getuid(), &handle);
809       if (PMINFO_R_OK != ret) {
810         LoggerE("Failed to get appInfo: %d (%s)", ret, get_error_message(ret));
811       } else {
812         picojson::array* array = static_cast<picojson::array*>(user_data);
813         array->push_back(picojson::value(picojson::object()));
814
815         utils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
816         pkgmgrinfo_appinfo_destroy_appinfo(handle);
817       }
818
819       return true;
820     };
821
822     picojson::object& response_obj = response->get<picojson::object>();
823     auto it_result = response_obj.find("result");
824     picojson::object& result_obj = it_result->second.get<picojson::object>();
825     auto array =
826         result_obj.insert(std::make_pair("informationArray", picojson::value(picojson::array())));
827
828     int ret = app_control_foreach_app_matched_internal(app_control_ptr.get(), app_control_matched,
829                                                        &array.first->second.get<picojson::array>());
830
831     if (APP_CONTROL_ERROR_NONE != ret) {
832       if (APP_CONTROL_ERROR_APP_NOT_FOUND == ret) {
833         LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Matched Application not found"),
834                           &response_obj, ("app_control_foreach_app_matched error: %d (%s)", ret,
835                                           get_error_message(ret)));
836       } else if (APP_CONTROL_ERROR_LAUNCH_FAILED == ret) {
837         LogAndReportError(
838             PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), &response_obj,
839             ("app_control_foreach_app_matched error: %d (%s)", ret, get_error_message(ret)));
840       } else if (APP_CONTROL_ERROR_INVALID_PARAMETER == ret) {
841         LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed"),
842                           &response_obj, ("app_control_foreach_app_matched error: %d (%s)", ret,
843                                           get_error_message(ret)));
844       }
845       // remove copied ApplicationControl from result
846       response_obj.erase(it_result);
847     } else {
848       ReportSuccess(response_obj);
849     }
850   };
851
852   auto find_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
853     ScopeLogger("Entered into asynchronous function, find_response");
854     Instance::PostMessage(&this->instance_, response->serialize().c_str());
855   };
856
857   // prepare result object, we need to do that here, as input parameter is passed to result callback
858   auto ret = response_obj.insert(std::make_pair("result", picojson::value(picojson::object())));
859   // reinsert application control
860   ret.first->second.get<picojson::object>().insert(
861       std::make_pair("appControl", args.get("appControl")));
862
863   TaskQueue::GetInstance().Queue<picojson::value>(find, find_response, response);
864 }
865
866 void ApplicationManager::GetAppsContext(const picojson::value& args) {
867   ScopeLogger();
868
869   int callback_id = -1;
870   const auto& callback = args.get(kCallbackId);
871   if (callback.is<double>()) {
872     callback_id = static_cast<int>(callback.get<double>());
873   }
874
875   auto get_apps_context = [](const std::shared_ptr<picojson::value>& response) -> void {
876     picojson::object& response_obj = response->get<picojson::object>();
877     picojson::value result = picojson::value(picojson::object());
878     picojson::object& result_obj = result.get<picojson::object>();
879     picojson::array& array =
880         result_obj.insert(std::make_pair("contexts", picojson::value(picojson::array())))
881             .first->second.get<picojson::array>();
882
883     auto app_context_cb = [](app_context_h app_context, void* user_data) -> bool {
884       if (nullptr == user_data) {
885         return false;
886       }
887
888       picojson::array* array = static_cast<picojson::array*>(user_data);
889       array->push_back(picojson::value(picojson::object()));
890
891       if (!utils::CreateApplicationContext(app_context, &array->back().get<picojson::object>())) {
892         array->pop_back();
893         return false;
894       }
895
896       return true;
897     };
898
899     int ret = app_manager_foreach_app_context(app_context_cb, &array);
900
901     if (APP_MANAGER_ERROR_NONE != ret) {
902       LogAndReportError(
903           PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
904           ("app_manager_foreach_app_context error: %d (%s)", ret, get_error_message(ret)));
905     } else {
906       ReportSuccess(result, response_obj);
907     }
908   };
909
910   auto get_apps_context_response =
911       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
912     picojson::object& obj = response->get<picojson::object>();
913     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
914     Instance::PostMessage(&this->instance_, response->serialize().c_str());
915   };
916
917   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
918
919   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_context, get_apps_context_response,
920                                                   data);
921 }
922
923 void ApplicationManager::GetAppContext(const picojson::value& args, picojson::object* out) {
924   ScopeLogger();
925   pid_t pid = 0;
926
927   const auto& context_id = args.get("contextId");
928   if (context_id.is<std::string>()) {
929     try {
930       pid = std::stoi(context_id.get<std::string>());
931     } catch (...) {
932       LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert context id."),
933                         out);
934       return;
935     }
936   } else {
937     pid = CurrentApplication::GetInstance().GetProcessId();
938   }
939
940   char* app_id = nullptr;
941
942   int ret = app_manager_get_app_id(pid, &app_id);
943   // automatically release the memory
944   std::unique_ptr<char, void (*)(void*)> app_id_ptr(app_id, &std::free);
945
946   if (APP_MANAGER_ERROR_NONE != ret || nullptr == app_id) {
947     switch (ret) {
948       case APP_MANAGER_ERROR_NO_SUCH_APP:
949         LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "No such application exist."), out,
950                           ("app_manager_get_app_id returned: APP_MANAGER_ERROR_NO_SUCH_APP"));
951         return;
952
953       case APP_MANAGER_ERROR_INVALID_PARAMETER:
954         LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Application not found."), out,
955                           ("app_manager_get_app_id returned: APP_MANAGER_ERROR_INVALID_PARAMETER"));
956         return;
957
958       default:
959         LogAndReportError(
960             PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), out,
961             ("app_manager_get_app_id returned: %d (%s)", ret, get_error_message(ret)));
962         return;
963     }
964   }
965
966   picojson::value result = picojson::value(picojson::object());
967   utils::CreateApplicationContext(pid, app_id, &result.get<picojson::object>());
968
969   ReportSuccess(result, *out);
970 }
971
972 void ApplicationManager::GetAppsInfo(const picojson::value& args) {
973   ScopeLogger();
974
975   int callback_id = -1;
976   const auto& callback = args.get(kCallbackId);
977   if (callback.is<double>()) {
978     callback_id = static_cast<int>(callback.get<double>());
979   }
980
981   auto get_apps_info = [](const std::shared_ptr<picojson::value>& response) -> void {
982     ScopeLogger("Entered into asynchronous function, get_apps_info");
983     picojson::object& response_obj = response->get<picojson::object>();
984     picojson::value result = picojson::value(picojson::object());
985     picojson::object& result_obj = result.get<picojson::object>();
986     picojson::array& array =
987         result_obj.insert(std::make_pair("informationArray", picojson::value(picojson::array())))
988             .first->second.get<picojson::array>();
989
990     auto app_info_cb = [](pkgmgrinfo_appinfo_h handle, void* user_data) -> int {
991       ScopeLogger("Entered into asynchronous function, app_info_cb");
992       if (nullptr == user_data) {
993         return -1;
994       }
995
996       picojson::array* array = static_cast<picojson::array*>(user_data);
997       array->push_back(picojson::value(picojson::object()));
998
999       utils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
1000
1001       return 0;
1002     };
1003
1004     int ret = pkgmgrinfo_appinfo_get_usr_installed_list(app_info_cb, getuid(), &array);
1005
1006     if (APP_MANAGER_ERROR_NONE != ret) {
1007       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj,
1008                         ("pkgmgrinfo_appinfo_get_usr_installed_list error"));
1009     } else {
1010       ReportSuccess(result, response_obj);
1011     }
1012   };
1013
1014   auto get_apps_info_response =
1015       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1016     ScopeLogger("Entered into asynchronous function, get_apps_info_response");
1017     picojson::object& obj = response->get<picojson::object>();
1018     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1019     Instance::PostMessage(&this->instance_, response->serialize().c_str());
1020   };
1021
1022   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1023
1024   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_info, get_apps_info_response, data);
1025 }
1026
1027 void ApplicationManager::GetAppInfo(const std::string& app_id, picojson::object* out) {
1028   ScopeLogger();
1029
1030   pkgmgrinfo_appinfo_h handle = nullptr;
1031
1032   if (PMINFO_R_OK != pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1033     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out);
1034     return;
1035   }
1036
1037   picojson::value result = picojson::value(picojson::object());
1038   utils::CreateApplicationInformation(handle, &result.get<picojson::object>());
1039   pkgmgrinfo_appinfo_destroy_appinfo(handle);
1040
1041   ReportSuccess(result, *out);
1042 }
1043
1044 char* ApplicationManager::GetPackageId(const std::string& app_id) {
1045   ScopeLogger();
1046   app_info_h handle;
1047   char* pkg_id = nullptr;
1048
1049   int ret = app_manager_get_app_info(app_id.c_str(), &handle);
1050   if (APP_MANAGER_ERROR_NONE != ret) {
1051     LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
1052     return nullptr;
1053   }
1054
1055   ret = app_info_get_package(handle, &pkg_id);
1056   if (APP_MANAGER_ERROR_NONE != ret) {
1057     LoggerE("Failed to get package id: %d (%s)", ret, get_error_message(ret));
1058     pkg_id = nullptr;
1059   }
1060
1061   ret = app_info_destroy(handle);
1062   if (APP_MANAGER_ERROR_NONE != ret) {
1063     LoggerE("Failed to destroy app info: %d (%s)", ret, get_error_message(ret));
1064   }
1065
1066   return pkg_id;
1067 }
1068
1069 void ApplicationManager::GetAppCerts(const std::string& app_id, picojson::object* out) {
1070   ScopeLogger();
1071
1072   char* package_id = nullptr;
1073
1074   package_id = GetPackageId(app_id);
1075   // automatically release the memory
1076   std::unique_ptr<char, void (*)(void*)> package_id_ptr(package_id, &std::free);
1077
1078   if (!package_id) {
1079     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
1080     return;
1081   }
1082
1083   package_info_h pkg_info = nullptr;
1084   int ret = package_info_create(package_id, &pkg_info);
1085
1086   std::unique_ptr<std::remove_pointer<package_info_h>::type, int (*)(package_info_h)> pkg_info_ptr(
1087       pkg_info, &package_info_destroy);  // automatically release the memory
1088
1089   if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1090     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get package info."), out,
1091                       ("Failed to get package info: %d (%s)", ret, get_error_message(ret)));
1092     return;
1093   }
1094
1095   auto cert_info_cb = [](package_info_h handle, package_cert_type_e cert_type,
1096                          const char* cert_value, void* user_data) -> bool {
1097     const char* cert_name = nullptr;
1098
1099     switch (cert_type) {
1100       case PACKAGE_INFO_AUTHOR_ROOT_CERT:
1101         cert_name = "AUTHOR_ROOT";
1102         break;
1103       case PACKAGE_INFO_AUTHOR_INTERMEDIATE_CERT:
1104         cert_name = "AUTHOR_INTERMEDIATE";
1105         break;
1106       case PACKAGE_INFO_AUTHOR_SIGNER_CERT:
1107         cert_name = "AUTHOR_SIGNER";
1108         break;
1109       case PACKAGE_INFO_DISTRIBUTOR_ROOT_CERT:
1110         cert_name = "DISTRIBUTOR_ROOT";
1111         break;
1112       case PACKAGE_INFO_DISTRIBUTOR_INTERMEDIATE_CERT:
1113         cert_name = "DISTRIBUTOR_INTERMEDIATE";
1114         break;
1115       case PACKAGE_INFO_DISTRIBUTOR_SIGNER_CERT:
1116         cert_name = "DISTRIBUTOR_SIGNER";
1117         break;
1118       case PACKAGE_INFO_DISTRIBUTOR2_ROOT_CERT:
1119         cert_name = "DISTRIBUTOR2_ROOT";
1120         break;
1121       case PACKAGE_INFO_DISTRIBUTOR2_INTERMEDIATE_CERT:
1122         cert_name = "DISTRIBUTOR2_INTERMEDIATE";
1123         break;
1124       case PACKAGE_INFO_DISTRIBUTOR2_SIGNER_CERT:
1125         cert_name = "DISTRIBUTOR2_SIGNER";
1126         break;
1127       default:
1128         LoggerD("Unknown certificate type: %d", cert_type);
1129         break;
1130     }
1131
1132     picojson::array* array = static_cast<picojson::array*>(user_data);
1133     array->push_back(picojson::value(picojson::object()));
1134
1135     utils::CreateApplicationCertificate(cert_name, cert_value,
1136                                         &array->back().get<picojson::object>());
1137
1138     return true;
1139   };
1140
1141   picojson::value result = picojson::value(picojson::array());
1142
1143   ret = package_info_foreach_cert_info(pkg_info, cert_info_cb, &result.get<picojson::array>());
1144
1145   if ((PACKAGE_MANAGER_ERROR_NONE != ret) && (PACKAGE_MANAGER_ERROR_IO_ERROR != ret)) {
1146     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificates info."),
1147                       out,
1148                       ("Failed to get certificates info: %d (%s)", ret, get_error_message(ret)));
1149     return;
1150   }
1151
1152   ReportSuccess(result, *out);
1153 }
1154
1155 void ApplicationManager::GetAppSharedUri(const std::string& app_id, picojson::object* out) {
1156   ScopeLogger();
1157   // this implementation assumes that shared/trusted path is the obligatory member of application
1158   // and it is used to extract the parent directory 'shared'
1159   char* path = nullptr;
1160   int ret = app_manager_get_shared_trusted_path(app_id.c_str(), &path);
1161   if (APP_MANAGER_ERROR_NONE != ret) {
1162     // if the application does not exist, there is no need to check "res" directory
1163     if (APP_MANAGER_ERROR_NO_SUCH_APP == ret) {
1164       LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get shared URI."), out);
1165       return;
1166     }
1167
1168     // if the shared_trusted directory is not properly returned, gathering the shared/res path,
1169     // which is the obligatory member. The global path could be different then:
1170     // e.g. instead of path: /opt/usr/home/owner/apps_rw/org.example.basic/shared/
1171     // returned path is:     /opt/usr/globalapps/org.example.basic/shared/
1172     LoggerW(
1173         "app_manager_get_shared_trusted_path failed(), trying "
1174         "app_manager_get_shared_resource_path() to gather path");
1175     int ret = app_manager_get_shared_resource_path(app_id.c_str(), &path);
1176     if (APP_MANAGER_ERROR_NONE != ret) {
1177       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get shared URI."), out);
1178       return;
1179     }
1180   }
1181
1182   std::string path_str = path;
1183   free(path);
1184
1185   std::string shared_path = path_str.substr(0, path_str.rfind("/", path_str.length() - 2));
1186
1187   // checking if path is valid
1188   struct stat stat_res;
1189   if (0 != stat(shared_path.c_str(), &stat_res)) {
1190     LoggerW("Path %s does not exist", shared_path.c_str());
1191     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get shared URI."), out);
1192     return;
1193   }
1194
1195   picojson::value result = picojson::value(kTizenApisFileScheme + shared_path);
1196   ReportSuccess(result, *out);
1197 }
1198
1199 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1200 PlatformResult ApplicationManager::BatteryUsageFilter(const picojson::value& args,
1201                                                       const context_history_filter_h filter,
1202                                                       context_history_data_e* data_type_out) {
1203   ScopeLogger();
1204   int ret = CONTEXT_HISTORY_ERROR_NONE;
1205   int limit = kMaximumBatteryRetrievedObjects;
1206   if (args.contains("limit")) {
1207     limit = static_cast<int>(args.get("limit").get<double>());
1208   }
1209
1210   ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1211
1212   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1213     return LogAndCreateResult(
1214         ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1215         ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1216   }
1217
1218   context_history_data_e data_type_in = CONTEXT_HISTORY_RECENT_BATTERY_USAGE;
1219
1220   if (args.contains("days")) {
1221     const int days = static_cast<int>(args.get("days").get<double>());
1222     data_type_in = CONTEXT_HISTORY_BATTERY_USAGE;
1223     ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, days);
1224
1225     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1226       return LogAndCreateResult(
1227           ErrorCode::INVALID_VALUES_ERR, "days given with invalid value.",
1228           ("days given with invalid value: %d (%s)", ret, get_error_message(ret)));
1229     }
1230   }
1231
1232   *data_type_out = data_type_in;
1233
1234   return PlatformResult(ErrorCode::NO_ERROR);
1235 }
1236
1237 PlatformResult ApplicationManager::BatteryUsageAttributes(const context_history_record_h record,
1238                                                           picojson::object* object) {
1239   ScopeLogger();
1240
1241   int ret = CONTEXT_HISTORY_ERROR_NONE;
1242   double amount = 0.0;
1243   char* app_id = nullptr;
1244   SCOPE_EXIT {
1245     free(app_id);
1246   };
1247
1248   ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1249   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1250     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1251                               ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1252   }
1253
1254   ret = context_history_record_get_double(record, CONTEXT_HISTORY_TOTAL_AMOUNT, &amount);
1255   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1256     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get amount.",
1257                               ("Failed to get amount: %d (%s)", ret, get_error_message(ret)));
1258   }
1259
1260   object->insert(std::make_pair("appId", picojson::value(app_id)));
1261   object->insert(std::make_pair("batteryUsage", picojson::value(amount)));
1262
1263   return PlatformResult(ErrorCode::NO_ERROR);
1264 }
1265
1266 PlatformResult ApplicationManager::AppsUsageFilter(const picojson::value& args,
1267                                                    const context_history_filter_h filter,
1268                                                    context_history_data_e* data_type_out) {
1269   ScopeLogger();
1270   int ret = CONTEXT_HISTORY_ERROR_NONE;
1271   int limit = kMaximumAppsRetrievedObjects;
1272   if (args.contains("limit")) {
1273     limit = static_cast<int>(args.get("limit").get<double>());
1274   }
1275
1276   ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
1277   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1278     return LogAndCreateResult(
1279         ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
1280         ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
1281   }
1282
1283   context_history_data_e data_type_in = CONTEXT_HISTORY_FREQUENTLY_USED_APP;
1284   if (args.contains("mode") && kAppUsageModeRecently == args.get("mode").get<std::string>()) {
1285     data_type_in = CONTEXT_HISTORY_RECENTLY_USED_APP;
1286   }
1287
1288   int time_span = kDefaultPeriodOfTime;
1289   const picojson::object& JS_filter = args.get("filter").get<picojson::object>();
1290   auto time_span_iter = JS_filter.find("timeSpan");
1291   if (JS_filter.end() != time_span_iter || (JS_filter.end() == JS_filter.find("startTime") &&
1292                                             JS_filter.end() == JS_filter.find("endTime"))) {
1293     // In the second case, we treat the filter object just like an empty object.
1294     // The default value of filter will be used instead.
1295     if (JS_filter.end() != time_span_iter) {
1296       time_span = static_cast<int>(time_span_iter->second.get<double>());
1297     }
1298     ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, time_span);
1299     // context_history_filter_set_int may return only success or
1300     // CONTEXT_HISTORY_ERROR_INVALID_PARAMETER
1301     // Although this should never happen, it's better to check ret's value
1302     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1303       return LogAndCreateResult(ErrorCode::ABORT_ERR,
1304                                 "Error while setting the default TIME_SPAN value.",
1305                                 ("Error while setting the default TIME_SPAN value: %d (%s)", ret,
1306                                  get_error_message(ret)));
1307     }
1308   } else {
1309     auto start_time_iter = JS_filter.find("startTime");
1310     auto end_time_iter = JS_filter.find("endTime");
1311     if (start_time_iter != JS_filter.end()) {
1312       int start_time = static_cast<int>(start_time_iter->second.get<double>());
1313       ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_START_TIME, start_time);
1314       if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1315         return LogAndCreateResult(
1316             ErrorCode::INVALID_VALUES_ERR, "startTime given with invalid value.",
1317             ("startTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1318       }
1319     }
1320     if (end_time_iter != JS_filter.end()) {
1321       int end_time = static_cast<int>(end_time_iter->second.get<double>());
1322       ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_END_TIME, end_time);
1323       if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1324         return LogAndCreateResult(
1325             ErrorCode::INVALID_VALUES_ERR, "endTime given with invalid value.",
1326             ("endTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
1327       }
1328     }
1329   }
1330
1331   *data_type_out = data_type_in;
1332
1333   return PlatformResult(ErrorCode::NO_ERROR);
1334 }
1335
1336 PlatformResult ApplicationManager::AppsUsageAttributes(const context_history_record_h record,
1337                                                        picojson::object* object) {
1338   ScopeLogger();
1339
1340   int ret = CONTEXT_HISTORY_ERROR_NONE;
1341   int total_count = 0;
1342   int total_duration = 0;
1343   int last_time = 0;
1344   char* app_id = nullptr;
1345   SCOPE_EXIT {
1346     free(app_id);
1347   };
1348
1349   ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
1350   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1351     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
1352                               ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
1353   }
1354
1355   ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_COUNT, &total_count);
1356   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1357     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get total count.",
1358                               ("Failed to get total count: %d (%s)", ret, get_error_message(ret)));
1359   }
1360
1361   ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_DURATION, &total_duration);
1362   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1363     return LogAndCreateResult(
1364         ErrorCode::ABORT_ERR, "Failed to get total duration.",
1365         ("Failed to get total duration: %d (%s)", ret, get_error_message(ret)));
1366   }
1367
1368   ret = context_history_record_get_int(record, CONTEXT_HISTORY_LAST_TIME, &last_time);
1369   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
1370     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get last time.",
1371                               ("Failed to get last time: %d (%s)", ret, get_error_message(ret)));
1372   }
1373
1374   object->insert(std::make_pair("appId", picojson::value(app_id)));
1375   object->insert(std::make_pair("totalCount", picojson::value(static_cast<double>(total_count))));
1376   object->insert(
1377       std::make_pair("totalDuration", picojson::value(static_cast<double>(total_duration))));
1378   object->insert(std::make_pair("lastTime", picojson::value(static_cast<double>(last_time))));
1379
1380   return PlatformResult(ErrorCode::NO_ERROR);
1381 }
1382 #endif
1383
1384 void ApplicationManager::GetBatteryUsageInfo(const picojson::value& args, picojson::object* out) {
1385   ScopeLogger();
1386
1387 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1388   int callback_id = -1;
1389   const auto& callback = args.get(kCallbackId);
1390   if (callback.is<double>()) {
1391     callback_id = static_cast<int>(callback.get<double>());
1392   }
1393
1394   auto get_battery_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1395     ScopeLogger();
1396     PlatformResult result = ApplicationManager::GetContextHistory(
1397         args, &response.get()->get<picojson::object>(), &ApplicationManager::BatteryUsageFilter,
1398         &ApplicationManager::BatteryUsageAttributes);
1399     if (!result) {
1400       LogAndReportError(result, &response.get()->get<picojson::object>());
1401     }
1402   };
1403
1404   auto get_battery_usage_response =
1405       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1406     ScopeLogger();
1407     picojson::object& obj = response->get<picojson::object>();
1408     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1409     Instance::PostMessage(&this->instance_, response->serialize().c_str());
1410   };
1411
1412   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1413
1414   TaskQueue::GetInstance().Queue<picojson::value>(get_battery_usage, get_battery_usage_response,
1415                                                   data);
1416 #else
1417   LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
1418                                    "This feature is not supported on this profile."),
1419                     out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1420 #endif
1421 }
1422
1423 void ApplicationManager::GetAppsUsageInfo(const picojson::value& args, picojson::object* out) {
1424   ScopeLogger();
1425
1426 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1427   int callback_id = static_cast<int>(args.get(kCallbackId).get<double>());
1428
1429   auto get_apps_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
1430     ScopeLogger();
1431     PlatformResult result = ApplicationManager::GetContextHistory(
1432         args, &response.get()->get<picojson::object>(), &ApplicationManager::AppsUsageFilter,
1433         &ApplicationManager::AppsUsageAttributes);
1434     if (!result) {
1435       LogAndReportError(result, &response.get()->get<picojson::object>());
1436     }
1437   };
1438
1439   auto get_apps_usage_response =
1440       [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
1441     ScopeLogger();
1442     picojson::object& obj = response->get<picojson::object>();
1443     obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
1444     Instance::PostMessage(&this->instance_, response->serialize().c_str());
1445   };
1446
1447   auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1448
1449   TaskQueue::GetInstance().Queue<picojson::value>(get_apps_usage, get_apps_usage_response, data);
1450 #else
1451   LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
1452                                    "This feature is not supported on this profile."),
1453                     out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
1454 #endif
1455 }
1456
1457 void ApplicationManager::GetAppMetaData(const std::string& app_id, picojson::object* out) {
1458   ScopeLogger();
1459
1460   pkgmgrinfo_appinfo_h handle = nullptr;
1461
1462   int ret = pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle);
1463   std::unique_ptr<std::remove_pointer<pkgmgrinfo_appinfo_h>::type, int (*)(pkgmgrinfo_appinfo_h)>
1464       pkg_info_ptr(handle,
1465                    &pkgmgrinfo_appinfo_destroy_appinfo);  // automatically release the memory
1466
1467   if (PMINFO_R_OK != ret) {
1468     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out,
1469                       ("Failed to get app info: %d (%s)", ret, get_error_message(ret)));
1470     return;
1471   }
1472
1473   auto meta_data_cb = [](const char* meta_key, const char* meta_value, void* user_data) -> int {
1474     if (nullptr == meta_key || nullptr == meta_value) {
1475       LoggerE("meta_key or meta_value is null");
1476       return 0;
1477     }
1478
1479     picojson::array* array = static_cast<picojson::array*>(user_data);
1480     array->push_back(picojson::value(picojson::object()));
1481
1482     utils::CreateApplicationMetaData(meta_key, meta_value, &array->back().get<picojson::object>());
1483     return 0;
1484   };
1485
1486   picojson::value result = picojson::value(picojson::array());
1487   ret = pkgmgrinfo_appinfo_foreach_metadata(handle, meta_data_cb, &result.get<picojson::array>());
1488
1489   if (PMINFO_R_OK != ret) {
1490     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get metadata."), out,
1491                       ("Failed to get metadata: %d (%s)", ret, get_error_message(ret)));
1492     return;
1493   }
1494
1495   ReportSuccess(result, *out);
1496 }
1497
1498 class ApplicationListChangedBroker {
1499  public:
1500   ApplicationListChangedBroker() : event_type_() {
1501   }
1502   enum class Event {
1503     kInstalled,
1504     kUpdated,
1505     kUninstalled,
1506   };
1507
1508   static int ClientStatusListener(unsigned int target_uid, int id, const char* type,
1509                                   const char* package, const char* key, const char* val,
1510                                   const void* msg, void* data) {
1511     ScopeLogger();
1512     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1513
1514     if (0 == strcasecmp(key, kStartKey)) {
1515       that->HandleStart(val, package);
1516     } else if (0 == strcasecmp(key, kEndKey) && 0 == strcasecmp(val, kOkValue)) {
1517       that->HandleEnd(package);
1518     } else {
1519       LoggerD("Ignored key: %s", key);
1520     }
1521
1522     return 0;
1523   }
1524
1525   static int AppUninstallListener(uid_t target_uid, int id, const char* type, const char* package,
1526                                   const char* key, const char* val, const void* msg, void* data) {
1527     ScopeLogger();
1528
1529     ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
1530
1531     if (0 == strcasecmp(key, kStartKey)) {
1532       that->HandleUninstallStart();
1533     } else if (0 == strcasecmp(key, kAppidKey)) {
1534       that->AddUninstalledAppId(val);
1535     } else if (0 == strcasecmp(key, kEndKey)) {
1536       that->HandleUninstallEnd();
1537     } else {
1538       LoggerD("Ignored key: %s", key);
1539     }
1540
1541     return 0;
1542   }
1543
1544   void AddApplicationInstance(ApplicationInstance* app_instance) {
1545     ScopeLogger();
1546     app_instance_list_.push_back(app_instance);
1547   }
1548
1549   void RemoveApplicationInstance(ApplicationInstance* app_instance) {
1550     ScopeLogger();
1551     for (auto it = app_instance_list_.begin(); it != app_instance_list_.end(); it++) {
1552       if (*it == app_instance) {
1553         app_instance_list_.erase(it);
1554         return;
1555       }
1556     }
1557   }
1558
1559  private:
1560   void HandleStart(const char* event_type, const char* package) {
1561     ScopeLogger();
1562     app_list_.clear();
1563     set_event_type(event_type);
1564   }
1565
1566   void HandleEnd(const char* package) {
1567     ScopeLogger();
1568
1569     if (Event::kUninstalled == event_type_) {
1570       return;
1571     }
1572
1573     GetApplicationIdsFromPackage(package);
1574
1575     for (auto& app_id : app_list_) {
1576       picojson::value value = picojson::value(picojson::object());
1577       picojson::object& data_obj = value.get<picojson::object>();
1578
1579       switch (event_type_) {
1580         case Event::kInstalled:
1581           data_obj.insert(std::make_pair(kAction, picojson::value(kOnInstalled)));
1582           break;
1583
1584         case Event::kUpdated:
1585           data_obj.insert(std::make_pair(kAction, picojson::value(kOnUpdated)));
1586           break;
1587         case Event::kUninstalled:
1588           LoggerD("Uninstalled called");
1589           break;
1590       }
1591
1592       switch (event_type_) {
1593         case Event::kInstalled:
1594         case Event::kUpdated: {
1595           pkgmgrinfo_appinfo_h handle = nullptr;
1596           if (PMINFO_R_OK !=
1597               pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), getuid(), &handle)) {
1598             LoggerE("Failed to get application information handle.");
1599             continue;
1600           }
1601           auto info = data_obj.insert(std::make_pair(kData, picojson::value(picojson::object())));
1602           utils::CreateApplicationInformation(handle, &info.first->second.get<picojson::object>());
1603           pkgmgrinfo_appinfo_destroy_appinfo(handle);
1604         } break;
1605         case Event::kUninstalled:
1606           LoggerD("Uninstalled called");
1607           break;
1608       }
1609
1610       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1611
1612       for (auto instance : app_instance_list_) {
1613         Instance::PostMessage(instance, value.serialize().c_str());
1614       }
1615     }
1616   }
1617
1618   void GetApplicationIdsFromPackage(const char* package) {
1619     ScopeLogger();
1620     package_info_h package_info = nullptr;
1621
1622     int ret = package_info_create(package, &package_info);
1623     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1624       LoggerE("Failed to create package info: %d (%s)", ret, get_error_message(ret));
1625       return;
1626     }
1627
1628     ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_APP_COMPONENT_TYPE_ALL,
1629                                                 ApplicationIdCallback, this);
1630     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1631       LoggerE("Failed to get application IDs: %d (%s)", ret, get_error_message(ret));
1632     }
1633
1634     ret = package_info_destroy(package_info);
1635     if (PACKAGE_MANAGER_ERROR_NONE != ret) {
1636       LoggerE("Failed to destroy package info: %d (%s)", ret, get_error_message(ret));
1637     }
1638   }
1639
1640   void set_event_type(const char* type) {
1641     ScopeLogger();
1642     if (0 == strcasecmp(type, kInstallEvent)) {
1643       event_type_ = Event::kInstalled;
1644     } else if (0 == strcasecmp(type, kUpdateEvent)) {
1645       event_type_ = Event::kUpdated;
1646     } else if (0 == strcasecmp(type, kUninstallEvent)) {
1647       event_type_ = Event::kUninstalled;
1648     }
1649   }
1650
1651   static bool ApplicationIdCallback(package_info_app_component_type_e comp_type, const char* app_id,
1652                                     void* user_data) {
1653     ScopeLogger();
1654     if (nullptr != app_id) {
1655       static_cast<ApplicationListChangedBroker*>(user_data)->app_list_.push_back(app_id);
1656     }
1657     return true;
1658   }
1659
1660   void HandleUninstallStart() {
1661     ScopeLogger();
1662     app_list_.clear();
1663     set_event_type(kUninstallEvent);
1664   }
1665
1666   void AddUninstalledAppId(const char* app_id) {
1667     ScopeLogger();
1668     if (nullptr != app_id) {
1669       app_list_.push_back(app_id);
1670     }
1671   }
1672
1673   void HandleUninstallEnd() {
1674     ScopeLogger();
1675     for (auto& app_id : app_list_) {
1676       picojson::value value = picojson::value(picojson::object());
1677       picojson::object& data_obj = value.get<picojson::object>();
1678
1679       data_obj.insert(std::make_pair(kAction, picojson::value(kOnUninstalled)));
1680       data_obj.insert(std::make_pair(kData, picojson::value(app_id)));
1681
1682       data_obj["listenerId"] = picojson::value("ApplicationEventListener");
1683
1684       for (auto instance : app_instance_list_) {
1685         Instance::PostMessage(instance, value.serialize().c_str());
1686       }
1687     }
1688   }
1689
1690   Event event_type_;
1691   std::vector<std::string> app_list_;
1692   std::vector<ApplicationInstance*> app_instance_list_;
1693 };
1694
1695 static ApplicationListChangedBroker g_application_list_changed_broker;
1696
1697 void ApplicationManager::StartAppInfoEventListener(picojson::object* out) {
1698   ScopeLogger();
1699
1700   if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgr_client_uninstall_handle_) {
1701     if (nullptr == pkgmgr_client_handle_) {
1702       pkgmgr_client_handle_ = pkgmgr_client_new(PC_LISTENING);
1703     }
1704     if (nullptr == pkgmgr_client_uninstall_handle_) {
1705       pkgmgr_client_uninstall_handle_ = pkgmgr_client_new(PC_LISTENING);
1706     }
1707
1708     if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgr_client_uninstall_handle_) {
1709       if (nullptr != pkgmgr_client_handle_) {
1710         pkgmgr_client_free(pkgmgr_client_handle_);
1711         pkgmgr_client_handle_ = nullptr;
1712       }
1713       if (nullptr != pkgmgr_client_uninstall_handle_) {
1714         pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1715         pkgmgr_client_uninstall_handle_ = nullptr;
1716       }
1717       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."),
1718                         out);
1719       return;
1720     }
1721
1722 #define CHECK_APPLICATION_EVENT_ERROR(result, function_name)                                \
1723   if (PKGMGR_R_OK > result) {                                                               \
1724     StopAppInfoEventListener();                                                             \
1725     LogAndReportError(                                                                      \
1726         PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."), out,        \
1727         ("Function %s failed: %s (%d)", function_name, get_error_message(result), result)); \
1728     return;                                                                                 \
1729   }
1730
1731     g_application_list_changed_broker.AddApplicationInstance(&instance_);
1732
1733     int result = pkgmgr_client_set_status_type(
1734         pkgmgr_client_handle_,
1735         PACKAGE_MANAGER_STATUS_TYPE_INSTALL | PACKAGE_MANAGER_STATUS_TYPE_UPGRADE);
1736     CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_set_status_type")
1737
1738     result = pkgmgr_client_set_status_type(pkgmgr_client_uninstall_handle_,
1739                                            PACKAGE_MANAGER_STATUS_TYPE_UNINSTALL);
1740     CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_set_status_type")
1741
1742     result = pkgmgr_client_listen_status(pkgmgr_client_handle_,
1743                                          ApplicationListChangedBroker::ClientStatusListener,
1744                                          &g_application_list_changed_broker);
1745     CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_listen_status")
1746
1747     result = pkgmgr_client_listen_status(pkgmgr_client_uninstall_handle_,
1748                                          ApplicationListChangedBroker::AppUninstallListener,
1749                                          &g_application_list_changed_broker);
1750     CHECK_APPLICATION_EVENT_ERROR(result, "pkgmgr_client_listen_status")
1751
1752 #undef CHECK_APPLICATION_EVENT_ERROR
1753   } else {
1754     LoggerD("Broker callback is already registered.");
1755   }
1756
1757   ReportSuccess(*out);
1758 }
1759
1760 void ApplicationManager::StopAppInfoEventListener() {
1761   ScopeLogger();
1762
1763   if (nullptr != pkgmgr_client_handle_ || nullptr != pkgmgr_client_uninstall_handle_) {
1764     if (nullptr != pkgmgr_client_handle_) {
1765       pkgmgr_client_free(pkgmgr_client_handle_);
1766       pkgmgr_client_handle_ = nullptr;
1767     }
1768     if (nullptr != pkgmgr_client_uninstall_handle_) {
1769       pkgmgr_client_free(pkgmgr_client_uninstall_handle_);
1770       pkgmgr_client_uninstall_handle_ = nullptr;
1771     }
1772     g_application_list_changed_broker.RemoveApplicationInstance(&instance_);
1773   } else {
1774     LoggerD("Broker callback is already unregistered.");
1775   }
1776 }
1777
1778 void ApplicationManager::GetApplicationInformationSize(const picojson::value& args,
1779                                                        picojson::object* out) {
1780   ScopeLogger();
1781
1782   const auto& package_id = args.get("packageId");
1783   if (!package_id.is<std::string>()) {
1784     LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
1785                       out);
1786     return;
1787   }
1788
1789   const std::string& package_id_str = package_id.get<std::string>();
1790
1791   // get installed size from package server (to solve smack issue)
1792   pkgmgr_client* pc = pkgmgr_client_new(PC_REQUEST);
1793   int size = -1;
1794
1795   if (nullptr == pc) {
1796     LoggerE("Failed to create pkgmgr client");
1797   } else {
1798     size = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, PM_GET_TOTAL_SIZE, pc, NULL,
1799                                          package_id_str.c_str(), NULL, NULL, NULL);
1800
1801     if (size < 0) {
1802       LoggerE("Failed to get installed size: %d (%s)", size, get_error_message(size));
1803     }
1804
1805     pkgmgr_client_free(pc);
1806   }
1807
1808   picojson::value result = picojson::value(picojson::object());
1809   picojson::object& result_obj = result.get<picojson::object>();
1810   result_obj.insert(std::make_pair("size", picojson::value(static_cast<double>(size))));
1811
1812   ReportSuccess(result, *out);
1813 }
1814
1815 void ApplicationManager::BroadcastEventHelper(const picojson::value& args, picojson::object& out,
1816                                               bool trusted) {
1817   ScopeLogger();
1818
1819   int ret;
1820   std::string event_str = args.get("name").get<std::string>();
1821   const char* event_name = event_str.c_str();
1822
1823   bundle* data = bundle_create();
1824   SCOPE_EXIT {
1825     bundle_free(data);
1826   };
1827
1828   ret = bundle_add(data, "data", args.get("data").serialize().c_str());
1829
1830   if (ret != EVENT_ERROR_NONE) {
1831     LoggerE("bundle_add failed, error: %d (%s)", ret, get_error_message(ret));
1832     ReportError(out);
1833     return;
1834   }
1835
1836   if (trusted) {
1837     ret = event_publish_trusted_app_event(event_name, data);
1838   } else {
1839     ret = event_publish_app_event(event_name, data);
1840   }
1841
1842   if (ret == EVENT_ERROR_NONE) {
1843     ReportSuccess(out);
1844   } else {
1845     LoggerE("event_publish_app_event failed, error: %d (%s)", ret, get_error_message(ret));
1846     ReportError(out);
1847   }
1848 }
1849
1850 void ApplicationManager::OnEvent(const char* event_name, bundle* event_data, void* user_data) {
1851   ScopeLogger("Event name is: '%s'", event_name);
1852
1853   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1854
1855   if (!manager->event_callback_) {
1856     LoggerD("No event listener registered, skipping.");
1857     return;
1858   }
1859
1860   picojson::value event = picojson::value(picojson::object());
1861   picojson::object& event_o = event.get<picojson::object>();
1862
1863   int ret;
1864   char* val = nullptr;
1865
1866   if (event_map_.count(event_name)) {  // system event
1867     const std::string& key = event_map_.at(event_name);
1868     std::string state = "true";
1869     if (key != "") {
1870       ret = bundle_get_str(event_data, key.c_str(), &val);
1871       if (EVENT_ERROR_NONE != ret) {
1872         LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
1873         return;
1874       }
1875
1876       state = std::string(val);
1877     }
1878
1879     LoggerD("State is %s", state.c_str());
1880     event_o["value"] = picojson::value(state);
1881
1882   } else {  // user event
1883     ret = bundle_get_str(event_data, "data", &val);
1884     if (EVENT_ERROR_NONE != ret) {
1885       LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
1886       return;
1887     }
1888
1889     picojson::value data;
1890     std::string err;
1891     picojson::parse(data, val, val + strlen(val), &err);
1892     if (!err.empty()) {
1893       LoggerE("Failed to parse bundle data: %s", err.c_str());
1894       return;
1895     }
1896
1897     event_o["data"] = data;
1898   }
1899
1900   LoggerD("event_name is: %s", event_name);
1901   event_o["name"] = picojson::value(event_name);
1902
1903   manager->event_callback_(&event);
1904 }
1905
1906 PlatformResult ApplicationManager::StartEventListener(const std::string& event_name,
1907                                                       const JsonCallback& callback) {
1908   ScopeLogger();
1909
1910   int ret;
1911   event_handler_h event_handler;
1912
1913   ret = event_add_event_handler(event_name.c_str(), OnEvent, this, &event_handler);
1914   LoggerD("event_add_event_handler() result: %d (%s)", ret, get_error_message(ret));
1915   if (EVENT_ERROR_PERMISSION_DENIED == ret) {
1916     return LogAndCreateResult(ErrorCode::SECURITY_ERR, "The privilege is required",
1917                               ("event_add_event_handler failed, error: %d", ret));
1918   } else if (EVENT_ERROR_NONE != ret) {
1919     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error setting event listener",
1920                               ("event_add_event_handler failed, error: %d", ret));
1921   }
1922
1923   event_handler_map_[event_name] = event_handler;
1924
1925   event_callback_ = callback;
1926   LoggerD("event_add_event_handler success");
1927   return PlatformResult(ErrorCode::NO_ERROR);
1928 }
1929
1930 void ApplicationManager::StopEventListener(const std::string& event_name) {
1931   ScopeLogger();
1932
1933   int ret;
1934   event_handler_h event_handler;
1935
1936   if (event_handler_map_.find(event_name) != event_handler_map_.end()) {
1937     event_handler = event_handler_map_[event_name];
1938
1939     ret = event_remove_event_handler(event_handler);
1940     if (EVENT_ERROR_NONE != ret) {
1941       LoggerE("event_remove_event_handler failed, error: %d (%s)", ret, get_error_message(ret));
1942       return;
1943     }
1944
1945     event_handler_map_.erase(event_name);
1946   }
1947 }
1948
1949 void ApplicationManager::OnStatusEvent(const char* type, const char* app_id,
1950                                        app_manager_event_type_e event_type,
1951                                        app_manager_event_state_e event_state,
1952                                        app_manager_event_h handle, void* user_data) {
1953   ScopeLogger();
1954
1955   if (APP_MANAGER_EVENT_STATE_COMPLETED != event_state) {
1956     LoggerD("State different from completed");
1957     return;
1958   }
1959
1960   ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
1961
1962   if (!manager || !manager->status_callback_) {
1963     LoggerD("No event listener registered, skipping.");
1964     return;
1965   }
1966
1967   bool status_type;
1968   switch (event_type) {
1969     case APP_MANAGER_EVENT_ENABLE_APP:
1970       status_type = true;
1971       break;
1972     case APP_MANAGER_EVENT_DISABLE_APP:
1973       status_type = false;
1974       break;
1975     default:
1976       LoggerD("Uknown status type skipping.");
1977       return;
1978   }
1979
1980   picojson::value event = picojson::value(picojson::object());
1981   picojson::object& event_o = event.get<picojson::object>();
1982
1983   event_o[kStatusType] = picojson::value(status_type);
1984   event_o[kAppId] = picojson::value(app_id);
1985   event_o[kListenerId] = picojson::value(kAppStatusChangeListener);
1986
1987   manager->status_callback_(&event);
1988 }
1989
1990 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
1991 PlatformResult ApplicationManager::GetContextHistory(
1992     const picojson::value& args, picojson::object* out,
1993     common::PlatformResult (*modify_filter_cb)(const picojson::value&,
1994                                                const context_history_filter_h,
1995                                                context_history_data_e* data_type),
1996     common::PlatformResult (*add_attributes_to_object)(const context_history_record_h,
1997                                                        picojson::object*)) {
1998   ScopeLogger();
1999   context_history_list_h list = nullptr;
2000   context_history_h handle = nullptr;
2001   context_history_filter_h filter = nullptr;
2002
2003   SCOPE_EXIT {
2004     context_history_list_destroy(list);
2005     context_history_destroy(handle);
2006     context_history_filter_destroy(filter);
2007   };
2008
2009   int ret = context_history_create(&handle);
2010   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2011     return LogAndCreateResult(
2012         ErrorCode::ABORT_ERR, "Failed to create context handle.",
2013         ("Failed to create context handle: %d (%s)", ret, get_error_message(ret)));
2014   }
2015
2016   ret = context_history_filter_create(&filter);
2017   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2018     return LogAndCreateResult(
2019         ErrorCode::ABORT_ERR, "Failed to create filter handle.",
2020         ("Failed to create filter handle: %d (%s)", ret, get_error_message(ret)));
2021   }
2022
2023   context_history_data_e data_type;
2024
2025   PlatformResult result = modify_filter_cb(args, filter, &data_type);
2026   if (!result) {
2027     return result;
2028   }
2029
2030   picojson::value result_array = picojson::value(picojson::array());
2031   picojson::array& array_obj = result_array.get<picojson::array>();
2032
2033   ret = context_history_get_list(handle, data_type, filter, &list);
2034   if (CONTEXT_HISTORY_ERROR_NO_DATA == ret) {
2035     ReportSuccess(result_array, *out);
2036     return PlatformResult(ErrorCode::NO_ERROR);
2037   } else if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2038     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list.",
2039                               ("Failed to get list: %d (%s)", ret, get_error_message(ret)));
2040   }
2041
2042   int size = 0;
2043   ret = context_history_list_get_count(list, &size);
2044   if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2045     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list size.",
2046                               ("Failed to get list size: %d (%s)", ret, get_error_message(ret)));
2047   }
2048
2049   array_obj.resize(size, picojson::value(picojson::object()));
2050
2051   for (int i = 0; i < size; ++i) {
2052     context_history_record_h record = nullptr;
2053     SCOPE_EXIT {
2054       context_history_record_destroy(record);
2055     };
2056
2057     ret = context_history_list_get_current(list, &record);
2058     if (CONTEXT_HISTORY_ERROR_NONE != ret) {
2059       return LogAndCreateResult(
2060           ErrorCode::ABORT_ERR, "Failed to get current record.",
2061           ("Failed to get current record: %d (%s)", ret, get_error_message(ret)));
2062     }
2063
2064     result = add_attributes_to_object(record, &array_obj[i].get<picojson::object>());
2065     if (!result) {
2066       return result;
2067     }
2068
2069     ret = context_history_list_move_next(list);
2070     if (CONTEXT_HISTORY_ERROR_NONE != ret && CONTEXT_HISTORY_ERROR_NO_DATA != ret) {
2071       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to move iterator.",
2072                                 ("Failed to move iterator: %d (%s)", ret, get_error_message(ret)));
2073     }
2074   }
2075
2076   ReportSuccess(result_array, *out);
2077   return PlatformResult(ErrorCode::NO_ERROR);
2078 }
2079 #endif
2080
2081 PlatformResult ApplicationManager::StartStatusListener(const JsonCallback& callback) {
2082   ScopeLogger();
2083
2084   int ret = APP_MANAGER_ERROR_NONE;
2085
2086   if (!app_status_handle_) {
2087     ret = app_manager_event_create(&app_status_handle_);
2088     if (APP_MANAGER_ERROR_NONE != ret) {
2089       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while creating event handle",
2090                                 ("app_manager_event_create failed, error: %d", ret));
2091     }
2092
2093     ret = app_manager_event_set_status(app_status_handle_, APP_MANAGER_EVENT_STATUS_TYPE_ALL);
2094     if (APP_MANAGER_ERROR_NONE != ret) {
2095       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status type",
2096                                 ("app_manager_event_set_status failed, error: %d", ret));
2097     }
2098   }
2099
2100   status_callback_ = callback;
2101   ret = app_manager_set_event_cb(app_status_handle_, OnStatusEvent, this);
2102   if (APP_MANAGER_ERROR_NONE != ret) {
2103     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status listener",
2104                               ("app_manager_set_event_cb failed, error: %d", ret));
2105   }
2106
2107   return PlatformResult(ErrorCode::NO_ERROR);
2108 }
2109
2110 PlatformResult ApplicationManager::StopStatusChangeListener() {
2111   ScopeLogger();
2112
2113   if (app_status_handle_) {
2114     int ret = app_manager_unset_event_cb(app_status_handle_);
2115     if (APP_MANAGER_ERROR_NONE != ret) {
2116       return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while removing status listener",
2117                                 ("app_manager_unset_event_cb failed, error: %d", ret));
2118     }
2119   }
2120
2121   return PlatformResult(ErrorCode::NO_ERROR);
2122 }
2123
2124 }  // namespace application
2125 }  // namespace extension