diff options
25 files changed, 292 insertions, 77 deletions
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index d7004ca..4beb040 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc @@ -438,6 +438,18 @@ void ChromeMetricsServiceClient::Initialize() { } void ChromeMetricsServiceClient::OnInitTaskGotHardwareClass() { + const base::Closure got_bluetooth_adapter_callback = + base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotBluetoothAdapter, + weak_ptr_factory_.GetWeakPtr()); +#if defined(OS_CHROMEOS) + chromeos_metrics_provider_->InitTaskGetBluetoothAdapter( + got_bluetooth_adapter_callback); +#else + got_bluetooth_adapter_callback.Run(); +#endif // defined(OS_CHROMEOS) +} + +void ChromeMetricsServiceClient::OnInitTaskGotBluetoothAdapter() { const base::Closure got_plugin_info_callback = base::Bind(&ChromeMetricsServiceClient::OnInitTaskGotPluginInfo, weak_ptr_factory_.GetWeakPtr()); diff --git a/chrome/browser/metrics/chrome_metrics_service_client.h b/chrome/browser/metrics/chrome_metrics_service_client.h index 34723b4..b991f61 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.h +++ b/chrome/browser/metrics/chrome_metrics_service_client.h @@ -83,9 +83,12 @@ class ChromeMetricsServiceClient // Completes the two-phase initialization of ChromeMetricsServiceClient. void Initialize(); - // Callback that continues the init task by loading plugin information. + // Callback that continues the init task by getting a Bluetooth Adapter. void OnInitTaskGotHardwareClass(); + // Callback that continues the init task by loading plugin information. + void OnInitTaskGotBluetoothAdapter(); + // Called after the Plugin init task has been completed that continues the // init task by launching a task to gather Google Update statistics. void OnInitTaskGotPluginInfo(); diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc index fae5560..7677d2d 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider.cc +++ b/chrome/browser/metrics/chromeos_metrics_provider.cc @@ -170,6 +170,13 @@ void ChromeOSMetricsProvider::InitTaskGetHardwareClassOnFileThread() { "hardware_class", &hardware_class_); } +void ChromeOSMetricsProvider::InitTaskGetBluetoothAdapter( + const base::Closure& callback) { + device::BluetoothAdapterFactory::GetAdapter( + base::Bind(&ChromeOSMetricsProvider::SetBluetoothAdapter, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + void ChromeOSMetricsProvider::ProvideSystemProfileMetrics( metrics::SystemProfileProto* system_profile_proto) { WriteBluetoothProto(system_profile_proto); @@ -228,12 +235,6 @@ void ChromeOSMetricsProvider::WriteBluetoothProto( metrics::SystemProfileProto::Hardware* hardware = system_profile_proto->mutable_hardware(); - // BluetoothAdapterFactory::GetAdapter is synchronous on Chrome OS; if that - // changes this will fail at the DCHECK(). - device::BluetoothAdapterFactory::GetAdapter(base::Bind( - &ChromeOSMetricsProvider::SetBluetoothAdapter, base::Unretained(this))); - DCHECK(adapter_.get()); - SystemProfileProto::Hardware::Bluetooth* bluetooth = hardware->mutable_bluetooth(); @@ -302,8 +303,10 @@ void ChromeOSMetricsProvider::UpdateMultiProfileUserCount( } void ChromeOSMetricsProvider::SetBluetoothAdapter( + base::Closure callback, scoped_refptr<device::BluetoothAdapter> adapter) { adapter_ = adapter; + callback.Run(); } void ChromeOSMetricsProvider::RecordEnrollmentStatus() { diff --git a/chrome/browser/metrics/chromeos_metrics_provider.h b/chrome/browser/metrics/chromeos_metrics_provider.h index 680c17a..5c8247a 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider.h +++ b/chrome/browser/metrics/chromeos_metrics_provider.h @@ -51,6 +51,10 @@ class ChromeOSMetricsProvider : public metrics::MetricsProvider { // is run. void InitTaskGetHardwareClass(const base::Closure& callback); + // Creates the Bluetooth adapter. When this task is complete, |callback| is + // run. + void InitTaskGetBluetoothAdapter(const base::Closure& callback); + // metrics::MetricsProvider: void Init() override; void OnDidCreateMetricsLog() override; @@ -72,8 +76,9 @@ class ChromeOSMetricsProvider : public metrics::MetricsProvider { metrics::SystemProfileProto* system_profile_proto); // Sets the Bluetooth Adapter instance used for the WriteBluetoothProto() - // call. - void SetBluetoothAdapter(scoped_refptr<device::BluetoothAdapter> adapter); + // call and calls callback. + void SetBluetoothAdapter(base::Closure callback, + scoped_refptr<device::BluetoothAdapter> adapter); // Writes info about paired Bluetooth devices on this system. void WriteBluetoothProto(metrics::SystemProfileProto* system_profile_proto); diff --git a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc index 19ee029..087b98e 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc +++ b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc @@ -7,6 +7,7 @@ #include <string> #include "base/macros.h" +#include "base/message_loop/message_loop.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" #include "chrome/browser/metrics/chromeos_metrics_provider.h" @@ -119,6 +120,22 @@ class ChromeOSMetricsProviderTest : public testing::Test { DISALLOW_COPY_AND_ASSIGN(ChromeOSMetricsProviderTest); }; +// Wrapper around ChromeOSMetricsProvider that initializes +// BluetoothAdapter in the constructor. +class TestChromeOSMetricsProvider : public ChromeOSMetricsProvider { + public: + TestChromeOSMetricsProvider() { + InitTaskGetBluetoothAdapter( + base::Bind(&TestChromeOSMetricsProvider::GetBluetoothAdapterCallback, + base::Unretained(this))); + base::MessageLoop::current()->Run(); + } + void GetBluetoothAdapterCallback() { + ASSERT_TRUE(base::MessageLoop::current()->is_running()); + base::MessageLoop::current()->QuitWhenIdle(); + } +}; + TEST_F(ChromeOSMetricsProviderTest, MultiProfileUserCount) { const AccountId account_id1(AccountId::FromUserEmail("user1@example.com")); const AccountId account_id2(AccountId::FromUserEmail("user2@example.com")); @@ -135,7 +152,7 @@ TEST_F(ChromeOSMetricsProviderTest, MultiProfileUserCount) { user_manager->LoginUser(account_id1); user_manager->LoginUser(account_id3); - ChromeOSMetricsProvider provider; + TestChromeOSMetricsProvider provider; provider.OnDidCreateMetricsLog(); metrics::SystemProfileProto system_profile; provider.ProvideSystemProfileMetrics(&system_profile); @@ -157,7 +174,7 @@ TEST_F(ChromeOSMetricsProviderTest, MultiProfileCountInvalidated) { user_manager->LoginUser(account_id1); - ChromeOSMetricsProvider provider; + TestChromeOSMetricsProvider provider; provider.OnDidCreateMetricsLog(); metrics::SystemProfileProto system_profile; @@ -170,7 +187,7 @@ TEST_F(ChromeOSMetricsProviderTest, MultiProfileCountInvalidated) { } TEST_F(ChromeOSMetricsProviderTest, BluetoothHardwareDisabled) { - ChromeOSMetricsProvider provider; + TestChromeOSMetricsProvider provider; provider.OnDidCreateMetricsLog(); metrics::SystemProfileProto system_profile; provider.ProvideSystemProfileMetrics(&system_profile); @@ -188,7 +205,7 @@ TEST_F(ChromeOSMetricsProviderTest, BluetoothHardwareEnabled) { dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); properties->powered.ReplaceValue(true); - ChromeOSMetricsProvider provider; + TestChromeOSMetricsProvider provider; metrics::SystemProfileProto system_profile; provider.ProvideSystemProfileMetrics(&system_profile); @@ -217,7 +234,7 @@ TEST_F(ChromeOSMetricsProviderTest, BluetoothPairedDevices) { dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath)); properties->paired.ReplaceValue(true); - ChromeOSMetricsProvider provider; + TestChromeOSMetricsProvider provider; provider.OnDidCreateMetricsLog(); metrics::SystemProfileProto system_profile; provider.ProvideSystemProfileMetrics(&system_profile); diff --git a/device/bluetooth/bluetooth_adapter_bluez.cc b/device/bluetooth/bluetooth_adapter_bluez.cc index 1d22ef7..4424b02 100644 --- a/device/bluetooth/bluetooth_adapter_bluez.cc +++ b/device/bluetooth/bluetooth_adapter_bluez.cc @@ -92,7 +92,7 @@ namespace device { // static base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( const InitCallback& init_callback) { - return bluez::BluetoothAdapterBlueZ::CreateAdapter(); + return bluez::BluetoothAdapterBlueZ::CreateAdapter(init_callback); } } // namespace device @@ -100,8 +100,9 @@ base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( namespace bluez { // static -base::WeakPtr<BluetoothAdapter> BluetoothAdapterBlueZ::CreateAdapter() { - BluetoothAdapterBlueZ* adapter = new BluetoothAdapterBlueZ(); +base::WeakPtr<BluetoothAdapter> BluetoothAdapterBlueZ::CreateAdapter( + const InitCallback& init_callback) { + BluetoothAdapterBlueZ* adapter = new BluetoothAdapterBlueZ(init_callback); return adapter->weak_ptr_factory_.GetWeakPtr(); } @@ -112,6 +113,13 @@ void BluetoothAdapterBlueZ::Shutdown() { << "Call BluetoothAdapterFactory::Shutdown() before " "BluezDBusManager::Shutdown()."; + // Since we don't initialize anything if Object Manager is not supported, + // no need to do any clean up. + if (!bluez::BluezDBusManager::Get()->IsObjectManagerSupported()) { + dbus_is_shutdown_ = true; + return; + } + if (IsPresent()) RemoveAdapter(); // Also deletes devices_. DCHECK(devices_.empty()); @@ -141,14 +149,36 @@ void BluetoothAdapterBlueZ::Shutdown() { dbus_is_shutdown_ = true; } -BluetoothAdapterBlueZ::BluetoothAdapterBlueZ() - : dbus_is_shutdown_(false), +BluetoothAdapterBlueZ::BluetoothAdapterBlueZ(const InitCallback& init_callback) + : init_callback_(init_callback), + initialized_(false), + dbus_is_shutdown_(false), num_discovery_sessions_(0), discovery_request_pending_(false), weak_ptr_factory_(this) { ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); socket_thread_ = device::BluetoothSocketThread::Get(); + // Can't initialize the adapter until DBus clients are ready. + if (bluez::BluezDBusManager::Get()->IsObjectManagerSupportKnown()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&BluetoothAdapterBlueZ::Init, + weak_ptr_factory_.GetWeakPtr())); + return; + } + bluez::BluezDBusManager::Get()->CallWhenObjectManagerSupportIsKnown( + base::Bind(&BluetoothAdapterBlueZ::Init, weak_ptr_factory_.GetWeakPtr())); +} + +void BluetoothAdapterBlueZ::Init() { + // If the platform doesn't support Object Manager then Bluez 5 is probably + // not present. In this case we just return without initializing anything. + if (!bluez::BluezDBusManager::Get()->IsObjectManagerSupported()) { + initialized_ = true; + init_callback_.Run(); + return; + } + bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->AddObserver( this); bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->AddObserver(this); @@ -168,6 +198,8 @@ BluetoothAdapterBlueZ::BluetoothAdapterBlueZ() VLOG(1) << object_paths.size() << " Bluetooth adapter(s) available."; SetAdapter(object_paths[0]); } + initialized_ = true; + init_callback_.Run(); } BluetoothAdapterBlueZ::~BluetoothAdapterBlueZ() { @@ -218,7 +250,7 @@ void BluetoothAdapterBlueZ::SetName(const std::string& name, } bool BluetoothAdapterBlueZ::IsInitialized() const { - return true; + return initialized_; } bool BluetoothAdapterBlueZ::IsPresent() const { diff --git a/device/bluetooth/bluetooth_adapter_bluez.h b/device/bluetooth/bluetooth_adapter_bluez.h index e2a07ff..4f847a5 100644 --- a/device/bluetooth/bluetooth_adapter_bluez.h +++ b/device/bluetooth/bluetooth_adapter_bluez.h @@ -73,7 +73,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterBlueZ typedef base::Callback<void(BluetoothAdapterProfileBlueZ* profile)> ProfileRegisteredCallback; - static base::WeakPtr<BluetoothAdapter> CreateAdapter(); + // Calls |init_callback| after a BluetoothAdapter is fully initialized. + static base::WeakPtr<BluetoothAdapter> CreateAdapter( + const InitCallback& init_callback); // BluetoothAdapter: void Shutdown() override; @@ -171,9 +173,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterBlueZ typedef std::pair<base::Closure, ErrorCompletionCallback> RegisterProfileCompletionPair; - BluetoothAdapterBlueZ(); + explicit BluetoothAdapterBlueZ(const InitCallback& init_callback); ~BluetoothAdapterBlueZ() override; + // Init will get asynchronouly called once we know if Object Manager is + // supported. + void Init(); + // bluez::BluetoothAdapterClient::Observer override. void AdapterAdded(const dbus::ObjectPath& object_path) override; void AdapterRemoved(const dbus::ObjectPath& object_path) override; @@ -333,6 +339,10 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterBlueZ // ended (with either success or failure). void ProcessQueuedDiscoveryRequests(); + InitCallback init_callback_; + + bool initialized_; + // Set in |Shutdown()|, makes IsPresent()| return false. bool dbus_is_shutdown_; diff --git a/device/bluetooth/bluetooth_adapter_factory.cc b/device/bluetooth/bluetooth_adapter_factory.cc index 2bcfbe90..dfea790 100644 --- a/device/bluetooth/bluetooth_adapter_factory.cc +++ b/device/bluetooth/bluetooth_adapter_factory.cc @@ -28,7 +28,7 @@ namespace { base::LazyInstance<base::WeakPtr<BluetoothAdapter> >::Leaky default_adapter = LAZY_INSTANCE_INITIALIZER; -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) typedef std::vector<BluetoothAdapterFactory::AdapterCallback> AdapterCallbackList; @@ -49,7 +49,7 @@ void RunAdapterCallbacks() { } adapter_callbacks.Get().clear(); } -#endif // defined(OS_WIN) +#endif // defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) } // namespace @@ -73,7 +73,7 @@ bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() { void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) { DCHECK(IsBluetoothAdapterAvailable()); -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) if (!default_adapter.Get()) { default_adapter.Get() = BluetoothAdapter::CreateAdapter(base::Bind(&RunAdapterCallbacks)); @@ -82,18 +82,17 @@ void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) { if (!default_adapter.Get()->IsInitialized()) adapter_callbacks.Get().push_back(callback); -#else // !defined(OS_WIN) +#else // !defined(OS_WIN) && !defined(OS_LINUX) && !defined(OS_CHROMEOS) if (!default_adapter.Get()) { default_adapter.Get() = BluetoothAdapter::CreateAdapter(BluetoothAdapter::InitCallback()); } DCHECK(default_adapter.Get()->IsInitialized()); -#endif // defined(OS_WIN) +#endif // defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) if (default_adapter.Get()->IsInitialized()) callback.Run(scoped_refptr<BluetoothAdapter>(default_adapter.Get().get())); - } #if defined(OS_CHROMEOS) || defined(OS_LINUX) diff --git a/device/bluetooth/bluetooth_adapter_profile_bluez_unittest.cc b/device/bluetooth/bluetooth_adapter_profile_bluez_unittest.cc index f64359d..8f06723 100644 --- a/device/bluetooth/bluetooth_adapter_profile_bluez_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_profile_bluez_unittest.cc @@ -55,6 +55,7 @@ class BluetoothAdapterProfileBlueZTest : public testing::Test { device::BluetoothAdapterFactory::GetAdapter( base::Bind(&BluetoothAdapterProfileBlueZTest::AdapterCallback, base::Unretained(this))); + base::MessageLoop::current()->Run(); ASSERT_TRUE(adapter_.get() != nullptr); ASSERT_TRUE(adapter_->IsInitialized()); ASSERT_TRUE(adapter_->IsPresent()); @@ -73,6 +74,10 @@ class BluetoothAdapterProfileBlueZTest : public testing::Test { void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { adapter_ = adapter; + if (base::MessageLoop::current() && + base::MessageLoop::current()->is_running()) { + base::MessageLoop::current()->QuitWhenIdle(); + } } class FakeDelegate : public bluez::BluetoothProfileServiceProvider::Delegate { diff --git a/device/bluetooth/bluetooth_advertisement_bluez_unittest.cc b/device/bluetooth/bluetooth_advertisement_bluez_unittest.cc index 27b2c8f..4e07002 100644 --- a/device/bluetooth/bluetooth_advertisement_bluez_unittest.cc +++ b/device/bluetooth/bluetooth_advertisement_bluez_unittest.cc @@ -80,6 +80,7 @@ class BluetoothAdvertisementBlueZTest : public testing::Test { BluetoothAdapterFactory::GetAdapter( base::Bind(&BluetoothAdvertisementBlueZTest::GetAdapterCallback, base::Unretained(this))); + base::MessageLoop::current()->Run(); } // Called whenever BluetoothAdapter is retrieved successfully. @@ -87,6 +88,10 @@ class BluetoothAdvertisementBlueZTest : public testing::Test { adapter_ = adapter; ASSERT_NE(adapter_.get(), nullptr); ASSERT_TRUE(adapter_->IsInitialized()); + if (base::MessageLoop::current() && + base::MessageLoop::current()->is_running()) { + base::MessageLoop::current()->QuitWhenIdle(); + } } scoped_ptr<BluetoothAdvertisement::Data> CreateAdvertisementData() { diff --git a/device/bluetooth/bluetooth_audio_sink_bluez_unittest.cc b/device/bluetooth/bluetooth_audio_sink_bluez_unittest.cc index 25b53d5..235ba2d 100644 --- a/device/bluetooth/bluetooth_audio_sink_bluez_unittest.cc +++ b/device/bluetooth/bluetooth_audio_sink_bluez_unittest.cc @@ -132,6 +132,7 @@ class BluetoothAudioSinkBlueZTest : public testing::Test { BluetoothAdapterFactory::GetAdapter( base::Bind(&BluetoothAudioSinkBlueZTest::GetAdapterCallback, base::Unretained(this))); + base::MessageLoop::current()->Run(); } // Called whenever BluetoothAdapter is retrieved successfully. @@ -152,6 +153,11 @@ class BluetoothAudioSinkBlueZTest : public testing::Test { // Resets callback_count_. --callback_count_; + + if (base::MessageLoop::current() && + base::MessageLoop::current()->is_running()) { + base::MessageLoop::current()->QuitWhenIdle(); + } } // Registers BluetoothAudioSinkBlueZ with default codec and capabilities. diff --git a/device/bluetooth/bluetooth_bluez_unittest.cc b/device/bluetooth/bluetooth_bluez_unittest.cc index f99caab..f2823dd 100644 --- a/device/bluetooth/bluetooth_bluez_unittest.cc +++ b/device/bluetooth/bluetooth_bluez_unittest.cc @@ -6,6 +6,7 @@ #include <stdint.h> #include <utility> +#include "base/bind_helpers.h" #include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" @@ -231,6 +232,8 @@ class BluetoothBlueZTest : public testing::Test { return base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)); } + void AdapterCallback() { QuitMessageLoop(); } + void DiscoverySessionCallback( scoped_ptr<BluetoothDiscoverySession> discovery_session) { ++callback_count_; @@ -293,7 +296,9 @@ class BluetoothBlueZTest : public testing::Test { // Call to fill the adapter_ member with a BluetoothAdapter instance. void GetAdapter() { - adapter_ = new BluetoothAdapterBlueZ(); + adapter_ = new BluetoothAdapterBlueZ(base::Bind( + &BluetoothBlueZTest::AdapterCallback, base::Unretained(this))); + base::MessageLoop::current()->Run(); ASSERT_TRUE(adapter_.get() != nullptr); ASSERT_TRUE(adapter_->IsInitialized()); } diff --git a/device/bluetooth/bluetooth_gatt_bluez_unittest.cc b/device/bluetooth/bluetooth_gatt_bluez_unittest.cc index 43daec0..6ae2d05 100644 --- a/device/bluetooth/bluetooth_gatt_bluez_unittest.cc +++ b/device/bluetooth/bluetooth_gatt_bluez_unittest.cc @@ -121,6 +121,7 @@ class BluetoothGattBlueZTest : public testing::Test { void GetAdapter() { device::BluetoothAdapterFactory::GetAdapter(base::Bind( &BluetoothGattBlueZTest::AdapterCallback, base::Unretained(this))); + base::MessageLoop::current()->Run(); ASSERT_TRUE(adapter_.get() != NULL); ASSERT_TRUE(adapter_->IsInitialized()); ASSERT_TRUE(adapter_->IsPresent()); @@ -128,6 +129,10 @@ class BluetoothGattBlueZTest : public testing::Test { void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { adapter_ = adapter; + if (base::MessageLoop::current() && + base::MessageLoop::current()->is_running()) { + base::MessageLoop::current()->QuitWhenIdle(); + } } void SuccessCallback() { ++success_callback_count_; } diff --git a/device/bluetooth/bluetooth_socket_bluez_unittest.cc b/device/bluetooth/bluetooth_socket_bluez_unittest.cc index 171d77d..80585bc 100644 --- a/device/bluetooth/bluetooth_socket_bluez_unittest.cc +++ b/device/bluetooth/bluetooth_socket_bluez_unittest.cc @@ -78,6 +78,9 @@ class BluetoothSocketBlueZTest : public testing::Test { // Grab a pointer to the adapter. device::BluetoothAdapterFactory::GetAdapter(base::Bind( &BluetoothSocketBlueZTest::AdapterCallback, base::Unretained(this))); + + base::MessageLoop::current()->Run(); + ASSERT_TRUE(adapter_.get() != nullptr); ASSERT_TRUE(adapter_->IsInitialized()); ASSERT_TRUE(adapter_->IsPresent()); @@ -96,6 +99,10 @@ class BluetoothSocketBlueZTest : public testing::Test { void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { adapter_ = adapter; + if (base::MessageLoop::current() && + base::MessageLoop::current()->is_running()) { + base::MessageLoop::current()->QuitWhenIdle(); + } } void SuccessCallback() { diff --git a/device/bluetooth/dbus/bluetooth_agent_service_provider.cc b/device/bluetooth/dbus/bluetooth_agent_service_provider.cc index 1bafcb0..ba51ba8 100644 --- a/device/bluetooth/dbus/bluetooth_agent_service_provider.cc +++ b/device/bluetooth/dbus/bluetooth_agent_service_provider.cc @@ -437,11 +437,10 @@ BluetoothAgentServiceProvider* BluetoothAgentServiceProvider::Create( dbus::Bus* bus, const dbus::ObjectPath& object_path, Delegate* delegate) { - if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) { return new BluetoothAgentServiceProviderImpl(bus, object_path, delegate); - } else { - return new FakeBluetoothAgentServiceProvider(object_path, delegate); } + return new FakeBluetoothAgentServiceProvider(object_path, delegate); } } // namespace bluez diff --git a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc index 1d53d8a..5e2fffd 100644 --- a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc +++ b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc @@ -36,9 +36,9 @@ namespace bluez { -BluetoothDBusClientBundle::BluetoothDBusClientBundle(bool use_stubs) - : use_stubs_(use_stubs) { - if (!use_stubs) { +BluetoothDBusClientBundle::BluetoothDBusClientBundle(bool use_fakes) + : use_fakes_(use_fakes) { + if (!use_fakes_) { bluetooth_adapter_client_.reset(BluetoothAdapterClient::Create()); bluetooth_le_advertising_manager_client_.reset( BluetoothLEAdvertisingManagerClient::Create()); diff --git a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h index 3beef61..2cd102e 100644 --- a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h +++ b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h @@ -31,11 +31,11 @@ class BluetoothProfileManagerClient; // system bus. See also the comment in the destructor of DBusThreadManager. class DEVICE_BLUETOOTH_EXPORT BluetoothDBusClientBundle { public: - explicit BluetoothDBusClientBundle(bool use_stubs); + explicit BluetoothDBusClientBundle(bool use_fakes); ~BluetoothDBusClientBundle(); // Returns true if |client| is stubbed. - bool IsUsingStub() { return use_stubs_; } + bool IsUsingFakes() { return use_fakes_; } BluetoothAdapterClient* bluetooth_adapter_client() { return bluetooth_adapter_client_.get(); @@ -89,7 +89,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDBusClientBundle { private: friend class BluezDBusManagerSetter; - bool use_stubs_; + bool use_fakes_; scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_; scoped_ptr<BluetoothLEAdvertisingManagerClient> diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc index bd578532..da27bd5 100644 --- a/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc +++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc @@ -457,7 +457,7 @@ BluetoothGattCharacteristicServiceProvider::Create( const std::vector<std::string>& flags, const std::vector<std::string>& permissions, const dbus::ObjectPath& service_path) { - if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) { return new BluetoothGattCharacteristicServiceProviderImpl( bus, object_path, delegate, uuid, flags, permissions, service_path); } diff --git a/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc index 53cc7f1..25a4e4c 100644 --- a/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc +++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc @@ -450,7 +450,7 @@ BluetoothGattDescriptorServiceProvider::Create( const std::string& uuid, const std::vector<std::string>& permissions, const dbus::ObjectPath& characteristic_path) { - if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) { return new BluetoothGattDescriptorServiceProviderImpl( bus, object_path, delegate, uuid, permissions, characteristic_path); } diff --git a/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc index c30587f..dc66fd0 100644 --- a/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc +++ b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc @@ -264,7 +264,7 @@ BluetoothGattServiceServiceProvider::Create( const dbus::ObjectPath& object_path, const std::string& uuid, const std::vector<dbus::ObjectPath>& includes) { - if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) { return new BluetoothGattServiceServiceProviderImpl(bus, object_path, uuid, includes); } diff --git a/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc index b5e6f81..6081112 100644 --- a/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc +++ b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc @@ -413,15 +413,14 @@ BluetoothLEAdvertisementServiceProvider::Create( scoped_ptr<ManufacturerData> manufacturer_data, scoped_ptr<UUIDList> solicit_uuids, scoped_ptr<ServiceData> service_data) { - if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) { return make_scoped_ptr(new BluetoothAdvertisementServiceProviderImpl( bus, object_path, delegate, type, std::move(service_uuids), std::move(manufacturer_data), std::move(solicit_uuids), std::move(service_data))); - } else { - return make_scoped_ptr( - new FakeBluetoothLEAdvertisementServiceProvider(object_path, delegate)); } + return make_scoped_ptr( + new FakeBluetoothLEAdvertisementServiceProvider(object_path, delegate)); } } // namespace bluez diff --git a/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc index 5a0d17f..7a9ce59 100644 --- a/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc +++ b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc @@ -306,7 +306,7 @@ BluetoothMediaEndpointServiceProvider::Create( const dbus::ObjectPath& object_path, Delegate* delegate) { // Returns a real implementation. - if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) { return new BluetoothMediaEndpointServiceProviderImpl(bus, object_path, delegate); } diff --git a/device/bluetooth/dbus/bluetooth_profile_service_provider.cc b/device/bluetooth/dbus/bluetooth_profile_service_provider.cc index 4d2845d..ef6dc8d 100644 --- a/device/bluetooth/dbus/bluetooth_profile_service_provider.cc +++ b/device/bluetooth/dbus/bluetooth_profile_service_provider.cc @@ -241,11 +241,10 @@ BluetoothProfileServiceProvider* BluetoothProfileServiceProvider::Create( dbus::Bus* bus, const dbus::ObjectPath& object_path, Delegate* delegate) { - if (!bluez::BluezDBusManager::Get()->IsUsingStub()) { + if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) { return new BluetoothProfileServiceProviderImpl(bus, object_path, delegate); - } else { - return new FakeBluetoothProfileServiceProvider(object_path, delegate); } + return new FakeBluetoothProfileServiceProvider(object_path, delegate); } } // namespace bluez diff --git a/device/bluetooth/dbus/bluez_dbus_manager.cc b/device/bluetooth/dbus/bluez_dbus_manager.cc index 9736f67..8c0690e 100644 --- a/device/bluetooth/dbus/bluez_dbus_manager.cc +++ b/device/bluetooth/dbus/bluez_dbus_manager.cc @@ -11,6 +11,9 @@ #include "base/threading/thread.h" #include "dbus/bus.h" #include "dbus/dbus_statistics.h" +#include "dbus/message.h" +#include "dbus/object_manager.h" +#include "dbus/object_proxy.h" #include "device/bluetooth/dbus/bluetooth_adapter_client.h" #include "device/bluetooth/dbus/bluetooth_agent_manager_client.h" #include "device/bluetooth/dbus/bluetooth_device_client.h" @@ -23,16 +26,48 @@ #include "device/bluetooth/dbus/bluetooth_media_client.h" #include "device/bluetooth/dbus/bluetooth_media_transport_client.h" #include "device/bluetooth/dbus/bluetooth_profile_manager_client.h" +#include "third_party/cros_system_api/dbus/service_constants.h" namespace bluez { static BluezDBusManager* g_bluez_dbus_manager = nullptr; static bool g_using_bluez_dbus_manager_for_testing = false; -BluezDBusManager::BluezDBusManager( - dbus::Bus* bus, - scoped_ptr<BluetoothDBusClientBundle> client_bundle) - : bus_(bus), client_bundle_(std::move(client_bundle)) {} +BluezDBusManager::BluezDBusManager(dbus::Bus* bus, bool use_dbus_fakes) + : bus_(bus), + object_manager_support_known_(false), + object_manager_supported_(false), + weak_ptr_factory_(this) { + // On Chrome OS, Bluez might not be ready by the time we initialize the + // BluezDBusManager so we initialize the clients anyway. + bool should_check_object_manager = true; +#if defined(OS_CHROMEOS) + should_check_object_manager = false; +#endif + + if (!should_check_object_manager || use_dbus_fakes) { + client_bundle_.reset(new BluetoothDBusClientBundle(use_dbus_fakes)); + InitializeClients(); + object_manager_supported_ = true; + object_manager_support_known_ = true; + return; + } + + CHECK(GetSystemBus()) << "Can't initialize real clients without DBus."; + dbus::MethodCall method_call(dbus::kObjectManagerInterface, + dbus::kObjectManagerGetManagedObjects); + GetSystemBus() + ->GetObjectProxy( + bluetooth_object_manager::kBluetoothObjectManagerServiceName, + dbus::ObjectPath( + bluetooth_object_manager::kBluetoothObjectManagerServicePath)) + ->CallMethodWithErrorCallback( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluezDBusManager::OnObjectManagerSupported, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluezDBusManager::OnObjectManagerNotSupported, + weak_ptr_factory_.GetWeakPtr())); +} BluezDBusManager::~BluezDBusManager() { // Delete all D-Bus clients before shutting down the system bus. @@ -43,75 +78,121 @@ dbus::Bus* bluez::BluezDBusManager::GetSystemBus() { return bus_; } +void BluezDBusManager::CallWhenObjectManagerSupportIsKnown( + base::Closure callback) { + object_manager_support_known_callback_ = callback; +} + BluetoothAdapterClient* bluez::BluezDBusManager::GetBluetoothAdapterClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_adapter_client(); } BluetoothLEAdvertisingManagerClient* bluez::BluezDBusManager::GetBluetoothLEAdvertisingManagerClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_le_advertising_manager_client(); } BluetoothAgentManagerClient* bluez::BluezDBusManager::GetBluetoothAgentManagerClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_agent_manager_client(); } BluetoothDeviceClient* bluez::BluezDBusManager::GetBluetoothDeviceClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_device_client(); } BluetoothGattCharacteristicClient* bluez::BluezDBusManager::GetBluetoothGattCharacteristicClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_gatt_characteristic_client(); } BluetoothGattDescriptorClient* bluez::BluezDBusManager::GetBluetoothGattDescriptorClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_gatt_descriptor_client(); } BluetoothGattManagerClient* bluez::BluezDBusManager::GetBluetoothGattManagerClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_gatt_manager_client(); } BluetoothGattServiceClient* bluez::BluezDBusManager::GetBluetoothGattServiceClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_gatt_service_client(); } BluetoothInputClient* bluez::BluezDBusManager::GetBluetoothInputClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_input_client(); } BluetoothMediaClient* bluez::BluezDBusManager::GetBluetoothMediaClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_media_client(); } BluetoothMediaTransportClient* bluez::BluezDBusManager::GetBluetoothMediaTransportClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_media_transport_client(); } BluetoothProfileManagerClient* bluez::BluezDBusManager::GetBluetoothProfileManagerClient() { + DCHECK(object_manager_support_known_); return client_bundle_->bluetooth_profile_manager_client(); } +void BluezDBusManager::OnObjectManagerSupported(dbus::Response* response) { + VLOG(1) << "Bluetooth supported. Initializing clients."; + object_manager_supported_ = true; + + client_bundle_.reset(new BluetoothDBusClientBundle(false /* use_fakes */)); + InitializeClients(); + + object_manager_support_known_ = true; + if (!object_manager_support_known_callback_.is_null()) { + object_manager_support_known_callback_.Run(); + object_manager_support_known_callback_.Reset(); + } +} + +void BluezDBusManager::OnObjectManagerNotSupported( + dbus::ErrorResponse* response) { + VLOG(1) << "Bluetooth not supported."; + object_manager_supported_ = false; + + // We don't initialize clients since the clients need ObjectManager. + + object_manager_support_known_ = true; + if (!object_manager_support_known_callback_.is_null()) { + object_manager_support_known_callback_.Run(); + object_manager_support_known_callback_.Reset(); + } +} + void BluezDBusManager::InitializeClients() { - GetBluetoothAdapterClient()->Init(GetSystemBus()); - GetBluetoothAgentManagerClient()->Init(GetSystemBus()); - GetBluetoothDeviceClient()->Init(GetSystemBus()); - GetBluetoothGattCharacteristicClient()->Init(GetSystemBus()); - GetBluetoothGattDescriptorClient()->Init(GetSystemBus()); - GetBluetoothGattManagerClient()->Init(GetSystemBus()); - GetBluetoothGattServiceClient()->Init(GetSystemBus()); - GetBluetoothInputClient()->Init(GetSystemBus()); - GetBluetoothLEAdvertisingManagerClient()->Init(GetSystemBus()); - GetBluetoothMediaClient()->Init(GetSystemBus()); - GetBluetoothMediaTransportClient()->Init(GetSystemBus()); - GetBluetoothProfileManagerClient()->Init(GetSystemBus()); + client_bundle_->bluetooth_adapter_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_agent_manager_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_device_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_gatt_characteristic_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_gatt_descriptor_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_gatt_manager_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_gatt_service_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_input_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_le_advertising_manager_client()->Init( + GetSystemBus()); + client_bundle_->bluetooth_media_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_media_transport_client()->Init(GetSystemBus()); + client_bundle_->bluetooth_profile_manager_client()->Init(GetSystemBus()); // This must be called after the list of clients so they've each had a // chance to register with their object g_dbus_thread_managers. @@ -144,9 +225,7 @@ bluez::BluezDBusManager::GetSetterForTesting() { // static void BluezDBusManager::CreateGlobalInstance(dbus::Bus* bus, bool use_stubs) { CHECK(!g_bluez_dbus_manager); - g_bluez_dbus_manager = new BluezDBusManager( - bus, make_scoped_ptr(new BluetoothDBusClientBundle(use_stubs))); - g_bluez_dbus_manager->InitializeClients(); + g_bluez_dbus_manager = new BluezDBusManager(bus, use_stubs); } // static diff --git a/device/bluetooth/dbus/bluez_dbus_manager.h b/device/bluetooth/dbus/bluez_dbus_manager.h index fe879c4..9ebe6b3 100644 --- a/device/bluetooth/dbus/bluez_dbus_manager.h +++ b/device/bluetooth/dbus/bluez_dbus_manager.h @@ -11,12 +11,15 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "device/bluetooth/bluetooth_export.h" #include "device/bluetooth/dbus/bluetooth_dbus_client_bundle.h" namespace dbus { class Bus; class ObjectPath; +class Response; +class ErrorResponse; } // namespace dbus namespace bluez { @@ -56,9 +59,10 @@ class DEVICE_BLUETOOTH_EXPORT BluezDBusManager { // Sets the global instance. Must be called before any calls to Get(). // We explicitly initialize and shut down the global object, rather than // making it a Singleton, to ensure clean startup and shutdown. - // This will initialize real or stub DBusClients depending on command-line - // arguments and whether this process runs in a real or test environment. - static void Initialize(dbus::Bus* bus, bool use_dbus_stub); + // This will initialize real, stub, or fake DBusClients depending on + // command-line arguments, whether Object Manager is supported and + // whether this process runs in a real or test environment. + static void Initialize(dbus::Bus* bus, bool use_dbus_fakes); // Returns a BluezDBusManagerSetter instance that allows tests to // replace individual D-Bus clients with their own implementations. @@ -75,12 +79,23 @@ class DEVICE_BLUETOOTH_EXPORT BluezDBusManager { // Gets the global instance. Initialize() must be called first. static BluezDBusManager* Get(); - // Returns true if |client| is stubbed. - bool IsUsingStub() { return client_bundle_->IsUsingStub(); } - // Returns various D-Bus bus instances, owned by BluezDBusManager. dbus::Bus* GetSystemBus(); + // Returns true once we know whether Object Manager is supported or not. + // Until this method returns true, no classes should try to use the + // DBus Clients. + bool IsObjectManagerSupportKnown() { return object_manager_support_known_; } + + // Calls |callback| once we know whether Object Manager is supported or not. + void CallWhenObjectManagerSupportIsKnown(base::Closure callback); + + // Returns true if Object Manager is supported. + bool IsObjectManagerSupported() { return object_manager_supported_; } + + // Returns true if |client| is fake. + bool IsUsingFakes() { return client_bundle_->IsUsingFakes(); } + // All returned objects are owned by BluezDBusManager. Do not use these // pointers after BluezDBusManager has been shut down. BluetoothAdapterClient* GetBluetoothAdapterClient(); @@ -101,15 +116,16 @@ class DEVICE_BLUETOOTH_EXPORT BluezDBusManager { // Creates a new BluezDBusManager using the DBusClients set in // |client_bundle|. - explicit BluezDBusManager( - dbus::Bus* bus, - scoped_ptr<BluetoothDBusClientBundle> client_bundle); + explicit BluezDBusManager(dbus::Bus* bus, bool use_stubs); ~BluezDBusManager(); // Creates a global instance of BluezDBusManager. Cannot be called more than // once. static void CreateGlobalInstance(dbus::Bus* bus, bool use_stubs); + void OnObjectManagerSupported(dbus::Response* response); + void OnObjectManagerNotSupported(dbus::ErrorResponse* response); + // Initializes all currently stored DBusClients with the system bus and // performs additional setup. void InitializeClients(); @@ -117,6 +133,15 @@ class DEVICE_BLUETOOTH_EXPORT BluezDBusManager { dbus::Bus* bus_; scoped_ptr<BluetoothDBusClientBundle> client_bundle_; + base::Closure object_manager_support_known_callback_; + + bool object_manager_support_known_; + bool object_manager_supported_; + + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluezDBusManager> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(BluezDBusManager); }; |