summaryrefslogtreecommitdiffstats
path: root/chrome/browser/geolocation/geolocation_dispatcher_host.cc
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-07-29 17:14:53 +0100
committerBen Murdoch <benm@google.com>2010-08-04 14:29:45 +0100
commitc407dc5cd9bdc5668497f21b26b09d988ab439de (patch)
tree7eaf8707c0309516bdb042ad976feedaf72b0bb1 /chrome/browser/geolocation/geolocation_dispatcher_host.cc
parent0998b1cdac5733f299c12d88bc31ef9c8035b8fa (diff)
downloadexternal_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.cc227
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);
+}