1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "modules/geolocation/GeolocationController.h"
28
29 #include "core/inspector/InspectorInstrumentation.h"
30 #include "modules/geolocation/GeolocationClient.h"
31 #include "modules/geolocation/GeolocationError.h"
32 #include "modules/geolocation/GeolocationPosition.h"
33
34 namespace WebCore {
35
GeolocationController(Page * page,GeolocationClient * client)36 GeolocationController::GeolocationController(Page* page, GeolocationClient* client)
37 : PageLifecycleObserver(page)
38 , m_client(client)
39 , m_isClientUpdating(false)
40 {
41 }
42
startUpdatingIfNeeded()43 void GeolocationController::startUpdatingIfNeeded()
44 {
45 if (m_isClientUpdating)
46 return;
47 m_isClientUpdating = true;
48 m_client->startUpdating();
49 }
50
stopUpdatingIfNeeded()51 void GeolocationController::stopUpdatingIfNeeded()
52 {
53 if (!m_isClientUpdating)
54 return;
55 m_isClientUpdating = false;
56 m_client->stopUpdating();
57 }
58
~GeolocationController()59 GeolocationController::~GeolocationController()
60 {
61 ASSERT(m_observers.isEmpty());
62
63 if (m_client)
64 m_client->geolocationDestroyed();
65 }
66
create(Page * page,GeolocationClient * client)67 PassOwnPtr<GeolocationController> GeolocationController::create(Page* page, GeolocationClient* client)
68 {
69 return adoptPtr(new GeolocationController(page, client));
70 }
71
addObserver(Geolocation * observer,bool enableHighAccuracy)72 void GeolocationController::addObserver(Geolocation* observer, bool enableHighAccuracy)
73 {
74 // This may be called multiple times with the same observer, though removeObserver()
75 // is called only once with each.
76 bool wasEmpty = m_observers.isEmpty();
77 m_observers.add(observer);
78 if (enableHighAccuracy)
79 m_highAccuracyObservers.add(observer);
80
81 if (m_client) {
82 if (enableHighAccuracy)
83 m_client->setEnableHighAccuracy(true);
84 if (wasEmpty && page() && page()->visibilityState() == PageVisibilityStateVisible)
85 startUpdatingIfNeeded();
86 }
87 }
88
removeObserver(Geolocation * observer)89 void GeolocationController::removeObserver(Geolocation* observer)
90 {
91 if (!m_observers.contains(observer))
92 return;
93
94 m_observers.remove(observer);
95 m_highAccuracyObservers.remove(observer);
96
97 if (m_client) {
98 if (m_observers.isEmpty())
99 stopUpdatingIfNeeded();
100 else if (m_highAccuracyObservers.isEmpty())
101 m_client->setEnableHighAccuracy(false);
102 }
103 }
104
requestPermission(Geolocation * geolocation)105 void GeolocationController::requestPermission(Geolocation* geolocation)
106 {
107 if (m_client)
108 m_client->requestPermission(geolocation);
109 }
110
cancelPermissionRequest(Geolocation * geolocation)111 void GeolocationController::cancelPermissionRequest(Geolocation* geolocation)
112 {
113 if (m_client)
114 m_client->cancelPermissionRequest(geolocation);
115 }
116
positionChanged(GeolocationPosition * position)117 void GeolocationController::positionChanged(GeolocationPosition* position)
118 {
119 position = InspectorInstrumentation::overrideGeolocationPosition(page(), position);
120 if (!position) {
121 errorOccurred(GeolocationError::create(GeolocationError::PositionUnavailable, "PositionUnavailable").get());
122 return;
123 }
124 m_lastPosition = position;
125 Vector<RefPtr<Geolocation> > observersVector;
126 copyToVector(m_observers, observersVector);
127 for (size_t i = 0; i < observersVector.size(); ++i)
128 observersVector[i]->positionChanged();
129 }
130
errorOccurred(GeolocationError * error)131 void GeolocationController::errorOccurred(GeolocationError* error)
132 {
133 Vector<RefPtr<Geolocation> > observersVector;
134 copyToVector(m_observers, observersVector);
135 for (size_t i = 0; i < observersVector.size(); ++i)
136 observersVector[i]->setError(error);
137 }
138
lastPosition()139 GeolocationPosition* GeolocationController::lastPosition()
140 {
141 if (m_lastPosition.get())
142 return m_lastPosition.get();
143
144 if (!m_client)
145 return 0;
146
147 return m_client->lastPosition();
148 }
149
pageVisibilityChanged()150 void GeolocationController::pageVisibilityChanged()
151 {
152 if (m_observers.isEmpty() || !m_client)
153 return;
154
155 if (page() && page()->visibilityState() == PageVisibilityStateVisible)
156 startUpdatingIfNeeded();
157 else
158 stopUpdatingIfNeeded();
159 }
160
supplementName()161 const char* GeolocationController::supplementName()
162 {
163 return "GeolocationController";
164 }
165
provideGeolocationTo(Page * page,GeolocationClient * client)166 void provideGeolocationTo(Page* page, GeolocationClient* client)
167 {
168 Supplement<Page>::provideTo(page, GeolocationController::supplementName(), GeolocationController::create(page, client));
169 }
170
171 } // namespace WebCore
172