Remove PlatformFile from profile_browsertest
[chromium-blink-merge.git] / content / browser / geolocation / geolocation_dispatcher_host.cc
blobedb2692f36f232894ace3e678a8a17d9ec4c43d8
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 <map>
8 #include <set>
9 #include <utility>
11 #include "base/bind.h"
12 #include "base/metrics/histogram.h"
13 #include "content/browser/geolocation/geolocation_provider_impl.h"
14 #include "content/browser/renderer_host/render_message_filter.h"
15 #include "content/browser/renderer_host/render_process_host_impl.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h"
17 #include "content/public/browser/geolocation_permission_context.h"
18 #include "content/public/common/geoposition.h"
19 #include "content/common/geolocation_messages.h"
21 namespace content {
22 namespace {
24 void NotifyGeolocationProviderPermissionGranted() {
25 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
26 GeolocationProviderImpl::GetInstance()->UserDidOptIntoLocationServices();
29 void SendGeolocationPermissionResponse(int render_process_id,
30 int render_view_id,
31 int bridge_id,
32 bool allowed) {
33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
34 RenderViewHostImpl* render_view_host =
35 RenderViewHostImpl::FromID(render_process_id, render_view_id);
36 if (!render_view_host)
37 return;
38 render_view_host->Send(
39 new GeolocationMsg_PermissionSet(render_view_id, bridge_id, allowed));
41 if (allowed) {
42 BrowserThread::PostTask(
43 BrowserThread::IO, FROM_HERE,
44 base::Bind(&NotifyGeolocationProviderPermissionGranted));
48 class GeolocationDispatcherHostImpl : public GeolocationDispatcherHost {
49 public:
50 GeolocationDispatcherHostImpl(
51 int render_process_id,
52 GeolocationPermissionContext* geolocation_permission_context);
54 // GeolocationDispatcherHost
55 virtual bool OnMessageReceived(const IPC::Message& msg,
56 bool* msg_was_ok) OVERRIDE;
58 private:
59 virtual ~GeolocationDispatcherHostImpl();
61 void OnRequestPermission(int render_view_id,
62 int bridge_id,
63 const GURL& requesting_frame);
64 void OnCancelPermissionRequest(int render_view_id,
65 int bridge_id,
66 const GURL& requesting_frame);
67 void OnStartUpdating(int render_view_id,
68 const GURL& requesting_frame,
69 bool enable_high_accuracy);
70 void OnStopUpdating(int render_view_id);
73 virtual void PauseOrResume(int render_view_id, bool should_pause) OVERRIDE;
75 // Updates the |geolocation_provider_| with the currently required update
76 // options.
77 void RefreshGeolocationOptions();
79 void OnLocationUpdate(const Geoposition& position);
81 int render_process_id_;
82 scoped_refptr<GeolocationPermissionContext> geolocation_permission_context_;
84 struct RendererGeolocationOptions {
85 bool high_accuracy;
86 bool is_paused;
89 // Used to keep track of the renderers in this process that are using
90 // geolocation and the options associated with them. The map is iterated
91 // when a location update is available and the fan out to individual bridge
92 // IDs happens renderer side, in order to minimize context switches.
93 // Only used on the IO thread.
94 std::map<int, RendererGeolocationOptions> geolocation_renderers_;
96 // Used by Android WebView to support that case that a renderer is in the
97 // 'paused' state but not yet using geolocation. If the renderer does start
98 // using geolocation while paused, we move from this set into
99 // |geolocation_renderers_|. If the renderer doesn't end up wanting to use
100 // geolocation while 'paused' then we remove from this set. A renderer id
101 // can exist only in this set or |geolocation_renderers_|, never both.
102 std::set<int> pending_paused_geolocation_renderers_;
104 // Only set whilst we are registered with the geolocation provider.
105 GeolocationProviderImpl* geolocation_provider_;
107 GeolocationProviderImpl::LocationUpdateCallback callback_;
109 DISALLOW_COPY_AND_ASSIGN(GeolocationDispatcherHostImpl);
112 GeolocationDispatcherHostImpl::GeolocationDispatcherHostImpl(
113 int render_process_id,
114 GeolocationPermissionContext* geolocation_permission_context)
115 : render_process_id_(render_process_id),
116 geolocation_permission_context_(geolocation_permission_context),
117 geolocation_provider_(NULL) {
118 callback_ = base::Bind(
119 &GeolocationDispatcherHostImpl::OnLocationUpdate, base::Unretained(this));
120 // This is initialized by ResourceMessageFilter. Do not add any non-trivial
121 // initialization here, defer to OnRegisterBridge which is triggered whenever
122 // a javascript geolocation object is actually initialized.
125 GeolocationDispatcherHostImpl::~GeolocationDispatcherHostImpl() {
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
127 if (geolocation_provider_)
128 geolocation_provider_->RemoveLocationUpdateCallback(callback_);
131 bool GeolocationDispatcherHostImpl::OnMessageReceived(
132 const IPC::Message& msg, bool* msg_was_ok) {
133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
134 *msg_was_ok = true;
135 bool handled = true;
136 IPC_BEGIN_MESSAGE_MAP_EX(GeolocationDispatcherHostImpl, msg, *msg_was_ok)
137 IPC_MESSAGE_HANDLER(GeolocationHostMsg_CancelPermissionRequest,
138 OnCancelPermissionRequest)
139 IPC_MESSAGE_HANDLER(GeolocationHostMsg_RequestPermission,
140 OnRequestPermission)
141 IPC_MESSAGE_HANDLER(GeolocationHostMsg_StartUpdating, OnStartUpdating)
142 IPC_MESSAGE_HANDLER(GeolocationHostMsg_StopUpdating, OnStopUpdating)
143 IPC_MESSAGE_UNHANDLED(handled = false)
144 IPC_END_MESSAGE_MAP()
145 return handled;
148 void GeolocationDispatcherHostImpl::OnLocationUpdate(
149 const Geoposition& geoposition) {
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
151 for (std::map<int, RendererGeolocationOptions>::iterator it =
152 geolocation_renderers_.begin();
153 it != geolocation_renderers_.end(); ++it) {
154 if (!(it->second.is_paused))
155 Send(new GeolocationMsg_PositionUpdated(it->first, geoposition));
159 void GeolocationDispatcherHostImpl::OnRequestPermission(
160 int render_view_id,
161 int bridge_id,
162 const GURL& requesting_frame) {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
164 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
165 << render_view_id << ":" << bridge_id;
166 if (geolocation_permission_context_.get()) {
167 geolocation_permission_context_->RequestGeolocationPermission(
168 render_process_id_,
169 render_view_id,
170 bridge_id,
171 requesting_frame,
172 base::Bind(&SendGeolocationPermissionResponse,
173 render_process_id_,
174 render_view_id,
175 bridge_id));
176 } else {
177 BrowserThread::PostTask(
178 BrowserThread::UI, FROM_HERE,
179 base::Bind(&SendGeolocationPermissionResponse, render_process_id_,
180 render_view_id, bridge_id, true));
184 void GeolocationDispatcherHostImpl::OnCancelPermissionRequest(
185 int render_view_id,
186 int bridge_id,
187 const GURL& requesting_frame) {
188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
189 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
190 << render_view_id << ":" << bridge_id;
191 if (geolocation_permission_context_.get()) {
192 geolocation_permission_context_->CancelGeolocationPermissionRequest(
193 render_process_id_, render_view_id, bridge_id, requesting_frame);
197 void GeolocationDispatcherHostImpl::OnStartUpdating(
198 int render_view_id,
199 const GURL& requesting_frame,
200 bool enable_high_accuracy) {
201 // StartUpdating() can be invoked as a result of high-accuracy mode
202 // being enabled / disabled. No need to record the dispatcher again.
203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
204 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
205 << render_view_id;
206 UMA_HISTOGRAM_BOOLEAN(
207 "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy",
208 enable_high_accuracy);
210 std::map<int, RendererGeolocationOptions>::iterator it =
211 geolocation_renderers_.find(render_view_id);
212 if (it == geolocation_renderers_.end()) {
213 bool should_start_paused = false;
214 if (pending_paused_geolocation_renderers_.erase(render_view_id) == 1) {
215 should_start_paused = true;
217 RendererGeolocationOptions opts = {
218 enable_high_accuracy,
219 should_start_paused
221 geolocation_renderers_[render_view_id] = opts;
222 } else {
223 it->second.high_accuracy = enable_high_accuracy;
225 RefreshGeolocationOptions();
228 void GeolocationDispatcherHostImpl::OnStopUpdating(int render_view_id) {
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
230 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
231 << render_view_id;
232 DCHECK_EQ(1U, geolocation_renderers_.count(render_view_id));
233 geolocation_renderers_.erase(render_view_id);
234 RefreshGeolocationOptions();
237 void GeolocationDispatcherHostImpl::PauseOrResume(int render_view_id,
238 bool should_pause) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
240 std::map<int, RendererGeolocationOptions>::iterator it =
241 geolocation_renderers_.find(render_view_id);
242 if (it == geolocation_renderers_.end()) {
243 // This renderer is not using geolocation yet, but if it does before
244 // we get a call to resume, we should start it up in the paused state.
245 if (should_pause) {
246 pending_paused_geolocation_renderers_.insert(render_view_id);
247 } else {
248 pending_paused_geolocation_renderers_.erase(render_view_id);
250 } else {
251 RendererGeolocationOptions* opts = &(it->second);
252 if (opts->is_paused != should_pause)
253 opts->is_paused = should_pause;
254 RefreshGeolocationOptions();
258 void GeolocationDispatcherHostImpl::RefreshGeolocationOptions() {
259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
261 bool needs_updates = false;
262 bool use_high_accuracy = false;
263 std::map<int, RendererGeolocationOptions>::const_iterator i =
264 geolocation_renderers_.begin();
265 for (; i != geolocation_renderers_.end(); ++i) {
266 needs_updates |= !(i->second.is_paused);
267 use_high_accuracy |= i->second.high_accuracy;
268 if (needs_updates && use_high_accuracy)
269 break;
271 if (needs_updates) {
272 if (!geolocation_provider_)
273 geolocation_provider_ = GeolocationProviderImpl::GetInstance();
274 // Re-add to re-establish our options, in case they changed.
275 geolocation_provider_->AddLocationUpdateCallback(
276 callback_, use_high_accuracy);
277 } else {
278 if (geolocation_provider_)
279 geolocation_provider_->RemoveLocationUpdateCallback(callback_);
280 geolocation_provider_ = NULL;
284 } // namespace
287 // GeolocationDispatcherHost --------------------------------------------------
289 // static
290 GeolocationDispatcherHost* GeolocationDispatcherHost::New(
291 int render_process_id,
292 GeolocationPermissionContext* geolocation_permission_context) {
293 return new GeolocationDispatcherHostImpl(
294 render_process_id,
295 geolocation_permission_context);
298 GeolocationDispatcherHost::GeolocationDispatcherHost()
299 : BrowserMessageFilter(GeolocationMsgStart) {
302 GeolocationDispatcherHost::~GeolocationDispatcherHost() {
305 } // namespace content