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 "device/bluetooth/bluetooth_adapter_factory.h"
6
7#include <vector>
8
9#include "base/bind.h"
10#include "base/lazy_instance.h"
11#include "base/memory/ref_counted.h"
12#include "base/memory/weak_ptr.h"
13#include "device/bluetooth/bluetooth_adapter.h"
14
15#if defined(OS_CHROMEOS)
16#include "device/bluetooth/bluetooth_adapter_chromeos.h"
17#elif defined(OS_WIN)
18#include "device/bluetooth/bluetooth_adapter_win.h"
19#elif defined(OS_MACOSX)
20#include "base/mac/mac_util.h"
21#include "device/bluetooth/bluetooth_adapter_mac.h"
22#endif
23
24namespace {
25
26using device::BluetoothAdapter;
27using device::BluetoothAdapterFactory;
28
29// Shared default adapter instance, we don't want to keep this class around
30// if nobody is using it so use a WeakPtr and create the object when needed;
31// since Google C++ Style (and clang's static analyzer) forbids us having
32// exit-time destructors we use a leaky lazy instance for it.
33base::LazyInstance<base::WeakPtr<device::BluetoothAdapter> >::Leaky
34    default_adapter = LAZY_INSTANCE_INITIALIZER;
35
36typedef std::vector<BluetoothAdapterFactory::AdapterCallback>
37    AdapterCallbackList;
38
39// List of adapter callbacks to be called once the adapter is initialized.
40// Since Google C++ Style (and clang's static analyzer) forbids us having
41// exit-time destructors we use a lazy instance for it.
42base::LazyInstance<AdapterCallbackList> adapter_callbacks =
43    LAZY_INSTANCE_INITIALIZER;
44
45#if defined(OS_WIN)
46void RunAdapterCallbacks() {
47  CHECK(default_adapter.Get().get());
48  scoped_refptr<BluetoothAdapter> adapter(default_adapter.Get().get());
49  for (std::vector<BluetoothAdapterFactory::AdapterCallback>::const_iterator
50           iter = adapter_callbacks.Get().begin();
51       iter != adapter_callbacks.Get().end();
52       ++iter) {
53    iter->Run(adapter);
54  }
55  adapter_callbacks.Get().clear();
56}
57#endif  // defined(OS_WIN)
58
59}  // namespace
60
61namespace device {
62
63// static
64bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() {
65#if defined(OS_CHROMEOS)
66  return true;
67#elif defined(OS_WIN)
68  return true;
69#elif defined(OS_MACOSX)
70  return base::mac::IsOSLionOrLater();
71#endif
72  return false;
73}
74
75// static
76void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) {
77  if (!default_adapter.Get().get()) {
78#if defined(OS_CHROMEOS)
79    chromeos::BluetoothAdapterChromeOS* new_adapter =
80        new chromeos::BluetoothAdapterChromeOS();
81    default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
82#elif defined(OS_WIN)
83    BluetoothAdapterWin* new_adapter = new BluetoothAdapterWin(
84        base::Bind(&RunAdapterCallbacks));
85    new_adapter->Init();
86    default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
87#elif defined(OS_MACOSX)
88    BluetoothAdapterMac* new_adapter = new BluetoothAdapterMac();
89    new_adapter->Init();
90    default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
91#endif
92  }
93
94  if (default_adapter.Get()->IsInitialized()) {
95    callback.Run(scoped_refptr<BluetoothAdapter>(default_adapter.Get().get()));
96  } else {
97    adapter_callbacks.Get().push_back(callback);
98  }
99}
100
101// static
102scoped_refptr<BluetoothAdapter> BluetoothAdapterFactory::MaybeGetAdapter() {
103  return scoped_refptr<BluetoothAdapter>(default_adapter.Get().get());
104}
105
106}  // namespace device
107