| // Copyright 2014 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "chrome/browser/metrics/chromeos_metrics_provider.h" | 
 |  | 
 | #include <string> | 
 |  | 
 | #include "base/basictypes.h" | 
 | #include "chrome/browser/chromeos/login/users/fake_user_manager.h" | 
 | #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" | 
 | #include "chrome/browser/metrics/chromeos_metrics_provider.h" | 
 | #include "chromeos/dbus/dbus_thread_manager.h" | 
 | #include "chromeos/dbus/fake_bluetooth_adapter_client.h" | 
 | #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" | 
 | #include "chromeos/dbus/fake_bluetooth_device_client.h" | 
 | #include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" | 
 | #include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h" | 
 | #include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" | 
 | #include "chromeos/dbus/fake_bluetooth_input_client.h" | 
 | #include "chromeos/dbus/power_manager_client.h" | 
 | #include "chromeos/login/login_state.h" | 
 | #include "components/metrics/proto/system_profile.pb.h" | 
 | #include "components/user_manager/user_manager.h" | 
 | #include "content/public/test/test_browser_thread_bundle.h" | 
 | #include "content/public/test/test_utils.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 |  | 
 | #if defined(USE_X11) | 
 | #include "ui/events/devices/x11/device_data_manager_x11.h" | 
 | #endif | 
 |  | 
 | using chromeos::DBusThreadManager; | 
 | using chromeos::DBusThreadManagerSetter; | 
 | using chromeos::BluetoothAdapterClient; | 
 | using chromeos::BluetoothAgentManagerClient; | 
 | using chromeos::BluetoothDeviceClient; | 
 | using chromeos::BluetoothGattCharacteristicClient; | 
 | using chromeos::BluetoothGattDescriptorClient; | 
 | using chromeos::BluetoothGattServiceClient; | 
 | using chromeos::BluetoothInputClient; | 
 | using chromeos::FakeBluetoothAdapterClient; | 
 | using chromeos::FakeBluetoothAgentManagerClient; | 
 | using chromeos::FakeBluetoothDeviceClient; | 
 | using chromeos::FakeBluetoothGattCharacteristicClient; | 
 | using chromeos::FakeBluetoothGattDescriptorClient; | 
 | using chromeos::FakeBluetoothGattServiceClient; | 
 | using chromeos::FakeBluetoothInputClient; | 
 | using chromeos::PowerManagerClient; | 
 | using chromeos::STUB_DBUS_CLIENT_IMPLEMENTATION; | 
 |  | 
 | class ChromeOSMetricsProviderTest : public testing::Test { | 
 |  public: | 
 |   ChromeOSMetricsProviderTest() {} | 
 |  | 
 |  protected: | 
 |   void SetUp() override { | 
 | #if defined(USE_X11) | 
 |     ui::DeviceDataManagerX11::CreateInstance(); | 
 | #endif | 
 |  | 
 |     // Set up the fake Bluetooth environment, | 
 |     scoped_ptr<DBusThreadManagerSetter> dbus_setter = | 
 |         DBusThreadManager::GetSetterForTesting(); | 
 |     dbus_setter->SetBluetoothAdapterClient( | 
 |         scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient)); | 
 |     dbus_setter->SetBluetoothDeviceClient( | 
 |         scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient)); | 
 |     dbus_setter->SetBluetoothGattCharacteristicClient( | 
 |         scoped_ptr<BluetoothGattCharacteristicClient>( | 
 |             new FakeBluetoothGattCharacteristicClient)); | 
 |     dbus_setter->SetBluetoothGattDescriptorClient( | 
 |         scoped_ptr<BluetoothGattDescriptorClient>( | 
 |             new FakeBluetoothGattDescriptorClient)); | 
 |     dbus_setter->SetBluetoothGattServiceClient( | 
 |         scoped_ptr<BluetoothGattServiceClient>( | 
 |             new FakeBluetoothGattServiceClient)); | 
 |     dbus_setter->SetBluetoothInputClient( | 
 |         scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient)); | 
 |     dbus_setter->SetBluetoothAgentManagerClient( | 
 |         scoped_ptr<BluetoothAgentManagerClient>( | 
 |             new FakeBluetoothAgentManagerClient)); | 
 |  | 
 |     // Set up a PowerManagerClient instance for PerfProvider. | 
 |     dbus_setter->SetPowerManagerClient( | 
 |         scoped_ptr<PowerManagerClient>( | 
 |             PowerManagerClient::Create(STUB_DBUS_CLIENT_IMPLEMENTATION))); | 
 |  | 
 |     // Grab pointers to members of the thread manager for easier testing. | 
 |     fake_bluetooth_adapter_client_ = static_cast<FakeBluetoothAdapterClient*>( | 
 |         DBusThreadManager::Get()->GetBluetoothAdapterClient()); | 
 |     fake_bluetooth_device_client_ = static_cast<FakeBluetoothDeviceClient*>( | 
 |         DBusThreadManager::Get()->GetBluetoothDeviceClient()); | 
 |  | 
 |     // Initialize the login state trackers. | 
 |     if (!chromeos::LoginState::IsInitialized()) | 
 |       chromeos::LoginState::Initialize(); | 
 |   } | 
 |  | 
 |   void TearDown() override { | 
 |     // Destroy the login state tracker if it was initialized. | 
 |     chromeos::LoginState::Shutdown(); | 
 |  | 
 |     DBusThreadManager::Shutdown(); | 
 |   } | 
 |  | 
 |  protected: | 
 |   FakeBluetoothAdapterClient* fake_bluetooth_adapter_client_; | 
 |   FakeBluetoothDeviceClient* fake_bluetooth_device_client_; | 
 |  | 
 |  private: | 
 |   content::TestBrowserThreadBundle thread_bundle_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(ChromeOSMetricsProviderTest); | 
 | }; | 
 |  | 
 | TEST_F(ChromeOSMetricsProviderTest, MultiProfileUserCount) { | 
 |   std::string user1("user1@example.com"); | 
 |   std::string user2("user2@example.com"); | 
 |   std::string user3("user3@example.com"); | 
 |  | 
 |   // |scoped_enabler| takes over the lifetime of |user_manager|. | 
 |   chromeos::FakeUserManager* user_manager = new chromeos::FakeUserManager(); | 
 |   chromeos::ScopedUserManagerEnabler scoped_enabler(user_manager); | 
 |   user_manager->AddKioskAppUser(user1); | 
 |   user_manager->AddKioskAppUser(user2); | 
 |   user_manager->AddKioskAppUser(user3); | 
 |  | 
 |   user_manager->LoginUser(user1); | 
 |   user_manager->LoginUser(user3); | 
 |  | 
 |   ChromeOSMetricsProvider provider; | 
 |   provider.OnDidCreateMetricsLog(); | 
 |   metrics::SystemProfileProto system_profile; | 
 |   provider.ProvideSystemProfileMetrics(&system_profile); | 
 |   EXPECT_EQ(2u, system_profile.multi_profile_user_count()); | 
 | } | 
 |  | 
 | TEST_F(ChromeOSMetricsProviderTest, MultiProfileCountInvalidated) { | 
 |   std::string user1("user1@example.com"); | 
 |   std::string user2("user2@example.com"); | 
 |   std::string user3("user3@example.com"); | 
 |  | 
 |   // |scoped_enabler| takes over the lifetime of |user_manager|. | 
 |   chromeos::FakeUserManager* user_manager = new chromeos::FakeUserManager(); | 
 |   chromeos::ScopedUserManagerEnabler scoped_enabler(user_manager); | 
 |   user_manager->AddKioskAppUser(user1); | 
 |   user_manager->AddKioskAppUser(user2); | 
 |   user_manager->AddKioskAppUser(user3); | 
 |  | 
 |   user_manager->LoginUser(user1); | 
 |  | 
 |   ChromeOSMetricsProvider provider; | 
 |   provider.OnDidCreateMetricsLog(); | 
 |  | 
 |   metrics::SystemProfileProto system_profile; | 
 |   provider.ProvideSystemProfileMetrics(&system_profile); | 
 |   EXPECT_EQ(1u, system_profile.multi_profile_user_count()); | 
 |  | 
 |   user_manager->LoginUser(user2); | 
 |   provider.ProvideSystemProfileMetrics(&system_profile); | 
 |   EXPECT_EQ(0u, system_profile.multi_profile_user_count()); | 
 | } | 
 |  | 
 | TEST_F(ChromeOSMetricsProviderTest, BluetoothHardwareDisabled) { | 
 |   ChromeOSMetricsProvider provider; | 
 |   provider.OnDidCreateMetricsLog(); | 
 |   metrics::SystemProfileProto system_profile; | 
 |   provider.ProvideSystemProfileMetrics(&system_profile); | 
 |  | 
 |   EXPECT_TRUE(system_profile.has_hardware()); | 
 |   EXPECT_TRUE(system_profile.hardware().has_bluetooth()); | 
 |  | 
 |   EXPECT_TRUE(system_profile.hardware().bluetooth().is_present()); | 
 |   EXPECT_FALSE(system_profile.hardware().bluetooth().is_enabled()); | 
 | } | 
 |  | 
 | TEST_F(ChromeOSMetricsProviderTest, BluetoothHardwareEnabled) { | 
 |   FakeBluetoothAdapterClient::Properties* properties = | 
 |       fake_bluetooth_adapter_client_->GetProperties( | 
 |           dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); | 
 |   properties->powered.ReplaceValue(true); | 
 |  | 
 |   ChromeOSMetricsProvider provider; | 
 |   metrics::SystemProfileProto system_profile; | 
 |   provider.ProvideSystemProfileMetrics(&system_profile); | 
 |  | 
 |   EXPECT_TRUE(system_profile.has_hardware()); | 
 |   EXPECT_TRUE(system_profile.hardware().has_bluetooth()); | 
 |  | 
 |   EXPECT_TRUE(system_profile.hardware().bluetooth().is_present()); | 
 |   EXPECT_TRUE(system_profile.hardware().bluetooth().is_enabled()); | 
 | } | 
 |  | 
 | TEST_F(ChromeOSMetricsProviderTest, BluetoothPairedDevices) { | 
 |   // The fake bluetooth adapter class already claims to be paired with one | 
 |   // device when initialized. Add a second and third fake device to it so we | 
 |   // can test the cases where a device is not paired (LE device, generally) | 
 |   // and a device that does not have Device ID information. | 
 |   fake_bluetooth_device_client_->CreateDevice( | 
 |       dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | 
 |       dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath)); | 
 |  | 
 |   fake_bluetooth_device_client_->CreateDevice( | 
 |       dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | 
 |       dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath)); | 
 |  | 
 |   FakeBluetoothDeviceClient::Properties* properties = | 
 |       fake_bluetooth_device_client_->GetProperties( | 
 |           dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath)); | 
 |   properties->paired.ReplaceValue(true); | 
 |  | 
 |   ChromeOSMetricsProvider provider; | 
 |   provider.OnDidCreateMetricsLog(); | 
 |   metrics::SystemProfileProto system_profile; | 
 |   provider.ProvideSystemProfileMetrics(&system_profile); | 
 |  | 
 |   ASSERT_TRUE(system_profile.has_hardware()); | 
 |   ASSERT_TRUE(system_profile.hardware().has_bluetooth()); | 
 |  | 
 |   // Only two of the devices should appear. | 
 |   EXPECT_EQ(2, system_profile.hardware().bluetooth().paired_device_size()); | 
 |  | 
 |   typedef metrics::SystemProfileProto::Hardware::Bluetooth::PairedDevice | 
 |       PairedDevice; | 
 |  | 
 |   // First device should match the Paired Device object, complete with | 
 |   // parsed Device ID information. | 
 |   PairedDevice device1 = system_profile.hardware().bluetooth().paired_device(0); | 
 |  | 
 |   EXPECT_EQ(FakeBluetoothDeviceClient::kPairedDeviceClass, | 
 |             device1.bluetooth_class()); | 
 |   EXPECT_EQ(PairedDevice::DEVICE_COMPUTER, device1.type()); | 
 |   EXPECT_EQ(0x001122U, device1.vendor_prefix()); | 
 |   EXPECT_EQ(PairedDevice::VENDOR_ID_USB, device1.vendor_id_source()); | 
 |   EXPECT_EQ(0x05ACU, device1.vendor_id()); | 
 |   EXPECT_EQ(0x030DU, device1.product_id()); | 
 |   EXPECT_EQ(0x0306U, device1.device_id()); | 
 |  | 
 |   // Second device should match the Confirm Passkey object, this has | 
 |   // no Device ID information. | 
 |   PairedDevice device2 = system_profile.hardware().bluetooth().paired_device(1); | 
 |  | 
 |   EXPECT_EQ(FakeBluetoothDeviceClient::kConfirmPasskeyClass, | 
 |             device2.bluetooth_class()); | 
 |   EXPECT_EQ(PairedDevice::DEVICE_PHONE, device2.type()); | 
 |   EXPECT_EQ(0x207D74U, device2.vendor_prefix()); | 
 |   EXPECT_EQ(PairedDevice::VENDOR_ID_UNKNOWN, device2.vendor_id_source()); | 
 | } |