#include "content/browser/geolocation/geolocation_dispatcher_host.h"
-#include <map>
-#include <set>
#include <utility>
#include "base/bind.h"
#include "base/metrics/histogram.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"
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);
+}
+
void NotifyGeolocationProviderPermissionGranted() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
GeolocationProviderImpl::GetInstance()->UserDidOptIntoLocationServices();
}
}
-class GeolocationDispatcherHostImpl : public GeolocationDispatcherHost {
- public:
- GeolocationDispatcherHostImpl(
- int render_process_id,
- GeolocationPermissionContext* geolocation_permission_context);
-
- // GeolocationDispatcherHost
- virtual bool OnMessageReceived(const IPC::Message& msg,
- bool* msg_was_ok) OVERRIDE;
-
- private:
- virtual ~GeolocationDispatcherHostImpl();
-
- 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,
- const GURL& requesting_frame,
- bool enable_high_accuracy);
- void OnStopUpdating(int render_view_id);
-
-
- virtual void PauseOrResume(int render_view_id, bool should_pause) OVERRIDE;
-
- // Updates the |geolocation_provider_| with the currently required update
- // options.
- void RefreshGeolocationOptions();
-
- void OnLocationUpdate(const Geoposition& position);
-
- int render_process_id_;
- scoped_refptr<GeolocationPermissionContext> geolocation_permission_context_;
-
- struct RendererGeolocationOptions {
- bool high_accuracy;
- bool is_paused;
- };
-
- // Used to keep track of the renderers in this process that are using
- // geolocation and the options associated with them. The map is iterated
- // when a location update is available and the fan out to individual bridge
- // IDs happens renderer side, in order to minimize context switches.
- // Only used on the IO thread.
- std::map<int, RendererGeolocationOptions> geolocation_renderers_;
-
- // Used by Android WebView to support that case that a renderer is in the
- // 'paused' state but not yet using geolocation. If the renderer does start
- // using geolocation while paused, we move from this set into
- // |geolocation_renderers_|. If the renderer doesn't end up wanting to use
- // geolocation while 'paused' then we remove from this set. A renderer id
- // can exist only in this set or |geolocation_renderers_|, never both.
- std::set<int> pending_paused_geolocation_renderers_;
-
- // Only set whilst we are registered with the geolocation provider.
- GeolocationProviderImpl* geolocation_provider_;
-
- GeolocationProviderImpl::LocationUpdateCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(GeolocationDispatcherHostImpl);
-};
+} // namespace
-GeolocationDispatcherHostImpl::GeolocationDispatcherHostImpl(
+GeolocationDispatcherHost::GeolocationDispatcherHost(
int render_process_id,
GeolocationPermissionContext* geolocation_permission_context)
- : render_process_id_(render_process_id),
+ : BrowserMessageFilter(GeolocationMsgStart),
+ render_process_id_(render_process_id),
geolocation_permission_context_(geolocation_permission_context),
geolocation_provider_(NULL) {
callback_ = base::Bind(
- &GeolocationDispatcherHostImpl::OnLocationUpdate, base::Unretained(this));
+ &GeolocationDispatcherHost::OnLocationUpdate, base::Unretained(this));
// 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() {
+GeolocationDispatcherHost::~GeolocationDispatcherHost() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (geolocation_provider_)
geolocation_provider_->RemoveLocationUpdateCallback(callback_);
}
-bool GeolocationDispatcherHostImpl::OnMessageReceived(
+bool GeolocationDispatcherHost::OnMessageReceived(
const IPC::Message& msg, bool* msg_was_ok) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
*msg_was_ok = true;
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP_EX(GeolocationDispatcherHostImpl, msg, *msg_was_ok)
+ IPC_BEGIN_MESSAGE_MAP_EX(GeolocationDispatcherHost, msg, *msg_was_ok)
IPC_MESSAGE_HANDLER(GeolocationHostMsg_CancelPermissionRequest,
OnCancelPermissionRequest)
IPC_MESSAGE_HANDLER(GeolocationHostMsg_RequestPermission,
return handled;
}
-void GeolocationDispatcherHostImpl::OnLocationUpdate(
+void GeolocationDispatcherHost::OnLocationUpdate(
const Geoposition& geoposition) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ RecordGeopositionErrorCode(geoposition.error_code);
for (std::map<int, RendererGeolocationOptions>::iterator it =
geolocation_renderers_.begin();
it != geolocation_renderers_.end(); ++it) {
}
}
-void GeolocationDispatcherHostImpl::OnRequestPermission(
+void GeolocationDispatcherHost::OnRequestPermission(
int render_view_id,
int bridge_id,
- const GURL& requesting_frame) {
+ const GURL& requesting_frame,
+ bool user_gesture) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
<< render_view_id << ":" << bridge_id;
render_view_id,
bridge_id,
requesting_frame,
+ user_gesture,
base::Bind(&SendGeolocationPermissionResponse,
render_process_id_,
render_view_id,
}
}
-void GeolocationDispatcherHostImpl::OnCancelPermissionRequest(
+void GeolocationDispatcherHost::OnCancelPermissionRequest(
int render_view_id,
int bridge_id,
const GURL& requesting_frame) {
}
}
-void GeolocationDispatcherHostImpl::OnStartUpdating(
+void GeolocationDispatcherHost::OnStartUpdating(
int render_view_id,
const GURL& requesting_frame,
bool enable_high_accuracy) {
RefreshGeolocationOptions();
}
-void GeolocationDispatcherHostImpl::OnStopUpdating(int render_view_id) {
+void GeolocationDispatcherHost::OnStopUpdating(int render_view_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
<< render_view_id;
RefreshGeolocationOptions();
}
-void GeolocationDispatcherHostImpl::PauseOrResume(int render_view_id,
- bool should_pause) {
+void GeolocationDispatcherHost::PauseOrResume(int render_view_id,
+ bool should_pause) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
std::map<int, RendererGeolocationOptions>::iterator it =
geolocation_renderers_.find(render_view_id);
}
}
-void GeolocationDispatcherHostImpl::RefreshGeolocationOptions() {
+void GeolocationDispatcherHost::RefreshGeolocationOptions() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
bool needs_updates = false;
}
}
-} // namespace
-
-
-// GeolocationDispatcherHost --------------------------------------------------
-
-// static
-GeolocationDispatcherHost* GeolocationDispatcherHost::New(
- int render_process_id,
- GeolocationPermissionContext* geolocation_permission_context) {
- return new GeolocationDispatcherHostImpl(
- render_process_id,
- geolocation_permission_context);
-}
-
-GeolocationDispatcherHost::GeolocationDispatcherHost()
- : BrowserMessageFilter(GeolocationMsgStart) {
-}
-
-GeolocationDispatcherHost::~GeolocationDispatcherHost() {
-}
-
} // namespace content