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_MACOSX)
16#include "base/mac/mac_util.h"
17#endif
18
19namespace device {
20
21namespace {
22
23// Shared default adapter instance.  We don't want to keep this class around
24// if nobody is using it, so use a WeakPtr and create the object when needed.
25// Since Google C++ Style (and clang's static analyzer) forbids us having
26// exit-time destructors, we use a leaky lazy instance for it.
27base::LazyInstance<base::WeakPtr<BluetoothAdapter> >::Leaky default_adapter =
28    LAZY_INSTANCE_INITIALIZER;
29
30#if defined(OS_WIN)
31typedef std::vector<BluetoothAdapterFactory::AdapterCallback>
32    AdapterCallbackList;
33
34// List of adapter callbacks to be called once the adapter is initialized.
35// Since Google C++ Style (and clang's static analyzer) forbids us having
36// exit-time destructors we use a lazy instance for it.
37base::LazyInstance<AdapterCallbackList> adapter_callbacks =
38    LAZY_INSTANCE_INITIALIZER;
39
40void RunAdapterCallbacks() {
41  DCHECK(default_adapter.Get());
42  scoped_refptr<BluetoothAdapter> adapter(default_adapter.Get().get());
43  for (std::vector<BluetoothAdapterFactory::AdapterCallback>::const_iterator
44           iter = adapter_callbacks.Get().begin();
45       iter != adapter_callbacks.Get().end();
46       ++iter) {
47    iter->Run(adapter);
48  }
49  adapter_callbacks.Get().clear();
50}
51#endif  // defined(OS_WIN)
52
53}  // namespace
54
55// static
56bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() {
57  // SetAdapterForTesting() may be used to provide a test or mock adapter
58  // instance even on platforms that would otherwise not support it.
59  if (default_adapter.Get())
60    return true;
61#if defined(OS_CHROMEOS) || defined(OS_WIN)
62  return true;
63#elif defined(OS_MACOSX)
64  return base::mac::IsOSLionOrLater();
65#else
66  return false;
67#endif
68}
69
70// static
71void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) {
72  DCHECK(IsBluetoothAdapterAvailable());
73
74#if defined(OS_WIN)
75  if (!default_adapter.Get()) {
76    default_adapter.Get() =
77        BluetoothAdapter::CreateAdapter(base::Bind(&RunAdapterCallbacks));
78    DCHECK(!default_adapter.Get()->IsInitialized());
79  }
80
81  if (!default_adapter.Get()->IsInitialized())
82    adapter_callbacks.Get().push_back(callback);
83#else  // !defined(OS_WIN)
84  if (!default_adapter.Get()) {
85    default_adapter.Get() =
86        BluetoothAdapter::CreateAdapter(BluetoothAdapter::InitCallback());
87  }
88
89  DCHECK(default_adapter.Get()->IsInitialized());
90#endif  // defined(OS_WIN)
91
92  if (default_adapter.Get()->IsInitialized())
93    callback.Run(scoped_refptr<BluetoothAdapter>(default_adapter.Get().get()));
94
95}
96
97// static
98void BluetoothAdapterFactory::SetAdapterForTesting(
99    scoped_refptr<BluetoothAdapter> adapter) {
100  default_adapter.Get() = adapter->GetWeakPtrForTesting();
101}
102
103// static
104bool BluetoothAdapterFactory::HasSharedInstanceForTesting() {
105  return default_adapter.Get();
106}
107
108}  // namespace device
109