Initialize geolocation provider
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / API / efl / ewk_geolocation_provider.cpp
1 /*
2    Copyright (C) 2012, 2013 Samsung Electronics
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21 #include "ewk_geolocation_provider.h"
22
23 #if ENABLE(TIZEN_GEOLOCATION)
24 #include "WKGeolocationManager.h"
25 #include "ewk_geolocation_provider_private.h"
26 #include "ewk_view_private.h"
27
28 Ewk_Geolocation_Provider::Ewk_Geolocation_Provider(WKContextRef contextRef)
29     : m_locationManagerStarted(false)
30     , m_locationManager(0)
31     , m_wkContext(contextRef)
32 {
33     ASSERT(m_wkContext.get());
34     WKGeolocationManagerRef geolocationManagerRef = WKContextGetGeolocationManager(m_wkContext.get());
35     ASSERT(geolocationManagerRef);
36
37     WKGeolocationProvider provider = {
38         kWKGeolocationProviderCurrentVersion,
39         this,
40         startUpdating,
41         stopUpdating,
42     };
43
44     WKGeolocationManagerSetProvider(geolocationManagerRef, &provider);
45 }
46
47 Ewk_Geolocation_Provider::~Ewk_Geolocation_Provider()
48 {
49     stopUpdating(0, this);
50     WKGeolocationManagerSetProvider(wkGeolocationManager(), 0);
51 }
52
53 void Ewk_Geolocation_Provider::watchValidity(const GeolocationValidityCallbackData& callbackData)
54 {
55     ASSERT(callbackData);
56     if (m_validityListeners.contains(callbackData.userData))
57         return;
58
59     m_validityListeners.add(callbackData.userData, callbackData);
60 }
61
62 void Ewk_Geolocation_Provider::unwatchValidity(void* userData)
63 {
64     ASSERT(userData);
65     m_validityListeners.remove(userData);
66
67     if (m_locationManagerStarted && m_validityListeners.isEmpty()) {
68         TIZEN_LOGI("no validityListeners now. So stop updating... ");
69         stopUpdating(0, this);
70     }
71 }
72
73 WKGeolocationManagerRef Ewk_Geolocation_Provider::wkGeolocationManager()
74 {
75     return WKContextGetGeolocationManager(m_wkContext.get());
76 }
77
78 static void ewkGeolocationProviderPositionChangedCallback(double latitude, double longitude, double altitude, time_t timestamp, void* user_data)
79 {
80     Ewk_Geolocation_Provider* ewkGeolocationProvider = static_cast<Ewk_Geolocation_Provider*>(user_data);
81     if(!timestamp || !ewkGeolocationProvider)
82         return;
83
84     location_accuracy_level_e level;
85     double horizontal;
86     double vertical;
87
88     location_manager_get_last_accuracy(ewkGeolocationProvider->locationManager(), &level, &horizontal, &vertical);
89
90     WKRetainPtr<WKGeolocationPositionRef> position(AdoptWK, WKGeolocationPositionCreate(timestamp, latitude, longitude, horizontal));
91     WKGeolocationManagerProviderDidChangePosition(ewkGeolocationProvider->wkGeolocationManager(), position.get());
92 }
93
94 void Ewk_Geolocation_Provider::startUpdating(WKGeolocationManagerRef, const void* clientInfo)
95 {
96     ASSERT(clientInfo);
97     Ewk_Geolocation_Provider* ewkGeolocationProvider = static_cast<Ewk_Geolocation_Provider*>(const_cast<void*>(clientInfo));
98
99     if (ewkGeolocationProvider->m_locationManagerStarted)
100         return;
101
102     if (ewkGeolocationProvider->m_validityListeners.isEmpty()) {
103         TIZEN_LOGE("No valid view exists");
104         WKGeolocationManagerProviderDidFailToDeterminePosition(ewkGeolocationProvider->wkGeolocationManager());
105         return;
106     }
107
108     ValidityListenerMap::const_iterator validtyListener = ewkGeolocationProvider->m_validityListeners.begin();
109     if (!validtyListener->second.callback(validtyListener->second.userData)) {
110         TIZEN_LOGE("No valid view exists");
111         WKGeolocationManagerProviderDidFailToDeterminePosition(ewkGeolocationProvider->wkGeolocationManager());
112         return;
113     }
114
115     location_error_e ret = static_cast<location_error_e>(location_manager_create(LOCATIONS_METHOD_HYBRID, &ewkGeolocationProvider->m_locationManager));
116     if (ret != LOCATIONS_ERROR_NONE) {
117         TIZEN_LOGE("location_manager_create error (%d)", ret);
118         WKGeolocationManagerProviderDidFailToDeterminePosition(ewkGeolocationProvider->wkGeolocationManager());
119         return;
120     }
121
122     ret = static_cast<location_error_e>(location_manager_set_position_updated_cb(ewkGeolocationProvider->m_locationManager, ewkGeolocationProviderPositionChangedCallback, 1, const_cast<Ewk_Geolocation_Provider*>(ewkGeolocationProvider)));
123     if (ret != LOCATIONS_ERROR_NONE){
124         TIZEN_LOGE("location_manager_set_position_updated_cb error(%d)", ret);
125         location_manager_destroy(ewkGeolocationProvider->m_locationManager);
126         WKGeolocationManagerProviderDidFailToDeterminePosition(ewkGeolocationProvider->wkGeolocationManager());
127         return;
128     }
129
130     ret = static_cast<location_error_e>(location_manager_start(ewkGeolocationProvider->m_locationManager));
131     if (ret != LOCATIONS_ERROR_NONE) {
132         TIZEN_LOGE("location_manager_start error(%d)", ret);
133         location_manager_unset_position_updated_cb(ewkGeolocationProvider->m_locationManager);
134         location_manager_destroy(ewkGeolocationProvider->m_locationManager);
135         WKGeolocationManagerProviderDidFailToDeterminePosition(ewkGeolocationProvider->wkGeolocationManager());
136         return;
137     }
138
139     ewkGeolocationProvider->m_locationManagerStarted = true;
140 }
141
142 void Ewk_Geolocation_Provider::stopUpdating(WKGeolocationManagerRef, const void* clientInfo)
143 {
144     ASSERT(clientInfo);
145     Ewk_Geolocation_Provider* ewkGeolocationProvider = static_cast<Ewk_Geolocation_Provider*>(const_cast<void*>(clientInfo));
146
147     if (!ewkGeolocationProvider->m_locationManagerStarted) {
148         TIZEN_LOGE("started error");
149         return;
150     }
151
152     location_error_e ret = static_cast<location_error_e>(location_manager_stop(ewkGeolocationProvider->m_locationManager));
153     if (ret != LOCATIONS_ERROR_NONE) {
154         TIZEN_LOGE("location_manager_stop error(%d)", ret);
155         location_manager_destroy(ewkGeolocationProvider->m_locationManager);
156     }
157
158     ret = static_cast<location_error_e>(location_manager_unset_position_updated_cb(ewkGeolocationProvider->m_locationManager));
159     if (ret != LOCATIONS_ERROR_NONE) {
160         TIZEN_LOGE("location_manager_unset_position_updated_cb error(%d)", ret);
161         return;
162     }
163
164     ret = static_cast<location_error_e>(location_manager_destroy(ewkGeolocationProvider->m_locationManager));
165     if (ret != LOCATIONS_ERROR_NONE) {
166         TIZEN_LOGE("location_manager_destroy error(%d)", ret);
167         return;
168     }
169
170     ewkGeolocationProvider->m_locationManagerStarted = false;
171 }
172 #endif // ENABLE(TIZEN_GEOLOCATION)