summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authorblundell <blundell@chromium.org>2014-10-28 04:58:13 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-28 11:58:30 +0000
commit28e88081438dc08b06d5f05cfdd980c407db1638 (patch)
treec9ea441004d5a29d9db720c0810586c72b279ba6 /content/browser
parentf7295f2e7b0c17a7784f23e06b924ab966fea3a8 (diff)
downloadchromium_src-28e88081438dc08b06d5f05cfdd980c407db1638.zip
chromium_src-28e88081438dc08b06d5f05cfdd980c407db1638.tar.gz
chromium_src-28e88081438dc08b06d5f05cfdd980c407db1638.tar.bz2
Partially convert geolocation IPC to Mojo.
This CL converts the non-permissions-related geolocation IPC to Mojo. The Mojo GeolocationService interface allows clients to observe location updates. In //content, the service and its client connect on a per-frame basis, eliminating the need for the tracking of multiple frames that GeolocationDispatcherHost had previously been doing. To handle the fact that geolocation updates can be paused and resumed at per-WebContents granularity, we introduce a GeolocationServiceContext class, which is used to scope the granularity of pauses and resumes. Currently, GeolocationDispatcherHost still handles permissions-related geolocation IPC. This IPC will be moved to Mojo once there is resolution on what the right model for handling permissions there is. BUG=420497 TEST=Go to maps.google.com, allow location tracking, and check that your location is correctly pinpointed on the map. Review URL: https://codereview.chromium.org/628773003 Cr-Commit-Position: refs/heads/master@{#301604}
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/BUILD.gn1
-rw-r--r--content/browser/android/content_view_core_impl.cc7
-rw-r--r--content/browser/devtools/protocol/page_handler.cc14
-rw-r--r--content/browser/frame_host/render_frame_host_delegate.cc5
-rw-r--r--content/browser/frame_host/render_frame_host_delegate.h4
-rw-r--r--content/browser/frame_host/render_frame_host_impl.cc27
-rw-r--r--content/browser/frame_host/render_frame_host_impl.h6
-rw-r--r--content/browser/geolocation/geolocation_dispatcher_host.cc161
-rw-r--r--content/browser/geolocation/geolocation_dispatcher_host.h47
-rw-r--r--content/browser/geolocation/geolocation_service_context.cc62
-rw-r--r--content/browser/geolocation/geolocation_service_context.h58
-rw-r--r--content/browser/geolocation/geolocation_service_impl.cc155
-rw-r--r--content/browser/geolocation/geolocation_service_impl.h64
-rw-r--r--content/browser/web_contents/web_contents_impl.cc16
-rw-r--r--content/browser/web_contents/web_contents_impl.h10
15 files changed, 419 insertions, 218 deletions
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index cab6cb9..a37e2b6 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -96,6 +96,7 @@ source_set("browser") {
"//content/app/strings",
"//content/browser/devtools:resources",
"//content/common:mojo_bindings",
+ "//content/public/common:mojo_bindings",
"//mojo/public/cpp/bindings",
"//mojo/public/interfaces/application",
"//mojo/public/js/bindings",
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index cdc2146..d9b9879 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -23,7 +23,7 @@
#include "content/browser/android/load_url_params.h"
#include "content/browser/android/popup_touch_handle_drawable.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
-#include "content/browser/geolocation/geolocation_dispatcher_host.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
#include "content/browser/media/media_web_contents_observer.h"
#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/browser/renderer_host/input/motion_event_android.h"
@@ -363,7 +363,10 @@ jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
}
void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
- web_contents_->geolocation_dispatcher_host()->PauseOrResume(should_pause);
+ if (should_pause)
+ web_contents_->GetGeolocationServiceContext()->PauseUpdates();
+ else
+ web_contents_->GetGeolocationServiceContext()->ResumeUpdates();
}
// All positions and sizes are in CSS pixels.
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc
index 856352e..6f5f361 100644
--- a/content/browser/devtools/protocol/page_handler.cc
+++ b/content/browser/devtools/protocol/page_handler.cc
@@ -12,7 +12,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/devtools/protocol/color_picker.h"
#include "content/browser/devtools/protocol/usage_and_quota_query.h"
-#include "content/browser/geolocation/geolocation_dispatcher_host.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -237,8 +237,8 @@ Response PageHandler::SetGeolocationOverride(double* latitude,
if (!web_contents)
return Response::InternalError("No WebContents to override");
- GeolocationDispatcherHost* geolocation_host =
- web_contents->geolocation_dispatcher_host();
+ GeolocationServiceContext* geolocation_context =
+ web_contents->GetGeolocationServiceContext();
scoped_ptr<Geoposition> geoposition(new Geoposition());
if (latitude && longitude && accuracy) {
geoposition->latitude = *latitude;
@@ -251,7 +251,7 @@ Response PageHandler::SetGeolocationOverride(double* latitude,
} else {
geoposition->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
}
- geolocation_host->SetOverride(geoposition.Pass());
+ geolocation_context->SetOverride(geoposition.Pass());
return Response::OK();
}
@@ -264,9 +264,9 @@ Response PageHandler::ClearGeolocationOverride() {
if (!web_contents)
return Response::InternalError("No WebContents to override");
- GeolocationDispatcherHost* geolocation_host =
- web_contents->geolocation_dispatcher_host();
- geolocation_host->ClearOverride();
+ GeolocationServiceContext* geolocation_context =
+ web_contents->GetGeolocationServiceContext();
+ geolocation_context->ClearOverride();
return Response::OK();
}
diff --git a/content/browser/frame_host/render_frame_host_delegate.cc b/content/browser/frame_host/render_frame_host_delegate.cc
index 799b40e..a83715d 100644
--- a/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/content/browser/frame_host/render_frame_host_delegate.cc
@@ -63,6 +63,11 @@ RenderFrameHost* RenderFrameHostDelegate::GetGuestByInstanceID(
return NULL;
}
+GeolocationServiceContext*
+RenderFrameHostDelegate::GetGeolocationServiceContext() {
+ return NULL;
+}
+
#if defined(OS_WIN)
gfx::NativeViewAccessible
RenderFrameHostDelegate::GetParentNativeViewAccessible() {
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index 0d927a4..6c22d94 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -26,6 +26,7 @@ class Message;
}
namespace content {
+class GeolocationServiceContext;
class RenderFrameHost;
class WebContents;
struct AXEventNotificationDetails;
@@ -147,6 +148,9 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual RenderFrameHost* GetGuestByInstanceID(
int browser_plugin_instance_id);
+ // Gets the GeolocationServiceContext associated with this delegate.
+ virtual GeolocationServiceContext* GetGeolocationServiceContext();
+
#if defined(OS_WIN)
// Returns the frame's parent's NativeViewAccessible.
virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index e2c9f77..9260d43 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -24,6 +24,7 @@
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
#include "content/browser/renderer_host/input/input_router.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -210,7 +211,6 @@ RenderFrameHostImpl::RenderFrameHostImpl(RenderViewHostImpl* render_view_host,
}
SetUpMojoIfNeeded();
-
swapout_event_monitor_timeout_.reset(new TimeoutMonitor(base::Bind(
&RenderFrameHostImpl::OnSwappedOut, weak_ptr_factory_.GetWeakPtr())));
}
@@ -1224,6 +1224,21 @@ void RenderFrameHostImpl::OnHidePopup() {
}
#endif
+void RenderFrameHostImpl::RegisterMojoServices() {
+ GeolocationServiceContext* geolocation_service_context =
+ delegate_ ? delegate_->GetGeolocationServiceContext() : NULL;
+ if (geolocation_service_context) {
+ // TODO(creis): Bind process ID here so that GeolocationServiceImpl
+ // can perform permissions checks once site isolation is complete.
+ // crbug.com/426384
+ GetServiceRegistry()->AddService<GeolocationService>(
+ base::Bind(&GeolocationServiceContext::CreateService,
+ base::Unretained(geolocation_service_context),
+ base::Bind(&RenderFrameHostImpl::DidUseGeolocationPermission,
+ base::Unretained(this))));
+ }
+}
+
void RenderFrameHostImpl::SetState(RenderFrameHostImplState rfh_state) {
// Only main frames should be swapped out and retained inside a proxy host.
if (rfh_state == STATE_SWAPPED_OUT)
@@ -1449,6 +1464,7 @@ void RenderFrameHostImpl::SetUpMojoIfNeeded() {
if (!GetProcess()->GetServiceRegistry())
return;
+ RegisterMojoServices();
RenderFrameSetupPtr setup;
GetProcess()->GetServiceRegistry()->ConnectToRemoteService(&setup);
mojo::ServiceProviderPtr service_provider;
@@ -1636,4 +1652,13 @@ void RenderFrameHostImpl::CancelSuspendedNavigations() {
navigations_suspended_ = false;
}
+void RenderFrameHostImpl::DidUseGeolocationPermission() {
+ RenderFrameHost* top_frame = frame_tree_node()->frame_tree()->GetMainFrame();
+ GetContentClient()->browser()->RegisterPermissionUsage(
+ PERMISSION_GEOLOCATION,
+ delegate_->GetAsWebContents(),
+ GetLastCommittedURL().GetOrigin(),
+ top_frame->GetLastCommittedURL().GetOrigin());
+}
+
} // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index fbc2c00..8c38ba8 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -451,6 +451,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
void OnHidePopup();
#endif
+ // Registers Mojo services that this frame host makes available.
+ void RegisterMojoServices();
+
// Updates the state of this RenderFrameHost and clears any waiting state
// that is no longer relevant.
void SetState(RenderFrameHostImplState rfh_state);
@@ -474,6 +477,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
void UpdateGuestFrameAccessibility(
const std::map<int32, int> node_to_browser_plugin_instance_id_map);
+ // Informs the content client that geolocation permissions were used.
+ void DidUseGeolocationPermission();
+
// For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a
// refcount that calls Shutdown when it reaches zero. This allows each
// RenderFrameHostManager to just care about RenderFrameHosts, while ensuring
diff --git a/content/browser/geolocation/geolocation_dispatcher_host.cc b/content/browser/geolocation/geolocation_dispatcher_host.cc
index d677ba0..9dfec90 100644
--- a/content/browser/geolocation/geolocation_dispatcher_host.cc
+++ b/content/browser/geolocation/geolocation_dispatcher_host.cc
@@ -7,64 +7,14 @@
#include <utility>
#include "base/bind.h"
-#include "base/metrics/histogram.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/geolocation/geolocation_provider_impl.h"
#include "content/browser/renderer_host/render_message_filter.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/common/geoposition.h"
#include "content/common/geolocation_messages.h"
namespace content {
-namespace {
-
-// Geoposition error codes for reporting in UMA.
-enum GeopositionErrorCode {
- // NOTE: Do not renumber these as that would confuse interpretation of
- // previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
-
- // There was no error.
- GEOPOSITION_ERROR_CODE_NONE = 0,
-
- // User denied use of geolocation.
- GEOPOSITION_ERROR_CODE_PERMISSION_DENIED = 1,
-
- // Geoposition could not be determined.
- GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE = 2,
-
- // Timeout.
- GEOPOSITION_ERROR_CODE_TIMEOUT = 3,
-
- // NOTE: Add entries only immediately above this line.
- GEOPOSITION_ERROR_CODE_COUNT = 4
-};
-
-void RecordGeopositionErrorCode(Geoposition::ErrorCode error_code) {
- GeopositionErrorCode code = GEOPOSITION_ERROR_CODE_NONE;
- switch (error_code) {
- case Geoposition::ERROR_CODE_NONE:
- code = GEOPOSITION_ERROR_CODE_NONE;
- break;
- case Geoposition::ERROR_CODE_PERMISSION_DENIED:
- code = GEOPOSITION_ERROR_CODE_PERMISSION_DENIED;
- break;
- case Geoposition::ERROR_CODE_POSITION_UNAVAILABLE:
- code = GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE;
- break;
- case Geoposition::ERROR_CODE_TIMEOUT:
- code = GEOPOSITION_ERROR_CODE_TIMEOUT;
- break;
- }
- UMA_HISTOGRAM_ENUMERATION("Geolocation.LocationUpdate.ErrorCode",
- code,
- GEOPOSITION_ERROR_CODE_COUNT);
-}
-
-} // namespace
GeolocationDispatcherHost::PendingPermission::PendingPermission(
int render_frame_id,
@@ -83,7 +33,6 @@ GeolocationDispatcherHost::PendingPermission::~PendingPermission() {
GeolocationDispatcherHost::GeolocationDispatcherHost(
WebContents* web_contents)
: WebContentsObserver(web_contents),
- paused_(false),
weak_factory_(this) {
// This is initialized by WebContentsImpl. Do not add any non-trivial
// initialization here, defer to OnStartUpdating which is triggered whenever
@@ -93,33 +42,11 @@ GeolocationDispatcherHost::GeolocationDispatcherHost(
GeolocationDispatcherHost::~GeolocationDispatcherHost() {
}
-void GeolocationDispatcherHost::SetOverride(
- scoped_ptr<Geoposition> geoposition) {
- geoposition_override_.swap(geoposition);
- RefreshGeolocationOptions();
- OnLocationUpdate(*geoposition_override_);
-}
-
-void GeolocationDispatcherHost::ClearOverride() {
- geoposition_override_.reset();
- RefreshGeolocationOptions();
-}
-
void GeolocationDispatcherHost::RenderFrameDeleted(
RenderFrameHost* render_frame_host) {
- OnStopUpdating(render_frame_host);
-
CancelPermissionRequestsForFrame(render_frame_host);
}
-void GeolocationDispatcherHost::RenderViewHostChanged(
- RenderViewHost* old_host,
- RenderViewHost* new_host) {
- updating_frames_.clear();
- paused_ = false;
- geolocation_subscription_.reset();
-}
-
void GeolocationDispatcherHost::DidNavigateAnyFrame(
RenderFrameHost* render_frame_host,
const LoadCommittedDetails& details,
@@ -137,44 +64,11 @@ bool GeolocationDispatcherHost::OnMessageReceived(
render_frame_host)
IPC_MESSAGE_HANDLER(GeolocationHostMsg_RequestPermission,
OnRequestPermission)
- IPC_MESSAGE_HANDLER(GeolocationHostMsg_StartUpdating, OnStartUpdating)
- IPC_MESSAGE_HANDLER(GeolocationHostMsg_StopUpdating, OnStopUpdating)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void GeolocationDispatcherHost::OnLocationUpdate(
- const Geoposition& geoposition) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- RecordGeopositionErrorCode(geoposition.error_code);
- if (paused_)
- return;
-
- for (std::map<RenderFrameHost*, bool>::iterator i = updating_frames_.begin();
- i != updating_frames_.end(); ++i) {
- UpdateGeoposition(i->first, geoposition);
- }
-}
-
-void GeolocationDispatcherHost::UpdateGeoposition(
- RenderFrameHost* frame,
- const Geoposition& geoposition) {
- RenderFrameHost* top_frame = frame;
- while (top_frame->GetParent()) {
- top_frame = top_frame->GetParent();
- }
- GetContentClient()->browser()->RegisterPermissionUsage(
- content::PERMISSION_GEOLOCATION,
- web_contents(),
- frame->GetLastCommittedURL().GetOrigin(),
- top_frame->GetLastCommittedURL().GetOrigin());
-
- frame->Send(new GeolocationMsg_PositionUpdated(
- frame->GetRoutingID(), geoposition));
-}
-
void GeolocationDispatcherHost::OnRequestPermission(
RenderFrameHost* render_frame_host,
int bridge_id,
@@ -200,59 +94,6 @@ void GeolocationDispatcherHost::OnRequestPermission(
bridge_id));
}
-void GeolocationDispatcherHost::OnStartUpdating(
- RenderFrameHost* render_frame_host,
- const GURL& requesting_origin,
- bool enable_high_accuracy) {
- // StartUpdating() can be invoked as a result of high-accuracy mode
- // being enabled / disabled. No need to record the dispatcher again.
- UMA_HISTOGRAM_BOOLEAN(
- "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy",
- enable_high_accuracy);
-
- updating_frames_[render_frame_host] = enable_high_accuracy;
- RefreshGeolocationOptions();
- if (geoposition_override_.get())
- UpdateGeoposition(render_frame_host, *geoposition_override_);
-}
-
-void GeolocationDispatcherHost::OnStopUpdating(
- RenderFrameHost* render_frame_host) {
- updating_frames_.erase(render_frame_host);
- RefreshGeolocationOptions();
-}
-
-void GeolocationDispatcherHost::PauseOrResume(bool should_pause) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- paused_ = should_pause;
- RefreshGeolocationOptions();
- if (geoposition_override_.get())
- OnLocationUpdate(*geoposition_override_);
-}
-
-void GeolocationDispatcherHost::RefreshGeolocationOptions() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (updating_frames_.empty() || paused_ || geoposition_override_.get()) {
- geolocation_subscription_.reset();
- return;
- }
-
- bool high_accuracy = false;
- for (std::map<RenderFrameHost*, bool>::iterator i =
- updating_frames_.begin(); i != updating_frames_.end(); ++i) {
- if (i->second) {
- high_accuracy = true;
- break;
- }
- }
- geolocation_subscription_ = GeolocationProvider::GetInstance()->
- AddLocationUpdateCallback(
- base::Bind(&GeolocationDispatcherHost::OnLocationUpdate,
- base::Unretained(this)),
- high_accuracy);
-}
-
void GeolocationDispatcherHost::SendGeolocationPermissionResponse(
int render_process_id,
int render_frame_id,
diff --git a/content/browser/geolocation/geolocation_dispatcher_host.h b/content/browser/geolocation/geolocation_dispatcher_host.h
index d942cff..6359de1 100644
--- a/content/browser/geolocation/geolocation_dispatcher_host.h
+++ b/content/browser/geolocation/geolocation_dispatcher_host.h
@@ -10,41 +10,29 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
-#include "content/browser/geolocation/geolocation_provider_impl.h"
#include "content/public/browser/web_contents_observer.h"
class GURL;
namespace content {
-// GeolocationDispatcherHost is an observer for Geolocation messages.
-// It's the complement of GeolocationDispatcher (owned by RenderView).
+// GeolocationDispatcherHost is an observer for Geolocation permissions-related
+// messages. In this role, it's the complement of GeolocationDispatcher (owned
+// by RenderFrame).
+// TODO(blundell): Eliminate this class in favor of having
+// Mojo handle permissions for geolocation once there is resolution on how
+// that will work. crbug.com/420498
class GeolocationDispatcherHost : public WebContentsObserver {
public:
explicit GeolocationDispatcherHost(WebContents* web_contents);
~GeolocationDispatcherHost() override;
- // Pause or resumes geolocation. Resuming when nothing is paused is a no-op.
- // If the web contents is paused while not currently using geolocation but
- // then goes on to do so before being resumed, then it will not get
- // geolocation updates until it is resumed.
- void PauseOrResume(bool should_pause);
-
- // Enables geolocation override. This method is used by DevTools to
- // trigger possible location-specific behavior in particular web contents.
- void SetOverride(scoped_ptr<Geoposition> geoposition);
-
- // Disables geolocation override.
- void ClearOverride();
-
private:
// WebContentsObserver
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
- void RenderViewHostChanged(RenderViewHost* old_host,
- RenderViewHost* new_host) override;
void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
- const LoadCommittedDetails& details,
- const FrameNavigateParams& params) override;
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) override;
bool OnMessageReceived(const IPC::Message& msg,
RenderFrameHost* render_frame_host) override;
@@ -55,17 +43,6 @@ class GeolocationDispatcherHost : public WebContentsObserver {
int bridge_id,
const GURL& requesting_origin,
bool user_gesture);
- void OnStartUpdating(RenderFrameHost* render_frame_host,
- const GURL& requesting_origin,
- bool enable_high_accuracy);
- void OnStopUpdating(RenderFrameHost* render_frame_host);
-
- // Updates the geolocation provider with the currently required update
- // options.
- void RefreshGeolocationOptions();
-
- void OnLocationUpdate(const Geoposition& position);
- void UpdateGeoposition(RenderFrameHost* frame, const Geoposition& position);
void SendGeolocationPermissionResponse(int render_process_id,
int render_frame_id,
@@ -76,11 +53,6 @@ class GeolocationDispatcherHost : public WebContentsObserver {
// browser to cancel the permission requests.
void CancelPermissionRequestsForFrame(RenderFrameHost* render_frame_host);
- // A map from the RenderFrameHosts that have requested geolocation updates to
- // the type of accuracy they requested (true = high accuracy).
- std::map<RenderFrameHost*, bool> updating_frames_;
- bool paused_;
-
struct PendingPermission {
PendingPermission(int render_frame_id,
int render_process_id,
@@ -94,9 +66,6 @@ class GeolocationDispatcherHost : public WebContentsObserver {
};
std::vector<PendingPermission> pending_permissions_;
- scoped_ptr<GeolocationProvider::Subscription> geolocation_subscription_;
- scoped_ptr<Geoposition> geoposition_override_;
-
base::WeakPtrFactory<GeolocationDispatcherHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(GeolocationDispatcherHost);
diff --git a/content/browser/geolocation/geolocation_service_context.cc b/content/browser/geolocation/geolocation_service_context.cc
new file mode 100644
index 0000000..bf3d46c
--- /dev/null
+++ b/content/browser/geolocation/geolocation_service_context.cc
@@ -0,0 +1,62 @@
+// Copyright 2014 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 "content/browser/geolocation/geolocation_service_context.h"
+
+namespace content {
+
+GeolocationServiceContext::GeolocationServiceContext() : paused_(false) {
+}
+
+GeolocationServiceContext::~GeolocationServiceContext() {
+}
+
+void GeolocationServiceContext::CreateService(
+ const base::Closure& update_callback,
+ mojo::InterfaceRequest<GeolocationService> request) {
+ GeolocationServiceImpl* service =
+ new GeolocationServiceImpl(this, update_callback);
+ if (geoposition_override_)
+ service->SetOverride(*geoposition_override_.get());
+ services_.push_back(service);
+ mojo::WeakBindToRequest(service, &request);
+ service->StartListeningForUpdates();
+}
+
+void GeolocationServiceContext::ServiceHadConnectionError(
+ GeolocationServiceImpl* service) {
+ auto it = std::find(services_.begin(), services_.end(), service);
+ DCHECK(it != services_.end());
+ services_.erase(it);
+}
+
+void GeolocationServiceContext::PauseUpdates() {
+ paused_ = true;
+ for (auto* service : services_) {
+ service->PauseUpdates();
+ }
+}
+
+void GeolocationServiceContext::ResumeUpdates() {
+ paused_ = false;
+ for (auto* service : services_) {
+ service->ResumeUpdates();
+ }
+}
+
+void GeolocationServiceContext::SetOverride(
+ scoped_ptr<Geoposition> geoposition) {
+ geoposition_override_.swap(geoposition);
+ for (auto* service : services_) {
+ service->SetOverride(*geoposition_override_.get());
+ }
+}
+
+void GeolocationServiceContext::ClearOverride() {
+ for (auto* service : services_) {
+ service->ClearOverride();
+ }
+}
+
+} // namespace content
diff --git a/content/browser/geolocation/geolocation_service_context.h b/content/browser/geolocation/geolocation_service_context.h
new file mode 100644
index 0000000..453c8b0
--- /dev/null
+++ b/content/browser/geolocation/geolocation_service_context.h
@@ -0,0 +1,58 @@
+// Copyright 2014 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.
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_CONTEXT_H_
+#define CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_CONTEXT_H_
+
+#include "base/memory/scoped_vector.h"
+#include "content/browser/geolocation/geolocation_service_impl.h"
+
+namespace content {
+
+// Provides information to a set of GeolocationServiceImpl instances that are
+// associated with a given context. Notably, allows pausing and resuming
+// geolocation on these instances.
+class GeolocationServiceContext {
+ public:
+ GeolocationServiceContext();
+ virtual ~GeolocationServiceContext();
+
+ // Creates a GeolocationServiceImpl that is weakly bound to |request|.
+ // |update_callback| will be called when services send
+ // location updates to their clients.
+ void CreateService(const base::Closure& update_callback,
+ mojo::InterfaceRequest<GeolocationService> request);
+
+ // Called when a service has a connection error. After this call, it is no
+ // longer safe to access |service|.
+ void ServiceHadConnectionError(GeolocationServiceImpl* service);
+
+ // Pauses and resumes geolocation. Resuming when nothing is paused is a
+ // no-op. If a service is added while geolocation is paused, that service
+ // will not get geolocation updates until geolocation is resumed.
+ void PauseUpdates();
+ void ResumeUpdates();
+
+ // Returns whether geolocation updates are currently paused.
+ bool paused() { return paused_; }
+
+ // Enables geolocation override. This method can be used to trigger possible
+ // location-specific behavior in a particular context.
+ void SetOverride(scoped_ptr<Geoposition> geoposition);
+
+ // Disables geolocation override.
+ void ClearOverride();
+
+ private:
+ ScopedVector<GeolocationServiceImpl> services_;
+ bool paused_;
+
+ scoped_ptr<Geoposition> geoposition_override_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationServiceContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_CONTEXT_H_
diff --git a/content/browser/geolocation/geolocation_service_impl.cc b/content/browser/geolocation/geolocation_service_impl.cc
new file mode 100644
index 0000000..4c855f2
--- /dev/null
+++ b/content/browser/geolocation/geolocation_service_impl.cc
@@ -0,0 +1,155 @@
+// Copyright 2014 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 "content/browser/geolocation/geolocation_service_impl.h"
+
+#include "base/bind.h"
+#include "base/metrics/histogram.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
+#include "content/public/common/mojo_geoposition.mojom.h"
+
+namespace content {
+
+namespace {
+
+// Geoposition error codes for reporting in UMA.
+enum GeopositionErrorCode {
+ // NOTE: Do not renumber these as that would confuse interpretation of
+ // previously logged data. When making changes, also update the enum list
+ // in tools/metrics/histograms/histograms.xml to keep it in sync.
+
+ // There was no error.
+ GEOPOSITION_ERROR_CODE_NONE = 0,
+
+ // User denied use of geolocation.
+ GEOPOSITION_ERROR_CODE_PERMISSION_DENIED = 1,
+
+ // Geoposition could not be determined.
+ GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE = 2,
+
+ // Timeout.
+ GEOPOSITION_ERROR_CODE_TIMEOUT = 3,
+
+ // NOTE: Add entries only immediately above this line.
+ GEOPOSITION_ERROR_CODE_COUNT = 4
+};
+
+void RecordGeopositionErrorCode(Geoposition::ErrorCode error_code) {
+ GeopositionErrorCode code = GEOPOSITION_ERROR_CODE_NONE;
+ switch (error_code) {
+ case Geoposition::ERROR_CODE_NONE:
+ code = GEOPOSITION_ERROR_CODE_NONE;
+ break;
+ case Geoposition::ERROR_CODE_PERMISSION_DENIED:
+ code = GEOPOSITION_ERROR_CODE_PERMISSION_DENIED;
+ break;
+ case Geoposition::ERROR_CODE_POSITION_UNAVAILABLE:
+ code = GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE;
+ break;
+ case Geoposition::ERROR_CODE_TIMEOUT:
+ code = GEOPOSITION_ERROR_CODE_TIMEOUT;
+ break;
+ }
+ UMA_HISTOGRAM_ENUMERATION("Geolocation.LocationUpdate.ErrorCode",
+ code,
+ GEOPOSITION_ERROR_CODE_COUNT);
+}
+
+} // namespace
+
+GeolocationServiceImpl::GeolocationServiceImpl(
+ GeolocationServiceContext* context,
+ const base::Closure& update_callback)
+ : context_(context),
+ update_callback_(update_callback),
+ high_accuracy_(false) {
+ DCHECK(context_);
+}
+
+GeolocationServiceImpl::~GeolocationServiceImpl() {
+}
+
+void GeolocationServiceImpl::PauseUpdates() {
+ geolocation_subscription_.reset();
+}
+
+void GeolocationServiceImpl::ResumeUpdates() {
+ if (position_override_.Validate()) {
+ OnLocationUpdate(position_override_);
+ return;
+ }
+
+ StartListeningForUpdates();
+}
+
+void GeolocationServiceImpl::StartListeningForUpdates() {
+ geolocation_subscription_ =
+ GeolocationProvider::GetInstance()->AddLocationUpdateCallback(
+ base::Bind(&GeolocationServiceImpl::OnLocationUpdate,
+ base::Unretained(this)),
+ high_accuracy_);
+}
+
+void GeolocationServiceImpl::SetHighAccuracy(bool high_accuracy) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy",
+ high_accuracy);
+ high_accuracy_ = high_accuracy;
+
+ if (position_override_.Validate()) {
+ OnLocationUpdate(position_override_);
+ return;
+ }
+
+ StartListeningForUpdates();
+}
+
+void GeolocationServiceImpl::SetOverride(const Geoposition& position) {
+ position_override_ = position;
+ if (!position_override_.Validate()) {
+ ResumeUpdates();
+ }
+
+ geolocation_subscription_.reset();
+
+ OnLocationUpdate(position_override_);
+}
+
+void GeolocationServiceImpl::ClearOverride() {
+ position_override_ = Geoposition();
+ StartListeningForUpdates();
+}
+
+void GeolocationServiceImpl::OnConnectionError() {
+ context_->ServiceHadConnectionError(this);
+
+ // The above call deleted this instance, so the only safe thing to do is
+ // return.
+}
+
+void GeolocationServiceImpl::OnLocationUpdate(const Geoposition& position) {
+ RecordGeopositionErrorCode(position.error_code);
+ DCHECK(context_);
+
+ if (context_->paused())
+ return;
+
+ MojoGeopositionPtr geoposition(MojoGeoposition::New());
+ geoposition->valid = position.Validate();
+ geoposition->latitude = position.latitude;
+ geoposition->longitude = position.longitude;
+ geoposition->altitude = position.altitude;
+ geoposition->accuracy = position.accuracy;
+ geoposition->altitude_accuracy = position.altitude_accuracy;
+ geoposition->heading = position.heading;
+ geoposition->speed = position.speed;
+ geoposition->timestamp = position.timestamp.ToDoubleT();
+ geoposition->error_code = MojoGeoposition::ErrorCode(position.error_code);
+ geoposition->error_message = position.error_message;
+
+ update_callback_.Run();
+ client()->OnLocationUpdate(geoposition.Pass());
+}
+
+} // namespace content
diff --git a/content/browser/geolocation/geolocation_service_impl.h b/content/browser/geolocation/geolocation_service_impl.h
new file mode 100644
index 0000000..172e4e1
--- /dev/null
+++ b/content/browser/geolocation/geolocation_service_impl.h
@@ -0,0 +1,64 @@
+// Copyright 2014 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 "base/memory/scoped_ptr.h"
+#include "content/browser/geolocation/geolocation_provider_impl.h"
+#include "content/common/geolocation_service.mojom.h"
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
+
+namespace content {
+
+class GeolocationProvider;
+class GeolocationServiceContext;
+
+// Implements the GeolocationService Mojo interface.
+class GeolocationServiceImpl : public mojo::InterfaceImpl<GeolocationService> {
+ public:
+ // |context| must outlive this object. |update_callback| will be
+ // called when location updates are sent.
+ GeolocationServiceImpl(GeolocationServiceContext* context,
+ const base::Closure& update_callback);
+ ~GeolocationServiceImpl() override;
+
+ // Starts listening for updates.
+ void StartListeningForUpdates();
+
+ // Pauses and resumes sending updates to the client of this instance.
+ void PauseUpdates();
+ void ResumeUpdates();
+
+ // Enables and disables geolocation override.
+ void SetOverride(const Geoposition& position);
+ void ClearOverride();
+
+ private:
+ // GeolocationService:
+ void SetHighAccuracy(bool high_accuracy) override;
+
+ // mojo::InterfaceImpl:
+ void OnConnectionError() override;
+
+ void OnLocationUpdate(const Geoposition& position);
+
+ // Owns this object.
+ GeolocationServiceContext* context_;
+ scoped_ptr<GeolocationProvider::Subscription> geolocation_subscription_;
+ base::Closure update_callback_;
+
+ // Valid iff SetOverride() has been called and ClearOverride() has not
+ // subsequently been called.
+ Geoposition position_override_;
+
+ // Whether this instance is currently observing location updates with high
+ // accuracy.
+ bool high_accuracy_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationServiceImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index e6ee4cf..eb78a82 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -36,6 +36,7 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/geolocation/geolocation_dispatcher_host.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/manifest/manifest_manager_host.h"
@@ -284,9 +285,8 @@ WebContentsImpl::ColorChooserInfo::~ColorChooserInfo() {
// WebContentsImpl -------------------------------------------------------------
-WebContentsImpl::WebContentsImpl(
- BrowserContext* browser_context,
- WebContentsImpl* opener)
+WebContentsImpl::WebContentsImpl(BrowserContext* browser_context,
+ WebContentsImpl* opener)
: delegate_(NULL),
controller_(this, browser_context),
render_view_host_delegate_view_(NULL),
@@ -296,7 +296,10 @@ WebContentsImpl::WebContentsImpl(
accessible_parent_(NULL),
#endif
frame_tree_(new NavigatorImpl(&controller_, this),
- this, this, this, this),
+ this,
+ this,
+ this,
+ this),
is_loading_(false),
is_load_to_different_document_(false),
crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
@@ -327,6 +330,7 @@ WebContentsImpl::WebContentsImpl(
is_subframe_(false),
force_disable_overscroll_content_(false),
last_dialog_suppressed_(false),
+ geolocation_service_context_(new GeolocationServiceContext()),
accessibility_mode_(
BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
audio_stream_monitor_(this),
@@ -1805,6 +1809,10 @@ RenderFrameHost* WebContentsImpl::GetGuestByInstanceID(
return guest->GetMainFrame();
}
+GeolocationServiceContext* WebContentsImpl::GetGeolocationServiceContext() {
+ return geolocation_service_context_.get();
+}
+
void WebContentsImpl::OnShowValidationMessage(
const gfx::Rect& anchor_in_root_view,
const base::string16& main_text,
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index c437796..88eaf22 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -52,6 +52,7 @@ class BrowserPluginGuestManager;
class DateTimeChooserAndroid;
class DownloadItem;
class GeolocationDispatcherHost;
+class GeolocationServiceContext;
class InterstitialPageImpl;
class JavaScriptDialogManager;
class ManifestManagerHost;
@@ -173,10 +174,6 @@ class CONTENT_EXPORT WebContentsImpl
WebContentsView* GetView() const;
- GeolocationDispatcherHost* geolocation_dispatcher_host() {
- return geolocation_dispatcher_host_.get();
- }
-
ScreenOrientationDispatcherHost* screen_orientation_dispatcher_host() {
return screen_orientation_dispatcher_host_.get();
}
@@ -385,8 +382,9 @@ class CONTENT_EXPORT WebContentsImpl
const std::vector<AXEventNotificationDetails>& details) override;
RenderFrameHost* GetGuestByInstanceID(
int browser_plugin_instance_id) override;
+ GeolocationServiceContext* GetGeolocationServiceContext() override;
#if defined(OS_WIN)
- virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() override;
+ gfx::NativeViewAccessible GetParentNativeViewAccessible() override;
#endif
// RenderViewHostDelegate ----------------------------------------------------
@@ -1194,6 +1192,8 @@ class CONTENT_EXPORT WebContentsImpl
// Whether the last JavaScript dialog shown was suppressed. Used for testing.
bool last_dialog_suppressed_;
+ scoped_ptr<GeolocationServiceContext> geolocation_service_context_;
+
scoped_ptr<GeolocationDispatcherHost> geolocation_dispatcher_host_;
scoped_ptr<MidiDispatcherHost> midi_dispatcher_host_;