Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(440)

Side by Side Diff: chrome/browser/policy/device_status_location_helper.cc

Issue 10103029: Add device location reporting (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Comments addressed. Also added lots of includes to IWYU. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/policy/device_status_location_helper.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/string_number_conversions.h"
14 #include "base/time.h"
15 #include "base/values.h"
16 #include "chrome/browser/prefs/pref_service.h"
17 #include "chrome/common/pref_names.h"
18 #include "content/browser/geolocation/geolocation_observer.h"
19 #include "content/browser/geolocation/geolocation_provider.h"
20 #include "content/public/browser/browser_thread.h"
21
22 namespace policy {
23
24 DeviceStatusLocationHelper::DeviceStatusLocationHelper(
25 PrefService* local_state)
26 : local_state_(local_state),
27 timer_(NULL),
28 provider_(NULL),
29 observing_(false) {
30 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
31 Geoposition position;
32 std::string timestamp_str;
33 int64 timestamp;
34 const base::DictionaryValue* location =
35 local_state_->GetDictionary(prefs::kDeviceLocation);
36 if (location->GetDouble("latitude", &position.latitude) &&
37 location->GetDouble("longitude", &position.longitude) &&
38 location->GetDouble("altitude", &position.altitude) &&
39 location->GetDouble("accuracy", &position.accuracy) &&
40 location->GetDouble("altitude_accuracy",
41 &position.altitude_accuracy) &&
42 location->GetDouble("heading", &position.heading) &&
43 location->GetDouble("speed", &position.speed) &&
44 location->GetString("timestamp", &timestamp_str) &&
45 base::StringToInt64(timestamp_str, &timestamp)) {
46 position.timestamp = base::Time::FromInternalValue(timestamp);
47 position_ = position;
48 }
49 content::BrowserThread::PostTask(
50 content::BrowserThread::IO,
51 FROM_HERE,
52 base::Bind(&DeviceStatusLocationHelper::Init,
53 base::Unretained(this),
54 position_));
55 }
56
57 void DeviceStatusLocationHelper::Destruct() {
58 // This class has a specific shutdown sequence that ensures all classes it
59 // interfaces with are notified on the appropriate threads and any tasks
60 // posted to it are processed before destruction.
61 //
62 // The shutdown sequence is initiated by calling Destruct() on the UI thread:
63 //
64 // 1. Destruct() makes the UI thread ignore any further updates it receives,
65 // then posts DestructInternal() to the IO thread.
66 // 2. DestructInternal() reaches the IO thread after any updates queued up for
67 // it have been processed. This function destroys the poll timer and
68 // detaches from the GeolocationProvider so that no further updates can be
69 // received by the IO thread. Then, it posts DeleteSoon() back to the UI
70 // thread.
71 // 3. DeleteSoon() reaches the UI thread after any updates queued for it have
72 // been processed. At this point, there are no more tasks queued up for
73 // either of the threads and it is safe for the object to be deleted.
74 // 4. ~DeviceStatusLocationHelper() is run by DeleteSoon() and the object RIP.
75 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
76 local_state_ = NULL;
77 content::BrowserThread::PostTask(
78 content::BrowserThread::IO,
79 FROM_HERE,
80 base::Bind(&DeviceStatusLocationHelper::DestructInternal,
81 base::Unretained(this)));
82 }
83
84 const Geoposition& DeviceStatusLocationHelper::GetPosition() const {
85 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
86 return position_;
87 }
88
89 // static
90 void DeviceStatusLocationHelper::RegisterPrefs(PrefService* local_state) {
91 local_state->RegisterDictionaryPref(prefs::kDeviceLocation,
92 new DictionaryValue);
93 }
94
95 void DeviceStatusLocationHelper::OnLocationUpdate(const Geoposition& position) {
96 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
97 if (!position.IsValidFix())
98 return;
99 content::BrowserThread::PostTask(
100 content::BrowserThread::UI,
101 FROM_HERE,
102 base::Bind(&DeviceStatusLocationHelper::ReceiveUpdate,
103 base::Unretained(this), position));
104 StopObserving();
105 ScheduleUpdate(position);
106 }
107
108 void DeviceStatusLocationHelper::SetGeolocationProviderForTest(
109 GeolocationProvider* provider) {
110 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
111 DCHECK(!provider_);
112 provider_ = provider;
113 }
114
115 DeviceStatusLocationHelper::~DeviceStatusLocationHelper() {
116 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
117 DCHECK(local_state_ == NULL);
118 DCHECK(timer_ == NULL);
119 }
120
121 void DeviceStatusLocationHelper::Init(const Geoposition& position) {
122 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
123 if (!provider_)
124 provider_ = GeolocationProvider::GetInstance();
125 timer_ = new base::OneShotTimer<DeviceStatusLocationHelper>();
126 provider_->OnPermissionGranted();
127 ScheduleUpdate(position);
128 }
129
130 void DeviceStatusLocationHelper::DestructInternal() {
131 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
132 delete timer_;
133 timer_ = 0;
134 StopObserving();
135 content::BrowserThread::DeleteSoon(content::BrowserThread::UI,
136 FROM_HERE,
137 this);
138 }
139
140 void DeviceStatusLocationHelper::ScheduleUpdate(const Geoposition& position) {
141 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
142 if (position.IsValidFix()) {
143 base::TimeDelta elapsed = base::Time::Now() - position.timestamp;
144 base::TimeDelta interval =
145 base::TimeDelta::FromSeconds(kPollIntervalSeconds);
146 if (elapsed > interval) {
147 StartObserving();
148 } else {
149 timer_->Start(FROM_HERE,
150 interval - elapsed,
151 this,
152 &DeviceStatusLocationHelper::StartObserving);
153 }
154 } else {
155 StartObserving();
156 }
157 }
158
159 void DeviceStatusLocationHelper::StartObserving() {
160 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
161 timer_->Stop();
162 provider_->AddObserver(this, GeolocationObserverOptions(true));
163 observing_ = true;
164 }
165
166 void DeviceStatusLocationHelper::StopObserving() {
167 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
168 if (!observing_)
169 return;
170 provider_->RemoveObserver(this);
171 observing_ = false;
172 }
173
174 void DeviceStatusLocationHelper::ReceiveUpdate(const Geoposition& position) {
175 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
176 if (!local_state_)
177 return;
178 position_ = position;
179 DictionaryValue location;
180 location.SetDouble("latitude", position.latitude);
181 location.SetDouble("longitude", position.longitude);
182 location.SetDouble("altitude", position.altitude);
183 location.SetDouble("accuracy", position.accuracy);
184 location.SetDouble("altitude_accuracy", position.altitude_accuracy);
185 location.SetDouble("heading", position.heading);
186 location.SetDouble("speed", position.speed);
187 location.SetString("timestamp",
188 base::Int64ToString(position.timestamp.ToInternalValue()));
189 local_state_->Set(prefs::kDeviceLocation, location);
190 }
191
192 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698