Update change log and spec for wrt-plugins-tizen_0.4.20
[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         LogDebug("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                 LogDebug("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                 LogDebug("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                 LogInfo(" notification id = " << notification->getID());
116                 notification_h handle = (notification_h)notification->getNotificationHandle();
117
118                 LogInfo("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                         if (service)
129                         {
130                                 if (service_to_bundle(service, &service_data)!= SERVICE_ERROR_NONE)
131                                 {
132                                         throw UnknownException("Can't create bundle");  
133                                 }
134                                 else
135                                 {
136                                         if (notification->getLaunchFlag())
137                                         {
138                                                 LogInfo("Notification Launch Flag True");
139                                                 notification_set_property(handle, 0);
140                                                 notification_set_execute_option(handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, service_data);
141                                         }
142                                         else
143                                         {
144                                                 LogInfo("Notification Launch Flag False");
145                                                 notification_set_property(handle, NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
146                                         }
147                                         
148                                         //bundle_free(service_data);
149                                 }
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                         LogDebug(" Layout type = " << noti_layout);
184                         ret = notification_set_layout(handle, noti_layout);
185                         LogDebug("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                                 LogDebug("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                                 LogInfo("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                                 LogInfo("get Percentage : " << value);
218                                 notification_update_progress(handle, NOTIFICATION_PRIV_ID_NONE, value);
219                         }
220
221                 }
222                 else
223                 {
224                         LogDebug("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                 LogDebug(" notification id = " << notification->getID());
240                 notification_h handle = (notification_h)notification->getNotificationHandle();
241                 
242                 LogDebug("handle = " << handle);
243                 
244                 if (handle)
245                 {
246                         LogDebug(" noti type = " << notification->getNotiType());
247                         if ( notification->getNotiType() == NOTI_TYPE_PROGRESS)
248                         {
249                                 int ret = 0;
250                                 LogDebug(" progress type = " << notification->getProgressType());
251                                 LogDebug(" noti id = " << notification->getID());
252                                 LogDebug(" noti progress value = " << notification->getProgressValue());
253
254                                 if (  NOTI_PROGRESS_TYPE_PERCENTAGE == notification->getProgressType() )
255                                 {
256                                         LogDebug( " 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                                         LogDebug( " size ");
262                                         ret = notification_update_size(handle, NOTIFICATION_PRIV_ID_NONE, notification->getProgressValue());
263                                 }
264                                                         
265                                 LogDebug(" 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                         LogDebug(" 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                                 LogDebug(" Layout type = " << noti_layout);
317                                 int ret = notification_set_layout(handle, noti_layout);
318                                 LogDebug("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                                                         LogInfo("Notification Launch Flag True");
335                                                         notification_set_property(handle, 0);
336                                                         notification_set_execute_option(handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, service_data);
337                                                 }
338                                                 else
339                                                 {
340                                                         LogInfo("Notification Launch Flag False");
341                                                         notification_set_property(handle, NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
342                                                 }
343                                                 
344                                         }
345                                 }
346
347                                 notification->setLaunchFlag(false);
348                                                         
349                                 LogDebug(" get Title = " << notification->getTitle());
350                                 ret = notification_update(handle);
351                                 LogDebug(" notification_update = " << ret);
352                                 notification->setUpdatedFlag(false);    //init
353                                 
354                                 if (ret != NOTIFICATION_ERROR_NONE)
355                                 {
356                                         throw UnknownException("Notification Object update fail, Error Code : ");
357                                 }
358                                 
359                                 LogDebug(" get Title = " << notification->getTitle());
360                         }
361                 }
362                 else
363                 {
364                         LogDebug("it has not notification handle.");
365                         throw UnknownException("It is Empty Notification.");
366                 }
367         }
368         else
369         {       
370                 LogDebug(" INotification is NULL");
371                 throw UnknownException("Notificaton Error.");
372         }
373    
374 }
375 void NotificationManager::remove(std::string id)
376 {
377         int privID = -1;
378         int ret = 0;
379         bool existFalg = false;
380         
381         LogDebug("id : " << id);
382         std::istringstream stream(id);
383         if (stream.fail())
384         {
385                 throw InvalidValuesException("Invalid notification ID, it don't match id format");
386         }
387         
388         stream >> privID;
389
390         notification_h noti = NULL;
391         notification_list_h noti_list = NULL;
392         notification_list_h noti_list_iter = NULL;
393         
394         if (notification_get_grouping_list( NOTIFICATION_TYPE_NONE , -1, &noti_list))
395         {
396                 LogDebug(" get notification list failed...");
397                 throw UnknownException("Can't get noti list");
398         }
399
400         noti_list_iter = notification_list_get_head(noti_list);
401
402         while ( noti_list_iter != NULL)
403         {
404                 noti = notification_list_get_data(noti_list_iter);
405                 if (noti != NULL /* && notification_package_equal(noti)*/)
406                 {
407                         int noti_priv = -1;
408                         notification_get_id(noti, NULL, &noti_priv);
409                         LogDebug(" notification id = " << noti_priv);
410                         if (noti_priv == privID)
411                                 existFalg = true;
412                 }
413                         noti_list_iter = notification_list_get_next(noti_list_iter);
414         }
415         
416         if (noti_list)
417                 notification_free_list(noti_list);      
418         
419         LogDebug(" notification ID : "<< privID);
420
421         if ( !existFalg )
422                 throw NotFoundException("not exist id");
423         
424         ret = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NONE, privID);
425         LogDebug("ret = " << ret);
426         if (ret != NOTIFICATION_ERROR_NONE)
427         {
428                 if (ret == NOTIFICATION_ERROR_NOT_EXIST_ID)
429                 {
430                         throw NotFoundException("not exist id");
431                 }
432                 else 
433                 {
434                         throw InvalidValuesException ("Invalid Data Error");
435                 }
436         } 
437
438 }
439 void NotificationManager::removeAll()
440 {
441         //remove all
442         if (notification_delete_all_by_type(NULL, 
443                 NOTIFICATION_TYPE_NONE) != NOTIFICATION_ERROR_NONE)
444         {
445                 throw UnknownException(" notification delete failed...");
446         }
447 }
448
449 StatusNotification* NotificationManager::get(std::string id)
450 {
451         int privID = 0;
452
453         LogDebug("id : " << id);
454         std::istringstream stream(id);
455         if (stream.fail())
456         {
457                 throw InvalidValuesException("Invalid notification ID, it don't match id format");
458         }
459         stream >> privID;
460
461         StatusNotification* notification = new StatusNotification(privID);
462         return notification;
463 }
464 std::vector<StatusNotification*> NotificationManager::getAll()
465 {
466         LogDebug("OK");
467         std::vector<StatusNotification*> data;
468
469         notification_h noti = NULL;
470         notification_list_h noti_list = NULL;
471         notification_list_h noti_list_iter = NULL;
472
473         if (notification_get_grouping_list( NOTIFICATION_TYPE_NONE , -1, &noti_list))
474         {
475                 LogDebug(" get notification list failed...");
476                 throw UnknownException("Can't get noti list");
477         }
478
479         noti_list_iter = notification_list_get_head(noti_list);
480
481         while ( noti_list_iter != NULL)
482         {
483                 noti = notification_list_get_data(noti_list_iter);
484                 if (noti != NULL  && notification_package_equal(noti))
485                 {
486                         int noti_priv = -1;
487                         notification_get_id(noti, NULL, &noti_priv);
488                         LogDebug(" notification id = " << noti_priv);
489                         
490                         StatusNotification* notification = new StatusNotification(noti_priv);
491
492                         notification_get_id((notification_h)notification->getNotificationHandle(), NULL, &noti_priv);
493                         LogDebug("loaded notification id = " << noti_priv);
494                         
495                         data.push_back(notification);                           
496                         
497                 }
498
499                 noti_list_iter = notification_list_get_next(noti_list_iter);
500         }
501         
502         if (noti_list)
503                 notification_free_list(noti_list);      
504         
505 #if 0
506         while ( noti_list != NULL)
507         {
508                 noti = notification_list_get_data(noti_list);
509                 if (noti != NULL  && notification_package_equal(noti))
510                 {
511                         int noti_priv = -1;
512                         notification_get_id(noti, NULL, &noti_priv);
513                         LogDebug(" notification id = " << noti_priv);
514                         
515                         StatusNotification* notification = new StatusNotification(noti_priv);
516
517                         notification_get_id((notification_h)notification->getNotificationHandle(), NULL, &noti_priv);
518                         LogDebug("loaded notification id = " << noti_priv);
519                         
520                         data.push_back(notification);                           
521                         
522                 }
523                 noti_list = notification_list_get_next(noti_list);
524         }
525         
526         if (noti_list)
527                 notification_free_list(noti_list);
528 #endif
529         return data;
530
531 }
532
533 } // Notification
534 } // DeviceAPI