15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_factory.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_adapter.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#if defined(OS_MACOSX)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/mac/mac_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace device {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Shared default adapter instance.  We don't want to keep this class around
240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// if nobody is using it, so use a WeakPtr and create the object when needed.
250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Since Google C++ Style (and clang's static analyzer) forbids us having
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// exit-time destructors, we use a leaky lazy instance for it.
270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbase::LazyInstance<base::WeakPtr<BluetoothAdapter> >::Leaky default_adapter =
280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    LAZY_INSTANCE_INITIALIZER;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#if defined(OS_WIN)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef std::vector<BluetoothAdapterFactory::AdapterCallback>
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AdapterCallbackList;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// List of adapter callbacks to be called once the adapter is initialized.
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Since Google C++ Style (and clang's static analyzer) forbids us having
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// exit-time destructors we use a lazy instance for it.
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::LazyInstance<AdapterCallbackList> adapter_callbacks =
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RunAdapterCallbacks() {
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(default_adapter.Get());
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<BluetoothAdapter> adapter(default_adapter.Get().get());
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<BluetoothAdapterFactory::AdapterCallback>::const_iterator
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           iter = adapter_callbacks.Get().begin();
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != adapter_callbacks.Get().end();
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    iter->Run(adapter);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  adapter_callbacks.Get().clear();
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif  // defined(OS_WIN)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() {
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // SetAdapterForTesting() may be used to provide a test or mock adapter
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // instance even on platforms that would otherwise not support it.
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (default_adapter.Get())
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return true;
6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#if defined(OS_CHROMEOS) || defined(OS_WIN)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#elif defined(OS_MACOSX)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::mac::IsOSLionOrLater();
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#else
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#endif
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) {
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(IsBluetoothAdapterAvailable());
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#if defined(OS_WIN)
750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!default_adapter.Get()) {
760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    default_adapter.Get() =
770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        BluetoothAdapter::CreateAdapter(base::Bind(&RunAdapterCallbacks));
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(!default_adapter.Get()->IsInitialized());
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!default_adapter.Get()->IsInitialized())
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_callbacks.Get().push_back(callback);
830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#else  // !defined(OS_WIN)
840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!default_adapter.Get()) {
850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    default_adapter.Get() =
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        BluetoothAdapter::CreateAdapter(BluetoothAdapter::InitCallback());
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(default_adapter.Get()->IsInitialized());
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#endif  // defined(OS_WIN)
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (default_adapter.Get()->IsInitialized())
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    callback.Run(scoped_refptr<BluetoothAdapter>(default_adapter.Get().get()));
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BluetoothAdapterFactory::SetAdapterForTesting(
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<BluetoothAdapter> adapter) {
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  default_adapter.Get() = adapter->GetWeakPtrForTesting();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool BluetoothAdapterFactory::HasSharedInstanceForTesting() {
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return default_adapter.Get();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace device
109