Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / content / browser / geolocation / geolocation_service_impl.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/geolocation/geolocation_service_impl.h"
6
7 #include "base/bind.h"
8 #include "base/metrics/histogram.h"
9 #include "content/browser/geolocation/geolocation_service_context.h"
10 #include "content/public/common/mojo_geoposition.mojom.h"
11
12 namespace content {
13
14 namespace {
15
16 // Geoposition error codes for reporting in UMA.
17 enum GeopositionErrorCode {
18   // NOTE: Do not renumber these as that would confuse interpretation of
19   // previously logged data. When making changes, also update the enum list
20   // in tools/metrics/histograms/histograms.xml to keep it in sync.
21
22   // There was no error.
23   GEOPOSITION_ERROR_CODE_NONE = 0,
24
25   // User denied use of geolocation.
26   GEOPOSITION_ERROR_CODE_PERMISSION_DENIED = 1,
27
28   // Geoposition could not be determined.
29   GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE = 2,
30
31   // Timeout.
32   GEOPOSITION_ERROR_CODE_TIMEOUT = 3,
33
34   // NOTE: Add entries only immediately above this line.
35   GEOPOSITION_ERROR_CODE_COUNT = 4
36 };
37
38 void RecordGeopositionErrorCode(Geoposition::ErrorCode error_code) {
39   GeopositionErrorCode code = GEOPOSITION_ERROR_CODE_NONE;
40   switch (error_code) {
41     case Geoposition::ERROR_CODE_NONE:
42       code = GEOPOSITION_ERROR_CODE_NONE;
43       break;
44     case Geoposition::ERROR_CODE_PERMISSION_DENIED:
45       code = GEOPOSITION_ERROR_CODE_PERMISSION_DENIED;
46       break;
47     case Geoposition::ERROR_CODE_POSITION_UNAVAILABLE:
48       code = GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE;
49       break;
50     case Geoposition::ERROR_CODE_TIMEOUT:
51       code = GEOPOSITION_ERROR_CODE_TIMEOUT;
52       break;
53   }
54   UMA_HISTOGRAM_ENUMERATION("Geolocation.LocationUpdate.ErrorCode",
55                             code,
56                             GEOPOSITION_ERROR_CODE_COUNT);
57 }
58
59 }  // namespace
60
61 GeolocationServiceImpl::GeolocationServiceImpl(
62     GeolocationServiceContext* context,
63     const base::Closure& update_callback)
64     : context_(context),
65       update_callback_(update_callback),
66       high_accuracy_(false) {
67   DCHECK(context_);
68 }
69
70 GeolocationServiceImpl::~GeolocationServiceImpl() {
71 }
72
73 void GeolocationServiceImpl::PauseUpdates() {
74   geolocation_subscription_.reset();
75 }
76
77 void GeolocationServiceImpl::ResumeUpdates() {
78   if (position_override_.Validate()) {
79     OnLocationUpdate(position_override_);
80     return;
81   }
82
83   StartListeningForUpdates();
84 }
85
86 void GeolocationServiceImpl::StartListeningForUpdates() {
87   geolocation_subscription_ =
88       GeolocationProvider::GetInstance()->AddLocationUpdateCallback(
89           base::Bind(&GeolocationServiceImpl::OnLocationUpdate,
90                      base::Unretained(this)),
91           high_accuracy_);
92 }
93
94 void GeolocationServiceImpl::SetHighAccuracy(bool high_accuracy) {
95   UMA_HISTOGRAM_BOOLEAN(
96       "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy",
97       high_accuracy);
98   high_accuracy_ = high_accuracy;
99
100   if (position_override_.Validate()) {
101     OnLocationUpdate(position_override_);
102     return;
103   }
104
105   StartListeningForUpdates();
106 }
107
108 void GeolocationServiceImpl::SetOverride(const Geoposition& position) {
109   position_override_ = position;
110   if (!position_override_.Validate()) {
111     ResumeUpdates();
112   }
113
114   geolocation_subscription_.reset();
115
116   OnLocationUpdate(position_override_);
117 }
118
119 void GeolocationServiceImpl::ClearOverride() {
120   position_override_ = Geoposition();
121   StartListeningForUpdates();
122 }
123
124 void GeolocationServiceImpl::OnConnectionError() {
125   context_->ServiceHadConnectionError(this);
126
127   // The above call deleted this instance, so the only safe thing to do is
128   // return.
129 }
130
131 void GeolocationServiceImpl::OnLocationUpdate(const Geoposition& position) {
132   RecordGeopositionErrorCode(position.error_code);
133   DCHECK(context_);
134
135   if (context_->paused())
136     return;
137
138   MojoGeopositionPtr geoposition(MojoGeoposition::New());
139   geoposition->valid = position.Validate();
140   geoposition->latitude = position.latitude;
141   geoposition->longitude = position.longitude;
142   geoposition->altitude = position.altitude;
143   geoposition->accuracy = position.accuracy;
144   geoposition->altitude_accuracy = position.altitude_accuracy;
145   geoposition->heading = position.heading;
146   geoposition->speed = position.speed;
147   geoposition->timestamp = position.timestamp.ToDoubleT();
148   geoposition->error_code = MojoGeoposition::ErrorCode(position.error_code);
149   geoposition->error_message = position.error_message;
150
151   update_callback_.Run();
152   client()->OnLocationUpdate(geoposition.Pass());
153 }
154
155 }  // namespace content