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