Remove hardcoded path for multiuser support
[platform/framework/web/wrt-plugins-tizen.git] / src / Notification / NotificationManager.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 <PlatformException.h>
19 #include <Logger.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <cassert>
24 #include <sys/stat.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <bundle.h>
29 #include <appsvc/appsvc.h>
30
31 #include "NotificationManager.h"
32
33 namespace DeviceAPI {
34 namespace Notification {
35
36 extern "C" int service_to_bundle(service_h service, bundle **data);
37
38 static bool notification_package_equal(notification_h handle)
39 {
40         char* package = NULL;
41         char* handle_package = NULL;
42         char cmdline[512] = {0,};
43         char buf[64] = {0,};
44         
45         if(notification_get_pkgname(handle, &handle_package))
46         {
47                 return false;   
48         }
49
50         LoggerD("handle package=" << handle_package);
51         
52         if (app_get_package(&package))
53         {
54
55                 int ret = 0;
56                 int fd = -1;
57                 int pid = getpid();
58
59                 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
60
61                 fd = open(buf, O_RDONLY);
62                 if (fd < 0) {
63                         return false;
64                 }
65
66                 ret = read(fd, cmdline, sizeof(cmdline) - 1);
67                 if (ret <= 0) {
68                         close(fd);
69                         return false;
70                 }
71
72                 cmdline[ret] = 0;
73                 close(fd);
74
75                 LoggerD("package=" << package);
76                 
77                 if (strlen(cmdline) == strlen(handle_package))
78                 {
79                         if (!strncmp(cmdline, handle_package, strlen(cmdline)))
80                         {
81                                 return true;
82                         }
83                 }
84         }
85         else
86         {
87                 LoggerD("package=" << package);
88                         
89                 if (strlen(package) == strlen(handle_package))
90                 {
91                                 if (!strncmp(package, handle_package, strlen(package)))
92                                 {
93                                         return true;
94                                 }
95                 }
96         }
97
98         return false;
99 }
100
101 NotificationManager::NotificationManager()
102 {
103 }
104
105 NotificationManager::~NotificationManager()
106 {
107 }
108
109 int NotificationManager::post(StatusNotification *notification)
110 {
111         int id = -1;
112
113         if ( notification )
114         {
115                 LoggerI(" notification id = " << notification->getID());
116                 notification_h handle = (notification_h)notification->getNotificationHandle();
117
118                 LoggerI("notification hanel :" << handle);
119
120                 if ( handle )
121                 {
122                         //set Service
123                         int ret = 0;
124         
125                         bundle *service_data = NULL;
126                         service_h service = notification->getService();
127
128                         LoggerI("Service :" << service << " Flag :" << notification->getLaunchFlag());
129                 
130                         if (service && notification->getLaunchFlag())
131                         {
132                                 if (service_to_bundle(service, &service_data)!= SERVICE_ERROR_NONE)
133                                 {
134                                         throw UnknownException("Can't create bundle");  
135                                 }
136                                 else
137                                 {
138                                         LoggerI("Notification Launch Flag True");
139                                         notification_set_property(handle, 0);
140                                         if (notification_set_execute_option(handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, service_data) != SERVICE_ERROR_NONE)
141                                         {
142                                                 LoggerD("can't set notification option");
143                                         }
144                                 }
145                         }
146                         else
147                         {
148                                 LoggerI("Notification Launch Flag False");
149                                 notification_set_property(handle, NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
150                         }
151                 
152                         //check layout.
153                         int type = (int)notification->getNotiType();
154                         notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
155                         
156                         switch (type)
157                         {
158                                 case NOTI_TYPE_SIMPLE:
159                                 {
160                                         if(notification->getNumber()>0)
161                                                 noti_layout = NOTIFICATION_LY_NOTI_EVENT_MULTIPLE;
162                                         else
163                                                 noti_layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
164                                         break;
165                                 }
166                                 case NOTI_TYPE_THUMBNAIL:
167                                 {
168                                         noti_layout = NOTIFICATION_LY_NOTI_THUMBNAIL;
169                                         break;
170                                 }
171                                 case NOTI_TYPE_ONGOING:
172                                 {
173                                         noti_layout = NOTIFICATION_LY_ONGOING_EVENT;
174                                         break;
175                                 }
176                                 case NOTI_TYPE_PROGRESS:
177                                 {
178                                         noti_layout = NOTIFICATION_LY_ONGOING_PROGRESS;
179                                         break;
180                                 }
181                         }
182  
183                         LoggerD(" Layout type = " << noti_layout);
184                         ret = notification_set_layout(handle, noti_layout);
185                         LoggerD("set Layout result= " << ret);
186
187                         int privID = -1;
188                         
189                         ret = notification_insert(handle, &privID);      //if noti already exist, it is update.
190                         if (NOTIFICATION_ERROR_NONE == ret)
191                         {
192                                 id = privID;
193                                 LoggerD("private ID : " << privID);
194                                 notification->setUpdatedFlag(false);
195                         }
196                         else
197                         {
198                                  throw UnknownException("Notification Object post fail");
199                         }
200
201                         if ( type == NOTI_TYPE_PROGRESS)
202                         {
203
204                                 double value = 0.0;
205                                 
206                                 if (notification_get_size(handle, &value) != NOTIFICATION_ERROR_NONE)
207                                 {
208                                         throw UnknownException("get notification size error");
209                                 }
210                                 LoggerI("get Size : " << value);
211                                 notification_update_size(handle, NOTIFICATION_PRIV_ID_NONE, value);
212                                 
213                                 if (notification_get_progress(handle, &value) != NOTIFICATION_ERROR_NONE)
214                                 {
215                                         throw UnknownException("get notification percentage error");
216                                 }
217                                 LoggerI("get Percentage : " << value);
218                                 notification_update_progress(handle, NOTIFICATION_PRIV_ID_NONE, value);
219                         }
220
221                 }
222                 else
223                 {
224                         LoggerD("it has not notification handle.");
225                         throw UnknownException("It is Empty Notification.");
226                 }
227         }
228         else
229         {
230                 throw UnknownException("Notification Handle is NULL.");
231         }
232
233         return id;
234 }
235 void NotificationManager::update(StatusNotification *notification)
236 {
237         if (notification)
238         {
239                 LoggerD(" notification id = " << notification->getID());
240                 notification_h handle = (notification_h)notification->getNotificationHandle();
241                 
242                 LoggerD("handle = " << handle);
243                 
244                 if (handle)
245                 {
246                         LoggerD(" noti type = " << notification->getNotiType());
247                         if ( notification->getNotiType() == NOTI_TYPE_PROGRESS)
248                         {
249                                 int ret = 0;
250                                 LoggerD(" progress type = " << notification->getProgressType());
251                                 LoggerD(" noti id = " << notification->getID());
252                                 LoggerD(" noti progress value = " << notification->getProgressValue());
253
254                                 if (  NOTI_PROGRESS_TYPE_PERCENTAGE == notification->getProgressType() )
255                                 {
256                                         LoggerD( " Percentage ");
257                                         ret = notification_update_progress(handle, NOTIFICATION_PRIV_ID_NONE, notification->getProgressValue());
258                                 }
259                                 else if ( NOTI_PROGRESS_TYPE_SIZE == notification->getProgressType())
260                                 {
261                                         LoggerD( " size ");
262                                         ret = notification_update_size(handle, NOTIFICATION_PRIV_ID_NONE, notification->getProgressValue());
263                                 }
264                                                         
265                                 LoggerD(" notification_update_progress = " << ret);
266
267                                 if (NOTIFICATION_ERROR_NONE != ret)
268                                 {
269                                         if ( NOTIFICATION_ERROR_NOT_EXIST_ID == ret)
270                                         {
271                                                 throw NotFoundException("maybe, notification is not inserted yet.");
272                                         }
273                                         else 
274                                         {
275                                                 throw UnknownException("Notification Object update grogress fail, Error Code : ");                      
276                                         }
277                                 }
278                 
279                         }
280                         
281                         LoggerD(" updated Flag = " << notification->getUpdatedFlag());
282                         
283                         if ( notification->getUpdatedFlag())
284                         {
285
286                                 int type = (int)notification->getNotiType();
287                                 notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
288                                 
289                                 switch (type)
290                                 {
291                                         case NOTI_TYPE_SIMPLE:
292                                         {
293                                                 if(notification->getNumber()>0)
294                                                         noti_layout = NOTIFICATION_LY_NOTI_EVENT_MULTIPLE;
295                                                 else
296                                                         noti_layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
297                                                 break;
298                                         }
299                                         case NOTI_TYPE_THUMBNAIL:
300                                         {
301                                                 noti_layout = NOTIFICATION_LY_NOTI_THUMBNAIL;
302                                                 break;
303                                         }
304                                         case NOTI_TYPE_ONGOING:
305                                         {
306                                                 noti_layout = NOTIFICATION_LY_ONGOING_EVENT;
307                                                 break;
308                                         }
309                                         case NOTI_TYPE_PROGRESS:
310                                         {
311                                                 noti_layout = NOTIFICATION_LY_ONGOING_PROGRESS;
312                                                 break;
313                                         }
314                                 }
315          
316                                 LoggerD(" Layout type = " << noti_layout);
317                                 int ret = notification_set_layout(handle, noti_layout);
318                                 LoggerD("set Layout result= " << ret);
319
320                                 
321                                 bundle *service_data = NULL;
322                                 service_h service = notification->getService();
323                         
324                                 if (service)
325                                 {
326                                         if (service_to_bundle(service, &service_data)!= SERVICE_ERROR_NONE)
327                                         {
328                                                 throw UnknownException("Can't create bundle");  
329                                         }
330                                         else
331                                         {
332                                                 if (notification->getLaunchFlag())
333                                                 {
334                                                         LoggerI("Notification Launch Flag True");
335                                                         notification_set_property(handle, 0);
336                                                         if (notification_set_execute_option(handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, service_data)!= SERVICE_ERROR_NONE)
337                                                         {
338                                                                 LoggerI("Can't set Service option");
339                                                         }
340                                                 }
341                                                 else
342                                                 {
343                                                         LoggerI("Notification Launch Flag False");
344                                                         notification_set_property(handle, NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
345                                                 }
346                                                 
347                                         }
348                                 }
349
350                                 notification->setLaunchFlag(false);
351                                                         
352                                 LoggerD(" get Title = " << notification->getTitle());
353                                 ret = notification_update(handle);
354                                 LoggerD(" notification_update = " << ret);
355                                 notification->setUpdatedFlag(false);    //init
356                                 
357                                 if (ret != NOTIFICATION_ERROR_NONE)
358                                 {
359                                         throw UnknownException("Notification Object update fail, Error Code : ");
360                                 }
361                                 
362                                 LoggerD(" get Title = " << notification->getTitle());
363                         }
364                 }
365                 else
366                 {
367                         LoggerD("it has not notification handle.");
368                         throw UnknownException("It is Empty Notification.");
369                 }
370         }
371         else
372         {       
373                 LoggerD(" INotification is NULL");
374                 throw UnknownException("Notificaton Error.");
375         }
376    
377 }
378 void NotificationManager::remove(std::string id)
379 {
380         int privID = -1;
381         int ret = 0;
382         bool existFalg = false;
383         
384         LoggerD("id : " << id);
385         std::istringstream stream(id);
386         if (stream.fail())
387         {
388                 throw InvalidValuesException("Invalid notification ID, it don't match id format");
389         }
390         
391         stream >> privID;
392
393         notification_h noti = NULL;
394         notification_list_h noti_list = NULL;
395         notification_list_h noti_list_iter = NULL;
396         
397         if (notification_get_grouping_list( NOTIFICATION_TYPE_NONE , -1, &noti_list))
398         {
399                 LoggerD(" get notification list failed...");
400                 throw UnknownException("Can't get noti list");
401         }
402
403         noti_list_iter = notification_list_get_head(noti_list);
404
405         while ( noti_list_iter != NULL)
406         {
407                 noti = notification_list_get_data(noti_list_iter);
408                 if (noti != NULL  && notification_package_equal(noti))
409                 {
410                         int noti_priv = -1;
411                         notification_get_id(noti, NULL, &noti_priv);
412                         LoggerD(" notification id = " << noti_priv);
413                         if (noti_priv == privID)
414                                 existFalg = true;
415                 }
416                         noti_list_iter = notification_list_get_next(noti_list_iter);
417         }
418         
419         if (noti_list)
420                 notification_free_list(noti_list);      
421         
422         LoggerD(" notification ID : "<< privID);
423
424         if ( !existFalg )
425                 throw NotFoundException("not exist id");
426         
427         ret = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NONE, privID);
428         LoggerD("ret = " << ret);
429         if (ret != NOTIFICATION_ERROR_NONE)
430         {
431                 if (ret == NOTIFICATION_ERROR_NOT_EXIST_ID)
432                 {
433                         throw NotFoundException("not exist id");
434                 }
435                 else 
436                 {
437                         throw InvalidValuesException ("Invalid Data Error");
438                 }
439         } 
440
441 }
442 void NotificationManager::removeAll()
443 {
444         //remove all
445         if (notification_delete_all_by_type(NULL, 
446                 NOTIFICATION_TYPE_NONE) != NOTIFICATION_ERROR_NONE)
447         {
448                 throw UnknownException(" notification delete failed...");
449         }
450 }
451
452 StatusNotification* NotificationManager::get(std::string id)
453 {
454         int privID = 0;
455
456         LoggerD("id : " << id);
457         std::istringstream stream(id);
458         if (stream.fail())
459         {
460                 throw InvalidValuesException("Invalid notification ID, it don't match id format");
461         }
462         stream >> privID;
463
464         LoggerI("priv ID : " << privID);
465
466         notification_h notification = notification_load( NULL, privID); //load notification.
467         LoggerI(" notification " << notification);
468
469         if (notification != NULL  && notification_package_equal(notification))
470         {
471                 StatusNotification* noti = new StatusNotification(notification);
472                 return noti;
473         }
474         else
475         {
476                 throw NotFoundException("It is not notification ID or removed notification");
477         }       
478         
479         return NULL;
480 }
481 std::vector<StatusNotification*> NotificationManager::getAll()
482 {
483         LoggerD("OK");
484         std::vector<StatusNotification*> data;
485
486         notification_h noti = NULL;
487         notification_list_h noti_list = NULL;
488         notification_list_h noti_list_iter = NULL;
489
490         if (notification_get_grouping_list( NOTIFICATION_TYPE_NONE , -1, &noti_list))
491         {
492                 LoggerD(" get notification list failed...");
493                 throw UnknownException("Can't get noti list");
494         }
495
496         noti_list_iter = notification_list_get_head(noti_list);
497
498         while ( noti_list_iter != NULL)
499         {
500                 noti = notification_list_get_data(noti_list_iter);
501                 if (noti != NULL  && notification_package_equal(noti))
502                 {
503                         int noti_priv = -1;
504                         notification_get_id(noti, NULL, &noti_priv);
505                         LoggerD(" notification id = " << noti_priv);
506                         
507                         StatusNotification* notification = new StatusNotification(noti_priv);
508
509                         notification_get_id((notification_h)notification->getNotificationHandle(), NULL, &noti_priv);
510                         LoggerD("loaded notification id = " << noti_priv);
511                         
512                         data.push_back(notification);                           
513                 }
514
515                 noti_list_iter = notification_list_get_next(noti_list_iter);
516         }
517         
518         if (noti_list)
519                 notification_free_list(noti_list);      
520         
521 #if 0
522         while ( noti_list != NULL)
523         {
524                 noti = notification_list_get_data(noti_list);
525                 if (noti != NULL  && notification_package_equal(noti))
526                 {
527                         int noti_priv = -1;
528                         notification_get_id(noti, NULL, &noti_priv);
529                         LoggerD(" notification id = " << noti_priv);
530                         
531                         StatusNotification* notification = new StatusNotification(noti_priv);
532
533                         notification_get_id((notification_h)notification->getNotificationHandle(), NULL, &noti_priv);
534                         LoggerD("loaded notification id = " << noti_priv);
535                         
536                         data.push_back(notification);                           
537                         
538                 }
539                 noti_list = notification_list_get_next(noti_list);
540         }
541         
542         if (noti_list)
543                 notification_free_list(noti_list);
544 #endif
545         return data;
546
547 }
548
549 } // Notification
550 } // DeviceAPI