OLD | NEW |
---|---|
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", ×tamp_str) && | |
114 base::StringToInt64(timestamp_str, ×tamp)) { | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |