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/chromeos/policy/device_status_collector.h" 6 7 #include "base/environment.h" 8 #include "base/logging.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/prefs/pref_service.h" 12 #include "base/prefs/testing_pref_service.h" 13 #include "base/run_loop.h" 14 #include "base/threading/sequenced_worker_pool.h" 15 #include "chrome/browser/chromeos/login/users/mock_user_manager.h" 16 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" 17 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 18 #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h" 19 #include "chrome/browser/chromeos/settings/cros_settings.h" 20 #include "chrome/browser/chromeos/settings/device_settings_service.h" 21 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" 22 #include "chrome/common/pref_names.h" 23 #include "chrome/test/base/testing_browser_process.h" 24 #include "chromeos/dbus/dbus_thread_manager.h" 25 #include "chromeos/dbus/shill_device_client.h" 26 #include "chromeos/network/network_handler.h" 27 #include "chromeos/settings/cros_settings_names.h" 28 #include "chromeos/settings/cros_settings_provider.h" 29 #include "chromeos/system/mock_statistics_provider.h" 30 #include "content/public/browser/browser_thread.h" 31 #include "content/public/browser/geolocation_provider.h" 32 #include "content/public/test/test_browser_thread.h" 33 #include "content/public/test/test_utils.h" 34 #include "policy/proto/device_management_backend.pb.h" 35 #include "testing/gmock/include/gmock/gmock.h" 36 #include "testing/gtest/include/gtest/gtest.h" 37 #include "third_party/cros_system_api/dbus/service_constants.h" 38 39 using ::testing::DoAll; 40 using ::testing::NotNull; 41 using ::testing::Return; 42 using ::testing::SetArgPointee; 43 using ::testing::_; 44 using base::Time; 45 using base::TimeDelta; 46 47 namespace em = enterprise_management; 48 49 namespace { 50 51 const int64 kMillisecondsPerDay = Time::kMicrosecondsPerDay / 1000; 52 53 scoped_ptr<content::Geoposition> mock_position_to_return_next; 54 55 void SetMockPositionToReturnNext(const content::Geoposition &position) { 56 mock_position_to_return_next.reset(new content::Geoposition(position)); 57 } 58 59 void MockPositionUpdateRequester( 60 const content::GeolocationProvider::LocationUpdateCallback& callback) { 61 if (!mock_position_to_return_next.get()) 62 return; 63 64 // If the fix is invalid, the DeviceStatusCollector will immediately request 65 // another update when it receives the callback. This is desirable and safe in 66 // real life where geolocation updates arrive asynchronously. In this testing 67 // harness, the callback is invoked synchronously upon request, leading to a 68 // request-callback loop. The loop is broken by returning the mock position 69 // only once. 70 scoped_ptr<content::Geoposition> position( 71 mock_position_to_return_next.release()); 72 callback.Run(*position); 73 } 74 75 class TestingDeviceStatusCollector : public policy::DeviceStatusCollector { 76 public: 77 TestingDeviceStatusCollector( 78 PrefService* local_state, 79 chromeos::system::StatisticsProvider* provider, 80 policy::DeviceStatusCollector::LocationUpdateRequester* 81 location_update_requester) 82 : policy::DeviceStatusCollector( 83 local_state, 84 provider, 85 location_update_requester) { 86 // Set the baseline time to a fixed value (1 AM) to prevent test flakiness 87 // due to a single activity period spanning two days. 88 SetBaselineTime(Time::Now().LocalMidnight() + TimeDelta::FromHours(1)); 89 } 90 91 void Simulate(IdleState* states, int len) { 92 for (int i = 0; i < len; i++) 93 IdleStateCallback(states[i]); 94 } 95 96 void set_max_stored_past_activity_days(unsigned int value) { 97 max_stored_past_activity_days_ = value; 98 } 99 100 void set_max_stored_future_activity_days(unsigned int value) { 101 max_stored_future_activity_days_ = value; 102 } 103 104 // Reset the baseline time. 105 void SetBaselineTime(Time time) { 106 baseline_time_ = time; 107 baseline_offset_periods_ = 0; 108 } 109 110 protected: 111 virtual void CheckIdleState() OVERRIDE { 112 // This should never be called in testing, as it results in a dbus call. 113 ADD_FAILURE(); 114 } 115 116 // Each time this is called, returns a time that is a fixed increment 117 // later than the previous time. 118 virtual Time GetCurrentTime() OVERRIDE { 119 int poll_interval = policy::DeviceStatusCollector::kIdlePollIntervalSeconds; 120 return baseline_time_ + 121 TimeDelta::FromSeconds(poll_interval * baseline_offset_periods_++); 122 } 123 124 private: 125 // Baseline time for the fake times returned from GetCurrentTime(). 126 Time baseline_time_; 127 128 // The number of simulated periods since the baseline time. 129 int baseline_offset_periods_; 130 }; 131 132 // Return the total number of active milliseconds contained in a device 133 // status report. 134 int64 GetActiveMilliseconds(em::DeviceStatusReportRequest& status) { 135 int64 active_milliseconds = 0; 136 for (int i = 0; i < status.active_period_size(); i++) { 137 active_milliseconds += status.active_period(i).active_duration(); 138 } 139 return active_milliseconds; 140 } 141 142 } // namespace 143 144 namespace policy { 145 146 // Though it is a unit test, this test is linked with browser_tests so that it 147 // runs in a separate process. The intention is to avoid overriding the timezone 148 // environment variable for other tests. 149 class DeviceStatusCollectorTest : public testing::Test { 150 public: 151 DeviceStatusCollectorTest() 152 : ui_thread_(content::BrowserThread::UI, &message_loop_), 153 file_thread_(content::BrowserThread::FILE, &message_loop_), 154 io_thread_(content::BrowserThread::IO, &message_loop_), 155 install_attributes_("managed.com", 156 "user (at) managed.com", 157 "device_id", 158 DEVICE_MODE_ENTERPRISE), 159 user_manager_(new chromeos::MockUserManager()), 160 user_manager_enabler_(user_manager_) { 161 // Run this test with a well-known timezone so that Time::LocalMidnight() 162 // returns the same values on all machines. 163 scoped_ptr<base::Environment> env(base::Environment::Create()); 164 env->SetVar("TZ", "UTC"); 165 166 TestingDeviceStatusCollector::RegisterPrefs(prefs_.registry()); 167 168 EXPECT_CALL(statistics_provider_, GetMachineStatistic(_, NotNull())) 169 .WillRepeatedly(Return(false)); 170 171 // Remove the real DeviceSettingsProvider and replace it with a stub. 172 cros_settings_ = chromeos::CrosSettings::Get(); 173 device_settings_provider_ = 174 cros_settings_->GetProvider(chromeos::kReportDeviceVersionInfo); 175 EXPECT_TRUE(device_settings_provider_ != NULL); 176 EXPECT_TRUE( 177 cros_settings_->RemoveSettingsProvider(device_settings_provider_)); 178 cros_settings_->AddSettingsProvider(&stub_settings_provider_); 179 180 RestartStatusCollector(); 181 } 182 183 virtual ~DeviceStatusCollectorTest() { 184 // Finish pending tasks. 185 content::BrowserThread::GetBlockingPool()->FlushForTesting(); 186 message_loop_.RunUntilIdle(); 187 188 // Restore the real DeviceSettingsProvider. 189 EXPECT_TRUE( 190 cros_settings_->RemoveSettingsProvider(&stub_settings_provider_)); 191 cros_settings_->AddSettingsProvider(device_settings_provider_); 192 } 193 194 virtual void SetUp() OVERRIDE { 195 // Disable network interface reporting since it requires additional setup. 196 cros_settings_->SetBoolean(chromeos::kReportDeviceNetworkInterfaces, false); 197 } 198 199 void RestartStatusCollector() { 200 policy::DeviceStatusCollector::LocationUpdateRequester callback = 201 base::Bind(&MockPositionUpdateRequester); 202 status_collector_.reset( 203 new TestingDeviceStatusCollector(&prefs_, 204 &statistics_provider_, 205 &callback)); 206 } 207 208 void GetStatus() { 209 status_.Clear(); 210 status_collector_->GetDeviceStatus(&status_); 211 } 212 213 void CheckThatNoLocationIsReported() { 214 GetStatus(); 215 EXPECT_FALSE(status_.has_device_location()); 216 } 217 218 void CheckThatAValidLocationIsReported() { 219 // Checks that a location is being reported which matches the valid fix 220 // set using SetMockPositionToReturnNext(). 221 GetStatus(); 222 EXPECT_TRUE(status_.has_device_location()); 223 em::DeviceLocation location = status_.device_location(); 224 if (location.has_error_code()) 225 EXPECT_EQ(em::DeviceLocation::ERROR_CODE_NONE, location.error_code()); 226 EXPECT_TRUE(location.has_latitude()); 227 EXPECT_TRUE(location.has_longitude()); 228 EXPECT_TRUE(location.has_accuracy()); 229 EXPECT_TRUE(location.has_timestamp()); 230 EXPECT_FALSE(location.has_altitude()); 231 EXPECT_FALSE(location.has_altitude_accuracy()); 232 EXPECT_FALSE(location.has_heading()); 233 EXPECT_FALSE(location.has_speed()); 234 EXPECT_FALSE(location.has_error_message()); 235 EXPECT_DOUBLE_EQ(4.3, location.latitude()); 236 EXPECT_DOUBLE_EQ(-7.8, location.longitude()); 237 EXPECT_DOUBLE_EQ(3., location.accuracy()); 238 // Check that the timestamp is not older than ten minutes. 239 EXPECT_TRUE(Time::Now() - Time::FromDoubleT(location.timestamp() / 1000.) < 240 TimeDelta::FromMinutes(10)); 241 } 242 243 void CheckThatALocationErrorIsReported() { 244 GetStatus(); 245 EXPECT_TRUE(status_.has_device_location()); 246 em::DeviceLocation location = status_.device_location(); 247 EXPECT_TRUE(location.has_error_code()); 248 EXPECT_EQ(em::DeviceLocation::ERROR_CODE_POSITION_UNAVAILABLE, 249 location.error_code()); 250 } 251 252 protected: 253 // Convenience method. 254 int64 ActivePeriodMilliseconds() { 255 return policy::DeviceStatusCollector::kIdlePollIntervalSeconds * 1000; 256 } 257 258 // Since this is a unit test running in browser_tests we must do additional 259 // unit test setup and make a TestingBrowserProcess. Must be first member. 260 TestingBrowserProcessInitializer initializer_; 261 base::MessageLoopForUI message_loop_; 262 content::TestBrowserThread ui_thread_; 263 content::TestBrowserThread file_thread_; 264 content::TestBrowserThread io_thread_; 265 266 ScopedStubEnterpriseInstallAttributes install_attributes_; 267 TestingPrefServiceSimple prefs_; 268 chromeos::system::MockStatisticsProvider statistics_provider_; 269 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 270 chromeos::ScopedTestCrosSettings test_cros_settings_; 271 chromeos::CrosSettings* cros_settings_; 272 chromeos::CrosSettingsProvider* device_settings_provider_; 273 chromeos::StubCrosSettingsProvider stub_settings_provider_; 274 chromeos::MockUserManager* user_manager_; 275 chromeos::ScopedUserManagerEnabler user_manager_enabler_; 276 em::DeviceStatusReportRequest status_; 277 scoped_ptr<TestingDeviceStatusCollector> status_collector_; 278 }; 279 280 TEST_F(DeviceStatusCollectorTest, AllIdle) { 281 IdleState test_states[] = { 282 IDLE_STATE_IDLE, 283 IDLE_STATE_IDLE, 284 IDLE_STATE_IDLE 285 }; 286 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 287 288 // Test reporting with no data. 289 GetStatus(); 290 EXPECT_EQ(0, status_.active_period_size()); 291 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 292 293 // Test reporting with a single idle sample. 294 status_collector_->Simulate(test_states, 1); 295 GetStatus(); 296 EXPECT_EQ(0, status_.active_period_size()); 297 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 298 299 // Test reporting with multiple consecutive idle samples. 300 status_collector_->Simulate(test_states, 301 sizeof(test_states) / sizeof(IdleState)); 302 GetStatus(); 303 EXPECT_EQ(0, status_.active_period_size()); 304 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 305 } 306 307 TEST_F(DeviceStatusCollectorTest, AllActive) { 308 IdleState test_states[] = { 309 IDLE_STATE_ACTIVE, 310 IDLE_STATE_ACTIVE, 311 IDLE_STATE_ACTIVE 312 }; 313 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 314 315 // Test a single active sample. 316 status_collector_->Simulate(test_states, 1); 317 GetStatus(); 318 EXPECT_EQ(1, status_.active_period_size()); 319 EXPECT_EQ(1 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 320 status_.clear_active_period(); // Clear the result protobuf. 321 322 // Test multiple consecutive active samples. 323 status_collector_->Simulate(test_states, 324 sizeof(test_states) / sizeof(IdleState)); 325 GetStatus(); 326 EXPECT_EQ(1, status_.active_period_size()); 327 EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 328 } 329 330 TEST_F(DeviceStatusCollectorTest, MixedStates) { 331 IdleState test_states[] = { 332 IDLE_STATE_ACTIVE, 333 IDLE_STATE_IDLE, 334 IDLE_STATE_ACTIVE, 335 IDLE_STATE_ACTIVE, 336 IDLE_STATE_IDLE, 337 IDLE_STATE_IDLE, 338 IDLE_STATE_ACTIVE 339 }; 340 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 341 status_collector_->Simulate(test_states, 342 sizeof(test_states) / sizeof(IdleState)); 343 GetStatus(); 344 EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 345 } 346 347 TEST_F(DeviceStatusCollectorTest, StateKeptInPref) { 348 IdleState test_states[] = { 349 IDLE_STATE_ACTIVE, 350 IDLE_STATE_IDLE, 351 IDLE_STATE_ACTIVE, 352 IDLE_STATE_ACTIVE, 353 IDLE_STATE_IDLE, 354 IDLE_STATE_IDLE 355 }; 356 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 357 status_collector_->Simulate(test_states, 358 sizeof(test_states) / sizeof(IdleState)); 359 360 // Process the list a second time after restarting the collector. It should be 361 // able to count the active periods found by the original collector, because 362 // the results are stored in a pref. 363 RestartStatusCollector(); 364 status_collector_->Simulate(test_states, 365 sizeof(test_states) / sizeof(IdleState)); 366 367 GetStatus(); 368 EXPECT_EQ(6 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 369 } 370 371 TEST_F(DeviceStatusCollectorTest, Times) { 372 IdleState test_states[] = { 373 IDLE_STATE_ACTIVE, 374 IDLE_STATE_IDLE, 375 IDLE_STATE_ACTIVE, 376 IDLE_STATE_ACTIVE, 377 IDLE_STATE_IDLE, 378 IDLE_STATE_IDLE 379 }; 380 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 381 status_collector_->Simulate(test_states, 382 sizeof(test_states) / sizeof(IdleState)); 383 GetStatus(); 384 EXPECT_EQ(3 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 385 } 386 387 TEST_F(DeviceStatusCollectorTest, MaxStoredPeriods) { 388 IdleState test_states[] = { 389 IDLE_STATE_ACTIVE, 390 IDLE_STATE_IDLE 391 }; 392 const int kMaxDays = 10; 393 394 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 395 status_collector_->set_max_stored_past_activity_days(kMaxDays - 1); 396 status_collector_->set_max_stored_future_activity_days(1); 397 Time baseline = Time::Now().LocalMidnight(); 398 399 // Simulate 12 active periods. 400 for (int i = 0; i < kMaxDays + 2; i++) { 401 status_collector_->Simulate(test_states, 402 sizeof(test_states) / sizeof(IdleState)); 403 // Advance the simulated clock by a day. 404 baseline += TimeDelta::FromDays(1); 405 status_collector_->SetBaselineTime(baseline); 406 } 407 408 // Check that we don't exceed the max number of periods. 409 GetStatus(); 410 EXPECT_EQ(kMaxDays - 1, status_.active_period_size()); 411 412 // Simulate some future times. 413 for (int i = 0; i < kMaxDays + 2; i++) { 414 status_collector_->Simulate(test_states, 415 sizeof(test_states) / sizeof(IdleState)); 416 // Advance the simulated clock by a day. 417 baseline += TimeDelta::FromDays(1); 418 status_collector_->SetBaselineTime(baseline); 419 } 420 // Set the clock back so the previous simulated times are in the future. 421 baseline -= TimeDelta::FromDays(20); 422 status_collector_->SetBaselineTime(baseline); 423 424 // Collect one more data point to trigger pruning. 425 status_collector_->Simulate(test_states, 1); 426 427 // Check that we don't exceed the max number of periods. 428 status_.clear_active_period(); 429 GetStatus(); 430 EXPECT_LT(status_.active_period_size(), kMaxDays); 431 } 432 433 TEST_F(DeviceStatusCollectorTest, ActivityTimesEnabledByDefault) { 434 // Device activity times should be reported by default. 435 IdleState test_states[] = { 436 IDLE_STATE_ACTIVE, 437 IDLE_STATE_ACTIVE, 438 IDLE_STATE_ACTIVE 439 }; 440 status_collector_->Simulate(test_states, 441 sizeof(test_states) / sizeof(IdleState)); 442 GetStatus(); 443 EXPECT_EQ(1, status_.active_period_size()); 444 EXPECT_EQ(3 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 445 } 446 447 TEST_F(DeviceStatusCollectorTest, ActivityTimesOff) { 448 // Device activity times should not be reported if explicitly disabled. 449 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, false); 450 451 IdleState test_states[] = { 452 IDLE_STATE_ACTIVE, 453 IDLE_STATE_ACTIVE, 454 IDLE_STATE_ACTIVE 455 }; 456 status_collector_->Simulate(test_states, 457 sizeof(test_states) / sizeof(IdleState)); 458 GetStatus(); 459 EXPECT_EQ(0, status_.active_period_size()); 460 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 461 } 462 463 TEST_F(DeviceStatusCollectorTest, ActivityCrossingMidnight) { 464 IdleState test_states[] = { 465 IDLE_STATE_ACTIVE 466 }; 467 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 468 469 // Set the baseline time to 10 seconds after midnight. 470 status_collector_->SetBaselineTime( 471 Time::Now().LocalMidnight() + TimeDelta::FromSeconds(10)); 472 473 status_collector_->Simulate(test_states, 1); 474 GetStatus(); 475 ASSERT_EQ(2, status_.active_period_size()); 476 477 em::ActiveTimePeriod period0 = status_.active_period(0); 478 em::ActiveTimePeriod period1 = status_.active_period(1); 479 EXPECT_EQ(ActivePeriodMilliseconds() - 10000, period0.active_duration()); 480 EXPECT_EQ(10000, period1.active_duration()); 481 482 em::TimePeriod time_period0 = period0.time_period(); 483 em::TimePeriod time_period1 = period1.time_period(); 484 485 EXPECT_EQ(time_period0.end_timestamp(), time_period1.start_timestamp()); 486 487 // Ensure that the start and end times for the period are a day apart. 488 EXPECT_EQ(time_period0.end_timestamp() - time_period0.start_timestamp(), 489 kMillisecondsPerDay); 490 EXPECT_EQ(time_period1.end_timestamp() - time_period1.start_timestamp(), 491 kMillisecondsPerDay); 492 } 493 494 TEST_F(DeviceStatusCollectorTest, ActivityTimesKeptUntilSubmittedSuccessfully) { 495 IdleState test_states[] = { 496 IDLE_STATE_ACTIVE, 497 IDLE_STATE_ACTIVE, 498 }; 499 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 500 501 status_collector_->Simulate(test_states, 2); 502 GetStatus(); 503 EXPECT_EQ(2 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 504 em::DeviceStatusReportRequest first_status(status_); 505 506 // The collector returns the same status again. 507 GetStatus(); 508 EXPECT_EQ(first_status.SerializeAsString(), status_.SerializeAsString()); 509 510 // After indicating a successful submit, the submitted status gets cleared, 511 // but what got collected meanwhile sticks around. 512 status_collector_->Simulate(test_states, 1); 513 status_collector_->OnSubmittedSuccessfully(); 514 GetStatus(); 515 EXPECT_EQ(ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 516 } 517 518 TEST_F(DeviceStatusCollectorTest, DevSwitchBootMode) { 519 // Test that boot mode data is reported by default. 520 EXPECT_CALL(statistics_provider_, 521 GetMachineStatistic("devsw_boot", NotNull())) 522 .WillOnce(DoAll(SetArgPointee<1>("0"), Return(true))); 523 GetStatus(); 524 EXPECT_EQ("Verified", status_.boot_mode()); 525 526 // Test that boot mode data is not reported if the pref turned off. 527 cros_settings_->SetBoolean(chromeos::kReportDeviceBootMode, false); 528 529 EXPECT_CALL(statistics_provider_, 530 GetMachineStatistic("devsw_boot", NotNull())) 531 .WillRepeatedly(DoAll(SetArgPointee<1>("0"), Return(true))); 532 GetStatus(); 533 EXPECT_FALSE(status_.has_boot_mode()); 534 535 // Turn the pref on, and check that the status is reported iff the 536 // statistics provider returns valid data. 537 cros_settings_->SetBoolean(chromeos::kReportDeviceBootMode, true); 538 539 EXPECT_CALL(statistics_provider_, 540 GetMachineStatistic("devsw_boot", NotNull())) 541 .WillOnce(DoAll(SetArgPointee<1>("(error)"), Return(true))); 542 GetStatus(); 543 EXPECT_FALSE(status_.has_boot_mode()); 544 545 EXPECT_CALL(statistics_provider_, 546 GetMachineStatistic("devsw_boot", NotNull())) 547 .WillOnce(DoAll(SetArgPointee<1>(" "), Return(true))); 548 GetStatus(); 549 EXPECT_FALSE(status_.has_boot_mode()); 550 551 EXPECT_CALL(statistics_provider_, 552 GetMachineStatistic("devsw_boot", NotNull())) 553 .WillOnce(DoAll(SetArgPointee<1>("0"), Return(true))); 554 GetStatus(); 555 EXPECT_EQ("Verified", status_.boot_mode()); 556 557 EXPECT_CALL(statistics_provider_, 558 GetMachineStatistic("devsw_boot", NotNull())) 559 .WillOnce(DoAll(SetArgPointee<1>("1"), Return(true))); 560 GetStatus(); 561 EXPECT_EQ("Dev", status_.boot_mode()); 562 } 563 564 TEST_F(DeviceStatusCollectorTest, VersionInfo) { 565 // Expect the version info to be reported by default. 566 GetStatus(); 567 EXPECT_TRUE(status_.has_browser_version()); 568 EXPECT_TRUE(status_.has_os_version()); 569 EXPECT_TRUE(status_.has_firmware_version()); 570 571 // When the pref to collect this data is not enabled, expect that none of 572 // the fields are present in the protobuf. 573 cros_settings_->SetBoolean(chromeos::kReportDeviceVersionInfo, false); 574 GetStatus(); 575 EXPECT_FALSE(status_.has_browser_version()); 576 EXPECT_FALSE(status_.has_os_version()); 577 EXPECT_FALSE(status_.has_firmware_version()); 578 579 cros_settings_->SetBoolean(chromeos::kReportDeviceVersionInfo, true); 580 GetStatus(); 581 EXPECT_TRUE(status_.has_browser_version()); 582 EXPECT_TRUE(status_.has_os_version()); 583 EXPECT_TRUE(status_.has_firmware_version()); 584 585 // Check that the browser version is not empty. OS version & firmware 586 // don't have any reasonable values inside the unit test, so those 587 // aren't checked. 588 EXPECT_NE("", status_.browser_version()); 589 } 590 591 TEST_F(DeviceStatusCollectorTest, Location) { 592 content::Geoposition valid_fix; 593 valid_fix.latitude = 4.3; 594 valid_fix.longitude = -7.8; 595 valid_fix.accuracy = 3.; 596 valid_fix.timestamp = Time::Now(); 597 598 content::Geoposition invalid_fix; 599 invalid_fix.error_code = 600 content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 601 invalid_fix.timestamp = Time::Now(); 602 603 // Check that when device location reporting is disabled, no location is 604 // reported. 605 SetMockPositionToReturnNext(valid_fix); 606 CheckThatNoLocationIsReported(); 607 608 // Check that when device location reporting is enabled and a valid fix is 609 // available, the location is reported and is stored in local state. 610 SetMockPositionToReturnNext(valid_fix); 611 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); 612 EXPECT_FALSE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); 613 CheckThatAValidLocationIsReported(); 614 615 // Restart the status collector. Check that the last known location has been 616 // retrieved from local state without requesting a geolocation update. 617 SetMockPositionToReturnNext(valid_fix); 618 RestartStatusCollector(); 619 CheckThatAValidLocationIsReported(); 620 EXPECT_TRUE(mock_position_to_return_next.get()); 621 622 // Check that after disabling location reporting again, the last known 623 // location has been cleared from local state and is no longer reported. 624 SetMockPositionToReturnNext(valid_fix); 625 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, false); 626 // Allow the new pref to propagate to the status collector. 627 message_loop_.RunUntilIdle(); 628 EXPECT_TRUE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); 629 CheckThatNoLocationIsReported(); 630 631 // Check that after enabling location reporting again, an error is reported 632 // if no valid fix is available. 633 SetMockPositionToReturnNext(invalid_fix); 634 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); 635 // Allow the new pref to propagate to the status collector. 636 message_loop_.RunUntilIdle(); 637 CheckThatALocationErrorIsReported(); 638 } 639 640 TEST_F(DeviceStatusCollectorTest, ReportUsers) { 641 user_manager_->CreatePublicAccountUser("public@localhost"); 642 user_manager_->AddUser("user0 (at) managed.com"); 643 user_manager_->AddUser("user1 (at) managed.com"); 644 user_manager_->AddUser("user2 (at) managed.com"); 645 user_manager_->AddUser("user3 (at) unmanaged.com"); 646 user_manager_->AddUser("user4 (at) managed.com"); 647 user_manager_->AddUser("user5 (at) managed.com"); 648 649 // Verify that users are reported by default. 650 GetStatus(); 651 EXPECT_EQ(6, status_.user_size()); 652 653 // Verify that users are reported after enabling the setting. 654 cros_settings_->SetBoolean(chromeos::kReportDeviceUsers, true); 655 GetStatus(); 656 EXPECT_EQ(6, status_.user_size()); 657 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(0).type()); 658 EXPECT_EQ("user0 (at) managed.com", status_.user(0).email()); 659 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(1).type()); 660 EXPECT_EQ("user1 (at) managed.com", status_.user(1).email()); 661 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(2).type()); 662 EXPECT_EQ("user2 (at) managed.com", status_.user(2).email()); 663 EXPECT_EQ(em::DeviceUser::USER_TYPE_UNMANAGED, status_.user(3).type()); 664 EXPECT_FALSE(status_.user(3).has_email()); 665 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(4).type()); 666 EXPECT_EQ("user4 (at) managed.com", status_.user(4).email()); 667 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(5).type()); 668 EXPECT_EQ("user5 (at) managed.com", status_.user(5).email()); 669 670 // Verify that users are no longer reported if setting is disabled. 671 cros_settings_->SetBoolean(chromeos::kReportDeviceUsers, false); 672 GetStatus(); 673 EXPECT_EQ(0, status_.user_size()); 674 } 675 676 // Fake device state. 677 struct FakeDeviceData { 678 const char* device_path; 679 const char* type; 680 const char* object_path; 681 const char* mac_address; 682 const char* meid; 683 const char* imei; 684 int expected_type; // proto enum type value, -1 for not present. 685 }; 686 687 static const FakeDeviceData kFakeDevices[] = { 688 { "/device/ethernet", shill::kTypeEthernet, "ethernet", 689 "112233445566", "", "", 690 em::NetworkInterface::TYPE_ETHERNET }, 691 { "/device/cellular1", shill::kTypeCellular, "cellular1", 692 "abcdefabcdef", "A10000009296F2", "", 693 em::NetworkInterface::TYPE_CELLULAR }, 694 { "/device/cellular2", shill::kTypeCellular, "cellular2", 695 "abcdefabcdef", "", "352099001761481", 696 em::NetworkInterface::TYPE_CELLULAR }, 697 { "/device/wifi", shill::kTypeWifi, "wifi", 698 "aabbccddeeff", "", "", 699 em::NetworkInterface::TYPE_WIFI }, 700 { "/device/bluetooth", shill::kTypeBluetooth, "bluetooth", 701 "", "", "", 702 em::NetworkInterface::TYPE_BLUETOOTH }, 703 { "/device/vpn", shill::kTypeVPN, "vpn", 704 "", "", "", 705 -1 }, 706 }; 707 708 class DeviceStatusCollectorNetworkInterfacesTest 709 : public DeviceStatusCollectorTest { 710 protected: 711 virtual void SetUp() OVERRIDE { 712 chromeos::DBusThreadManager::Initialize(); 713 chromeos::NetworkHandler::Initialize(); 714 chromeos::ShillDeviceClient::TestInterface* test_device_client = 715 chromeos::DBusThreadManager::Get()->GetShillDeviceClient()-> 716 GetTestInterface(); 717 test_device_client->ClearDevices(); 718 for (size_t i = 0; i < arraysize(kFakeDevices); ++i) { 719 const FakeDeviceData& dev = kFakeDevices[i]; 720 test_device_client->AddDevice(dev.device_path, dev.type, 721 dev.object_path); 722 if (*dev.mac_address) { 723 test_device_client->SetDeviceProperty( 724 dev.device_path, shill::kAddressProperty, 725 base::StringValue(dev.mac_address)); 726 } 727 if (*dev.meid) { 728 test_device_client->SetDeviceProperty( 729 dev.device_path, shill::kMeidProperty, 730 base::StringValue(dev.meid)); 731 } 732 if (*dev.imei) { 733 test_device_client->SetDeviceProperty( 734 dev.device_path, shill::kImeiProperty, 735 base::StringValue(dev.imei)); 736 } 737 } 738 739 // Flush out pending state updates. 740 base::RunLoop().RunUntilIdle(); 741 } 742 743 virtual void TearDown() OVERRIDE { 744 chromeos::NetworkHandler::Shutdown(); 745 chromeos::DBusThreadManager::Shutdown(); 746 } 747 }; 748 749 TEST_F(DeviceStatusCollectorNetworkInterfacesTest, NetworkInterfaces) { 750 // Interfaces should be reported by default. 751 GetStatus(); 752 EXPECT_TRUE(status_.network_interface_size() > 0); 753 754 // No interfaces should be reported if the policy is off. 755 cros_settings_->SetBoolean(chromeos::kReportDeviceNetworkInterfaces, false); 756 GetStatus(); 757 EXPECT_EQ(0, status_.network_interface_size()); 758 759 // Switch the policy on and verify the interface list is present. 760 cros_settings_->SetBoolean(chromeos::kReportDeviceNetworkInterfaces, true); 761 GetStatus(); 762 763 int count = 0; 764 for (size_t i = 0; i < arraysize(kFakeDevices); ++i) { 765 const FakeDeviceData& dev = kFakeDevices[i]; 766 if (dev.expected_type == -1) 767 continue; 768 769 // Find the corresponding entry in reporting data. 770 bool found_match = false; 771 google::protobuf::RepeatedPtrField<em::NetworkInterface>::const_iterator 772 iface; 773 for (iface = status_.network_interface().begin(); 774 iface != status_.network_interface().end(); 775 ++iface) { 776 // Check whether type, field presence and field values match. 777 if (dev.expected_type == iface->type() && 778 iface->has_mac_address() == !!*dev.mac_address && 779 iface->has_meid() == !!*dev.meid && 780 iface->has_imei() == !!*dev.imei && 781 iface->mac_address() == dev.mac_address && 782 iface->meid() == dev.meid && 783 iface->imei() == dev.imei) { 784 found_match = true; 785 break; 786 } 787 } 788 789 EXPECT_TRUE(found_match) << "No matching interface for fake device " << i; 790 count++; 791 } 792 793 EXPECT_EQ(count, status_.network_interface_size()); 794 } 795 796 } // namespace policy 797