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
34namespace WebCore {
35
36GeolocationController::GeolocationController(Page* page, GeolocationClient* client)
37    : m_client(client)
38    , m_page(page)
39{
40}
41
42GeolocationController::~GeolocationController()
43{
44    ASSERT(m_observers.isEmpty());
45
46    if (m_client)
47        m_client->geolocationDestroyed();
48}
49
50PassOwnPtr<GeolocationController> GeolocationController::create(Page* page, GeolocationClient* client)
51{
52    return adoptPtr(new GeolocationController(page, client));
53}
54
55void GeolocationController::addObserver(Geolocation* observer, bool enableHighAccuracy)
56{
57    // This may be called multiple times with the same observer, though removeObserver()
58    // is called only once with each.
59    bool wasEmpty = m_observers.isEmpty();
60    m_observers.add(observer);
61    if (enableHighAccuracy)
62        m_highAccuracyObservers.add(observer);
63
64    if (m_client) {
65        if (enableHighAccuracy)
66            m_client->setEnableHighAccuracy(true);
67        if (wasEmpty)
68            m_client->startUpdating();
69    }
70}
71
72void GeolocationController::removeObserver(Geolocation* observer)
73{
74    if (!m_observers.contains(observer))
75        return;
76
77    m_observers.remove(observer);
78    m_highAccuracyObservers.remove(observer);
79
80    if (m_client) {
81        if (m_observers.isEmpty())
82            m_client->stopUpdating();
83        else if (m_highAccuracyObservers.isEmpty())
84            m_client->setEnableHighAccuracy(false);
85    }
86}
87
88void GeolocationController::requestPermission(Geolocation* geolocation)
89{
90    if (m_client)
91        m_client->requestPermission(geolocation);
92}
93
94void GeolocationController::cancelPermissionRequest(Geolocation* geolocation)
95{
96    if (m_client)
97        m_client->cancelPermissionRequest(geolocation);
98}
99
100void GeolocationController::positionChanged(GeolocationPosition* position)
101{
102    position = InspectorInstrumentation::overrideGeolocationPosition(m_page, position);
103    if (!position) {
104        errorOccurred(GeolocationError::create(GeolocationError::PositionUnavailable, "PositionUnavailable").get());
105        return;
106    }
107    m_lastPosition = position;
108    Vector<RefPtr<Geolocation> > observersVector;
109    copyToVector(m_observers, observersVector);
110    for (size_t i = 0; i < observersVector.size(); ++i)
111        observersVector[i]->positionChanged();
112}
113
114void GeolocationController::errorOccurred(GeolocationError* error)
115{
116    Vector<RefPtr<Geolocation> > observersVector;
117    copyToVector(m_observers, observersVector);
118    for (size_t i = 0; i < observersVector.size(); ++i)
119        observersVector[i]->setError(error);
120}
121
122GeolocationPosition* GeolocationController::lastPosition()
123{
124    if (m_lastPosition.get())
125        return m_lastPosition.get();
126
127    if (!m_client)
128        return 0;
129
130    return m_client->lastPosition();
131}
132
133const char* GeolocationController::supplementName()
134{
135    return "GeolocationController";
136}
137
138void provideGeolocationTo(Page* page, GeolocationClient* client)
139{
140    Supplement<Page>::provideTo(page, GeolocationController::supplementName(), GeolocationController::create(page, client));
141}
142
143} // namespace WebCore
144