Chromium Code Reviews| Index: chrome/browser/policy/device_status_location_helper.cc |
| diff --git a/chrome/browser/policy/device_status_location_helper.cc b/chrome/browser/policy/device_status_location_helper.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..99fac1098a7224a7daa5585dbb4d08a2fa1c9821 |
| --- /dev/null |
| +++ b/chrome/browser/policy/device_status_location_helper.cc |
| @@ -0,0 +1,182 @@ |
| +// 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 "chrome/browser/policy/device_status_location_helper.h" |
| + |
| +#include "base/string_number_conversions.h" |
| +#include "base/time.h" |
| +#include "chrome/browser/prefs/pref_service.h" |
| +#include "chrome/common/pref_names.h" |
| +#include "content/browser/geolocation/geolocation_provider.h" |
| +#include "content/public/browser/browser_thread.h" |
| + |
| +namespace policy { |
| + |
| +DeviceStatusLocationHelper::DeviceStatusLocationHelper( |
| + PrefService* local_state) |
| + : local_state_(local_state), |
| + timer_(NULL), |
| + provider_(NULL), |
| + observing_(false) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + Geoposition position; |
| + std::string timestamp_str; |
|
Joao da Silva
2012/04/20 14:21:09
#include <string>
bartfab (slow)
2012/04/23 09:48:54
Done.
|
| + int64 timestamp; |
| + const base::DictionaryValue* location = |
|
Joao da Silva
2012/04/20 14:21:09
#include "base/values.h"
bartfab (slow)
2012/04/23 09:48:54
Done.
|
| + local_state_->GetDictionary(prefs::kDeviceLocation); |
| + if (location->GetDouble("latitude", &position.latitude) && |
|
joth
2012/04/23 10:05:14
a comment would be useful - explaining why the loc
bartfab (slow)
2012/04/23 12:21:28
Done.
|
| + location->GetDouble("longitude", &position.longitude) && |
| + location->GetDouble("altitude", &position.altitude) && |
| + location->GetDouble("accuracy", &position.accuracy) && |
| + location->GetDouble("altitude_accuracy", |
| + &position.altitude_accuracy) && |
| + location->GetDouble("heading", &position.heading) && |
| + location->GetDouble("speed", &position.speed) && |
| + location->GetString("timestamp", ×tamp_str) && |
| + base::StringToInt64(timestamp_str, ×tamp)) { |
| + position.timestamp = base::Time::FromInternalValue(timestamp); |
| + position_ = position; |
| + } |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(&DeviceStatusLocationHelper::Init, |
| + base::Unretained(this), |
| + position_)); |
| +} |
| + |
| +void DeviceStatusLocationHelper::Destruct() { |
| + // This class has a specific shutdown sequence that ensures all classes it |
| + // interfaces with are notified on the appropriate threads and any tasks |
| + // posted to it are processed before destruction. |
| + // |
| + // The shutdown sequence is initiated by calling Destruct() on the UI thread: |
| + // |
| + // 1. Destruct() makes the UI thread ignore any further updates it receives, |
| + // then posts DestructInternal() to the IO thread. |
| + // 2. DestructInteral() reaches the IO thread after any updates queued up for |
|
Joao da Silva
2012/04/20 14:21:09
nit: DestructInteral -> DestructInternal
bartfab (slow)
2012/04/23 09:48:54
Done.
|
| + // it have been processed. This function destroys the poll timer and |
| + // detaches from the GeolocationProvider so that no further updates can be |
| + // received by the IO thread. Then, it posts DeleteSoon() back to the UI |
| + // thread. |
| + // 3. DeleteSoon() reaches the UI thread after any updates queued for it have |
| + // been processed. At this point, there are no more tasks queued up for |
| + // either of the threads and it is safe for the object to be deleted. |
| + // 4. ~DeviceStatusLocationHelper() is run by DeleteSoon() and the object RIP. |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + local_state_ = NULL; |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(&DeviceStatusLocationHelper::DestructInternal, |
| + base::Unretained(this))); |
| +} |
| + |
| +const Geoposition& DeviceStatusLocationHelper::GetPosition() const { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + return position_; |
| +} |
| + |
| +// static |
| +void DeviceStatusLocationHelper::RegisterPrefs(PrefService* local_state) { |
| + local_state->RegisterDictionaryPref(prefs::kDeviceLocation, |
| + new DictionaryValue); |
| +} |
| + |
| +void DeviceStatusLocationHelper::OnLocationUpdate(const Geoposition& position) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| + if (!position.IsValidFix()) |
| + return; |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::UI, |
| + FROM_HERE, |
| + base::Bind(&DeviceStatusLocationHelper::ReceiveUpdate, |
| + base::Unretained(this), position)); |
| + StopObserving(); |
| + ScheduleUpdate(position); |
| +} |
| + |
| +void DeviceStatusLocationHelper::SetGeolocationProviderForTest( |
| + GeolocationProvider* provider) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| + DCHECK(!provider_); |
| + provider_ = provider; |
| +} |
| + |
| +DeviceStatusLocationHelper::~DeviceStatusLocationHelper() { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + DCHECK(local_state_ == NULL); |
| + DCHECK(timer_ == NULL); |
| +} |
| + |
| +void DeviceStatusLocationHelper::Init(const Geoposition& position) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| + if (!provider_) |
| + provider_ = GeolocationProvider::GetInstance(); |
| + timer_ = new base::OneShotTimer<DeviceStatusLocationHelper>(); |
| + provider_->OnPermissionGranted(); |
| + ScheduleUpdate(position); |
| +} |
| + |
| +void DeviceStatusLocationHelper::DestructInternal() { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| + delete timer_; |
| + timer_ = 0; |
| + StopObserving(); |
| + content::BrowserThread::DeleteSoon(content::BrowserThread::UI, |
| + FROM_HERE, |
| + this); |
| +} |
| + |
| +void DeviceStatusLocationHelper::ScheduleUpdate(const Geoposition& position) { |
|
joth
2012/04/23 10:05:14
comment explaining why the timer is needed here wo
bartfab (slow)
2012/04/23 12:21:28
Done.
|
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| + if (position.IsValidFix()) { |
| + base::TimeDelta elapsed = base::Time::Now() - position.timestamp; |
| + base::TimeDelta interval = |
| + base::TimeDelta::FromSeconds(kPollIntervalSeconds); |
| + if (elapsed > interval) { |
| + StartObserving(); |
| + } else { |
| + timer_->Start(FROM_HERE, interval - elapsed, this, |
| + &DeviceStatusLocationHelper::StartObserving); |
| + } |
| + } else { |
| + StartObserving(); |
| + } |
| +} |
| + |
| +void DeviceStatusLocationHelper::StartObserving() { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| + timer_->Stop(); |
| + provider_->AddObserver(this, GeolocationObserverOptions(true)); |
| + observing_ = true; |
| +} |
| + |
| +void DeviceStatusLocationHelper::StopObserving() { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| + if (!observing_) |
| + return; |
| + provider_->RemoveObserver(this); |
| + observing_ = false; |
| +} |
| + |
| +void DeviceStatusLocationHelper::ReceiveUpdate(const Geoposition& position) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + if (!local_state_) |
| + return; |
| + position_ = position; |
| + DictionaryValue location; |
| + location.SetDouble("latitude", position.latitude); |
| + location.SetDouble("longitude", position.longitude); |
| + location.SetDouble("altitude", position.altitude); |
| + location.SetDouble("accuracy", position.accuracy); |
| + location.SetDouble("altitude_accuracy", position.altitude_accuracy); |
| + location.SetDouble("heading", position.heading); |
| + location.SetDouble("speed", position.speed); |
| + location.SetString("timestamp", |
| + base::Int64ToString(position.timestamp.ToInternalValue())); |
| + local_state_->Set(prefs::kDeviceLocation, location); |
| +} |
| + |
| +} // namespace policy |