499ae4c9534b5261b4649fc050c1dd685f67e5d4
[WebKit.git] / Source / WebKit / blackberry / WebCoreSupport / GeolocationClientBlackBerry.cpp
1 /*
2  * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include "config.h"
20 #include "GeolocationClientBlackBerry.h"
21
22 #include "Chrome.h"
23 #include "Geolocation.h"
24 #include "GeolocationController.h"
25 #include "GeolocationError.h"
26 #include "Page.h"
27 #include "WebPage_p.h"
28
29 #include <BlackBerryPlatformString.h>
30
31 using namespace WebCore;
32
33 GeolocationClientBlackBerry::GeolocationClientBlackBerry(BlackBerry::WebKit::WebPagePrivate* webPagePrivate)
34     : m_webPagePrivate(webPagePrivate)
35     , m_accuracy(false)
36     , m_isActive(false)
37 {
38 }
39
40 void GeolocationClientBlackBerry::geolocationDestroyed()
41 {
42     BlackBerry::Platform::GeolocationHandler::instance()->unregisterFromPermissionTracking(this);
43
44     delete this;
45 }
46
47 void GeolocationClientBlackBerry::startUpdating()
48 {
49     if (!m_isActive)
50         BlackBerry::Platform::GeolocationHandler::instance()->addListener(this);
51     m_isActive = true;
52 }
53
54 void GeolocationClientBlackBerry::stopUpdating()
55 {
56     if (m_isActive)
57         BlackBerry::Platform::GeolocationHandler::instance()->removeListener(this);
58     m_isActive = false;
59 }
60
61 GeolocationPosition* GeolocationClientBlackBerry::lastPosition()
62 {
63     return m_lastPosition.get();
64 }
65
66 void GeolocationClientBlackBerry::requestPermission(Geolocation* location)
67 {
68     Frame* frame = location->frame();
69     if (!frame)
70         return;
71
72     // FIXME: The geolocation setting for WebSettings is always true. Nothing ever toggles that setting.
73     if (!m_webPagePrivate->m_webSettings->isGeolocationEnabled()) {
74         location->setIsAllowed(false);
75         return;
76     }
77
78     const String origin = frame->document()->securityOrigin()->toString();
79
80     // Check global location setting, if it is off then we request an infobar that invokes a location settings card.
81     // If it's on, then we request an infobar that allows the site to have permission to use geolocation.
82     if (!BlackBerry::Platform::GeolocationHandler::instance()->isGlobalServiceActive()) {
83         // We only want to ask them once per session. If we get here again, automatically fail the request.
84         if (!BlackBerry::Platform::GeolocationHandler::instance()->didAskUserForGlobalPermission()) {
85             m_webPagePrivate->m_client->requestGlobalLocalServicePermission(this, origin);
86             BlackBerry::Platform::GeolocationHandler::instance()->setAskedUserForGlobalPermission();
87         } else
88             location->setIsAllowed(false);
89         return;
90     }
91
92     // Register the listener with the GeolocationHandler to receive permissions.
93     if (m_geolocationRequestMap.isEmpty())
94         BlackBerry::Platform::GeolocationHandler::instance()->registerPermissionTracking(this);
95
96     // Add this geolocation permission request to our request map.
97     Vector<RefPtr<Geolocation> > geoRequestsForOrigin;
98     HashMap<String, Vector<RefPtr<Geolocation> > >::AddResult result = m_geolocationRequestMap.add(origin, geoRequestsForOrigin);
99     result.iterator->value.append(location);
100
101     // Avoid sending another request if the vector already has another geolocation pending for this origin in this page.
102     if (result.isNewEntry)
103         m_webPagePrivate->m_client->requestGeolocationPermission(this, origin);
104 }
105
106 void GeolocationClientBlackBerry::cancelPermissionRequest(Geolocation* location)
107 {
108     Frame* frame = location->frame();
109     if (!frame)
110         return;
111
112     const String origin = frame->document()->securityOrigin()->toString();
113
114     // Remove the geolocation from the pending permission map.
115     HashMap<String, Vector<RefPtr<Geolocation> > >::iterator it = m_geolocationRequestMap.find(origin);
116
117     ASSERT(it != m_geolocationRequestMap.end());
118     if (it == m_geolocationRequestMap.end())
119         return;
120
121     Vector<RefPtr<Geolocation> >* result = &(it->value);
122
123     size_t geolocationCount = result->size();
124     for (size_t i = 0; i < geolocationCount; ++i) {
125         if ((*result)[i].get() == location) {
126             result->remove(i);
127             // Remove this vector from the pending permission map is it doesn't contain anymore geo objects
128             if (result->isEmpty())
129                 m_geolocationRequestMap.remove(origin);
130             break;
131         }
132     }
133
134     if (m_geolocationRequestMap.isEmpty())
135         BlackBerry::Platform::GeolocationHandler::instance()->unregisterFromPermissionTracking(this);
136
137     m_webPagePrivate->m_client->cancelGeolocationPermission();
138 }
139
140 void GeolocationClientBlackBerry::onLocationUpdate(double timestamp, double latitude, double longitude, double accuracy, double altitude, bool altitudeValid,
141                                                              double altitudeAccuracy, bool altitudeAccuracyValid, double speed, bool speedValid, double heading, bool headingValid)
142 {
143     m_lastPosition = GeolocationPosition::create(timestamp, latitude, longitude, accuracy, altitudeValid, altitude, altitudeAccuracyValid,
144                                                  altitudeAccuracy, headingValid, heading, speedValid, speed);
145     GeolocationController::from(m_webPagePrivate->m_page)->positionChanged(m_lastPosition.get());
146 }
147
148 void GeolocationClientBlackBerry::onLocationError(const char* errorStr)
149 {
150     RefPtr<GeolocationError> error = GeolocationError::create(GeolocationError::PositionUnavailable, String::fromUTF8(errorStr));
151     GeolocationController::from(m_webPagePrivate->m_page)->errorOccurred(error.get());
152 }
153
154 void GeolocationClientBlackBerry::onPermission(const BlackBerry::Platform::String& origin, bool isAllowed)
155 {
156     Vector<RefPtr<Geolocation> > pendingPermissionGeolocation = m_geolocationRequestMap.get(origin);
157
158     if (pendingPermissionGeolocation.isEmpty())
159         return;
160
161     size_t numberOfGeolocations = pendingPermissionGeolocation.size();
162     for (size_t i = 0; i < numberOfGeolocations; ++i)
163         pendingPermissionGeolocation[i]->setIsAllowed(isAllowed);
164     m_geolocationRequestMap.remove(origin);
165
166     if (m_geolocationRequestMap.isEmpty())
167         BlackBerry::Platform::GeolocationHandler::instance()->unregisterFromPermissionTracking(this);
168 }
169
170 void GeolocationClientBlackBerry::setEnableHighAccuracy(bool newAccuracy)
171 {
172     if (m_accuracy != newAccuracy) {
173         m_accuracy = newAccuracy;
174         BlackBerry::Platform::GeolocationHandler::instance()->switchAccuracy(this);
175     }
176 }
177