[Push] update logs
[platform/core/api/webapi-plugins.git] / src / push / push_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 "push/push_manager.h"
18 #include <unistd.h>
19 #include <pcrecpp.h>
20 #include <app_control.h>
21 #include <app_manager.h>
22 #include "common/logger.h"
23
24 namespace extension {
25 namespace push {
26
27 using common::PlatformResult;
28 using common::ErrorCode;
29
30 PushManager::PushManager() :
31     m_handle(NULL),
32     m_listener(NULL),
33     m_state(PUSH_STATE_UNREGISTERED) {
34     LoggerD("Enter");
35     initAppId();
36
37     int ret = push_connect(m_pkgId.c_str(), onPushState, onPushNotify, NULL,
38         &m_handle);
39     if (ret != PUSH_ERROR_NONE) {
40         LoggerE("Failed to connect to push (%d)", ret);
41     }
42 }
43
44 PushManager::~PushManager() {
45     LoggerD("Enter");
46     push_disconnect(m_handle);
47 }
48
49 void PushManager::setListener(EventListener* listener) {
50     LoggerD("Enter");
51     m_listener = listener;
52 }
53
54 void PushManager::initAppId() {
55     LoggerD("Enter");
56     int pid = getpid();
57     char *temp = NULL;
58     int ret = app_manager_get_app_id(pid, &temp);
59     if (ret != APP_MANAGER_ERROR_NONE || temp == NULL) {
60         LoggerE("Failed to get appid (%d)", ret);
61         return;
62     }
63
64     m_appId = temp;
65     free(temp);
66     temp = NULL;
67
68     app_info_h info;
69     ret = app_manager_get_app_info(m_appId.c_str(), &info);
70     if (ret != APP_MANAGER_ERROR_NONE) {
71         LoggerE("Failed to get app info (%d)", ret);
72         return;
73     }
74
75     ret = app_info_get_package(info, &temp);
76     if (ret == APP_MANAGER_ERROR_NONE && temp != NULL) {
77         m_pkgId = temp;
78         free(temp);
79     } else {
80         LoggerE("Failed to get pkg id (%d)", ret);
81     }
82
83     app_info_destroy(info);
84 }
85
86 PushManager& PushManager::getInstance() {
87   static PushManager instance;
88   return instance;
89 }
90
91 PlatformResult PushManager::registerService(
92         const ApplicationControl &appControl, double callbackId) {
93     LoggerD("Enter");
94     app_control_h service;
95     int ret = app_control_create(&service);
96     if (ret != APP_CONTROL_ERROR_NONE) {
97         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
98             "Failed to create service",
99             ("Failed to create service: app_control_create failed(%d)", ret));
100     }
101
102     if (appControl.operation.empty()) {
103         app_control_destroy(service);
104         return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
105             "Operation is empty");
106     }
107     ret = app_control_set_operation(service, appControl.operation.c_str());
108     if (ret != APP_CONTROL_ERROR_NONE) {
109         app_control_destroy(service);
110         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
111             "Failed to set operation",
112             ("Failed to set operation: app_control_set_operation failed(%d)", ret));
113     }
114
115     if (!appControl.uri.empty()) {
116         ret = app_control_set_uri(service, appControl.uri.c_str());
117         if (ret != APP_CONTROL_ERROR_NONE) {
118             app_control_destroy(service);
119             return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
120                 "Failed to set uri",
121                 ("Failed to set uri: app_control_set_uri failed(%d)", ret));
122         }
123     }
124
125     if (!appControl.mime.empty()) {
126         ret = app_control_set_mime(service, appControl.mime.c_str());
127         if (ret != APP_CONTROL_ERROR_NONE) {
128             app_control_destroy(service);
129             return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
130                 "Failed to set mime",
131                 ("Failed to set mime: app_control_set_mime failed(%d)", ret));
132         }
133     }
134
135     if (!appControl.category.empty()) {
136         ret = app_control_set_category(service, appControl.category.c_str());
137         if (ret != APP_CONTROL_ERROR_NONE) {
138             app_control_destroy(service);
139             return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
140                 "Failed to set category",
141                 ("Failed to set category: app_control_set_category failed"));
142         }
143     }
144
145     ret = app_control_set_app_id(service, m_appId.c_str());
146     if (ret != APP_CONTROL_ERROR_NONE) {
147         app_control_destroy(service);
148         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
149             "Failed to set app id",
150             ("Failed to set app id: app_control_set_app_id failed(%d)", ret));
151     }
152
153     for (auto &item : appControl.data) {
154         if (item.second.size() == 1) {
155             ret = app_control_add_extra_data(service, item.first.c_str(),
156                 item.second.front().c_str());
157         } else {
158             const char *values[item.second.size()];
159             for (size_t i = 0; i < item.second.size(); ++i) {
160                 values[i] = item.second.at(i).c_str();
161             }
162             ret = app_control_add_extra_data_array(service,
163                 item.first.c_str(), values, item.second.size());
164         }
165         if (ret != APP_CONTROL_ERROR_NONE) {
166             app_control_destroy(service);
167             return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
168                 "Failed to set extra data",
169                 ("Failed to set extra data: app_control_add_extra_data failed(%d)", ret));
170         }
171     }
172
173     double* pcallback = new double(callbackId);
174     ret = push_register(m_handle, service, onPushRegister, pcallback);
175     app_control_destroy(service);
176     if (ret != PUSH_ERROR_NONE) {
177         delete pcallback;
178         if (ret == PUSH_ERROR_INVALID_PARAMETER) {
179           LoggerE("[push_register] PUSH_ERROR_INVALID_PARAMETER");
180         } else if (ret == PUSH_ERROR_OUT_OF_MEMORY) {
181           LoggerE("[push_register] PUSH_ERROR_OUT_OF_MEMORY");
182         } else if (ret == PUSH_ERROR_NOT_CONNECTED) {
183           LoggerE("[push_register] PUSH_ERROR_NOT_CONNECTED");
184         } else if (ret == PUSH_ERROR_OPERATION_FAILED) {
185           LoggerE("[push_register] PUSH_ERROR_OPERATION_FAILED");
186         }
187         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
188             "Failed to register",
189             ("Failed to register push: push_register failed (%d)", ret));
190     }
191
192     return common::PlatformResult(ErrorCode::NO_ERROR);
193 }
194
195 common::PlatformResult PushManager::unregisterService(double callbackId) {
196     LoggerD("Enter");
197     double* pcallbackId = new double(callbackId);
198     if (m_state == PUSH_STATE_UNREGISTERED) {
199         LoggerD("Already unregister, call unregister callback");
200         if (!g_idle_add(onFakeDeregister, pcallbackId)) {
201             delete pcallbackId;
202             return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
203                 "Unknown error", ("g_idle_add failed"));
204         }
205     } else {
206         int ret = push_deregister(m_handle, onDeregister, pcallbackId);
207         if (ret != PUSH_ERROR_NONE) {
208             delete pcallbackId;
209             if (ret == PUSH_ERROR_INVALID_PARAMETER) {
210               LoggerE("[push_deregister] PUSH_ERROR_INVALID_PARAMETER");
211             } else if (ret == PUSH_ERROR_OUT_OF_MEMORY) {
212               LoggerE("[push_deregister] PUSH_ERROR_OUT_OF_MEMORY");
213             } else if (ret == PUSH_ERROR_NOT_CONNECTED) {
214               LoggerE("[push_deregister] PUSH_ERROR_NOT_CONNECTED");
215             } else if (ret == PUSH_ERROR_OPERATION_FAILED) {
216               LoggerE("[push_deregister] PUSH_ERROR_OPERATION_FAILED");
217             }
218             return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
219                 "Unknown error",
220                 ("Failed to deregister: push_deregister failed (%d)", ret));
221         }
222     }
223     return common::PlatformResult(ErrorCode::NO_ERROR);
224 }
225
226 common::PlatformResult PushManager::getRegistrationId(std::string& id) {
227     LoggerD("Enter");
228     char* temp = NULL;
229     int ret = push_get_registration_id(m_handle, &temp);
230     if (ret != PUSH_ERROR_NONE) {
231         if (ret == PUSH_ERROR_INVALID_PARAMETER) {
232           LoggerE("[push_get_registration_id]   PUSH_ERROR_INVALID_PARAMETER");
233         } else if (ret == PUSH_ERROR_OUT_OF_MEMORY) {
234           LoggerE("[push_get_registration_id]   PUSH_ERROR_OUT_OF_MEMORY");
235         } else if (ret == PUSH_ERROR_NO_DATA) {
236           LoggerE("[push_get_registration_id]   PUSH_ERROR_NO_DATA");
237         }
238         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
239             "Unknown error",
240             ("Failed to get id: push_get_registration_id failed (%d)", ret));
241     }
242     id = temp;
243     free(temp);
244     return common::PlatformResult(ErrorCode::NO_ERROR);
245 }
246
247 common::PlatformResult PushManager::getUnreadNotifications() {
248     LoggerD("Enter");
249     int ret = push_request_unread_notification(m_handle);
250     if (ret != PUSH_ERROR_NONE) {
251         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
252             "Unknown error",
253             ("Failed to send request: push_request_unread_notification failed (%d)", ret));
254     }
255     return common::PlatformResult(ErrorCode::NO_ERROR);
256 }
257
258 void PushManager::onPushState(push_state_e state, const char* err,
259         void* user_data) {
260     LoggerD("Enter %d, err: %s", state, err);
261     getInstance().m_state = state;
262 }
263
264 void PushManager::onPushNotify(push_notification_h noti, void* user_data) {
265     LoggerD("Enter");
266     if (!getInstance().m_listener) {
267         LoggerW("Listener not set, ignoring");
268         return;
269     }
270
271     char* temp = NULL;
272     int ret = push_get_notification_data(noti, &temp);
273     if (ret != PUSH_ERROR_NONE) {
274         LoggerE("Failed to get appData");
275         return;
276     }
277     std::string appData = temp;
278     free(temp);
279
280     temp = NULL;
281     ret = push_get_notification_message(noti, &temp);
282     if (ret != PUSH_ERROR_NONE) {
283         LoggerE("Failed to get message");
284         return;
285     }
286
287     // parse query string and find value for alertMessage
288     pcrecpp::StringPiece input(temp);
289     pcrecpp::RE re("([^=]+)=([^&]*)&?");
290     string key;
291     string value;
292     std::string alertMessage;
293     while (re.Consume(&input, &key, &value)) {
294         if (key == "alertMessage") {
295             alertMessage = value;
296             break;
297         }
298     }
299     free(temp);
300
301     long long int date = -1;
302     ret = push_get_notification_time(noti, &date);
303     if (ret != PUSH_ERROR_NONE) {
304         LoggerE("Failed to get date");
305         return;
306     }
307     getInstance().m_listener->onPushNotify(appData, alertMessage, date);
308 }
309
310 void PushManager::onPushRegister(push_result_e result, const char* msg,
311         void* user_data) {
312     LoggerD("Enter");
313     if (!getInstance().m_listener) {
314         LoggerW("Listener not set, ignoring");
315         return;
316     }
317     double* callbackId = static_cast<double*>(user_data);
318     std::string id;
319     PlatformResult res(ErrorCode::NO_ERROR);
320     if (result == PUSH_RESULT_SUCCESS) {
321         LoggerD("Success");
322         char *temp = NULL;
323         int ret = push_get_registration_id(getInstance().m_handle, &temp);
324         if (ret == PUSH_ERROR_NONE) {
325             LoggerD("Registration id retrieved");
326             id = temp;
327             free(temp);
328         } else {
329             res = LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
330                 "Failed to retrieve registration id",
331                 ("Failed to retrieve registration id: push_get_registration_id(%d)", ret));
332         }
333     } else {
334         if (result == PUSH_RESULT_TIMEOUT) {
335             LoggerE("PUSH_RESULT_TIMEOUT");
336         } else if (result == PUSH_RESULT_SERVER_ERROR) {
337             LoggerE("PUSH_RESULT_SERVER_ERROR");
338         } else if (result == PUSH_RESULT_SYSTEM_ERROR) {
339             LoggerE("PUSH_RESULT_SYSTEM_ERROR");
340         }
341         res = LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
342                 msg == NULL ? "Unknown error" : msg);
343     }
344     // onPushState is not always called when onPushRegister is successfull
345     getInstance().m_state = PUSH_STATE_REGISTERED;
346     getInstance().m_listener->onPushRegister(*callbackId, res, id);
347     delete callbackId;
348 }
349
350 gboolean PushManager::onFakeDeregister(gpointer user_data) {
351     LoggerD("Enter");
352     if (!getInstance().m_listener) {
353         LoggerW("Listener not set, ignoring");
354         return G_SOURCE_REMOVE;
355     }
356     double* callbackId = static_cast<double*>(user_data);
357     getInstance().m_listener->onDeregister(*callbackId,
358         PlatformResult(ErrorCode::NO_ERROR));
359     delete callbackId;
360     return G_SOURCE_REMOVE;
361 }
362
363 void PushManager::onDeregister(push_result_e result, const char* msg,
364         void* user_data) {
365     LoggerD("Enter");
366     if (!getInstance().m_listener) {
367         LoggerW("Listener not set, ignoring");
368         return;
369     }
370     double* callbackId = static_cast<double*>(user_data);
371     if (result == PUSH_RESULT_SUCCESS) {
372         getInstance().m_listener->onDeregister(*callbackId,
373             PlatformResult(ErrorCode::NO_ERROR));
374     } else {
375         getInstance().m_listener->onDeregister(*callbackId,
376             LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
377                 msg == NULL ? "Unknown error" : msg));
378     }
379     delete callbackId;
380 }
381
382 }  // namespace push
383 }  // namespace extension
384