1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
// Copyright (c) 2012 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/renderer/geolocation_dispatcher.h"
#include "content/child/child_thread.h"
#include "content/public/common/geoposition.h"
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebGeolocationPermissionRequest.h"
#include "third_party/WebKit/public/web/WebGeolocationPermissionRequestManager.h"
#include "third_party/WebKit/public/web/WebGeolocationClient.h"
#include "third_party/WebKit/public/web/WebGeolocationPosition.h"
#include "third_party/WebKit/public/web/WebGeolocationError.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
using blink::WebGeolocationController;
using blink::WebGeolocationError;
using blink::WebGeolocationPermissionRequest;
using blink::WebGeolocationPermissionRequestManager;
using blink::WebGeolocationPosition;
namespace content {
GeolocationDispatcher::GeolocationDispatcher(RenderFrame* render_frame)
: RenderFrameObserver(render_frame),
pending_permissions_(new WebGeolocationPermissionRequestManager()),
enable_high_accuracy_(false) {
}
GeolocationDispatcher::~GeolocationDispatcher() {}
void GeolocationDispatcher::startUpdating() {
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() {
geolocation_service_.reset();
}
void GeolocationDispatcher::setEnableHighAccuracy(bool enable_high_accuracy) {
// GeolocationController calls setEnableHighAccuracy(true) before
// startUpdating in response to the first high-accuracy Geolocation
// subscription. When the last high-accuracy Geolocation unsubscribes
// it calls setEnableHighAccuracy(false) after stopUpdating.
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 (geolocation_service_.get() && has_changed)
geolocation_service_->SetHighAccuracy(enable_high_accuracy_);
}
void GeolocationDispatcher::setController(
WebGeolocationController* controller) {
controller_.reset(controller);
}
bool GeolocationDispatcher::lastPosition(WebGeolocationPosition&) {
// The latest position is stored in the browser, not the renderer, so we
// would have to fetch it synchronously to give a good value here. The
// WebCore::GeolocationController already caches the last position it
// receives, so there is not much benefit to more position caching here.
return false;
}
// TODO(jknotten): Change the messages to use a security origin, so no
// conversion is necessary.
void GeolocationDispatcher::requestPermission(
const WebGeolocationPermissionRequest& permissionRequest) {
if (!permission_service_.get()) {
render_frame()->GetServiceRegistry()->ConnectToRemoteService(
&permission_service_);
}
int permission_request_id = pending_permissions_->add(permissionRequest);
permission_service_->RequestPermission(
PERMISSION_NAME_GEOLOCATION,
permissionRequest.securityOrigin().toString().utf8(),
blink::WebUserGestureIndicator::isProcessingUserGesture(),
base::Bind(&GeolocationDispatcher::OnPermissionSet,
base::Unretained(this),
permission_request_id));
}
void GeolocationDispatcher::cancelPermissionRequest(
const blink::WebGeolocationPermissionRequest& permissionRequest) {
int permission_request_id;
pending_permissions_->remove(permissionRequest, permission_request_id);
}
// Permission for using geolocation has been set.
void GeolocationDispatcher::OnPermissionSet(
int permission_request_id,
PermissionStatus status) {
WebGeolocationPermissionRequest permissionRequest;
if (!pending_permissions_->remove(permission_request_id, permissionRequest))
return;
permissionRequest.setIsAllowed(status == PERMISSION_STATUS_GRANTED);
}
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) {
case Geoposition::ERROR_CODE_PERMISSION_DENIED:
code = WebGeolocationError::ErrorPermissionDenied;
break;
case Geoposition::ERROR_CODE_POSITION_UNAVAILABLE:
code = WebGeolocationError::ErrorPositionUnavailable;
break;
default:
NOTREACHED() << geoposition->error_code;
return;
}
controller_->errorOccurred(WebGeolocationError(
code, blink::WebString::fromUTF8(geoposition->error_message)));
}
}
} // namespace content
|