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

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

Issue 10103029: Add device location reporting (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: New implementation on top of a new content geolocation API. Created 8 years, 7 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/policy/device_status_collector.h" 5 #include "chrome/browser/policy/device_status_collector.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/bind_helpers.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
9 #include "base/string_number_conversions.h" 12 #include "base/string_number_conversions.h"
13 #include "base/values.h"
10 #include "chrome/browser/chromeos/cros_settings.h" 14 #include "chrome/browser/chromeos/cros_settings.h"
11 #include "chrome/browser/chromeos/cros_settings_names.h" 15 #include "chrome/browser/chromeos/cros_settings_names.h"
12 #include "chrome/browser/chromeos/system/statistics_provider.h" 16 #include "chrome/browser/chromeos/system/statistics_provider.h"
13 #include "chrome/browser/policy/proto/device_management_backend.pb.h" 17 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
14 #include "chrome/browser/prefs/pref_service.h" 18 #include "chrome/browser/prefs/pref_service.h"
15 #include "chrome/browser/prefs/scoped_user_pref_update.h" 19 #include "chrome/browser/prefs/scoped_user_pref_update.h"
16 #include "chrome/common/chrome_notification_types.h" 20 #include "chrome/common/chrome_notification_types.h"
17 #include "chrome/common/chrome_version_info.h" 21 #include "chrome/common/chrome_version_info.h"
18 #include "chrome/common/pref_names.h" 22 #include "chrome/common/pref_names.h"
23 #include "content/public/browser/notification_details.h"
24 #include "content/public/browser/notification_source.h"
19 25
20 using base::Time; 26 using base::Time;
21 using base::TimeDelta; 27 using base::TimeDelta;
22 using chromeos::VersionLoader; 28 using chromeos::VersionLoader;
23 29
24 namespace em = enterprise_management; 30 namespace em = enterprise_management;
25 31
26 namespace { 32 namespace {
27 // How many seconds of inactivity triggers the idle state. 33 // How many seconds of inactivity triggers the idle state.
28 const unsigned int kIdleStateThresholdSeconds = 300; 34 const unsigned int kIdleStateThresholdSeconds = 300;
29 35
30 // How many days in the past to store active periods for. 36 // How many days in the past to store active periods for.
31 const unsigned int kMaxStoredPastActivityDays = 30; 37 const unsigned int kMaxStoredPastActivityDays = 30;
32 38
33 // How many days in the future to store active periods for. 39 // How many days in the future to store active periods for.
34 const unsigned int kMaxStoredFutureActivityDays = 2; 40 const unsigned int kMaxStoredFutureActivityDays = 2;
35 41
42 // How often, in seconds, to update the device location.
43 const unsigned int kGeolocationPollIntervalSeconds = 30 * 60;
44
36 const int64 kMillisecondsPerDay = Time::kMicrosecondsPerDay / 1000; 45 const int64 kMillisecondsPerDay = Time::kMicrosecondsPerDay / 1000;
37 46
38 // Record device activity for the specified day into the given dictionary. 47 // Record device activity for the specified day into the given dictionary.
39 void AddDeviceActivity(DictionaryValue* activity_times, 48 void AddDeviceActivity(DictionaryValue* activity_times,
40 Time day_midnight, 49 Time day_midnight,
41 TimeDelta activity) { 50 TimeDelta activity) {
42 DCHECK(activity.InMilliseconds() < kMillisecondsPerDay); 51 DCHECK(activity.InMilliseconds() < kMillisecondsPerDay);
43 int64 day_start_timestamp = 52 int64 day_start_timestamp =
44 (day_midnight - Time::UnixEpoch()).InMilliseconds(); 53 (day_midnight - Time::UnixEpoch()).InMilliseconds();
45 std::string day_key = base::Int64ToString(day_start_timestamp); 54 std::string day_key = base::Int64ToString(day_start_timestamp);
46 int previous_activity = 0; 55 int previous_activity = 0;
47 activity_times->GetInteger(day_key, &previous_activity); 56 activity_times->GetInteger(day_key, &previous_activity);
48 activity_times->SetInteger(day_key, 57 activity_times->SetInteger(day_key,
49 previous_activity + activity.InMilliseconds()); 58 previous_activity + activity.InMilliseconds());
50 } 59 }
51 60
52 } // namespace 61 } // namespace
53 62
54 namespace policy { 63 namespace policy {
55 64
56 DeviceStatusCollector::DeviceStatusCollector( 65 DeviceStatusCollector::DeviceStatusCollector(
57 PrefService* local_state, 66 PrefService* local_state,
58 chromeos::system::StatisticsProvider* provider) 67 chromeos::system::StatisticsProvider* provider,
68 LocationUpdateRequester location_update_requester)
59 : max_stored_past_activity_days_(kMaxStoredPastActivityDays), 69 : max_stored_past_activity_days_(kMaxStoredPastActivityDays),
60 max_stored_future_activity_days_(kMaxStoredFutureActivityDays), 70 max_stored_future_activity_days_(kMaxStoredFutureActivityDays),
61 local_state_(local_state), 71 local_state_(local_state),
62 last_idle_check_(Time()), 72 last_idle_check_(Time()),
73 geolocation_update_in_progress_(false),
63 statistics_provider_(provider), 74 statistics_provider_(provider),
75 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
76 location_update_requester_(location_update_requester),
64 report_version_info_(false), 77 report_version_info_(false),
65 report_activity_times_(false), 78 report_activity_times_(false),
66 report_boot_mode_(false) { 79 report_boot_mode_(false),
67 timer_.Start(FROM_HERE, 80 report_location_(false) {
68 TimeDelta::FromSeconds(kPollIntervalSeconds), 81 if (!location_update_requester_)
69 this, &DeviceStatusCollector::CheckIdleState); 82 location_update_requester_ = &content::RequestLocationUpdate;
83 idle_poll_timer_.Start(FROM_HERE,
84 TimeDelta::FromSeconds(kIdlePollIntervalSeconds),
85 this, &DeviceStatusCollector::CheckIdleState);
70 86
71 cros_settings_ = chromeos::CrosSettings::Get(); 87 cros_settings_ = chromeos::CrosSettings::Get();
72 88
73 // Watch for changes to the individual policies that control what the status 89 // Watch for changes to the individual policies that control what the status
74 // reports contain. 90 // reports contain.
75 cros_settings_->AddSettingsObserver(chromeos::kReportDeviceVersionInfo, this); 91 cros_settings_->AddSettingsObserver(chromeos::kReportDeviceVersionInfo, this);
76 cros_settings_->AddSettingsObserver(chromeos::kReportDeviceActivityTimes, 92 cros_settings_->AddSettingsObserver(chromeos::kReportDeviceActivityTimes,
77 this); 93 this);
78 cros_settings_->AddSettingsObserver(chromeos::kReportDeviceBootMode, this); 94 cros_settings_->AddSettingsObserver(chromeos::kReportDeviceBootMode, this);
95 cros_settings_->AddSettingsObserver(chromeos::kReportDeviceLocation, this);
96
97 // The last known location is persisted in local state. This makes location
98 // information available immediately upon startup and avoids the need to
99 // reacquire the location on every user session change or browser crash.
100 content::Geoposition position;
101 std::string timestamp_str;
102 int64 timestamp;
103 const base::DictionaryValue* location =
104 local_state_->GetDictionary(prefs::kDeviceLocation);
105 if (location->GetDouble("latitude", &position.latitude) &&
Joao da Silva 2012/05/03 19:04:08 It'd be nicer to use constants for these strings:
bartfab (slow) 2012/05/04 09:14:57 Done.
106 location->GetDouble("longitude", &position.longitude) &&
107 location->GetDouble("altitude", &position.altitude) &&
108 location->GetDouble("accuracy", &position.accuracy) &&
109 location->GetDouble("altitude_accuracy",
110 &position.altitude_accuracy) &&
111 location->GetDouble("heading", &position.heading) &&
112 location->GetDouble("speed", &position.speed) &&
113 location->GetString("timestamp", &timestamp_str) &&
114 base::StringToInt64(timestamp_str, &timestamp)) {
115 position.timestamp = base::Time::FromInternalValue(timestamp);
Joao da Silva 2012/05/03 19:04:08 nit: drop the base::
bartfab (slow) 2012/05/04 09:14:57 Done.
116 position_ = position;
117 }
79 118
80 // Fetch the current values of the policies. 119 // Fetch the current values of the policies.
81 UpdateReportingSettings(); 120 UpdateReportingSettings();
82 121
83 // Get the the OS and firmware version info. 122 // Get the the OS and firmware version info.
84 version_loader_.GetVersion(&consumer_, 123 version_loader_.GetVersion(&consumer_,
85 base::Bind(&DeviceStatusCollector::OnOSVersion, 124 base::Bind(&DeviceStatusCollector::OnOSVersion,
86 base::Unretained(this)), 125 base::Unretained(this)),
87 VersionLoader::VERSION_FULL); 126 VersionLoader::VERSION_FULL);
88 version_loader_.GetFirmware(&consumer_, 127 version_loader_.GetFirmware(&consumer_,
89 base::Bind(&DeviceStatusCollector::OnOSFirmware, 128 base::Bind(&DeviceStatusCollector::OnOSFirmware,
90 base::Unretained(this))); 129 base::Unretained(this)));
91 } 130 }
92 131
93 DeviceStatusCollector::~DeviceStatusCollector() { 132 DeviceStatusCollector::~DeviceStatusCollector() {
94 cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceVersionInfo, 133 cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceVersionInfo,
95 this); 134 this);
96 cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceActivityTimes, 135 cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceActivityTimes,
97 this); 136 this);
98 cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceBootMode, this); 137 cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceBootMode, this);
138 cros_settings_->RemoveSettingsObserver(chromeos::kReportDeviceLocation, this);
99 } 139 }
100 140
101 // static 141 // static
102 void DeviceStatusCollector::RegisterPrefs(PrefService* local_state) { 142 void DeviceStatusCollector::RegisterPrefs(PrefService* local_state) {
103 local_state->RegisterDictionaryPref(prefs::kDeviceActivityTimes, 143 local_state->RegisterDictionaryPref(prefs::kDeviceActivityTimes,
104 new DictionaryValue); 144 new DictionaryValue);
145 local_state->RegisterDictionaryPref(prefs::kDeviceLocation,
146 new DictionaryValue);
105 } 147 }
106 148
107 void DeviceStatusCollector::CheckIdleState() { 149 void DeviceStatusCollector::CheckIdleState() {
108 CalculateIdleState(kIdleStateThresholdSeconds, 150 CalculateIdleState(kIdleStateThresholdSeconds,
109 base::Bind(&DeviceStatusCollector::IdleStateCallback, 151 base::Bind(&DeviceStatusCollector::IdleStateCallback,
110 base::Unretained(this))); 152 base::Unretained(this)));
111 } 153 }
112 154
113 void DeviceStatusCollector::UpdateReportingSettings() { 155 void DeviceStatusCollector::UpdateReportingSettings() {
114 // Attempt to fetch the current value of the reporting settings. 156 // Attempt to fetch the current value of the reporting settings.
115 // If trusted values are not available, register this function to be called 157 // If trusted values are not available, register this function to be called
116 // back when they are available. 158 // back when they are available.
117 if (!cros_settings_->PrepareTrustedValues( 159 if (!cros_settings_->PrepareTrustedValues(
118 base::Bind(&DeviceStatusCollector::UpdateReportingSettings, 160 base::Bind(&DeviceStatusCollector::UpdateReportingSettings,
119 base::Unretained(this)))) { 161 base::Unretained(this)))) {
120 return; 162 return;
121 } 163 }
122 cros_settings_->GetBoolean( 164 cros_settings_->GetBoolean(
123 chromeos::kReportDeviceVersionInfo, &report_version_info_); 165 chromeos::kReportDeviceVersionInfo, &report_version_info_);
124 cros_settings_->GetBoolean( 166 cros_settings_->GetBoolean(
125 chromeos::kReportDeviceActivityTimes, &report_activity_times_); 167 chromeos::kReportDeviceActivityTimes, &report_activity_times_);
126 cros_settings_->GetBoolean( 168 cros_settings_->GetBoolean(
127 chromeos::kReportDeviceBootMode, &report_boot_mode_); 169 chromeos::kReportDeviceBootMode, &report_boot_mode_);
170 cros_settings_->GetBoolean(
171 chromeos::kReportDeviceLocation, &report_location_);
172
173 if (report_location_) {
174 ScheduleGeolocationUpdateRequest();
175 } else {
176 geolocation_update_timer_.Stop();
177 position_ = content::Geoposition();
178 local_state_->ClearPref(prefs::kDeviceLocation);
179 }
128 } 180 }
129 181
130 Time DeviceStatusCollector::GetCurrentTime() { 182 Time DeviceStatusCollector::GetCurrentTime() {
131 return Time::Now(); 183 return Time::Now();
132 } 184 }
133 185
134 // Remove all out-of-range activity times from the local store. 186 // Remove all out-of-range activity times from the local store.
135 void DeviceStatusCollector::PruneStoredActivityPeriods(Time base_time) { 187 void DeviceStatusCollector::PruneStoredActivityPeriods(Time base_time) {
136 const DictionaryValue* activity_times = 188 const DictionaryValue* activity_times =
137 local_state_->GetDictionary(prefs::kDeviceActivityTimes); 189 local_state_->GetDictionary(prefs::kDeviceActivityTimes);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 return; 246 return;
195 247
196 Time now = GetCurrentTime(); 248 Time now = GetCurrentTime();
197 249
198 if (state == IDLE_STATE_ACTIVE) { 250 if (state == IDLE_STATE_ACTIVE) {
199 // If it's been too long since the last report, or if the activity is 251 // If it's been too long since the last report, or if the activity is
200 // negative (which can happen when the clock changes), assume a single 252 // negative (which can happen when the clock changes), assume a single
201 // interval of activity. 253 // interval of activity.
202 int active_seconds = (now - last_idle_check_).InSeconds(); 254 int active_seconds = (now - last_idle_check_).InSeconds();
203 if (active_seconds < 0 || 255 if (active_seconds < 0 ||
204 active_seconds >= static_cast<int>((2 * kPollIntervalSeconds))) 256 active_seconds >= static_cast<int>((2 * kIdlePollIntervalSeconds)))
205 AddActivePeriod(now - TimeDelta::FromSeconds(kPollIntervalSeconds), now); 257 AddActivePeriod(now - TimeDelta::FromSeconds(kIdlePollIntervalSeconds),
258 now);
206 else 259 else
207 AddActivePeriod(last_idle_check_, now); 260 AddActivePeriod(last_idle_check_, now);
208 261
209 PruneStoredActivityPeriods(now); 262 PruneStoredActivityPeriods(now);
210 } 263 }
211 last_idle_check_ = now; 264 last_idle_check_ = now;
212 } 265 }
213 266
214 void DeviceStatusCollector::GetActivityTimes( 267 void DeviceStatusCollector::GetActivityTimes(
215 em::DeviceStatusReportRequest* request) { 268 em::DeviceStatusReportRequest* request) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 std::string dev_switch_mode; 304 std::string dev_switch_mode;
252 if (statistics_provider_->GetMachineStatistic( 305 if (statistics_provider_->GetMachineStatistic(
253 "devsw_boot", &dev_switch_mode)) { 306 "devsw_boot", &dev_switch_mode)) {
254 if (dev_switch_mode == "1") 307 if (dev_switch_mode == "1")
255 request->set_boot_mode("Dev"); 308 request->set_boot_mode("Dev");
256 else if (dev_switch_mode == "0") 309 else if (dev_switch_mode == "0")
257 request->set_boot_mode("Verified"); 310 request->set_boot_mode("Verified");
258 } 311 }
259 } 312 }
260 313
314 void DeviceStatusCollector::GetLocation(
315 em::DeviceStatusReportRequest* request) {
316 em::DeviceLocation* location = request->mutable_device_location();
317 if (!position_.Validate()) {
318 location->set_error_code(
319 em::DeviceLocation::ERROR_CODE_POSITION_UNAVAILABLE);
320 location->set_error_message(position_.error_message);
321 } else {
322 location->set_latitude(position_.latitude);
323 location->set_longitude(position_.longitude);
324 location->set_accuracy(position_.accuracy);
325 location->set_timestamp(
326 (position_.timestamp - Time::UnixEpoch()).InMilliseconds());
327 // Lowest point on land is at approximately -400 meters.
328 if (position_.altitude > -10000.)
329 location->set_altitude(position_.altitude);
330 if (position_.altitude_accuracy >= 0.)
331 location->set_altitude_accuracy(position_.altitude_accuracy);
332 if (position_.heading >= 0. && position_.heading <= 360)
333 location->set_heading(position_.heading);
334 if (position_.speed >= 0.)
335 location->set_speed(position_.speed);
336 location->set_error_code(em::DeviceLocation::ERROR_CODE_NONE);
337 }
338 }
339
261 void DeviceStatusCollector::GetStatus(em::DeviceStatusReportRequest* request) { 340 void DeviceStatusCollector::GetStatus(em::DeviceStatusReportRequest* request) {
262 if (report_activity_times_) 341 if (report_activity_times_)
263 GetActivityTimes(request); 342 GetActivityTimes(request);
264 343
265 if (report_version_info_) 344 if (report_version_info_)
266 GetVersionInfo(request); 345 GetVersionInfo(request);
267 346
268 if (report_boot_mode_) 347 if (report_boot_mode_)
269 GetBootMode(request); 348 GetBootMode(request);
349
350 if (report_location_)
351 GetLocation(request);
270 } 352 }
271 353
272 void DeviceStatusCollector::OnOSVersion(VersionLoader::Handle handle, 354 void DeviceStatusCollector::OnOSVersion(VersionLoader::Handle handle,
273 std::string version) { 355 std::string version) {
274 os_version_ = version; 356 os_version_ = version;
275 } 357 }
276 358
277 void DeviceStatusCollector::OnOSFirmware(VersionLoader::Handle handle, 359 void DeviceStatusCollector::OnOSFirmware(VersionLoader::Handle handle,
278 std::string version) { 360 std::string version) {
279 firmware_version_ = version; 361 firmware_version_ = version;
280 } 362 }
281 363
282 void DeviceStatusCollector::Observe( 364 void DeviceStatusCollector::Observe(
283 int type, 365 int type,
284 const content::NotificationSource& source, 366 const content::NotificationSource& source,
285 const content::NotificationDetails& details) { 367 const content::NotificationDetails& details) {
286 if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED) 368 if (type == chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED)
287 UpdateReportingSettings(); 369 UpdateReportingSettings();
288 else 370 else
289 NOTREACHED(); 371 NOTREACHED();
290 } 372 }
291 373
374 void DeviceStatusCollector::ScheduleGeolocationUpdateRequest() {
375 if (geolocation_update_timer_.IsRunning() || geolocation_update_in_progress_)
376 return;
377
378 if (position_.Validate()) {
379 base::TimeDelta elapsed = base::Time::Now() - position_.timestamp;
380 base::TimeDelta interval =
381 base::TimeDelta::FromSeconds(kGeolocationPollIntervalSeconds);
Joao da Silva 2012/05/03 19:04:08 nit: drop the base:: in these 3 lines
bartfab (slow) 2012/05/04 09:14:57 Done.
382 if (elapsed > interval) {
383 geolocation_update_in_progress_ = true;
384 location_update_requester_(base::Bind(
385 &DeviceStatusCollector::ReceiveGeolocationUpdate,
386 weak_ptr_factory_.GetWeakPtr()));
387 } else {
388 geolocation_update_timer_.Start(
389 FROM_HERE,
390 interval - elapsed,
391 this,
392 &DeviceStatusCollector::ScheduleGeolocationUpdateRequest);
393 }
394 } else {
395 geolocation_update_in_progress_ = true;
396 location_update_requester_(base::Bind(
397 &DeviceStatusCollector::ReceiveGeolocationUpdate,
398 weak_ptr_factory_.GetWeakPtr()));
399
400 }
401 }
402
403 void DeviceStatusCollector::ReceiveGeolocationUpdate(
404 const content::Geoposition& position) {
405 geolocation_update_in_progress_ = false;
406
407 // Ignore update if device location reporting has since been disabled.
408 if (!report_location_)
409 return;
410
411 if (position.Validate()) {
412 position_ = position;
413 DictionaryValue location;
Joao da Silva 2012/05/03 19:04:08 nit: base::*Value (here and elsewhere)
bartfab (slow) 2012/05/04 09:14:57 Done.
414 location.SetDouble("latitude", position.latitude);
415 location.SetDouble("longitude", position.longitude);
416 location.SetDouble("altitude", position.altitude);
417 location.SetDouble("accuracy", position.accuracy);
418 location.SetDouble("altitude_accuracy", position.altitude_accuracy);
419 location.SetDouble("heading", position.heading);
420 location.SetDouble("speed", position.speed);
421 location.SetString("timestamp",
422 base::Int64ToString(position.timestamp.ToInternalValue()));
423 local_state_->Set(prefs::kDeviceLocation, location);
424 }
425
426 ScheduleGeolocationUpdateRequest();
427 }
428
292 } // namespace policy 429 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698