diff options
Diffstat (limited to 'content')
27 files changed, 570 insertions, 282 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_; diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 0417e92..276b5b5 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn @@ -318,10 +318,12 @@ source_set("common") { mojom("mojo_bindings") { sources = [ + "geolocation_service.mojom", "render_frame_setup.mojom", ] deps = [ + "//content/public/common:mojo_bindings", "//mojo/public/interfaces/application:application", ] } diff --git a/content/common/OWNERS b/content/common/OWNERS index 88d8954..4bc5132 100644 --- a/content/common/OWNERS +++ b/content/common/OWNERS @@ -55,6 +55,11 @@ per-file *param_traits*.h=palmer@chromium.org per-file *param_traits*.h=tsepez@chromium.org per-file *param_traits*.h=wfh@chromium.org +# Changes to Mojo interfaces require a security review to avoid +# introducing new sandbox escapes. +per-file *.mojom=set noparent +per-file *.mojom=tsepez@chromium.org + # Accessibility per-file accessibility_node_data.*=dmazzoni@chromium.org per-file accessibility_node_data.*=dtseng@chromium.org diff --git a/content/common/geolocation_messages.h b/content/common/geolocation_messages.h index f89424c..b66a191 100644 --- a/content/common/geolocation_messages.h +++ b/content/common/geolocation_messages.h @@ -34,12 +34,6 @@ IPC_MESSAGE_ROUTED2(GeolocationMsg_PermissionSet, int /* bridge_id */, bool /* is_allowed */) -// Sent after GeolocationHostMsg_StartUpdating iff the user has granted -// permission and we have a position available or an error occurs (such as -// permission denied, position unavailable, etc.) -IPC_MESSAGE_ROUTED1(GeolocationMsg_PositionUpdated, - content::Geoposition /* geoposition */) - // Messages sent from the renderer to the browser. // The |bridge_id| representing |host| is requesting permission to access @@ -50,16 +44,3 @@ IPC_MESSAGE_ROUTED3(GeolocationHostMsg_RequestPermission, int /* bridge_id */, GURL /* origin in the frame requesting geolocation */, bool /* user_gesture */) - -// The render view requests the Geolocation service to start updating. -// This is an asynchronous call, and the browser process may eventually reply -// with the updated geoposition, or an error (access denied, location -// unavailable, etc.) -IPC_MESSAGE_ROUTED2(GeolocationHostMsg_StartUpdating, - GURL /* origin in the frame requesting geolocation */, - bool /* enable_high_accuracy */) - -// The render view requests Geolocation service to stop updating. -// Note that the geolocation service may continue to fetch geolocation data -// for other origins. -IPC_MESSAGE_ROUTED0(GeolocationHostMsg_StopUpdating) diff --git a/content/common/geolocation_service.mojom b/content/common/geolocation_service.mojom new file mode 100644 index 0000000..bde7e0f --- /dev/null +++ b/content/common/geolocation_service.mojom @@ -0,0 +1,21 @@ +// 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. + +import "content/public/common/mojo_geoposition.mojom" + +module content { + +// The Geolocation service provides updates on the device's location to its +// client. By default, it provides updates with low accuracy, but +// |SetHighAccuracy()| can be called to change this. +[Client=GeolocationServiceClient] +interface GeolocationService { + SetHighAccuracy(bool high_accuracy); +}; + +interface GeolocationServiceClient { + OnLocationUpdate(MojoGeoposition geoposition); +}; + +} diff --git a/content/content_browser.gypi b/content/content_browser.gypi index c9dcea9..df89b9c 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -686,6 +686,10 @@ 'browser/geolocation/geolocation_dispatcher_host.h', 'browser/geolocation/geolocation_provider_impl.cc', 'browser/geolocation/geolocation_provider_impl.h', + 'browser/geolocation/geolocation_service_context.cc', + 'browser/geolocation/geolocation_service_context.h', + 'browser/geolocation/geolocation_service_impl.cc', + 'browser/geolocation/geolocation_service_impl.h', 'browser/geolocation/location_api_adapter_android.cc', 'browser/geolocation/location_api_adapter_android.h', 'browser/geolocation/location_arbitrator.h', diff --git a/content/content_common_mojo_bindings.gypi b/content/content_common_mojo_bindings.gypi index 15bb27d..da5c00a 100644 --- a/content/content_common_mojo_bindings.gypi +++ b/content/content_common_mojo_bindings.gypi @@ -13,7 +13,13 @@ '../mojo/public/mojo_public.gyp:mojo_cpp_bindings', ], 'sources': [ + # NOTE: Sources duplicated in //content/common/BUILD.gn:mojo_bindings. + 'common/geolocation_service.mojom', 'common/render_frame_setup.mojom', + + # NOTE: Sources duplicated in + # //content/public/common/BUILD.gn:mojo_bindings. + 'public/common/mojo_geoposition.mojom', ], 'includes': [ '../mojo/public/tools/bindings/mojom_bindings_generator.gypi' ], 'export_dependent_settings': [ diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn index a1244a2..c4d0036 100644 --- a/content/public/common/BUILD.gn +++ b/content/public/common/BUILD.gn @@ -4,6 +4,7 @@ import("//build/config/features.gni") import("//content/common/common.gni") +import("//mojo/public/tools/bindings/mojom.gni") # See //content/BUILD.gn for how this works. group("common") { @@ -43,3 +44,9 @@ source_set("common_sources") { ] } } + +mojom("mojo_bindings") { + sources = [ + "mojo_geoposition.mojom", + ] +} diff --git a/content/public/common/OWNERS b/content/public/common/OWNERS index 1e8a3aa..86e4104 100644 --- a/content/public/common/OWNERS +++ b/content/public/common/OWNERS @@ -12,3 +12,8 @@ per-file *param_traits*.h=nasko@chromium.org per-file *param_traits*.h=palmer@chromium.org per-file *param_traits*.h=tsepez@chromium.org per-file *param_traits*.h=wfh@chromium.org + +# Changes to Mojo interfaces require a security review to avoid +# introducing new sandbox escapes. +per-file *.mojom=set noparent +per-file *.mojom=tsepez@chromium.org diff --git a/content/public/common/mojo_geoposition.mojom b/content/public/common/mojo_geoposition.mojom new file mode 100644 index 0000000..f9818b5 --- /dev/null +++ b/content/public/common/mojo_geoposition.mojom @@ -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. + +// This file declares the Geoposition structure, used to represent a position +// fix. It was originally derived from: +// http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation.h +// TODO(blundell): Investigate killing content::Geoposition in favor of using +// this struct everywhere (and renaming it to Geoposition). + +module content { + +struct MojoGeoposition { + // These values follow the W3C geolocation specification and can be returned + // to JavaScript without the need for a conversion. + enum ErrorCode { + ERROR_CODE_NONE = 0, // Chrome addition. + ERROR_CODE_PERMISSION_DENIED = 1, + ERROR_CODE_POSITION_UNAVAILABLE = 2, + ERROR_CODE_TIMEOUT = 3, + ERROR_CODE_LAST = ERROR_CODE_TIMEOUT + }; + + // Whether this geoposition is valid. + bool valid; + + // These properties correspond to those of the JavaScript Position object + // although their types may differ. + // Latitude in decimal degrees north (WGS84 coordinate frame). + double latitude; + // Longitude in decimal degrees west (WGS84 coordinate frame). + double longitude; + // Altitude in meters (above WGS84 datum). + double altitude; + // Accuracy of horizontal position in meters. + double accuracy; + // Accuracy of altitude in meters. + double altitude_accuracy; + // Heading in decimal degrees clockwise from true north. + double heading; + // Horizontal component of device velocity in meters per second. + double speed; + // TODO(blundell): If I need to represent this differently to use this + // struct to replace content::Geolocation, I'll need to convert + // correctly into seconds-since-epoch when using this in + // GeolocationDispatcher::OnLocationUpdate(). + // Time of position measurement in seconds since Epoch in UTC time. This is + // taken from the host computer's system clock (i.e. from Time::Now(), not the + // source device's clock). + double timestamp; + + // Error code, see enum above. + ErrorCode error_code; + // Human-readable error message. + string error_message; +}; + +} diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 388570b..a9b54c2 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn @@ -31,6 +31,7 @@ source_set("renderer") { "//content/common:mojo_bindings", "//content/public/child:child_sources", "//content/public/common:common_sources", + "//content/public/common:mojo_bindings", "//gin", "//gpu", "//gpu/command_buffer/client:gles2_interface", diff --git a/content/renderer/geolocation_dispatcher.cc b/content/renderer/geolocation_dispatcher.cc index a099a3d9..fde4fc9 100644 --- a/content/renderer/geolocation_dispatcher.cc +++ b/content/renderer/geolocation_dispatcher.cc @@ -25,8 +25,7 @@ namespace content { GeolocationDispatcher::GeolocationDispatcher(RenderFrame* render_frame) : RenderFrameObserver(render_frame), pending_permissions_(new WebGeolocationPermissionRequestManager()), - enable_high_accuracy_(false), - updating_(false) { + enable_high_accuracy_(false) { } GeolocationDispatcher::~GeolocationDispatcher() {} @@ -35,22 +34,23 @@ bool GeolocationDispatcher::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(GeolocationDispatcher, message) IPC_MESSAGE_HANDLER(GeolocationMsg_PermissionSet, OnPermissionSet) - IPC_MESSAGE_HANDLER(GeolocationMsg_PositionUpdated, OnPositionUpdated) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void GeolocationDispatcher::startUpdating() { - GURL url; - Send(new GeolocationHostMsg_StartUpdating( - routing_id(), url, enable_high_accuracy_)); - updating_ = true; + if (!geolocation_service_.get()) { + render_frame()->GetServiceRegistry()->ConnectToRemoteService( + &geolocation_service_); + geolocation_service_.set_client(this); + } + if (enable_high_accuracy_) + geolocation_service_->SetHighAccuracy(true); } void GeolocationDispatcher::stopUpdating() { - Send(new GeolocationHostMsg_StopUpdating(routing_id())); - updating_ = false; + geolocation_service_.reset(); } void GeolocationDispatcher::setEnableHighAccuracy(bool enable_high_accuracy) { @@ -61,8 +61,8 @@ void GeolocationDispatcher::setEnableHighAccuracy(bool enable_high_accuracy) { bool has_changed = enable_high_accuracy_ != enable_high_accuracy; enable_high_accuracy_ = enable_high_accuracy; // We have a different accuracy requirement. Request browser to update. - if (updating_ && has_changed) - startUpdating(); + if (geolocation_service_.get() && has_changed) + geolocation_service_->SetHighAccuracy(enable_high_accuracy_); } void GeolocationDispatcher::setController( @@ -103,32 +103,27 @@ void GeolocationDispatcher::OnPermissionSet(int bridge_id, bool is_allowed) { permissionRequest.setIsAllowed(is_allowed); } -// We have an updated geolocation position or error code. -void GeolocationDispatcher::OnPositionUpdated( - const Geoposition& geoposition) { - // It is possible for the browser process to have queued an update message - // before receiving the stop updating message. - if (!updating_) - return; - - if (geoposition.Validate()) { - controller_->positionChanged( - WebGeolocationPosition( - geoposition.timestamp.ToDoubleT(), - geoposition.latitude, geoposition.longitude, - geoposition.accuracy, - // Lowest point on land is at approximately -400 meters. - geoposition.altitude > -10000., - geoposition.altitude, - geoposition.altitude_accuracy >= 0., - geoposition.altitude_accuracy, - geoposition.heading >= 0. && geoposition.heading <= 360., - geoposition.heading, - geoposition.speed >= 0., - geoposition.speed)); +void GeolocationDispatcher::OnLocationUpdate(MojoGeopositionPtr geoposition) { + DCHECK(geolocation_service_.get()); + + if (geoposition->valid) { + controller_->positionChanged(WebGeolocationPosition( + geoposition->timestamp, + geoposition->latitude, + geoposition->longitude, + geoposition->accuracy, + // Lowest point on land is at approximately -400 meters. + geoposition->altitude > -10000., + geoposition->altitude, + geoposition->altitude_accuracy >= 0., + geoposition->altitude_accuracy, + geoposition->heading >= 0. && geoposition->heading <= 360., + geoposition->heading, + geoposition->speed >= 0., + geoposition->speed)); } else { WebGeolocationError::Error code; - switch (geoposition.error_code) { + switch (geoposition->error_code) { case Geoposition::ERROR_CODE_PERMISSION_DENIED: code = WebGeolocationError::ErrorPermissionDenied; break; @@ -136,12 +131,11 @@ void GeolocationDispatcher::OnPositionUpdated( code = WebGeolocationError::ErrorPositionUnavailable; break; default: - NOTREACHED() << geoposition.error_code; + NOTREACHED() << geoposition->error_code; return; } - controller_->errorOccurred( - WebGeolocationError( - code, blink::WebString::fromUTF8(geoposition.error_message))); + controller_->errorOccurred(WebGeolocationError( + code, blink::WebString::fromUTF8(geoposition->error_message))); } } diff --git a/content/renderer/geolocation_dispatcher.h b/content/renderer/geolocation_dispatcher.h index 53fa151..454859d 100644 --- a/content/renderer/geolocation_dispatcher.h +++ b/content/renderer/geolocation_dispatcher.h @@ -6,6 +6,7 @@ #define CONTENT_RENDERER_GEOLOCATION_DISPATCHER_H_ #include "base/memory/scoped_ptr.h" +#include "content/common/geolocation_service.mojom.h" #include "content/public/renderer/render_frame_observer.h" #include "third_party/WebKit/public/web/WebGeolocationClient.h" #include "third_party/WebKit/public/web/WebGeolocationController.h" @@ -23,8 +24,10 @@ struct Geoposition; // GeolocationDispatcher is a delegate for Geolocation messages used by // WebKit. // It's the complement of GeolocationDispatcherHost. -class GeolocationDispatcher : public RenderFrameObserver, - public blink::WebGeolocationClient { +class GeolocationDispatcher + : public RenderFrameObserver, + public blink::WebGeolocationClient, + public mojo::InterfaceImpl<GeolocationServiceClient> { public: explicit GeolocationDispatcher(RenderFrame* render_frame); virtual ~GeolocationDispatcher(); @@ -44,18 +47,18 @@ class GeolocationDispatcher : public RenderFrameObserver, virtual void cancelPermissionRequest( const blink::WebGeolocationPermissionRequest& permissionRequest); + // GeolocationServiceClient + void OnLocationUpdate(MojoGeopositionPtr geoposition) override; + // Permission for using geolocation has been set. void OnPermissionSet(int bridge_id, bool is_allowed); - // We have an updated geolocation position or error code. - void OnPositionUpdated(const content::Geoposition& geoposition); - scoped_ptr<blink::WebGeolocationController> controller_; scoped_ptr<blink::WebGeolocationPermissionRequestManager> pending_permissions_; + GeolocationServicePtr geolocation_service_; bool enable_high_accuracy_; - bool updating_; }; } // namespace content |