Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / content / browser / geolocation / geolocation_dispatcher_host.cc
blob547944699b85d3fa42000ef09b5e9ffd18d2a525
1 // Copyright (c) 2012 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.
5 #include "content/browser/geolocation/geolocation_dispatcher_host.h"
7 #include <utility>
9 #include "base/bind.h"
10 #include "base/metrics/histogram.h"
11 #include "content/browser/renderer_host/render_message_filter.h"
12 #include "content/browser/renderer_host/render_process_host_impl.h"
13 #include "content/browser/renderer_host/render_view_host_impl.h"
14 #include "content/public/browser/geolocation_permission_context.h"
15 #include "content/public/common/geoposition.h"
16 #include "content/common/geolocation_messages.h"
18 namespace content {
19 namespace {
21 // Geoposition error codes for reporting in UMA.
22 enum GeopositionErrorCode {
23 // NOTE: Do not renumber these as that would confuse interpretation of
24 // previously logged data. When making changes, also update the enum list
25 // in tools/metrics/histograms/histograms.xml to keep it in sync.
27 // There was no error.
28 GEOPOSITION_ERROR_CODE_NONE = 0,
30 // User denied use of geolocation.
31 GEOPOSITION_ERROR_CODE_PERMISSION_DENIED = 1,
33 // Geoposition could not be determined.
34 GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE = 2,
36 // Timeout.
37 GEOPOSITION_ERROR_CODE_TIMEOUT = 3,
39 // NOTE: Add entries only immediately above this line.
40 GEOPOSITION_ERROR_CODE_COUNT = 4
43 void RecordGeopositionErrorCode(Geoposition::ErrorCode error_code) {
44 GeopositionErrorCode code = GEOPOSITION_ERROR_CODE_NONE;
45 switch (error_code) {
46 case Geoposition::ERROR_CODE_NONE:
47 code = GEOPOSITION_ERROR_CODE_NONE;
48 break;
49 case Geoposition::ERROR_CODE_PERMISSION_DENIED:
50 code = GEOPOSITION_ERROR_CODE_PERMISSION_DENIED;
51 break;
52 case Geoposition::ERROR_CODE_POSITION_UNAVAILABLE:
53 code = GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE;
54 break;
55 case Geoposition::ERROR_CODE_TIMEOUT:
56 code = GEOPOSITION_ERROR_CODE_TIMEOUT;
57 break;
59 UMA_HISTOGRAM_ENUMERATION("Geolocation.LocationUpdate.ErrorCode",
60 code,
61 GEOPOSITION_ERROR_CODE_COUNT);
64 void NotifyGeolocationProviderPermissionGranted() {
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
66 GeolocationProviderImpl::GetInstance()->UserDidOptIntoLocationServices();
69 void SendGeolocationPermissionResponse(int render_process_id,
70 int render_view_id,
71 int bridge_id,
72 bool allowed) {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74 RenderViewHostImpl* render_view_host =
75 RenderViewHostImpl::FromID(render_process_id, render_view_id);
76 if (!render_view_host)
77 return;
78 render_view_host->Send(
79 new GeolocationMsg_PermissionSet(render_view_id, bridge_id, allowed));
81 if (allowed) {
82 BrowserThread::PostTask(
83 BrowserThread::IO, FROM_HERE,
84 base::Bind(&NotifyGeolocationProviderPermissionGranted));
88 } // namespace
90 GeolocationDispatcherHost::GeolocationDispatcherHost(
91 int render_process_id,
92 GeolocationPermissionContext* geolocation_permission_context)
93 : BrowserMessageFilter(GeolocationMsgStart),
94 render_process_id_(render_process_id),
95 geolocation_permission_context_(geolocation_permission_context),
96 geolocation_provider_(NULL) {
97 callback_ = base::Bind(
98 &GeolocationDispatcherHost::OnLocationUpdate, base::Unretained(this));
99 // This is initialized by ResourceMessageFilter. Do not add any non-trivial
100 // initialization here, defer to OnRegisterBridge which is triggered whenever
101 // a javascript geolocation object is actually initialized.
104 GeolocationDispatcherHost::~GeolocationDispatcherHost() {
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
106 if (geolocation_provider_)
107 geolocation_provider_->RemoveLocationUpdateCallback(callback_);
110 bool GeolocationDispatcherHost::OnMessageReceived(
111 const IPC::Message& msg, bool* msg_was_ok) {
112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
113 *msg_was_ok = true;
114 bool handled = true;
115 IPC_BEGIN_MESSAGE_MAP_EX(GeolocationDispatcherHost, msg, *msg_was_ok)
116 IPC_MESSAGE_HANDLER(GeolocationHostMsg_CancelPermissionRequest,
117 OnCancelPermissionRequest)
118 IPC_MESSAGE_HANDLER(GeolocationHostMsg_RequestPermission,
119 OnRequestPermission)
120 IPC_MESSAGE_HANDLER(GeolocationHostMsg_StartUpdating, OnStartUpdating)
121 IPC_MESSAGE_HANDLER(GeolocationHostMsg_StopUpdating, OnStopUpdating)
122 IPC_MESSAGE_UNHANDLED(handled = false)
123 IPC_END_MESSAGE_MAP()
124 return handled;
127 void GeolocationDispatcherHost::OnLocationUpdate(
128 const Geoposition& geoposition) {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
130 RecordGeopositionErrorCode(geoposition.error_code);
131 for (std::map<int, RendererGeolocationOptions>::iterator it =
132 geolocation_renderers_.begin();
133 it != geolocation_renderers_.end(); ++it) {
134 if (!(it->second.is_paused))
135 Send(new GeolocationMsg_PositionUpdated(it->first, geoposition));
139 void GeolocationDispatcherHost::OnRequestPermission(
140 int render_view_id,
141 int bridge_id,
142 const GURL& requesting_frame,
143 bool user_gesture) {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
145 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
146 << render_view_id << ":" << bridge_id;
147 if (geolocation_permission_context_.get()) {
148 geolocation_permission_context_->RequestGeolocationPermission(
149 render_process_id_,
150 render_view_id,
151 bridge_id,
152 requesting_frame,
153 user_gesture,
154 base::Bind(&SendGeolocationPermissionResponse,
155 render_process_id_,
156 render_view_id,
157 bridge_id));
158 } else {
159 BrowserThread::PostTask(
160 BrowserThread::UI, FROM_HERE,
161 base::Bind(&SendGeolocationPermissionResponse, render_process_id_,
162 render_view_id, bridge_id, true));
166 void GeolocationDispatcherHost::OnCancelPermissionRequest(
167 int render_view_id,
168 int bridge_id,
169 const GURL& requesting_frame) {
170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
171 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
172 << render_view_id << ":" << bridge_id;
173 if (geolocation_permission_context_.get()) {
174 geolocation_permission_context_->CancelGeolocationPermissionRequest(
175 render_process_id_, render_view_id, bridge_id, requesting_frame);
179 void GeolocationDispatcherHost::OnStartUpdating(
180 int render_view_id,
181 const GURL& requesting_frame,
182 bool enable_high_accuracy) {
183 // StartUpdating() can be invoked as a result of high-accuracy mode
184 // being enabled / disabled. No need to record the dispatcher again.
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
186 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
187 << render_view_id;
188 UMA_HISTOGRAM_BOOLEAN(
189 "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy",
190 enable_high_accuracy);
192 std::map<int, RendererGeolocationOptions>::iterator it =
193 geolocation_renderers_.find(render_view_id);
194 if (it == geolocation_renderers_.end()) {
195 bool should_start_paused = false;
196 if (pending_paused_geolocation_renderers_.erase(render_view_id) == 1) {
197 should_start_paused = true;
199 RendererGeolocationOptions opts = {
200 enable_high_accuracy,
201 should_start_paused
203 geolocation_renderers_[render_view_id] = opts;
204 } else {
205 it->second.high_accuracy = enable_high_accuracy;
207 RefreshGeolocationOptions();
210 void GeolocationDispatcherHost::OnStopUpdating(int render_view_id) {
211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
212 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
213 << render_view_id;
214 DCHECK_EQ(1U, geolocation_renderers_.count(render_view_id));
215 geolocation_renderers_.erase(render_view_id);
216 RefreshGeolocationOptions();
219 void GeolocationDispatcherHost::PauseOrResume(int render_view_id,
220 bool should_pause) {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
222 std::map<int, RendererGeolocationOptions>::iterator it =
223 geolocation_renderers_.find(render_view_id);
224 if (it == geolocation_renderers_.end()) {
225 // This renderer is not using geolocation yet, but if it does before
226 // we get a call to resume, we should start it up in the paused state.
227 if (should_pause) {
228 pending_paused_geolocation_renderers_.insert(render_view_id);
229 } else {
230 pending_paused_geolocation_renderers_.erase(render_view_id);
232 } else {
233 RendererGeolocationOptions* opts = &(it->second);
234 if (opts->is_paused != should_pause)
235 opts->is_paused = should_pause;
236 RefreshGeolocationOptions();
240 void GeolocationDispatcherHost::RefreshGeolocationOptions() {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
243 bool needs_updates = false;
244 bool use_high_accuracy = false;
245 std::map<int, RendererGeolocationOptions>::const_iterator i =
246 geolocation_renderers_.begin();
247 for (; i != geolocation_renderers_.end(); ++i) {
248 needs_updates |= !(i->second.is_paused);
249 use_high_accuracy |= i->second.high_accuracy;
250 if (needs_updates && use_high_accuracy)
251 break;
253 if (needs_updates) {
254 if (!geolocation_provider_)
255 geolocation_provider_ = GeolocationProviderImpl::GetInstance();
256 // Re-add to re-establish our options, in case they changed.
257 geolocation_provider_->AddLocationUpdateCallback(
258 callback_, use_high_accuracy);
259 } else {
260 if (geolocation_provider_)
261 geolocation_provider_->RemoveLocationUpdateCallback(callback_);
262 geolocation_provider_ = NULL;
266 } // namespace content