diff options
author | Ben Murdoch <benm@google.com> | 2010-07-29 17:14:53 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-08-04 14:29:45 +0100 |
commit | c407dc5cd9bdc5668497f21b26b09d988ab439de (patch) | |
tree | 7eaf8707c0309516bdb042ad976feedaf72b0bb1 /chrome/browser/geolocation/geolocation_dispatcher_host.cc | |
parent | 0998b1cdac5733f299c12d88bc31ef9c8035b8fa (diff) | |
download | external_chromium-c407dc5cd9bdc5668497f21b26b09d988ab439de.zip external_chromium-c407dc5cd9bdc5668497f21b26b09d988ab439de.tar.gz external_chromium-c407dc5cd9bdc5668497f21b26b09d988ab439de.tar.bz2 |
Merge Chromium src@r53293
Change-Id: Ia79acf8670f385cee48c45b0a75371d8e950af34
Diffstat (limited to 'chrome/browser/geolocation/geolocation_dispatcher_host.cc')
-rw-r--r-- | chrome/browser/geolocation/geolocation_dispatcher_host.cc | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/chrome/browser/geolocation/geolocation_dispatcher_host.cc b/chrome/browser/geolocation/geolocation_dispatcher_host.cc new file mode 100644 index 0000000..5e4dc40 --- /dev/null +++ b/chrome/browser/geolocation/geolocation_dispatcher_host.cc @@ -0,0 +1,227 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/geolocation/geolocation_dispatcher_host.h" + +#include <map> +#include <set> +#include <utility> + +#include "chrome/common/geoposition.h" +#include "chrome/browser/geolocation/geolocation_permission_context.h" +#include "chrome/browser/geolocation/location_arbitrator.h" +#include "chrome/browser/renderer_host/render_process_host.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/renderer_host/render_view_host_notification_task.h" +#include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/common/render_messages.h" +#include "ipc/ipc_message.h" + +namespace { +class GeolocationDispatcherHostImpl : public GeolocationDispatcherHost, + public GeolocationArbitrator::Delegate { + public: + GeolocationDispatcherHostImpl( + int resource_message_filter_process_id, + GeolocationPermissionContext* geolocation_permission_context); + + // GeolocationDispatcherHost + // Called to possibly handle the incoming IPC message. Returns true if + // handled. Called in the browser process. + virtual bool OnMessageReceived(const IPC::Message& msg, bool* msg_was_ok); + + // GeolocationArbitrator::Delegate + virtual void OnLocationUpdate(const Geoposition& position); + + private: + friend class base::RefCountedThreadSafe<GeolocationDispatcherHostImpl>; + virtual ~GeolocationDispatcherHostImpl(); + + void OnRegisterDispatcher(int render_view_id); + void OnUnregisterDispatcher(int render_view_id); + void OnRequestPermission( + int render_view_id, int bridge_id, const GURL& requesting_frame); + void OnCancelPermissionRequest( + int render_view_id, int bridge_id, const GURL& requesting_frame); + void OnStartUpdating( + int render_view_id, int bridge_id, const GURL& requesting_frame, + bool enable_high_accuracy); + void OnStopUpdating(int render_view_id, int bridge_id); + void OnSuspend(int render_view_id, int bridge_id); + void OnResume(int render_view_id, int bridge_id); + + // Updates the |location_arbitrator_| with the currently required update + // options, based on |bridge_update_options_|. + void RefreshUpdateOptions(); + + int resource_message_filter_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. + // Only used on the IO thread. + std::set<int> geolocation_renderer_ids_; + // Maps <renderer_id, bridge_id> to the location arbitrator update options + // that correspond to this particular bridge. + std::map<std::pair<int, int>, GeolocationArbitrator::UpdateOptions> + bridge_update_options_; + // Only set whilst we are registered with the arbitrator. + scoped_refptr<GeolocationArbitrator> location_arbitrator_; + + DISALLOW_COPY_AND_ASSIGN(GeolocationDispatcherHostImpl); +}; + +GeolocationDispatcherHostImpl::GeolocationDispatcherHostImpl( + int resource_message_filter_process_id, + GeolocationPermissionContext* geolocation_permission_context) + : resource_message_filter_process_id_(resource_message_filter_process_id), + geolocation_permission_context_(geolocation_permission_context) { + // This is initialized by ResourceMessageFilter. Do not add any non-trivial + // initialization here, defer to OnRegisterBridge which is triggered whenever + // a javascript geolocation object is actually initialized. +} + +GeolocationDispatcherHostImpl::~GeolocationDispatcherHostImpl() { + if (location_arbitrator_) + location_arbitrator_->RemoveObserver(this); +} + +bool GeolocationDispatcherHostImpl::OnMessageReceived( + const IPC::Message& msg, bool* msg_was_ok) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + *msg_was_ok = true; + bool handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(GeolocationDispatcherHostImpl, msg, *msg_was_ok) + IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_RegisterDispatcher, + OnRegisterDispatcher) + IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_UnregisterDispatcher, + OnUnregisterDispatcher) + IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_CancelPermissionRequest, + OnCancelPermissionRequest) + IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_RequestPermission, + OnRequestPermission) + IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_StartUpdating, + OnStartUpdating) + IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_StopUpdating, + OnStopUpdating) + IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_Suspend, + OnSuspend) + IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_Resume, + OnResume) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void GeolocationDispatcherHostImpl::OnLocationUpdate( + const Geoposition& geoposition) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + for (std::set<int>::iterator it = geolocation_renderer_ids_.begin(); + it != geolocation_renderer_ids_.end(); ++it) { + IPC::Message* message = + new ViewMsg_Geolocation_PositionUpdated(*it, geoposition); + CallRenderViewHost(resource_message_filter_process_id_, *it, + &RenderViewHost::Send, message); + } +} + +void GeolocationDispatcherHostImpl::OnRegisterDispatcher(int render_view_id) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + DCHECK_EQ(0u, geolocation_renderer_ids_.count(render_view_id)); + geolocation_renderer_ids_.insert(render_view_id); +} + +void GeolocationDispatcherHostImpl::OnUnregisterDispatcher(int render_view_id) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + DCHECK_EQ(1u, geolocation_renderer_ids_.count(render_view_id)); + geolocation_renderer_ids_.erase(render_view_id); +} + +void GeolocationDispatcherHostImpl::OnRequestPermission( + int render_view_id, int bridge_id, const GURL& requesting_frame) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + DLOG(INFO) << __FUNCTION__ << " " << resource_message_filter_process_id_ + << ":" << render_view_id << ":" << bridge_id; + geolocation_permission_context_->RequestGeolocationPermission( + resource_message_filter_process_id_, render_view_id, bridge_id, + requesting_frame); +} + +void GeolocationDispatcherHostImpl::OnCancelPermissionRequest( + int render_view_id, int bridge_id, const GURL& requesting_frame) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + DLOG(INFO) << __FUNCTION__ << " " << resource_message_filter_process_id_ + << ":" << render_view_id << ":" << bridge_id; + geolocation_permission_context_->CancelGeolocationPermissionRequest( + resource_message_filter_process_id_, render_view_id, bridge_id, + requesting_frame); +} + +void GeolocationDispatcherHostImpl::OnStartUpdating( + int render_view_id, int bridge_id, const GURL& requesting_frame, + bool enable_high_accuracy) { + // WebKit sends the startupdating request before checking permissions, to + // optimize the no-location-available case and reduce latency in the success + // case (location lookup happens in parallel with the permission request). + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + DLOG(INFO) << __FUNCTION__ << " " << resource_message_filter_process_id_ + << ":" << render_view_id << ":" << bridge_id; + bridge_update_options_[std::make_pair(render_view_id, bridge_id)] = + GeolocationArbitrator::UpdateOptions(enable_high_accuracy); + location_arbitrator_ = + geolocation_permission_context_->StartUpdatingRequested( + resource_message_filter_process_id_, render_view_id, bridge_id, + requesting_frame); + RefreshUpdateOptions(); +} + +void GeolocationDispatcherHostImpl::OnStopUpdating( + int render_view_id, int bridge_id) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + DLOG(INFO) << __FUNCTION__ << " " << resource_message_filter_process_id_ + << ":" << render_view_id << ":" << bridge_id; + if (bridge_update_options_.erase(std::make_pair(render_view_id, bridge_id))) + RefreshUpdateOptions(); + geolocation_permission_context_->StopUpdatingRequested( + resource_message_filter_process_id_, render_view_id, bridge_id); +} + +void GeolocationDispatcherHostImpl::OnSuspend( + int render_view_id, int bridge_id) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + DLOG(INFO) << __FUNCTION__ << " " << resource_message_filter_process_id_ + << ":" << render_view_id << ":" << bridge_id; + // TODO(bulach): connect this with GeolocationArbitrator. +} + +void GeolocationDispatcherHostImpl::OnResume( + int render_view_id, int bridge_id) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + DLOG(INFO) << __FUNCTION__ << " " << resource_message_filter_process_id_ + << ":" << render_view_id << ":" << bridge_id; + // TODO(bulach): connect this with GeolocationArbitrator. +} + +void GeolocationDispatcherHostImpl::RefreshUpdateOptions() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + DCHECK(location_arbitrator_); + if (bridge_update_options_.empty()) { + location_arbitrator_->RemoveObserver(this); + location_arbitrator_ = NULL; + } else { + location_arbitrator_->AddObserver( + this, + GeolocationArbitrator::UpdateOptions::Collapse( + bridge_update_options_)); + } +} +} // namespace + +GeolocationDispatcherHost* GeolocationDispatcherHost::New( + int resource_message_filter_process_id, + GeolocationPermissionContext* geolocation_permission_context) { + return new GeolocationDispatcherHostImpl(resource_message_filter_process_id, + geolocation_permission_context); +} |