Add LCOV remarkers to increase line coverage rate
[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_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                 //LCOV_EXCL_STOP
123         }
124
125         return l;
126 }
127
128 plugin::provider_info plugin::find_by_names(const string &provider)
129 {
130         const vector<provider_info> v = discovery().get_available_list();
131         for (int i = 0; i < int (v.size()); i++)
132                 if (v[i].provider == provider)
133                         return v[i];
134
135         return provider_info::empty_instance;
136 }
137
138 void plugin::split_provider_name(const char *original, char **provider, char **module)
139 {
140         char *save, *_provider, *_module;
141
142         _provider = strtok_r(g_strdup(original), "/", &save);
143         _module = g_strdup(strtok_r(NULL, "", &save));
144
145         if (provider)
146                 *provider = g_strdup(_provider);
147         if (module)
148                 *module = g_strdup(_module);
149
150         g_free(_provider);
151         g_free(_module);
152 }
153
154
155 typedef struct
156 {
157         maps_service_request_user_consent_cb callback;
158         char *provider;
159         void *user_data;
160         void *plugin;
161 } user_consent_s;
162
163 gboolean user_consent_shutdown(gpointer data)
164 {
165         if (!data) return false;
166
167         user_consent_s *uc = (user_consent_s*)data;
168         plugin::user_consent_checker().shutdown(uc->plugin);
169         g_free(uc->provider);
170         g_free(uc);
171         return false;
172 }
173
174 void plugin::user_consent_cb(bool consented, const char *provider, void *user_data)
175 {
176         MAPS_LOGE("user_consent_cb is called");
177         user_consent_s *uc = (user_consent_s*)user_data;
178         if (uc && uc->callback)
179                 uc->callback(consented, provider, uc->user_data);
180         g_idle_add(user_consent_shutdown, (void*)uc);
181 }
182
183 int plugin::request_user_consent(const char *maps_provider, void *callback, void *user_data)
184 {
185         if (!maps_provider || !callback)
186                 return MAPS_ERROR_INVALID_PARAMETER;
187
188         char *provider = NULL, *module = NULL;
189         plugin::split_provider_name(maps_provider, &provider, &module);
190         const plugin::provider_info info = plugin::find_by_names(provider);
191
192         /* 1. initialize the requested plugin */
193         int error = MAPS_ERROR_SERVICE_NOT_AVAILABLE;
194         int init_error = MAPS_ERROR_NONE; /* Storage for init error code */
195         plugin_s *plugin_handle = (plugin_s*)plugin::user_consent_checker().init(info, module, &init_error);
196         g_free(provider);
197         g_free(module);
198         if (!plugin_handle) {
199                 MAPS_LOGE("ERROR! Plugin init failed");
200                 return init_error;
201         }
202
203         /* 2. request user consent */
204         user_consent_s *uc = NULL;
205         if (plugin_handle->interface.maps_plugin_request_user_consent) {
206                 uc = (user_consent_s*)g_malloc0(sizeof(user_consent_s));
207                 if (!uc) {
208                         error = MAPS_ERROR_OUT_OF_MEMORY;
209                 } else {
210                         uc->callback = (maps_service_request_user_consent_cb)callback;
211                         uc->provider = g_strdup(maps_provider);
212                         uc->user_data = user_data;
213                         uc->plugin = plugin_handle;
214                         error = plugin_handle->interface.maps_plugin_request_user_consent(
215                                                                         (const char*)uc->provider, user_consent_cb, (void*)uc);
216                         MAPS_LOGD("maps_plugin_request_user_consent = %d", error);
217                         if (error == MAPS_ERROR_USER_NOT_CONSENTED)
218                                 error = MAPS_ERROR_NONE; //LCOV_EXCL_LINE
219                 }
220         }
221
222         /* 3. shutdown plugin */
223         if (error != MAPS_ERROR_NONE) {
224                 //LCOV_EXCL_START
225                 plugin::user_consent_checker().shutdown(plugin_handle);
226                 if (uc) {
227                         g_free(uc->provider);
228                         g_free(uc);
229                 }
230                 //LCOV_EXCL_STOP
231         }
232
233         return error;
234 }