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/mock_user_manager.h" 16 #include "chrome/browser/chromeos/login/user_manager.h" 17 #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h" 18 #include "chrome/browser/chromeos/settings/cros_settings.h" 19 #include "chrome/browser/chromeos/settings/device_settings_service.h" 20 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" 21 #include "chrome/browser/policy/browser_policy_connector.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 : message_loop_(base::MessageLoop::TYPE_UI), 153 ui_thread_(content::BrowserThread::UI, &message_loop_), 154 file_thread_(content::BrowserThread::FILE, &message_loop_), 155 io_thread_(content::BrowserThread::IO, &message_loop_), 156 user_manager_(new chromeos::MockUserManager()), 157 user_manager_enabler_(user_manager_) { 158 // Run this test with a well-known timezone so that Time::LocalMidnight() 159 // returns the same values on all machines. 160 scoped_ptr<base::Environment> env(base::Environment::Create()); 161 env->SetVar("TZ", "UTC"); 162 163 TestingDeviceStatusCollector::RegisterPrefs(prefs_.registry()); 164 165 EXPECT_CALL(statistics_provider_, GetMachineStatistic(_, NotNull())) 166 .WillRepeatedly(Return(false)); 167 168 // Remove the real DeviceSettingsProvider and replace it with a stub. 169 cros_settings_ = chromeos::CrosSettings::Get(); 170 device_settings_provider_ = 171 cros_settings_->GetProvider(chromeos::kReportDeviceVersionInfo); 172 EXPECT_TRUE(device_settings_provider_ != NULL); 173 EXPECT_TRUE( 174 cros_settings_->RemoveSettingsProvider(device_settings_provider_)); 175 cros_settings_->AddSettingsProvider(&stub_settings_provider_); 176 177 // Set up fake install attributes. 178 StubEnterpriseInstallAttributes* attributes = 179 new StubEnterpriseInstallAttributes(); 180 attributes->SetDomain("managed.com"); 181 attributes->SetRegistrationUser("user (at) managed.com"); 182 BrowserPolicyConnector::SetInstallAttributesForTesting(attributes); 183 184 RestartStatusCollector(); 185 } 186 187 virtual ~DeviceStatusCollectorTest() { 188 // Finish pending tasks. 189 content::BrowserThread::GetBlockingPool()->FlushForTesting(); 190 message_loop_.RunUntilIdle(); 191 192 // Restore the real DeviceSettingsProvider. 193 EXPECT_TRUE( 194 cros_settings_->RemoveSettingsProvider(&stub_settings_provider_)); 195 cros_settings_->AddSettingsProvider(device_settings_provider_); 196 } 197 198 void RestartStatusCollector() { 199 policy::DeviceStatusCollector::LocationUpdateRequester callback = 200 base::Bind(&MockPositionUpdateRequester); 201 status_collector_.reset( 202 new TestingDeviceStatusCollector(&prefs_, 203 &statistics_provider_, 204 &callback)); 205 } 206 207 void GetStatus() { 208 status_.Clear(); 209 status_collector_->GetDeviceStatus(&status_); 210 } 211 212 void CheckThatNoLocationIsReported() { 213 GetStatus(); 214 EXPECT_FALSE(status_.has_device_location()); 215 } 216 217 void CheckThatAValidLocationIsReported() { 218 // Checks that a location is being reported which matches the valid fix 219 // set using SetMockPositionToReturnNext(). 220 GetStatus(); 221 EXPECT_TRUE(status_.has_device_location()); 222 em::DeviceLocation location = status_.device_location(); 223 if (location.has_error_code()) 224 EXPECT_EQ(em::DeviceLocation::ERROR_CODE_NONE, location.error_code()); 225 EXPECT_TRUE(location.has_latitude()); 226 EXPECT_TRUE(location.has_longitude()); 227 EXPECT_TRUE(location.has_accuracy()); 228 EXPECT_TRUE(location.has_timestamp()); 229 EXPECT_FALSE(location.has_altitude()); 230 EXPECT_FALSE(location.has_altitude_accuracy()); 231 EXPECT_FALSE(location.has_heading()); 232 EXPECT_FALSE(location.has_speed()); 233 EXPECT_FALSE(location.has_error_message()); 234 EXPECT_DOUBLE_EQ(4.3, location.latitude()); 235 EXPECT_DOUBLE_EQ(-7.8, location.longitude()); 236 EXPECT_DOUBLE_EQ(3., location.accuracy()); 237 // Check that the timestamp is not older than ten minutes. 238 EXPECT_TRUE(Time::Now() - Time::FromDoubleT(location.timestamp() / 1000.) < 239 TimeDelta::FromMinutes(10)); 240 } 241 242 void CheckThatALocationErrorIsReported() { 243 GetStatus(); 244 EXPECT_TRUE(status_.has_device_location()); 245 em::DeviceLocation location = status_.device_location(); 246 EXPECT_TRUE(location.has_error_code()); 247 EXPECT_EQ(em::DeviceLocation::ERROR_CODE_POSITION_UNAVAILABLE, 248 location.error_code()); 249 } 250 251 protected: 252 // Convenience method. 253 int64 ActivePeriodMilliseconds() { 254 return policy::DeviceStatusCollector::kIdlePollIntervalSeconds * 1000; 255 } 256 257 // Since this is a unit test running in browser_tests we must do additional 258 // unit test setup and make a TestingBrowserProcess. Must be first member. 259 TestingBrowserProcessInitializer initializer_; 260 base::MessageLoop message_loop_; 261 content::TestBrowserThread ui_thread_; 262 content::TestBrowserThread file_thread_; 263 content::TestBrowserThread io_thread_; 264 265 TestingPrefServiceSimple prefs_; 266 chromeos::system::MockStatisticsProvider statistics_provider_; 267 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 268 chromeos::ScopedTestCrosSettings test_cros_settings_; 269 chromeos::CrosSettings* cros_settings_; 270 chromeos::CrosSettingsProvider* device_settings_provider_; 271 chromeos::StubCrosSettingsProvider stub_settings_provider_; 272 chromeos::MockUserManager* user_manager_; 273 chromeos::ScopedUserManagerEnabler user_manager_enabler_; 274 em::DeviceStatusReportRequest status_; 275 scoped_ptr<TestingDeviceStatusCollector> status_collector_; 276 }; 277 278 TEST_F(DeviceStatusCollectorTest, AllIdle) { 279 IdleState test_states[] = { 280 IDLE_STATE_IDLE, 281 IDLE_STATE_IDLE, 282 IDLE_STATE_IDLE 283 }; 284 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 285 286 // Test reporting with no data. 287 GetStatus(); 288 EXPECT_EQ(0, status_.active_period_size()); 289 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 290 291 // Test reporting with a single idle sample. 292 status_collector_->Simulate(test_states, 1); 293 GetStatus(); 294 EXPECT_EQ(0, status_.active_period_size()); 295 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 296 297 // Test reporting with multiple consecutive idle samples. 298 status_collector_->Simulate(test_states, 299 sizeof(test_states) / sizeof(IdleState)); 300 GetStatus(); 301 EXPECT_EQ(0, status_.active_period_size()); 302 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 303 } 304 305 TEST_F(DeviceStatusCollectorTest, AllActive) { 306 IdleState test_states[] = { 307 IDLE_STATE_ACTIVE, 308 IDLE_STATE_ACTIVE, 309 IDLE_STATE_ACTIVE 310 }; 311 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 312 313 // Test a single active sample. 314 status_collector_->Simulate(test_states, 1); 315 GetStatus(); 316 EXPECT_EQ(1, status_.active_period_size()); 317 EXPECT_EQ(1 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 318 status_.clear_active_period(); // Clear the result protobuf. 319 320 // Test multiple consecutive active samples. 321 status_collector_->Simulate(test_states, 322 sizeof(test_states) / sizeof(IdleState)); 323 GetStatus(); 324 EXPECT_EQ(1, status_.active_period_size()); 325 EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 326 } 327 328 TEST_F(DeviceStatusCollectorTest, MixedStates) { 329 IdleState test_states[] = { 330 IDLE_STATE_ACTIVE, 331 IDLE_STATE_IDLE, 332 IDLE_STATE_ACTIVE, 333 IDLE_STATE_ACTIVE, 334 IDLE_STATE_IDLE, 335 IDLE_STATE_IDLE, 336 IDLE_STATE_ACTIVE 337 }; 338 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 339 status_collector_->Simulate(test_states, 340 sizeof(test_states) / sizeof(IdleState)); 341 GetStatus(); 342 EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 343 } 344 345 TEST_F(DeviceStatusCollectorTest, StateKeptInPref) { 346 IdleState test_states[] = { 347 IDLE_STATE_ACTIVE, 348 IDLE_STATE_IDLE, 349 IDLE_STATE_ACTIVE, 350 IDLE_STATE_ACTIVE, 351 IDLE_STATE_IDLE, 352 IDLE_STATE_IDLE 353 }; 354 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 355 status_collector_->Simulate(test_states, 356 sizeof(test_states) / sizeof(IdleState)); 357 358 // Process the list a second time after restarting the collector. It should be 359 // able to count the active periods found by the original collector, because 360 // the results are stored in a pref. 361 RestartStatusCollector(); 362 status_collector_->Simulate(test_states, 363 sizeof(test_states) / sizeof(IdleState)); 364 365 GetStatus(); 366 EXPECT_EQ(6 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 367 } 368 369 TEST_F(DeviceStatusCollectorTest, Times) { 370 IdleState test_states[] = { 371 IDLE_STATE_ACTIVE, 372 IDLE_STATE_IDLE, 373 IDLE_STATE_ACTIVE, 374 IDLE_STATE_ACTIVE, 375 IDLE_STATE_IDLE, 376 IDLE_STATE_IDLE 377 }; 378 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 379 status_collector_->Simulate(test_states, 380 sizeof(test_states) / sizeof(IdleState)); 381 GetStatus(); 382 EXPECT_EQ(3 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 383 } 384 385 TEST_F(DeviceStatusCollectorTest, MaxStoredPeriods) { 386 IdleState test_states[] = { 387 IDLE_STATE_ACTIVE, 388 IDLE_STATE_IDLE 389 }; 390 const int kMaxDays = 10; 391 392 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 393 status_collector_->set_max_stored_past_activity_days(kMaxDays - 1); 394 status_collector_->set_max_stored_future_activity_days(1); 395 Time baseline = Time::Now().LocalMidnight(); 396 397 // Simulate 12 active periods. 398 for (int i = 0; i < kMaxDays + 2; i++) { 399 status_collector_->Simulate(test_states, 400 sizeof(test_states) / sizeof(IdleState)); 401 // Advance the simulated clock by a day. 402 baseline += TimeDelta::FromDays(1); 403 status_collector_->SetBaselineTime(baseline); 404 } 405 406 // Check that we don't exceed the max number of periods. 407 GetStatus(); 408 EXPECT_EQ(kMaxDays - 1, status_.active_period_size()); 409 410 // Simulate some future times. 411 for (int i = 0; i < kMaxDays + 2; i++) { 412 status_collector_->Simulate(test_states, 413 sizeof(test_states) / sizeof(IdleState)); 414 // Advance the simulated clock by a day. 415 baseline += TimeDelta::FromDays(1); 416 status_collector_->SetBaselineTime(baseline); 417 } 418 // Set the clock back so the previous simulated times are in the future. 419 baseline -= TimeDelta::FromDays(20); 420 status_collector_->SetBaselineTime(baseline); 421 422 // Collect one more data point to trigger pruning. 423 status_collector_->Simulate(test_states, 1); 424 425 // Check that we don't exceed the max number of periods. 426 status_.clear_active_period(); 427 GetStatus(); 428 EXPECT_LT(status_.active_period_size(), kMaxDays); 429 } 430 431 TEST_F(DeviceStatusCollectorTest, ActivityTimesDisabledByDefault) { 432 // If the pref for collecting device activity times isn't explicitly turned 433 // on, no data on activity times should be reported. 434 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(0, status_.active_period_size()); 444 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 445 } 446 447 TEST_F(DeviceStatusCollectorTest, ActivityCrossingMidnight) { 448 IdleState test_states[] = { 449 IDLE_STATE_ACTIVE 450 }; 451 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 452 453 // Set the baseline time to 10 seconds after midnight. 454 status_collector_->SetBaselineTime( 455 Time::Now().LocalMidnight() + TimeDelta::FromSeconds(10)); 456 457 status_collector_->Simulate(test_states, 1); 458 GetStatus(); 459 ASSERT_EQ(2, status_.active_period_size()); 460 461 em::ActiveTimePeriod period0 = status_.active_period(0); 462 em::ActiveTimePeriod period1 = status_.active_period(1); 463 EXPECT_EQ(ActivePeriodMilliseconds() - 10000, period0.active_duration()); 464 EXPECT_EQ(10000, period1.active_duration()); 465 466 em::TimePeriod time_period0 = period0.time_period(); 467 em::TimePeriod time_period1 = period1.time_period(); 468 469 EXPECT_EQ(time_period0.end_timestamp(), time_period1.start_timestamp()); 470 471 // Ensure that the start and end times for the period are a day apart. 472 EXPECT_EQ(time_period0.end_timestamp() - time_period0.start_timestamp(), 473 kMillisecondsPerDay); 474 EXPECT_EQ(time_period1.end_timestamp() - time_period1.start_timestamp(), 475 kMillisecondsPerDay); 476 } 477 478 TEST_F(DeviceStatusCollectorTest, ActivityTimesKeptUntilSubmittedSuccessfully) { 479 IdleState test_states[] = { 480 IDLE_STATE_ACTIVE, 481 IDLE_STATE_ACTIVE, 482 }; 483 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 484 485 status_collector_->Simulate(test_states, 2); 486 GetStatus(); 487 EXPECT_EQ(2 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 488 em::DeviceStatusReportRequest first_status(status_); 489 490 // The collector returns the same status again. 491 GetStatus(); 492 EXPECT_EQ(first_status.SerializeAsString(), status_.SerializeAsString()); 493 494 // After indicating a successful submit, the submitted status gets cleared, 495 // but what got collected meanwhile sticks around. 496 status_collector_->Simulate(test_states, 1); 497 status_collector_->OnSubmittedSuccessfully(); 498 GetStatus(); 499 EXPECT_EQ(ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 500 } 501 502 TEST_F(DeviceStatusCollectorTest, DevSwitchBootMode) { 503 // Test that boot mode data is not reported if the pref is not turned on. 504 EXPECT_CALL(statistics_provider_, 505 GetMachineStatistic("devsw_boot", NotNull())) 506 .WillRepeatedly(DoAll(SetArgPointee<1>("0"), Return(true))); 507 GetStatus(); 508 EXPECT_FALSE(status_.has_boot_mode()); 509 510 // Turn the pref on, and check that the status is reported iff the 511 // statistics provider returns valid data. 512 cros_settings_->SetBoolean(chromeos::kReportDeviceBootMode, true); 513 514 EXPECT_CALL(statistics_provider_, 515 GetMachineStatistic("devsw_boot", NotNull())) 516 .WillOnce(DoAll(SetArgPointee<1>("(error)"), Return(true))); 517 GetStatus(); 518 EXPECT_FALSE(status_.has_boot_mode()); 519 520 EXPECT_CALL(statistics_provider_, 521 GetMachineStatistic("devsw_boot", NotNull())) 522 .WillOnce(DoAll(SetArgPointee<1>(" "), Return(true))); 523 GetStatus(); 524 EXPECT_FALSE(status_.has_boot_mode()); 525 526 EXPECT_CALL(statistics_provider_, 527 GetMachineStatistic("devsw_boot", NotNull())) 528 .WillOnce(DoAll(SetArgPointee<1>("0"), Return(true))); 529 GetStatus(); 530 EXPECT_EQ("Verified", status_.boot_mode()); 531 532 EXPECT_CALL(statistics_provider_, 533 GetMachineStatistic("devsw_boot", NotNull())) 534 .WillOnce(DoAll(SetArgPointee<1>("1"), Return(true))); 535 GetStatus(); 536 EXPECT_EQ("Dev", status_.boot_mode()); 537 } 538 539 TEST_F(DeviceStatusCollectorTest, VersionInfo) { 540 // When the pref to collect this data is not enabled, expect that none of 541 // the fields are present in the protobuf. 542 GetStatus(); 543 EXPECT_FALSE(status_.has_browser_version()); 544 EXPECT_FALSE(status_.has_os_version()); 545 EXPECT_FALSE(status_.has_firmware_version()); 546 547 cros_settings_->SetBoolean(chromeos::kReportDeviceVersionInfo, true); 548 GetStatus(); 549 EXPECT_TRUE(status_.has_browser_version()); 550 EXPECT_TRUE(status_.has_os_version()); 551 EXPECT_TRUE(status_.has_firmware_version()); 552 553 // Check that the browser version is not empty. OS version & firmware 554 // don't have any reasonable values inside the unit test, so those 555 // aren't checked. 556 EXPECT_NE("", status_.browser_version()); 557 } 558 559 TEST_F(DeviceStatusCollectorTest, Location) { 560 content::Geoposition valid_fix; 561 valid_fix.latitude = 4.3; 562 valid_fix.longitude = -7.8; 563 valid_fix.accuracy = 3.; 564 valid_fix.timestamp = Time::Now(); 565 566 content::Geoposition invalid_fix; 567 invalid_fix.error_code = 568 content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 569 invalid_fix.timestamp = Time::Now(); 570 571 // Check that when device location reporting is disabled, no location is 572 // reported. 573 SetMockPositionToReturnNext(valid_fix); 574 CheckThatNoLocationIsReported(); 575 576 // Check that when device location reporting is enabled and a valid fix is 577 // available, the location is reported and is stored in local state. 578 SetMockPositionToReturnNext(valid_fix); 579 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); 580 EXPECT_FALSE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); 581 CheckThatAValidLocationIsReported(); 582 583 // Restart the status collector. Check that the last known location has been 584 // retrieved from local state without requesting a geolocation update. 585 SetMockPositionToReturnNext(valid_fix); 586 RestartStatusCollector(); 587 CheckThatAValidLocationIsReported(); 588 EXPECT_TRUE(mock_position_to_return_next.get()); 589 590 // Check that after disabling location reporting again, the last known 591 // location has been cleared from local state and is no longer reported. 592 SetMockPositionToReturnNext(valid_fix); 593 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, false); 594 // Allow the new pref to propagate to the status collector. 595 message_loop_.RunUntilIdle(); 596 EXPECT_TRUE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); 597 CheckThatNoLocationIsReported(); 598 599 // Check that after enabling location reporting again, an error is reported 600 // if no valid fix is available. 601 SetMockPositionToReturnNext(invalid_fix); 602 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); 603 // Allow the new pref to propagate to the status collector. 604 message_loop_.RunUntilIdle(); 605 CheckThatALocationErrorIsReported(); 606 } 607 608 TEST_F(DeviceStatusCollectorTest, ReportUsers) { 609 user_manager_->CreatePublicAccountUser("public@localhost"); 610 user_manager_->AddUser("user0 (at) managed.com"); 611 user_manager_->AddUser("user1 (at) managed.com"); 612 user_manager_->AddUser("user2 (at) managed.com"); 613 user_manager_->AddUser("user3 (at) unmanaged.com"); 614 user_manager_->AddUser("user4 (at) managed.com"); 615 user_manager_->AddUser("user5 (at) managed.com"); 616 617 // Verify that users are not reported by default. 618 GetStatus(); 619 EXPECT_EQ(0, status_.user_size()); 620 621 // Verify that users are reported after enabling the setting. 622 cros_settings_->SetBoolean(chromeos::kReportDeviceUsers, true); 623 GetStatus(); 624 EXPECT_EQ(5, status_.user_size()); 625 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(0).type()); 626 EXPECT_EQ("user0 (at) managed.com", status_.user(0).email()); 627 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(1).type()); 628 EXPECT_EQ("user1 (at) managed.com", status_.user(1).email()); 629 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(2).type()); 630 EXPECT_EQ("user2 (at) managed.com", status_.user(2).email()); 631 EXPECT_EQ(em::DeviceUser::USER_TYPE_UNMANAGED, status_.user(3).type()); 632 EXPECT_FALSE(status_.user(3).has_email()); 633 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(4).type()); 634 EXPECT_EQ("user4 (at) managed.com", status_.user(4).email()); 635 636 // Verify that users are no longer reported if setting is disabled. 637 cros_settings_->SetBoolean(chromeos::kReportDeviceUsers, false); 638 GetStatus(); 639 EXPECT_EQ(0, status_.user_size()); 640 } 641 642 TEST_F(DeviceStatusCollectorTest, ReportManagedUser) { 643 // Verify that at least one managed user is reported regardless of list size. 644 user_manager_->AddUser("user0 (at) unmanaged.com"); 645 user_manager_->AddUser("user1 (at) unmanaged.com"); 646 user_manager_->AddUser("user2 (at) unmanaged.com"); 647 user_manager_->AddUser("user3 (at) unmanaged.com"); 648 user_manager_->AddUser("user4 (at) unmanaged.com"); 649 user_manager_->AddUser("user5 (at) unmanaged.com"); 650 user_manager_->AddUser("user6 (at) managed.com"); 651 user_manager_->AddUser("user7 (at) managed.com"); 652 653 cros_settings_->SetBoolean(chromeos::kReportDeviceUsers, true); 654 GetStatus(); 655 EXPECT_EQ(7, status_.user_size()); 656 for (int i = 0; i < 6; ++i) 657 EXPECT_EQ(em::DeviceUser::USER_TYPE_UNMANAGED, status_.user(i).type()); 658 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(6).type()); 659 EXPECT_EQ("user6 (at) managed.com", status_.user(6).email()); 660 } 661 662 // Fake device state. 663 struct FakeDeviceData { 664 const char* device_path; 665 const char* type; 666 const char* object_path; 667 const char* mac_address; 668 const char* meid; 669 const char* imei; 670 int expected_type; // proto enum type value, -1 for not present. 671 }; 672 673 static const FakeDeviceData kFakeDevices[] = { 674 { "/device/ethernet", shill::kTypeEthernet, "ethernet", 675 "112233445566", "", "", 676 em::NetworkInterface::TYPE_ETHERNET }, 677 { "/device/cellular1", shill::kTypeCellular, "cellular1", 678 "abcdefabcdef", "A10000009296F2", "", 679 em::NetworkInterface::TYPE_CELLULAR }, 680 { "/device/cellular2", shill::kTypeCellular, "cellular2", 681 "abcdefabcdef", "", "352099001761481", 682 em::NetworkInterface::TYPE_CELLULAR }, 683 { "/device/wifi", shill::kTypeWifi, "wifi", 684 "aabbccddeeff", "", "", 685 em::NetworkInterface::TYPE_WIFI }, 686 { "/device/bluetooth", shill::kTypeBluetooth, "bluetooth", 687 "", "", "", 688 em::NetworkInterface::TYPE_BLUETOOTH }, 689 { "/device/vpn", shill::kTypeVPN, "vpn", 690 "", "", "", 691 -1 }, 692 }; 693 694 class DeviceStatusCollectorNetworkInterfacesTest 695 : public DeviceStatusCollectorTest { 696 protected: 697 virtual void SetUp() OVERRIDE { 698 chromeos::DBusThreadManager::InitializeWithStub(); 699 chromeos::NetworkHandler::Initialize(); 700 chromeos::ShillDeviceClient::TestInterface* test_device_client = 701 chromeos::DBusThreadManager::Get()->GetShillDeviceClient()-> 702 GetTestInterface(); 703 test_device_client->ClearDevices(); 704 for (size_t i = 0; i < arraysize(kFakeDevices); ++i) { 705 const FakeDeviceData& dev = kFakeDevices[i]; 706 test_device_client->AddDevice(dev.device_path, dev.type, 707 dev.object_path); 708 if (*dev.mac_address) { 709 test_device_client->SetDeviceProperty( 710 dev.device_path, shill::kAddressProperty, 711 base::StringValue(dev.mac_address)); 712 } 713 if (*dev.meid) { 714 test_device_client->SetDeviceProperty( 715 dev.device_path, shill::kMeidProperty, 716 base::StringValue(dev.meid)); 717 } 718 if (*dev.imei) { 719 test_device_client->SetDeviceProperty( 720 dev.device_path, shill::kImeiProperty, 721 base::StringValue(dev.imei)); 722 } 723 } 724 725 // Flush out pending state updates. 726 base::RunLoop().RunUntilIdle(); 727 } 728 729 virtual void TearDown() OVERRIDE { 730 chromeos::NetworkHandler::Shutdown(); 731 chromeos::DBusThreadManager::Shutdown(); 732 } 733 }; 734 735 TEST_F(DeviceStatusCollectorNetworkInterfacesTest, NetworkInterfaces) { 736 // No interfaces should be reported if the policy is off. 737 GetStatus(); 738 EXPECT_EQ(0, status_.network_interface_size()); 739 740 // Switch the policy on and verify the interface list is present. 741 cros_settings_->SetBoolean(chromeos::kReportDeviceNetworkInterfaces, true); 742 GetStatus(); 743 744 int count = 0; 745 for (size_t i = 0; i < arraysize(kFakeDevices); ++i) { 746 const FakeDeviceData& dev = kFakeDevices[i]; 747 if (dev.expected_type == -1) 748 continue; 749 750 // Find the corresponding entry in reporting data. 751 bool found_match = false; 752 google::protobuf::RepeatedPtrField<em::NetworkInterface>::const_iterator 753 iface; 754 for (iface = status_.network_interface().begin(); 755 iface != status_.network_interface().end(); 756 ++iface) { 757 // Check whether type, field presence and field values match. 758 if (dev.expected_type == iface->type() && 759 iface->has_mac_address() == !!*dev.mac_address && 760 iface->has_meid() == !!*dev.meid && 761 iface->has_imei() == !!*dev.imei && 762 iface->mac_address() == dev.mac_address && 763 iface->meid() == dev.meid && 764 iface->imei() == dev.imei) { 765 found_match = true; 766 break; 767 } 768 } 769 770 EXPECT_TRUE(found_match) << "No matching interface for fake device " << i; 771 count++; 772 } 773 774 EXPECT_EQ(count, status_.network_interface_size()); 775 } 776 777 } // namespace policy 778