[BlackBerry] GeolocationClientBB should show file system path in prompts when host...
[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 static String getOrigin(Frame* frame) 
34 {
35     String origin; 
36     SecurityOrigin* securityOrigin = frame->document()->securityOrigin();
37
38     // Special case for file.
39     if (securityOrigin->protocol() == "file")
40         origin = securityOrigin->fileSystemPath();
41     else
42         origin = securityOrigin->toString();
43
44     return origin;
45 }
46
47 GeolocationClientBlackBerry::GeolocationClientBlackBerry(BlackBerry::WebKit::WebPagePrivate* webPagePrivate)
48     : m_webPagePrivate(webPagePrivate)
49     , m_accuracy(false)
50     , m_isActive(false)
51 {
52 }
53
54 void GeolocationClientBlackBerry::geolocationDestroyed()
55 {
56     BlackBerry::Platform::GeolocationHandler::instance()->unregisterFromPermissionTracking(this);
57
58     delete this;
59 }
60
61 void GeolocationClientBlackBerry::startUpdating()
62 {
63     if (!m_isActive)
64         BlackBerry::Platform::GeolocationHandler::instance()->addListener(this);
65     m_isActive = true;
66 }
67
68 void GeolocationClientBlackBerry::stopUpdating()
69 {
70     if (m_isActive)
71         BlackBerry::Platform::GeolocationHandler::instance()->removeListener(this);
72     m_isActive = false;
73 }
74
75 GeolocationPosition* GeolocationClientBlackBerry::lastPosition()
76 {
77     return m_lastPosition.get();
78 }
79
80 void GeolocationClientBlackBerry::requestPermission(Geolocation* location)
81 {
82     Frame* frame = location->frame();
83     if (!frame)
84         return;
85
86     if (!m_webPagePrivate->m_webSettings->isGeolocationEnabled()) {
87         location->setIsAllowed(false);
88         return;
89     }
90
91     const String origin = getOrigin(frame);
92
93     // Special case for documents with the isUnique flag on. (ie. sandboxed iframes)
94     if (origin == "null")
95         location->setIsAllowed(false);
96
97     // Check global location setting, if it is off then we request an infobar that invokes a location settings card.
98     // If it's on, then we request an infobar that allows the site to have permission to use geolocation.
99     if (!BlackBerry::Platform::GeolocationHandler::instance()->isGlobalServiceActive()) {
100         // We only want to ask them once per session. If we get here again, automatically fail the request.
101         if (!BlackBerry::Platform::GeolocationHandler::instance()->didAskUserForGlobalPermission()) {
102             m_webPagePrivate->m_client->requestGlobalLocalServicePermission(this, origin);
103             BlackBerry::Platform::GeolocationHandler::instance()->setAskedUserForGlobalPermission();
104         } else
105             location->setIsAllowed(false);
106         return;
107     }
108
109     // Register the listener with the GeolocationHandler to receive permissions.
110     if (m_geolocationRequestMap.isEmpty())
111         BlackBerry::Platform::GeolocationHandler::instance()->registerPermissionTracking(this);
112
113     // Add this geolocation permission request to our request map.
114     Vector<RefPtr<Geolocation> > geoRequestsForOrigin;
115     HashMap<String, Vector<RefPtr<Geolocation> > >::AddResult result = m_geolocationRequestMap.add(origin, geoRequestsForOrigin);
116     result.iterator->value.append(location);
117
118     // Avoid sending another request if the vector already has another geolocation pending for this origin in this page.
119     if (result.isNewEntry)
120         m_webPagePrivate->m_client->requestGeolocationPermission(this, origin);
121 }
122
123 void GeolocationClientBlackBerry::cancelPermissionRequest(Geolocation* location)
124 {
125     Frame* frame = location->frame();
126     if (!frame)
127         return;
128
129     const String origin = getOrigin(frame);
130
131     // Remove the geolocation from the pending permission map.
132     HashMap<String, Vector<RefPtr<Geolocation> > >::iterator it = m_geolocationRequestMap.find(origin);
133
134     ASSERT(it != m_geolocationRequestMap.end());
135     if (it == m_geolocationRequestMap.end())
136         return;
137
138     Vector<RefPtr<Geolocation> >* result = &(it->value);
139
140     size_t geolocationCount = result->size();
141     for (size_t i = 0; i < geolocationCount; ++i) {
142         if ((*result)[i].get() == location) {
143             result->remove(i);
144             // Remove this vector from the pending permission map is it doesn't contain anymore geo objects
145             if (result->isEmpty())
146                 m_geolocationRequestMap.remove(origin);
147             break;
148         }
149     }
150
151     if (m_geolocationRequestMap.isEmpty())
152         BlackBerry::Platform::GeolocationHandler::instance()->unregisterFromPermissionTracking(this);
153
154     m_webPagePrivate->m_client->cancelGeolocationPermission();
155 }
156
157 void GeolocationClientBlackBerry::onLocationUpdate(double timestamp, double latitude, double longitude, double accuracy, double altitude, bool altitudeValid,
158                                                              double altitudeAccuracy, bool altitudeAccuracyValid, double speed, bool speedValid, double heading, bool headingValid)
159 {
160     m_lastPosition = GeolocationPosition::create(timestamp, latitude, longitude, accuracy, altitudeValid, altitude, altitudeAccuracyValid,
161                                                  altitudeAccuracy, headingValid, heading, speedValid, speed);
162     GeolocationController::from(m_webPagePrivate->m_page)->positionChanged(m_lastPosition.get());
163 }
164
165 void GeolocationClientBlackBerry::onLocationError(const char* errorStr)
166 {
167     RefPtr<GeolocationError> error = GeolocationError::create(GeolocationError::PositionUnavailable, String::fromUTF8(errorStr));
168     GeolocationController::from(m_webPagePrivate->m_page)->errorOccurred(error.get());
169 }
170
171 void GeolocationClientBlackBerry::onPermission(const BlackBerry::Platform::String& origin, bool isAllowed)
172 {
173     Vector<RefPtr<Geolocation> > pendingPermissionGeolocation = m_geolocationRequestMap.get(origin);
174
175     if (pendingPermissionGeolocation.isEmpty())
176         return;
177
178     size_t numberOfGeolocations = pendingPermissionGeolocation.size();
179     for (size_t i = 0; i < numberOfGeolocations; ++i)
180         pendingPermissionGeolocation[i]->setIsAllowed(isAllowed);
181     m_geolocationRequestMap.remove(origin);
182
183     if (m_geolocationRequestMap.isEmpty())
184         BlackBerry::Platform::GeolocationHandler::instance()->unregisterFromPermissionTracking(this);
185 }
186
187 void GeolocationClientBlackBerry::setEnableHighAccuracy(bool newAccuracy)
188 {
189     if (m_accuracy != newAccuracy) {
190         m_accuracy = newAccuracy;
191         BlackBerry::Platform::GeolocationHandler::instance()->switchAccuracy(this);
192     }
193 }
194