Chromium Code Reviews| Index: content/browser/geolocation/geolocation_dispatcher_host.cc |
| diff --git a/content/browser/geolocation/geolocation_dispatcher_host.cc b/content/browser/geolocation/geolocation_dispatcher_host.cc |
| index 96071c748f5e72d5e00dce006be77a7ee903e730..b3975079d3a87479dbace16ac2952e4568c58be3 100644 |
| --- a/content/browser/geolocation/geolocation_dispatcher_host.cc |
| +++ b/content/browser/geolocation/geolocation_dispatcher_host.cc |
| @@ -69,23 +69,29 @@ class GeolocationDispatcherHostImpl : public GeolocationDispatcherHost { |
| bool enable_high_accuracy); |
| void OnStopUpdating(int render_view_id); |
| + virtual void PauseOrResume(int render_view_id, bool should_pause) OVERRIDE; |
| + |
| // Updates the |geolocation_provider_| with the currently required update |
| - // options, based on |renderer_high_accuracy_|. |
| - void RefreshHighAccuracy(); |
| + // options. |
| + void RefreshGeolocationOptions(); |
| void OnLocationUpdate(const Geoposition& position); |
| int render_process_id_; |
| scoped_refptr<GeolocationPermissionContext> geolocation_permission_context_; |
| - // Iterated when sending location updates to renderer processes. The fan out |
| - // to individual bridge IDs happens renderer side, in order to minimize |
| - // context switches. |
| + struct RendererGeolocationOptions { |
| + bool high_accuracy; |
| + bool is_paused; |
| + }; |
| + |
| + // Used to keep track of the renderers in this process that are using |
| + // geolocation and the options associated with them. The map is iterated |
| + // when a location update is available and the fan out to individual bridge |
| + // IDs happens renderer side, in order to minimize context switches. |
| // Only used on the IO thread. |
| - std::set<int> geolocation_renderer_ids_; |
| - // Maps renderer_id to whether high accuracy is requested for this particular |
| - // bridge. |
| - std::map<int, bool> renderer_high_accuracy_; |
| + std::map<int, RendererGeolocationOptions> geolocation_renderers_; |
| + |
| // Only set whilst we are registered with the geolocation provider. |
| GeolocationProviderImpl* geolocation_provider_; |
| @@ -132,9 +138,10 @@ bool GeolocationDispatcherHostImpl::OnMessageReceived( |
| void GeolocationDispatcherHostImpl::OnLocationUpdate( |
| const Geoposition& geoposition) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - for (std::set<int>::iterator it = geolocation_renderer_ids_.begin(); |
| - it != geolocation_renderer_ids_.end(); ++it) { |
| - Send(new GeolocationMsg_PositionUpdated(*it, geoposition)); |
| + for (std::map<int, RendererGeolocationOptions>::iterator it = |
| + geolocation_renderers_.begin(); |
| + it != geolocation_renderers_.end(); ++it) { |
| + Send(new GeolocationMsg_PositionUpdated(it->first, geoposition)); |
|
joth
2013/11/10 17:59:02
technically should only send if (!it->second.is_p
Michael van Ouwerkerk
2013/11/11 14:19:49
Agreed, I think that would be clearer. Otherwise t
benm (inactive)
2013/11/11 14:50:41
Right. Otherwise in this case as long as one rende
|
| } |
| } |
| @@ -188,45 +195,58 @@ void GeolocationDispatcherHostImpl::OnStartUpdating( |
| UMA_HISTOGRAM_BOOLEAN( |
| "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy", |
| enable_high_accuracy); |
| - if (!geolocation_renderer_ids_.count(render_view_id)) |
| - geolocation_renderer_ids_.insert(render_view_id); |
| - |
| - renderer_high_accuracy_[render_view_id] = enable_high_accuracy; |
| - RefreshHighAccuracy(); |
| + RendererGeolocationOptions opts = { enable_high_accuracy, false }; |
| + geolocation_renderers_[render_view_id] = opts; |
| + RefreshGeolocationOptions(); |
| } |
| void GeolocationDispatcherHostImpl::OnStopUpdating(int render_view_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":" |
| << render_view_id; |
| - if (renderer_high_accuracy_.erase(render_view_id)) |
| - RefreshHighAccuracy(); |
| + DCHECK_EQ(1U, geolocation_renderers_.count(render_view_id)); |
| + geolocation_renderers_.erase(render_view_id); |
| + RefreshGeolocationOptions(); |
| +} |
| + |
| +void GeolocationDispatcherHostImpl::PauseOrResume(int render_view_id, |
| + bool should_pause) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + std::map<int, RendererGeolocationOptions>::iterator it = |
| + geolocation_renderers_.find(render_view_id); |
| + if (it == geolocation_renderers_.end()) |
| + return; |
| - DCHECK_EQ(1U, geolocation_renderer_ids_.count(render_view_id)); |
| - geolocation_renderer_ids_.erase(render_view_id); |
| + RendererGeolocationOptions* opts = &(it->second); |
| + if (opts->is_paused != should_pause) { |
| + opts->is_paused = should_pause; |
| + RefreshGeolocationOptions(); |
| + } |
| } |
| -void GeolocationDispatcherHostImpl::RefreshHighAccuracy() { |
| +void GeolocationDispatcherHostImpl::RefreshGeolocationOptions() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - if (renderer_high_accuracy_.empty()) { |
| - if (geolocation_provider_) { |
| - geolocation_provider_->RemoveLocationUpdateCallback(callback_); |
| - geolocation_provider_ = NULL; |
| - } |
| - } else { |
| + |
| + bool needs_updates = false; |
| + bool use_high_accuracy = false; |
| + std::map<int, RendererGeolocationOptions>::const_iterator i = |
| + geolocation_renderers_.begin(); |
| + for (; i != geolocation_renderers_.end(); ++i) { |
| + needs_updates |= !(i->second.is_paused); |
| + use_high_accuracy |= i->second.high_accuracy; |
| + if (needs_updates && use_high_accuracy) |
| + break; |
| + } |
| + if (needs_updates) { |
| if (!geolocation_provider_) |
| geolocation_provider_ = GeolocationProviderImpl::GetInstance(); |
| // Re-add to re-establish our options, in case they changed. |
| - bool use_high_accuracy = false; |
| - std::map<int, bool>::iterator i = renderer_high_accuracy_.begin(); |
| - for (; i != renderer_high_accuracy_.end(); ++i) { |
| - if (i->second) { |
| - use_high_accuracy = true; |
| - break; |
| - } |
| - } |
| geolocation_provider_->AddLocationUpdateCallback( |
| callback_, use_high_accuracy); |
| + } else { |
| + if (geolocation_provider_) |
| + geolocation_provider_->RemoveLocationUpdateCallback(callback_); |
| + geolocation_provider_ = NULL; |
| } |
| } |
| } // namespace |