8df07db5a42139450378b3847c491c6fa6de69fa
[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         LoggerE("Failed to create service: app_control_create failed(%d)", ret);
98         return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
99             "Failed to create service");
100     }
101
102     if (appControl.operation.empty()) {
103         LoggerE("Operation is empty");
104         app_control_destroy(service);
105         return common::PlatformResult(ErrorCode::INVALID_VALUES_ERR,
106             "Operation is empty");
107     }
108     ret = app_control_set_operation(service, appControl.operation.c_str());
109     if (ret != APP_CONTROL_ERROR_NONE) {
110         LoggerE("Failed to set operation: app_control_set_operation failed(%d)", ret);
111         app_control_destroy(service);
112         return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
113             "Failed to set operation");
114     }
115
116     if (!appControl.uri.empty()) {
117         ret = app_control_set_uri(service, appControl.uri.c_str());
118         if (ret != APP_CONTROL_ERROR_NONE) {
119             LoggerE("Failed to set uri: app_control_set_uri failed(%d)", ret);
120             app_control_destroy(service);
121             return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
122                 "Failed to set uri");
123         }
124     }
125
126     if (!appControl.mime.empty()) {
127         ret = app_control_set_mime(service, appControl.mime.c_str());
128         if (ret != APP_CONTROL_ERROR_NONE) {
129             LoggerE("Failed to set mime: app_control_set_mime failed(%d)", ret);
130             app_control_destroy(service);
131             return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
132                 "Failed to set mime");
133         }
134     }
135
136     if (!appControl.category.empty()) {
137         ret = app_control_set_category(service, appControl.category.c_str());
138         if (ret != APP_CONTROL_ERROR_NONE) {
139             LoggerE("Failed to set category: app_control_set_category failed");
140             app_control_destroy(service);
141             return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
142                 "Failed to set category");
143         }
144     }
145
146     ret = app_control_set_app_id(service, m_appId.c_str());
147     if (ret != APP_CONTROL_ERROR_NONE) {
148         LoggerE("Failed to set app id: app_control_set_app_id failed(%d)", ret);
149         app_control_destroy(service);
150         return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
151             "Failed to set app id");
152     }
153
154     for (auto &item : appControl.data) {
155         if (item.second.size() == 1) {
156             ret = app_control_add_extra_data(service, item.first.c_str(),
157                 item.second.front().c_str());
158         } else {
159             const char *values[item.second.size()];
160             for (size_t i = 0; i < item.second.size(); ++i) {
161                 values[i] = item.second.at(i).c_str();
162             }
163             ret = app_control_add_extra_data_array(service,
164                 item.first.c_str(), values, item.second.size());
165         }
166         if (ret != APP_CONTROL_ERROR_NONE) {
167             LoggerE(
168                 "Failed to set extra data: app_control_add_extra_data failed(%d)", ret);
169             app_control_destroy(service);
170             return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
171                 "Failed to set extra data");
172         }
173     }
174
175     double* pcallback = new double(callbackId);
176     ret = push_register(m_handle, service, onPushRegister, pcallback);
177     app_control_destroy(service);
178     if (ret != PUSH_ERROR_NONE) {
179         delete pcallback;
180         if (ret == PUSH_ERROR_INVALID_PARAMETER) {
181           LoggerE("[push_register] PUSH_ERROR_INVALID_PARAMETER");
182         } else if (ret == PUSH_ERROR_OUT_OF_MEMORY) {
183           LoggerE("[push_register] PUSH_ERROR_OUT_OF_MEMORY");
184         } else if (ret == PUSH_ERROR_NOT_CONNECTED) {
185           LoggerE("[push_register] PUSH_ERROR_NOT_CONNECTED");
186         } else if (ret == PUSH_ERROR_OPERATION_FAILED) {
187           LoggerE("[push_register] PUSH_ERROR_OPERATION_FAILED");
188         }
189         LoggerE("Failed to register push: push_register failed (%d)", ret);
190         return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
191             "Failed to register");
192     }
193
194     return common::PlatformResult(ErrorCode::NO_ERROR);
195 }
196
197 common::PlatformResult PushManager::unregisterService(double callbackId) {
198     LoggerD("Enter");
199     double* pcallbackId = new double(callbackId);
200     if (m_state == PUSH_STATE_UNREGISTERED) {
201         LoggerD("Already unregister, call unregister callback");
202         if (!g_idle_add(onFakeDeregister, pcallbackId)) {
203             delete pcallbackId;
204             LoggerE("g_idle_add failed");
205             return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
206                 "Unknown error");
207         }
208     } else {
209         int ret = push_deregister(m_handle, onDeregister, pcallbackId);
210         if (ret != PUSH_ERROR_NONE) {
211             delete pcallbackId;
212             if (ret == PUSH_ERROR_INVALID_PARAMETER) {
213               LoggerE("[push_deregister] PUSH_ERROR_INVALID_PARAMETER");
214             } else if (ret == PUSH_ERROR_OUT_OF_MEMORY) {
215               LoggerE("[push_deregister] PUSH_ERROR_OUT_OF_MEMORY");
216             } else if (ret == PUSH_ERROR_NOT_CONNECTED) {
217               LoggerE("[push_deregister] PUSH_ERROR_NOT_CONNECTED");
218             } else if (ret == PUSH_ERROR_OPERATION_FAILED) {
219               LoggerE("[push_deregister] PUSH_ERROR_OPERATION_FAILED");
220             }
221             LoggerE("Failed to deregister: push_deregister failed (%d)", ret);
222             return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
223                 "Unknown error");
224         }
225     }
226     return common::PlatformResult(ErrorCode::NO_ERROR);
227 }
228
229 common::PlatformResult PushManager::getRegistrationId(std::string& id) {
230     LoggerD("Enter");
231     char* temp = NULL;
232     int ret = push_get_registration_id(m_handle, &temp);
233     if (ret != PUSH_ERROR_NONE) {
234         if (ret == PUSH_ERROR_INVALID_PARAMETER) {
235           LoggerE("[push_get_registration_id]   PUSH_ERROR_INVALID_PARAMETER");
236         } else if (ret == PUSH_ERROR_OUT_OF_MEMORY) {
237           LoggerE("[push_get_registration_id]   PUSH_ERROR_OUT_OF_MEMORY");
238         } else if (ret == PUSH_ERROR_NO_DATA) {
239           LoggerE("[push_get_registration_id]   PUSH_ERROR_NO_DATA");
240         }
241         LoggerE("Failed to get id: push_get_registration_id failed (%d)", ret);
242         return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
243             "Unknown error");
244     }
245     id = temp;
246     free(temp);
247     return common::PlatformResult(ErrorCode::NO_ERROR);
248 }
249
250 common::PlatformResult PushManager::getUnreadNotifications() {
251     LoggerD("Enter");
252     int ret = push_request_unread_notification(m_handle);
253     if (ret != PUSH_ERROR_NONE) {
254         LoggerE(
255             "Failed to send request: push_request_unread_notification failed (%d)", ret);
256         return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
257             "Unknown error");
258     }
259     return common::PlatformResult(ErrorCode::NO_ERROR);
260 }
261
262 void PushManager::onPushState(push_state_e state, const char* err,
263         void* user_data) {
264     LoggerD("Enter %d, err: %s", state, err);
265     getInstance().m_state = state;
266 }
267
268 void PushManager::onPushNotify(push_notification_h noti, void* user_data) {
269     LoggerD("Enter");
270     if (!getInstance().m_listener) {
271         LoggerW("Listener not set, ignoring");
272         return;
273     }
274
275     char* temp = NULL;
276     int ret = push_get_notification_data(noti, &temp);
277     if (ret != PUSH_ERROR_NONE) {
278         LoggerE("Failed to get appData");
279         return;
280     }
281     std::string appData = temp;
282     free(temp);
283
284     temp = NULL;
285     ret = push_get_notification_message(noti, &temp);
286     if (ret != PUSH_ERROR_NONE) {
287         LoggerE("Failed to get message");
288         return;
289     }
290
291     // parse query string and find value for alertMessage
292     pcrecpp::StringPiece input(temp);
293     pcrecpp::RE re("([^=]+)=([^&]*)&?");
294     string key;
295     string value;
296     std::string alertMessage;
297     while (re.Consume(&input, &key, &value)) {
298         if (key == "alertMessage") {
299             alertMessage = value;
300             break;
301         }
302     }
303     free(temp);
304
305     long long int date = -1;
306     ret = push_get_notification_time(noti, &date);
307     if (ret != PUSH_ERROR_NONE) {
308         LoggerE("Failed to get date");
309         return;
310     }
311     getInstance().m_listener->onPushNotify(appData, alertMessage, date);
312 }
313
314 void PushManager::onPushRegister(push_result_e result, const char* msg,
315         void* user_data) {
316     LoggerD("Enter");
317     if (!getInstance().m_listener) {
318         LoggerW("Listener not set, ignoring");
319         return;
320     }
321     double* callbackId = static_cast<double*>(user_data);
322     std::string id;
323     PlatformResult res(ErrorCode::NO_ERROR);
324     if (result == PUSH_RESULT_SUCCESS) {
325         LoggerD("Success");
326         char *temp = NULL;
327         int ret = push_get_registration_id(getInstance().m_handle, &temp);
328         if (ret == PUSH_ERROR_NONE) {
329             LoggerD("Registration id retrieved");
330             id = temp;
331             free(temp);
332         } else {
333             LoggerD("Failed to retrieve registration id: push_get_registration_id(%d)", ret);
334             res = PlatformResult(ErrorCode::UNKNOWN_ERR,
335                 "Failed to retrieve registration id");
336         }
337     } else {
338         if (result == PUSH_RESULT_TIMEOUT) {
339             LoggerE("PUSH_RESULT_TIMEOUT");
340         } else if (result == PUSH_RESULT_SERVER_ERROR) {
341             LoggerE("PUSH_RESULT_SERVER_ERROR");
342         } else if (result == PUSH_RESULT_SYSTEM_ERROR) {
343             LoggerE("PUSH_RESULT_SYSTEM_ERROR");
344         }
345         res = PlatformResult(ErrorCode::UNKNOWN_ERR,
346                 msg == NULL ? "Unknown error" : msg);
347     }
348     // onPushState is not always called when onPushRegister is successfull
349     getInstance().m_state = PUSH_STATE_REGISTERED;
350     getInstance().m_listener->onPushRegister(*callbackId, res, id);
351     delete callbackId;
352 }
353
354 gboolean PushManager::onFakeDeregister(gpointer user_data) {
355     LoggerD("Enter");
356     if (!getInstance().m_listener) {
357         LoggerW("Listener not set, ignoring");
358         return G_SOURCE_REMOVE;
359     }
360     double* callbackId = static_cast<double*>(user_data);
361     getInstance().m_listener->onDeregister(*callbackId,
362         PlatformResult(ErrorCode::NO_ERROR));
363     delete callbackId;
364     return G_SOURCE_REMOVE;
365 }
366
367 void PushManager::onDeregister(push_result_e result, const char* msg,
368         void* user_data) {
369     LoggerD("Enter");
370     if (!getInstance().m_listener) {
371         LoggerW("Listener not set, ignoring");
372         return;
373     }
374     double* callbackId = static_cast<double*>(user_data);
375     if (result == PUSH_RESULT_SUCCESS) {
376         getInstance().m_listener->onDeregister(*callbackId,
377             PlatformResult(ErrorCode::NO_ERROR));
378     } else {
379         getInstance().m_listener->onDeregister(*callbackId,
380             PlatformResult(ErrorCode::UNKNOWN_ERR,
381                 msg == NULL ? "Unknown error" : msg));
382     }
383     delete callbackId;
384 }
385
386 }  // namespace push
387 }  // namespace extension
388