#include "content/browser/geolocation/win7_location_provider_win.h"
#include <algorithm>
#include <cmath>
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop.h"
namespace{
const int kPollPeriodMovingMillis = 500;
const int kPollPeriodStationaryMillis = kPollPeriodMovingMillis * 3;
const int kMovementThresholdMeters = 20;
bool PositionsDifferSiginificantly(const content::Geoposition& position_1,
const content::Geoposition& position_2) {
const bool pos_1_valid = position_1.Validate();
if (pos_1_valid != position_2.Validate())
return true;
if (!pos_1_valid) {
DCHECK(!position_2.Validate());
return false;
}
double delta = std::sqrt(
std::pow(std::fabs(position_1.latitude - position_2.latitude), 2) +
std::pow(std::fabs(position_1.longitude - position_2.longitude), 2));
delta *= 60 * 1852;
return delta > kMovementThresholdMeters;
}
}
Win7LocationProvider::Win7LocationProvider(Win7LocationApi* api)
: ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
DCHECK(api != NULL);
api_.reset(api);
}
Win7LocationProvider::~Win7LocationProvider() {
api_.reset();
}
bool Win7LocationProvider::StartProvider(bool high_accuracy){
if (api_ == NULL)
return false;
api_->SetHighAccuracy(high_accuracy);
if (!weak_factory_.HasWeakPtrs())
ScheduleNextPoll(0);
return true;
}
void Win7LocationProvider::StopProvider() {
weak_factory_.InvalidateWeakPtrs();
}
void Win7LocationProvider::GetPosition(content::Geoposition* position) {
DCHECK(position);
*position = position_;
}
void Win7LocationProvider::UpdatePosition() {
ScheduleNextPoll(0);
}
void Win7LocationProvider::DoPollTask() {
content::Geoposition new_position;
api_->GetPosition(&new_position);
const bool differ = PositionsDifferSiginificantly(position_, new_position);
ScheduleNextPoll(differ ? kPollPeriodMovingMillis :
kPollPeriodStationaryMillis);
if (differ ||
new_position.error_code != content::Geoposition::ERROR_CODE_NONE) {
position_ = new_position;
UpdateListeners();
}
}
void Win7LocationProvider::ScheduleNextPoll(int interval) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&Win7LocationProvider::DoPollTask, weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(interval));
}
LocationProviderBase* NewSystemLocationProvider() {
Win7LocationApi* api = Win7LocationApi::Create();
if (api == NULL)
return NULL;
return new Win7LocationProvider(api);
}