Update change log and spec for wrt-plugins-tizen_0.4.70
[framework/web/wrt-plugins-tizen.git] / src / Application / AppManagerWrapper.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include "AppManagerWrapper.h"
19 #include <Commons/Exception.h>
20 #include <Commons/Regex.h>
21
22 // To get package id from appId
23 #include <package_manager.h>
24 #include <TimeTracer.h>
25
26 #include <Logger.h>
27
28 namespace DeviceAPI {
29 namespace Application {
30
31 using namespace std;
32 using namespace WrtDeviceApis::Commons;
33
34
35 AppManagerWrapper::AppManagerWrapper() :
36                 m_manager_handle(NULL),
37                 m_watchIdAcc(0)
38 {
39 }
40
41 AppManagerWrapper::~AppManagerWrapper()
42 {
43         if(m_manager_handle != NULL)
44         {
45                 unregisterAppListChangedCallbacks();
46         }
47 }
48
49 void AppManagerWrapper::setCurrentAppId(std::string appId)
50 {
51         m_curr_app_id = appId;
52 }
53
54 std::string AppManagerWrapper::getCurrentAppId() const
55 {
56         return m_curr_app_id;
57 }
58
59
60 void AppManagerWrapper::registerAppListChangedCallbacks(IAppManagerAppListChangedCallbacks *callbacks)
61 {
62         if(callbacks == NULL)
63         {
64                 LoggerE("callback cannot be set to NULL.");
65                 return;
66         }
67
68         if(!m_manager_handle)
69         {
70                 registerAppListChangedCallbacks();
71         }
72
73         m_callbacks.insert(callbacks);
74 }
75
76 void AppManagerWrapper::unregisterAppListChangedCallbacks(IAppManagerAppListChangedCallbacks *callbacks)
77 {
78         if(callbacks == NULL)
79         {
80                 LoggerE("callback cannot be set to NULL.");
81                 return;
82         }
83
84         if(m_callbacks.size() == 0)
85         {
86                 LoggerE("No callbacks are registered.");
87                 return;
88         }
89
90         AppListChangedCallbacksSet::iterator iter = m_callbacks.find(callbacks);
91         if(iter == m_callbacks.end())
92         {
93                 LoggerE("Callback " << callbacks << " is not registered.");
94                 return;
95         }
96
97         m_callbacks.erase(iter);
98
99         if(m_callbacks.size() == 0)
100         {
101                 unregisterAppListChangedCallbacks();
102         }
103 }
104
105
106 long AppManagerWrapper::getWatchIdAndInc()
107 {
108         return ++m_watchIdAcc;
109 }
110
111
112 bool AppManagerWrapper::app_callback(package_info_app_component_type_e comp_type, const char *app_id, void *user_data)
113 {
114         if(app_id == NULL) {
115                 LoggerE("Callback is called. but no package name is passed. skip this request");
116                 return true;
117         }
118
119         if(user_data == NULL) {
120                 LoggerE("user data is not exist. skip this request");
121                 return true;
122         }
123         
124         AppManagerWrapper *appManager = (AppManagerWrapper *)user_data;
125         appManager->applist.push_back(app_id);
126
127         return true;
128 }
129
130 void AppManagerWrapper::appListChangedCallback(app_manger_event_type_e event_type, const char *pkgId, void *user_data)
131 {
132         if(user_data == NULL) {
133                 LoggerE("user data is not exist. skip this request");
134                 return;
135         }
136
137         AppManagerWrapper *appManager = (AppManagerWrapper *)user_data;
138
139         if (event_type == APP_MANAGER_EVENT_UNINSTALLED) {
140                 for (size_t i = 0; i < appManager->applist.size(); i++) {
141                         appListAppUninstalled(appManager->applist.at(i).c_str());
142                 }
143         } else {
144                 package_info_h package_info;
145         
146                 int ret = package_manager_get_package_info(pkgId, &package_info);
147                 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
148                         LoggerE("Cannot create package info");
149                         return;
150                 }
151
152                 ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_ALLAPP, app_callback, user_data);
153                 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
154                         LoggerE("failed while getting appids");
155                         package_info_destroy(package_info);
156                         return;
157                 }
158
159                 ret = package_info_destroy(package_info);
160                 if (ret != PACKAGE_MANAGER_ERROR_NONE) {
161                         LoggerE("Cannot destroy package info");
162                 }
163
164                 for (size_t i = 0; i < appManager->applist.size(); i++) {
165                         switch(event_type)
166                         {
167                         case APP_MANAGER_EVENT_INSTALLED:
168                                 appListAppInstalled(appManager->applist.at(i).c_str());
169                                 break;
170                         case APP_MANAGER_EVENT_UPDATED:
171                                 appListAppUpdated(appManager->applist.at(i).c_str());
172                                 break;
173                         default:
174                                 LoggerE("app_manager listener gave wrong event_type : " << event_type);
175                                 break;
176                         }
177                 }
178         }
179
180         // clean-up applist
181         appManager->applist.clear();
182 }
183
184
185 void AppManagerWrapper::appListAppInstalled(const char *appId)
186 {
187         AppListChangedCallbacksSet::iterator iter = m_callbacks.begin();
188         for(; iter != m_callbacks.end(); iter++)
189         {
190                 (*iter)->onAppManagerEventInstalled(appId);
191         }
192 }
193
194 void AppManagerWrapper::appListAppUninstalled(const char *appId)
195 {
196         AppListChangedCallbacksSet::iterator iter = m_callbacks.begin();
197         for(; iter != m_callbacks.end(); iter++)
198         {
199                 (*iter)->onAppManagerEventUninstalled(appId);
200         }
201 }
202
203 void AppManagerWrapper::appListAppUpdated(const char *appId)    
204 {
205         AppListChangedCallbacksSet::iterator iter = m_callbacks.begin();
206         for(; iter != m_callbacks.end(); iter++)
207         {
208                 (*iter)->onAppManagerEventUpdated(appId);
209         }
210 }
211
212
213 int AppManagerWrapper::app_list_changed_cb_broker(int id, const char *type, const char *package, const char *key, const char *val, const void *msg, void *data)
214 {
215         static app_manger_event_type_e event_type;
216
217         if (!strcasecmp(key, "start")) {
218                 if (!strcasecmp(val, "install")) {
219                         event_type = APP_MANAGER_EVENT_INSTALLED;
220                 } else if (!strcasecmp(val, "uninstall"))       {
221                         // After uninstallation, we cannot get app ids from package name.
222                         // So, we have to store app ids which is included to target package.
223                         package_info_h package_info;
224
225                         int ret = package_manager_get_package_info(package, &package_info);
226                         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
227                                 LoggerE("Cannot create package info");
228                         }
229
230                         ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_ALLAPP, app_callback, data);
231                         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
232                                 LoggerE("failed while getting appids");
233                         }
234
235                         ret = package_info_destroy(package_info);
236                         if (ret != PACKAGE_MANAGER_ERROR_NONE) {
237                                 LoggerE("Cannot destroy package info");
238                         }
239                         event_type = APP_MANAGER_EVENT_UNINSTALLED;
240                 } else if (!strcasecmp(val, "update")) {
241                         event_type = APP_MANAGER_EVENT_UPDATED;
242                 }
243         } else if (!strcasecmp(key, "end") && !strcasecmp(val, "ok"))   {
244                 if (event_type >= 0) {
245                         if (data != NULL) {
246                                 AppManagerWrapper *appManager = (AppManagerWrapper *)data;
247                                 appManager->appListChangedCallback(event_type, package, data);
248                         }
249                 }
250         }
251
252         return APP_MANAGER_ERROR_NONE;
253 }
254
255
256 void AppManagerWrapper::registerAppListChangedCallbacks()
257 {
258         if (m_manager_handle != NULL) {
259                 LoggerW("Callback is already registered.");
260                 return;
261         }
262
263         TIME_TRACER_ITEM_BEGIN("(addAppInfoEventListener)pkgmgr_client_new", 0);
264         m_manager_handle = pkgmgr_client_new(PC_LISTENING);
265         TIME_TRACER_ITEM_END("(addAppInfoEventListener)pkgmgr_client_new", 0);
266         if (m_manager_handle == NULL) {
267                 ThrowMsg(InvalidArgumentException, "Error while registering listener to app_manager");
268         }
269
270         TIME_TRACER_ITEM_BEGIN("(addAppInfoEventListener)pkgmgr_client_listen_status", 0);
271         pkgmgr_client_listen_status(m_manager_handle, app_list_changed_cb_broker, this);
272         TIME_TRACER_ITEM_END("(addAppInfoEventListener)pkgmgr_client_listen_status", 0);
273 }
274
275 void AppManagerWrapper::unregisterAppListChangedCallbacks()
276 {
277         if (m_manager_handle == NULL) {
278                 LoggerE("No callback is registered");
279                 return;
280         }
281
282         TIME_TRACER_ITEM_BEGIN("(removeAppInfoEventListener)pkgmgr_client_free", 0);
283         pkgmgr_client_free(m_manager_handle);
284         TIME_TRACER_ITEM_END("(removeAppInfoEventListener)pkgmgr_client_free", 0);
285         m_manager_handle = NULL;
286 }
287
288 bool AppManagerWrapper::initializeAppInfo(ApplicationInformationPtr &appInfo)
289 {
290         LoggerD("Enter");
291
292         char* packageId = NULL;
293         int ret = 0;
294
295         ret = package_manager_get_package_id_by_app_id(appInfo->getAppId().c_str(), &packageId);
296         if ((ret != PACKAGE_MANAGER_ERROR_NONE) || (packageId == NULL)) {
297                 LoggerE("Fail to get package id");
298         } else {
299                 // get installed size from package server (to solve smack issue)
300                 pkgmgr_client *pc = pkgmgr_client_new(PC_REQUEST);
301                 if (pc == NULL) {
302                         LoggerE("Fail to create pkgmgr client");
303                 } else {
304                         ret = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, PM_GET_TOTAL_SIZE, pc, NULL, packageId, NULL, NULL, NULL);
305                         if (ret < 0) {
306                                 LoggerE("Fail to get installed size");
307                         } else {
308                                 appInfo->setInstallSize(ret);
309                         }
310
311                         pkgmgr_client_free(pc);
312                         pc = NULL;
313                 }
314
315                 if (packageId) {
316                         free(packageId);
317                 }
318         }
319
320         // if error occured, retry? or not?
321         appInfo->setInitialize();
322
323         return true;
324 }
325
326 SINGLETON_IMPLEMENTATION(AppManagerWrapper)
327         
328 } // Application
329 } // DeviceAPI