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