1 | /* |
2 | * Copyright (C) 2010 Google Inc. All rights reserved. |
3 | * Copyright (C) 2012 Apple Inc. All Rights Reserved. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are |
7 | * met: |
8 | * |
9 | * * Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * * Redistributions in binary form must reproduce the above |
12 | * copyright notice, this list of conditions and the following disclaimer |
13 | * in the documentation and/or other materials provided with the |
14 | * distribution. |
15 | * * Neither the name of Google Inc. nor the names of its |
16 | * contributors may be used to endorse or promote products derived from |
17 | * this software without specific prior written permission. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | */ |
31 | |
32 | #include "config.h" |
33 | #include "GeolocationClientMock.h" |
34 | |
35 | #if ENABLE(GEOLOCATION) |
36 | |
37 | #include "GeolocationController.h" |
38 | #include "GeolocationError.h" |
39 | #include "GeolocationPosition.h" |
40 | |
41 | namespace WebCore { |
42 | |
43 | GeolocationClientMock::GeolocationClientMock() |
44 | : m_controller(0) |
45 | , m_hasError(false) |
46 | , m_controllerTimer(*this, &GeolocationClientMock::controllerTimerFired) |
47 | , m_permissionTimer(*this, &GeolocationClientMock::permissionTimerFired) |
48 | , m_isActive(false) |
49 | , m_permissionState(PermissionStateUnset) |
50 | { |
51 | } |
52 | |
53 | GeolocationClientMock::~GeolocationClientMock() |
54 | { |
55 | ASSERT(!m_isActive); |
56 | } |
57 | |
58 | void GeolocationClientMock::setController(GeolocationController *controller) |
59 | { |
60 | ASSERT(controller && !m_controller); |
61 | m_controller = controller; |
62 | } |
63 | |
64 | void GeolocationClientMock::setPosition(GeolocationPosition&& position) |
65 | { |
66 | m_lastPosition = WTFMove(position); |
67 | clearError(); |
68 | asyncUpdateController(); |
69 | } |
70 | |
71 | void GeolocationClientMock::setPositionUnavailableError(const String& errorMessage) |
72 | { |
73 | m_hasError = true; |
74 | m_errorMessage = errorMessage; |
75 | m_lastPosition = WTF::nullopt; |
76 | asyncUpdateController(); |
77 | } |
78 | |
79 | void GeolocationClientMock::setPermission(bool allowed) |
80 | { |
81 | m_permissionState = allowed ? PermissionStateAllowed : PermissionStateDenied; |
82 | asyncUpdatePermission(); |
83 | } |
84 | |
85 | int GeolocationClientMock::numberOfPendingPermissionRequests() const |
86 | { |
87 | return m_pendingPermission.size(); |
88 | } |
89 | |
90 | void GeolocationClientMock::requestPermission(Geolocation& geolocation) |
91 | { |
92 | m_pendingPermission.add(&geolocation); |
93 | if (m_permissionState != PermissionStateUnset) |
94 | asyncUpdatePermission(); |
95 | } |
96 | |
97 | void GeolocationClientMock::cancelPermissionRequest(Geolocation& geolocation) |
98 | { |
99 | // Called from Geolocation::disconnectFrame() in response to Frame destruction. |
100 | m_pendingPermission.remove(&geolocation); |
101 | if (m_pendingPermission.isEmpty() && m_permissionTimer.isActive()) |
102 | m_permissionTimer.stop(); |
103 | } |
104 | |
105 | void GeolocationClientMock::asyncUpdatePermission() |
106 | { |
107 | ASSERT(m_permissionState != PermissionStateUnset); |
108 | if (!m_permissionTimer.isActive()) |
109 | m_permissionTimer.startOneShot(0_s); |
110 | } |
111 | |
112 | void GeolocationClientMock::permissionTimerFired() |
113 | { |
114 | ASSERT(m_permissionState != PermissionStateUnset); |
115 | bool allowed = m_permissionState == PermissionStateAllowed; |
116 | GeolocationSet::iterator end = m_pendingPermission.end(); |
117 | |
118 | // Once permission has been set (or denied) on a Geolocation object, there can be |
119 | // no further requests for permission to the mock. Consequently the callbacks |
120 | // which fire synchronously from Geolocation::setIsAllowed() cannot reentrantly modify |
121 | // m_pendingPermission. |
122 | for (GeolocationSet::iterator it = m_pendingPermission.begin(); it != end; ++it) |
123 | (*it)->setIsAllowed(allowed); |
124 | m_pendingPermission.clear(); |
125 | } |
126 | |
127 | void GeolocationClientMock::reset() |
128 | { |
129 | m_lastPosition = WTF::nullopt; |
130 | clearError(); |
131 | m_permissionState = PermissionStateUnset; |
132 | } |
133 | |
134 | void GeolocationClientMock::geolocationDestroyed() |
135 | { |
136 | ASSERT(!m_isActive); |
137 | } |
138 | |
139 | void GeolocationClientMock::startUpdating() |
140 | { |
141 | ASSERT(!m_isActive); |
142 | m_isActive = true; |
143 | asyncUpdateController(); |
144 | } |
145 | |
146 | void GeolocationClientMock::stopUpdating() |
147 | { |
148 | ASSERT(m_isActive); |
149 | m_isActive = false; |
150 | m_controllerTimer.stop(); |
151 | } |
152 | |
153 | void GeolocationClientMock::setEnableHighAccuracy(bool) |
154 | { |
155 | // FIXME: We need to add some tests regarding "high accuracy" mode. |
156 | // See https://bugs.webkit.org/show_bug.cgi?id=49438 |
157 | } |
158 | |
159 | Optional<GeolocationPosition> GeolocationClientMock::lastPosition() |
160 | { |
161 | return m_lastPosition; |
162 | } |
163 | |
164 | void GeolocationClientMock::asyncUpdateController() |
165 | { |
166 | ASSERT(m_controller); |
167 | if (m_isActive && !m_controllerTimer.isActive()) |
168 | m_controllerTimer.startOneShot(0_s); |
169 | } |
170 | |
171 | void GeolocationClientMock::controllerTimerFired() |
172 | { |
173 | ASSERT(m_controller); |
174 | |
175 | if (m_lastPosition) { |
176 | ASSERT(!m_hasError); |
177 | m_controller->positionChanged(*m_lastPosition); |
178 | } else if (m_hasError) { |
179 | auto geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, m_errorMessage); |
180 | m_controller->errorOccurred(geolocatioError.get()); |
181 | } |
182 | } |
183 | |
184 | void GeolocationClientMock::clearError() |
185 | { |
186 | m_hasError = false; |
187 | m_errorMessage = String(); |
188 | } |
189 | |
190 | } // WebCore |
191 | |
192 | #endif // ENABLE(GEOLOCATION) |
193 | |