Fix glib inclusion issue
[platform/core/api/maps-service.git] / src / plugin / discovery.cpp
1 /* Copyright (c) 2010-2014 Samsung Electronics Co., Ltd. All rights reserved.
2  *
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 "discovery.h"
18 #include "module.h"
19 #include "maps_util.h"
20 #include <algorithm>
21 #include <glib.h>
22
23
24 plugin::provider_info plugin::provider_info::empty_instance;
25
26 plugin::provider_info::provider_info()
27 {
28 }
29
30 //LCOV_EXCL_START
31 plugin::provider_info::provider_info(const string &p, const string &f)
32 : provider(p)
33 , file(f)
34 {
35 }
36 //LCOV_EXCL_STOP
37
38 plugin::provider_info::provider_info(const provider_info &src)
39 {
40         *this = src;
41 }
42
43 plugin::provider_info &plugin::provider_info::operator=(const
44                                                         provider_info &src)
45 {
46         if (this != &src) {
47                 provider = src.provider;
48                 file = src.file;
49         }
50         return* this;
51 }
52
53 void plugin::provider_info::construct(const string &p, const string &f)
54 {
55         provider = p;
56         file = f;
57 }
58
59 bool plugin::provider_info::empty() const
60 {
61         if (!provider.empty())
62                 return false;
63         if (!file.empty())
64                 return false;
65         return true;
66 }
67
68 plugin::discovery::discovery()
69 {
70 }
71
72 plugin::discovery::~discovery()
73 {
74 }
75
76 vector<plugin::provider_info> plugin::discovery::get_available_list() const
77 {
78         vector <provider_info> v;
79         binary_extractor be;
80
81         /* Enumerate all available plugin binaries */
82         const vector <string> l = get_module_file_list();
83         for (int i = 0; i < int(l.size()); i++) {
84                 /* Request the next plugin binary to get provider info */
85                 const provider_info info = be.get_plugin_info(l[i]);
86                 if (info.empty())
87                         continue; //LCOV_EXCL_LINE
88
89                 /* Add provider info to the resulting list */
90                 v.push_back(info);
91         }
92
93         return v;
94 }
95
96 vector<string> plugin::discovery::get_module_file_list() const
97 {
98         vector<string> l;
99
100         GDir *dir = NULL;
101         GError *error = NULL;
102         const gchar *filename = NULL;
103
104         MAPS_LOGD("START PLUGIN FILES DISCOVERY:");
105         dir = g_dir_open(MAPS_PLUGINS_PATH_PREFIX, 0, &error);
106         if (dir) {
107                 GPatternSpec *plugin_name_pattern = g_pattern_spec_new("*?.so");
108
109                 while ((filename = g_dir_read_name(dir))) {
110                         MAPS_LOGD("found plugin binary: %s", filename);
111                         if (g_pattern_spec_match_string(plugin_name_pattern, filename)) {
112                                 MAPS_LOGD("\tadded plugin binary: %s", filename);
113                                 l.push_back(string(filename));
114                         }
115                 }
116
117                 g_pattern_spec_free(plugin_name_pattern);
118                 g_dir_close(dir);
119                 //LCOV_EXCL_START
120         } else if (error) {
121                 MAPS_LOGE("%d: Can not open directory: %s\n", error->code, error->message);
122                 g_error_free(error);
123                 //LCOV_EXCL_STOP
124         }
125
126         return l;
127 }
128
129 plugin::provider_info plugin::find_by_names(const string &provider)
130 {
131         const vector<provider_info> v = discovery().get_available_list();
132         for (int i = 0; i < int (v.size()); i++)
133                 if (v[i].provider == provider)
134                         return v[i];
135
136         return provider_info::empty_instance;
137 }
138
139 void plugin::split_provider_name(const char *original, char **provider, char **module)
140 {
141         char *save = NULL, *_provider = NULL, *_module = NULL;
142
143         _provider = strtok_r(g_strdup(original), "/", &save);
144         _module = g_strdup(strtok_r(NULL, "", &save));
145
146         if (provider)
147                 *provider = g_strdup(_provider);
148         if (module)
149                 *module = g_strdup(_module);
150
151         g_free(_provider);
152         g_free(_module);
153 }
154
155
156 typedef struct
157 {
158         maps_service_request_user_consent_cb callback;
159         char *provider;
160         void *user_data;
161         void *plugin;
162 } user_consent_s;
163
164 gboolean user_consent_shutdown(gpointer data)
165 {
166         if (!data) return false;
167
168         user_consent_s *uc = (user_consent_s*)data;
169         plugin::user_consent_checker().shutdown(uc->plugin);
170         g_free(uc->provider);
171         g_free(uc);
172         return false;
173 }
174
175 void plugin::user_consent_cb(bool consented, const char *provider, void *user_data)
176 {
177         MAPS_LOGE("user_consent_cb is called");
178         user_consent_s *uc = (user_consent_s*)user_data;
179         if (uc && uc->callback)
180                 uc->callback(consented, provider, uc->user_data);
181         g_idle_add(user_consent_shutdown, (void*)uc);
182 }
183
184 int plugin::request_user_consent(const char *maps_provider, void *callback, void *user_data)
185 {
186         if (!maps_provider || !callback)
187                 return MAPS_ERROR_INVALID_PARAMETER;
188
189         char *provider = NULL, *module = NULL;
190         plugin::split_provider_name(maps_provider, &provider, &module);
191         const plugin::provider_info info = plugin::find_by_names(provider);
192
193         /* 1. initialize the requested plugin */
194         int error = MAPS_ERROR_SERVICE_NOT_AVAILABLE;
195         int init_error = MAPS_ERROR_NONE; /* Storage for init error code */
196         plugin_s *plugin_handle = (plugin_s*)plugin::user_consent_checker().init(info, module, &init_error);
197         g_free(provider);
198         g_free(module);
199         if (!plugin_handle) {
200                 MAPS_LOGE("ERROR! Plugin init failed");
201                 return init_error;
202         }
203
204         /* 2. request user consent */
205         user_consent_s *uc = NULL;
206         if (plugin_handle->interface.maps_plugin_request_user_consent) {
207                 uc = (user_consent_s*)g_malloc0(sizeof(user_consent_s));
208                 if (!uc) {
209                         error = MAPS_ERROR_OUT_OF_MEMORY;
210                 } else {
211                         uc->callback = (maps_service_request_user_consent_cb)callback;
212                         uc->provider = g_strdup(maps_provider);
213                         uc->user_data = user_data;
214                         uc->plugin = plugin_handle;
215                         error = plugin_handle->interface.maps_plugin_request_user_consent(
216                                                                         (const char*)uc->provider, user_consent_cb, (void*)uc);
217                         MAPS_LOGD("maps_plugin_request_user_consent = %d", error);
218                         if (error == MAPS_ERROR_USER_NOT_CONSENTED)
219                                 error = MAPS_ERROR_NONE; //LCOV_EXCL_LINE
220                 }
221         }
222
223         /* 3. shutdown plugin */
224         if (error != MAPS_ERROR_NONE) {
225                 //LCOV_EXCL_START
226                 plugin::user_consent_checker().shutdown(plugin_handle);
227                 if (uc) {
228                         g_free(uc->provider);
229                         g_free(uc);
230                 }
231                 //LCOV_EXCL_STOP
232         }
233
234         return error;
235 }