Tizen 2.4.0 rev3 SDK Public Release
[framework/location/maps-service.git] / src / api / maps_service.cpp
1 /*
2  * Copyright (c) 2014 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 <glib.h>
18 #include "maps_service.h"
19 #include "maps_error.h"
20 #include "maps_service.h"
21 #include "maps_util.h"
22
23 #include "command_queue.h"
24 #include "commands.h"
25 #include "discovery.h"
26 #include "module.h"
27
28 #include <privilege_checker.h>
29
30 /*----------------------------------------------------------------------------*/
31 /* Structure of maps_service */
32 /* maps_service_s* is used as maps_service_h */
33 typedef struct _maps_service_s
34 {
35         maps_plugin_h plugin;
36 } maps_service_s;
37
38 const gsize _MAPS_PROVIDER_KEY_MAX_LENGTH = 1024;
39
40 static session::command_queue *q()
41 {
42         return session::command_queue::interface();
43 }
44
45 /* This function is used in command class */
46 plugin::plugin_s *__extract_plugin(maps_service_h maps)
47 {
48         if (!maps)
49                 return NULL;
50         maps_service_s *maps_service = (maps_service_s *) maps;
51         return (plugin::plugin_s *) maps_service->plugin;
52 }
53
54 static bool __maps_provider_supported(maps_service_h maps,
55                                       maps_service_e service)
56 {
57         if (!maps)
58                 return false;
59         bool supported = false;
60         if (maps_service_provider_is_service_supported(maps, service,
61                         &supported) != MAPS_ERROR_NONE)
62                 return false;
63         return supported;
64 }
65
66 static bool __has_maps_service_privilege()
67 {
68         return (privilege_checker_check_privilege(
69                 "http://tizen.org/privilege/mapservice")
70                         == PRIVILEGE_CHECKER_ERR_NONE);
71 }
72
73 /*----------------------------------------------------------------------------*/
74 /* */
75 /* Maps Service & Preference */
76
77 EXPORT_API int maps_service_foreach_provider(maps_service_provider_info_cb
78                                              callback,
79                                              void *user_data)
80 {
81         if (!callback)
82                 return MAPS_ERROR_INVALID_PARAMETER;
83
84         /* The list of map provider info, obtained by enumerating available
85          *  plugins */
86         plugin::discovery pd;
87         vector < plugin::provider_info > v = pd.get_available_list();
88
89         /* Send obtained provider info to the user */
90         const int total = int(v.size());
91         for (int i = 0; i < total; i++) {
92                 /* Get a plugin info handle from the array */
93                 /* and send a callback with provider info to the user */
94                 char *provider = g_strdup(v[i].provider.c_str());
95                 if (!callback(provider, user_data))
96                         break;
97         }
98
99         return MAPS_ERROR_NONE;
100 }
101
102 EXPORT_API int maps_service_create(const char *maps_provider,
103                                    maps_service_h *maps)
104 {
105         /* Check if parameters are valid */
106         if (!maps || !maps_provider)
107                 return MAPS_ERROR_INVALID_PARAMETER;
108
109         /* Check if privileges enough */
110         if (!__has_maps_service_privilege())
111                 return MAPS_ERROR_PERMISSION_DENIED;
112
113         int error = MAPS_ERROR_NOT_SUPPORTED;
114
115         do {
116                 /* 0. Find the plugin, requested by the user */
117                 const plugin::provider_info info =
118                         plugin::find_by_names(string(maps_provider));
119
120                 /* 1. Check whether provider info is valid */
121                 if (info.empty()) {
122                         MAPS_LOGE("ERROR! Provider info not found for name: %s",
123                                 maps_provider);
124                         error = MAPS_ERROR_NOT_SUPPORTED;
125                         break;
126                 }
127
128                 /* 2. Setup maps service handling structure */
129                 maps_service_s *maps_service = g_slice_new0(maps_service_s);
130
131                 if (maps_service == NULL) {
132                         MAPS_LOGE("OUT_OF_MEMORY(0x%08x)",
133                                 MAPS_ERROR_OUT_OF_MEMORY);
134                         error = MAPS_ERROR_OUT_OF_MEMORY;
135                         break;
136                 }
137
138                 /* 3. Initialize the requested plugin */
139
140                 int init_error = MAPS_ERROR_NONE; /* Storage for init error code */
141
142                 maps_plugin_h plugin_h =
143                         plugin::binary_extractor().init(info, &init_error);
144                 if (!plugin_h) {
145                         error = init_error;
146                         MAPS_LOGE("ERROR! Plugin init failed");
147                         break;
148                 }
149
150                 maps_service->plugin = plugin_h;
151
152                 /* 4. Initialize an output pointer to maps service */
153                 *maps = maps_service;
154
155                 /* 5. Set status of completely correct plugin initialization */
156                 error = MAPS_ERROR_NONE;
157
158         } while(false);
159
160         if (error != MAPS_ERROR_NONE)
161                 maps_service_destroy(*maps);
162
163         return error;
164 }
165
166 EXPORT_API int maps_service_destroy(maps_service_h maps)
167 {
168         /* Check if parameters are valid */
169         if (!maps)
170                 return MAPS_ERROR_INVALID_PARAMETER;
171
172         /* Check if privileges enough */
173         if (!__has_maps_service_privilege())
174                 return MAPS_ERROR_PERMISSION_DENIED;
175
176         maps_service_s *maps_service = (maps_service_s *) maps;
177
178         if (maps_service->plugin)
179                 plugin::binary_extractor().shutdown(maps_service->plugin);
180
181         g_slice_free(maps_service_s, maps);
182
183         return MAPS_ERROR_NONE;
184 }
185
186 EXPORT_API int maps_service_set_provider_key(maps_service_h maps,
187                                              const char *provider_key)
188 {
189         if (!maps || !provider_key)
190                 return MAPS_ERROR_INVALID_PARAMETER;
191         const plugin::plugin_s *p = __extract_plugin(maps);
192         if (!p)
193                 return MAPS_ERROR_INVALID_PARAMETER;
194         return p->interface.maps_plugin_set_provider_key(provider_key);
195 }
196
197 EXPORT_API int maps_service_get_provider_key(const maps_service_h maps,
198                                              char **provider_key)
199 {
200         if (!maps || !provider_key)
201                 return MAPS_ERROR_INVALID_PARAMETER;
202         const plugin::plugin_s *p = __extract_plugin(maps);
203         if (!p)
204                 return MAPS_ERROR_INVALID_PARAMETER;
205         return p->interface.maps_plugin_get_provider_key(provider_key);
206 }
207
208 EXPORT_API int maps_service_set_preference(maps_service_h maps,
209                                            maps_string_hashtable_h preference)
210 {
211         if (!maps || !preference)
212                 return MAPS_ERROR_INVALID_PARAMETER;
213         const plugin::plugin_s *p = __extract_plugin(maps);
214         if (!p)
215                 return MAPS_ERROR_INVALID_PARAMETER;
216         return p->interface.maps_plugin_set_preference(preference);
217 }
218
219 EXPORT_API int maps_service_get_preference(maps_service_h maps,
220                                            maps_string_hashtable_h *preference)
221 {
222         if (!maps || !preference)
223                 return MAPS_ERROR_INVALID_PARAMETER;
224         const plugin::plugin_s *p = __extract_plugin(maps);
225         if (!p)
226                 return MAPS_ERROR_INVALID_PARAMETER;
227         return p->interface.maps_plugin_get_preference(preference);
228 }
229
230 EXPORT_API int maps_service_provider_is_service_supported(const maps_service_h
231                                                           maps,
232                                                         maps_service_e service,
233                                                         bool *supported)
234 {
235         if (!maps || !supported)
236                 return MAPS_ERROR_INVALID_PARAMETER;
237         if ((service < MAPS_SERVICE_GEOCODE)
238             || (service > MAPS_SERVICE_CANCEL_REQUEST))
239                 return MAPS_ERROR_INVALID_PARAMETER;
240         const plugin::plugin_s *p = __extract_plugin(maps);
241         if (!p)
242                 return MAPS_ERROR_NOT_SUPPORTED;
243         return p->interface.maps_plugin_is_service_supported(service,
244                 supported);
245 }
246
247 EXPORT_API int maps_service_provider_is_data_supported(const maps_service_h
248                                                        maps,
249                                                        maps_service_data_e data,
250                                                        bool *supported)
251 {
252         if (!maps || !supported)
253                 return MAPS_ERROR_INVALID_PARAMETER;
254         if ((data < MAPS_PLACE_ADDRESS)
255             || (data > MAPS_ROUTE_SEGMENTS_MANEUVERS))
256                 return MAPS_ERROR_INVALID_PARAMETER;
257
258         const plugin::plugin_s *p = __extract_plugin(maps);
259         if (!p)
260                 return MAPS_ERROR_NOT_SUPPORTED;
261         return p->interface.maps_plugin_is_data_supported(data, supported);
262 }
263
264 /*----------------------------------------------------------------------------*/
265 /* */
266 /* Geocoder Service */
267
268 EXPORT_API int maps_service_geocode(const maps_service_h maps,
269                                     const char *address,
270                                     const maps_preference_h preference,
271                                     maps_service_geocode_cb callback,
272                                     void *user_data,
273                                     int *request_id)
274 {
275         /* Check if the handle of the Maps Service is valid */
276         if (!maps)
277                 return MAPS_ERROR_INVALID_PARAMETER;
278
279         /* Check if this API feature available */
280         if (!__maps_provider_supported(maps, MAPS_SERVICE_GEOCODE))
281                 return MAPS_ERROR_NOT_SUPPORTED;
282
283         /* Check if parameters are valid */
284         if (!address || !callback || !request_id)
285                 return MAPS_ERROR_INVALID_PARAMETER;
286
287         /* Check if privileges enough */
288         if (!__has_maps_service_privilege())
289                 return MAPS_ERROR_PERMISSION_DENIED;
290
291         return q()->push(new session::command_geocode(maps, address, preference,
292                         callback, user_data, request_id));
293 }
294
295 EXPORT_API int maps_service_geocode_inside_area(const maps_service_h maps,
296                                                 const char *address,
297                                                 const maps_area_h bounds,
298                                         const maps_preference_h preference,
299                                         maps_service_geocode_cb callback,
300                                         void *user_data, int *request_id)
301 {
302         /* Check if the handle of the Maps Service is valid */
303         if (!maps)
304                 return MAPS_ERROR_INVALID_PARAMETER;
305
306         /* Check if this API feature available */
307         if (!__maps_provider_supported(maps,
308                         MAPS_SERVICE_GEOCODE_INSIDE_AREA))
309                 return MAPS_ERROR_NOT_SUPPORTED;
310
311         /* Check if parameters are valid */
312         if (!address || !bounds || !callback || !request_id)
313                 return MAPS_ERROR_INVALID_PARAMETER;
314
315         /* Check if privileges enough */
316         if (!__has_maps_service_privilege())
317                 return MAPS_ERROR_PERMISSION_DENIED;
318
319         return q()->push(new session::command_geocode_inside_bounds(maps,
320                         address, bounds, preference, callback, user_data,
321                         request_id));
322 }
323
324 EXPORT_API int maps_service_geocode_by_structured_address(const maps_service_h
325                                                           maps,
326                                         const maps_address_h address,
327                                         const maps_preference_h preference,
328                                         maps_service_geocode_cb callback,
329                                         void *user_data, int *request_id)
330 {
331         /* Check if the handle of the Maps Service is valid */
332         if (!maps)
333                 return MAPS_ERROR_INVALID_PARAMETER;
334
335         /* Check if this API feature available */
336         if (!__maps_provider_supported(maps,
337                         MAPS_SERVICE_GEOCODE_BY_STRUCTURED_ADDRESS))
338                 return MAPS_ERROR_NOT_SUPPORTED;
339
340         /* Check if parameters are valid */
341         if (!address || !callback || !request_id)
342                 return MAPS_ERROR_INVALID_PARAMETER;
343
344         /* Check if privileges enough */
345         if (!__has_maps_service_privilege())
346                 return MAPS_ERROR_PERMISSION_DENIED;
347
348         return q()->
349                 push(new session::command_geocode_by_structured_address(maps,
350                         address, preference, callback, user_data, request_id));
351 }
352
353 EXPORT_API int maps_service_reverse_geocode(const maps_service_h maps,
354                                             double latitude, double longitude,
355                                             const maps_preference_h preference,
356                                             maps_service_reverse_geocode_cb
357                                             callback, void * user_data,
358                                             int *request_id)
359 {
360         /* Check if the handle of the Maps Service is valid */
361         if (!maps)
362                 return MAPS_ERROR_INVALID_PARAMETER;
363
364         /* Check if this API feature available */
365         if (!__maps_provider_supported(maps, MAPS_SERVICE_REVERSE_GEOCODE))
366                 return MAPS_ERROR_NOT_SUPPORTED;
367
368         /* Check if parameters are valid */
369         if (!callback || !request_id)
370                 return MAPS_ERROR_INVALID_PARAMETER;
371         if (latitude <= -90 && latitude >= 90)
372                 return MAPS_ERROR_INVALID_PARAMETER;
373         if (longitude <= -180 && longitude >= 180)
374                 return MAPS_ERROR_INVALID_PARAMETER;
375
376         /* Check if privileges enough */
377         if (!__has_maps_service_privilege())
378                 return MAPS_ERROR_PERMISSION_DENIED;
379
380         return q()->push(new session::command_reverse_geocode(maps, latitude,
381                         longitude, preference, callback, user_data,
382                         request_id));
383 }
384
385 /*----------------------------------------------------------------------------*/
386 /* */
387 /* Place Service */
388
389 EXPORT_API int maps_service_search_place(const maps_service_h maps,
390                                          const maps_coordinates_h position,
391                                          int distance,
392                                          const maps_place_filter_h filter,
393                                          maps_preference_h preference,
394                                          maps_service_search_place_cb callback,
395                                          void *user_data, int *request_id)
396 {
397         /* Check if the handle of the Maps Service is valid */
398         if (!maps)
399                 return MAPS_ERROR_INVALID_PARAMETER;
400
401         /* Check if this API feature available */
402         if (!__maps_provider_supported(maps, MAPS_SERVICE_SEARCH_PLACE))
403                 return MAPS_ERROR_NOT_SUPPORTED;
404
405         /* Check if parameters are valid */
406         if (!position || !filter || !callback || !request_id)
407                 return MAPS_ERROR_INVALID_PARAMETER;
408
409         /* Check if privileges enough */
410         if (!__has_maps_service_privilege())
411                 return MAPS_ERROR_PERMISSION_DENIED;
412
413         return q()->push(new session::command_search_place(maps, position,
414                         distance, preference, filter, callback, user_data,
415                         request_id));
416 }
417
418 EXPORT_API int maps_service_search_place_by_area(const maps_service_h maps,
419                                                  const maps_area_h boundary,
420                                                  const maps_place_filter_h
421                                                  filter,
422                                                  maps_preference_h preference,
423                                                  maps_service_search_place_cb
424                                                  callback,
425                                                  void *user_data,
426                                                  int *request_id)
427 {
428         /* Check if the handle of the Maps Service is valid */
429         if (!maps)
430                 return MAPS_ERROR_INVALID_PARAMETER;
431
432         /* Check if this API feature available */
433         if (!__maps_provider_supported(maps,
434                         MAPS_SERVICE_SEARCH_PLACE_BY_AREA))
435                 return MAPS_ERROR_NOT_SUPPORTED;
436
437         /* Check if parameters are valid */
438         if (!boundary || !filter || !callback || !request_id)
439                 return MAPS_ERROR_INVALID_PARAMETER;
440
441         /* Check if privileges enough */
442         if (!__has_maps_service_privilege())
443                 return MAPS_ERROR_PERMISSION_DENIED;
444
445         return q()->push(new session::command_search_by_area_place(maps,
446                         boundary, preference, filter, callback, user_data,
447                         request_id));
448 }
449
450 EXPORT_API int maps_service_search_place_by_address(const maps_service_h maps,
451                                                     const char *address,
452                                                     const maps_area_h boundary,
453                                                     const maps_place_filter_h
454                                                     filter,
455                                                     maps_preference_h
456                                                     preference,
457                                                 maps_service_search_place_cb
458                                                 callback,
459                                                 void *user_data,
460                                                 int *request_id)
461 {
462         /* Check if the handle of the Maps Service is valid */
463         if (!maps)
464                 return MAPS_ERROR_INVALID_PARAMETER;
465
466         /* Check if this API feature available */
467         if (!__maps_provider_supported(maps,
468                         MAPS_SERVICE_SEARCH_PLACE_BY_ADDRESS))
469                 return MAPS_ERROR_NOT_SUPPORTED;
470
471         /* Check if parameters are valid */
472         if (!address || !boundary || !filter || !callback || !request_id)
473                 return MAPS_ERROR_INVALID_PARAMETER;
474
475         /* Check if privileges enough */
476         if (!__has_maps_service_privilege())
477                 return MAPS_ERROR_PERMISSION_DENIED;
478
479         return q()->push(new session::command_search_by_address_place(maps,
480                         address, boundary, preference, filter, callback,
481                         user_data, request_id));
482 }
483
484 /*----------------------------------------------------------------------------*/
485 /* */
486 /* Route Service */
487
488 EXPORT_API int maps_service_search_route(const maps_service_h maps,
489                                          const maps_coordinates_h origin,
490                                          const maps_coordinates_h destination,
491                                          maps_preference_h preference,
492                                          maps_service_search_route_cb callback,
493                                          void *user_data, int *request_id)
494 {
495         /* Check if the handle of the Maps Service is valid */
496         if (!maps)
497                 return MAPS_ERROR_INVALID_PARAMETER;
498
499         /* Check if this API feature available */
500         if (!__maps_provider_supported(maps, MAPS_SERVICE_SEARCH_ROUTE))
501                 return MAPS_ERROR_NOT_SUPPORTED;
502
503         /* Check if parameters are valid */
504         if (!origin || !destination || !callback || !request_id)
505                 return MAPS_ERROR_INVALID_PARAMETER;
506
507         /* Check if privileges enough */
508         if (!__has_maps_service_privilege())
509                 return MAPS_ERROR_PERMISSION_DENIED;
510
511         return q()->push(new session::command_search_route(maps, preference,
512                         origin, destination, callback, user_data, request_id));
513 }
514
515 EXPORT_API int maps_service_search_route_waypoints(const maps_service_h maps,
516                                                    const maps_coordinates_h *
517                                                    waypoint_list,
518                                                    int waypoint_num,
519                                                    maps_preference_h preference,
520                                                    maps_service_search_route_cb
521                                                    callback,
522                                                    void *user_data,
523                                                    int *request_id)
524 {
525         /* Check if the handle of the Maps Service is valid */
526         if (!maps)
527                 return MAPS_ERROR_INVALID_PARAMETER;
528
529         /* Check if this API feature available */
530         if (!__maps_provider_supported(maps,
531                         MAPS_SERVICE_SEARCH_ROUTE_WAYPOINTS))
532                 return MAPS_ERROR_NOT_SUPPORTED;
533
534         /* Check if parameters are valid */
535         if (!waypoint_list || (waypoint_num < 2) || !callback || !request_id)
536                 return MAPS_ERROR_INVALID_PARAMETER;
537
538         /* Check if privileges enough */
539         if (!__has_maps_service_privilege())
540                 return MAPS_ERROR_PERMISSION_DENIED;
541
542         return q()->push(new session::command_search_route_waypoints(maps,
543                         preference, waypoint_list, waypoint_num, callback,
544                         user_data, request_id));
545 }
546
547 /*----------------------------------------------------------------------------*/
548 /* */
549 /* Cancel Service Request */
550
551 EXPORT_API int maps_service_cancel_request(const maps_service_h maps,
552                                            int request_id)
553 {
554         /* Check if the handle of the Maps Service is valid */
555         if (!maps)
556                 return MAPS_ERROR_INVALID_PARAMETER;
557
558         /* Check if this API feature available */
559         if (!__maps_provider_supported(maps, MAPS_SERVICE_CANCEL_REQUEST))
560                 return MAPS_ERROR_NOT_SUPPORTED;
561
562         /* Check if parameters are valid */
563         if (request_id < 0)
564                 return MAPS_ERROR_INVALID_PARAMETER;
565
566         /* Check if privileges enough */
567         if (!__has_maps_service_privilege())
568                 return MAPS_ERROR_PERMISSION_DENIED;
569
570         return q()->push(new session::command_cancel_request(maps, request_id));
571 }