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