1 // Copyright 2013 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 "content/browser/geolocation/wifi_data_provider.h" 6 7 namespace content { 8 9 // static 10 WifiDataProvider* WifiDataProvider::instance_ = NULL; 11 12 // static 13 WifiDataProvider::ImplFactoryFunction WifiDataProvider::factory_function_ = 14 DefaultFactoryFunction; 15 16 // static SetFactory(ImplFactoryFunction factory_function_in)17void WifiDataProvider::SetFactory(ImplFactoryFunction factory_function_in) { 18 factory_function_ = factory_function_in; 19 } 20 21 // static ResetFactory()22void WifiDataProvider::ResetFactory() { 23 factory_function_ = DefaultFactoryFunction; 24 } 25 26 // static Register(WifiDataUpdateCallback * callback)27WifiDataProvider* WifiDataProvider::Register(WifiDataUpdateCallback* callback) { 28 bool need_to_start_data_provider = false; 29 if (!instance_) { 30 instance_ = new WifiDataProvider(); 31 need_to_start_data_provider = true; 32 } 33 DCHECK(instance_); 34 instance_->AddCallback(callback); 35 // Start the provider after adding the callback, to avoid any race in 36 // it running early. 37 if (need_to_start_data_provider) 38 instance_->StartDataProvider(); 39 return instance_; 40 } 41 42 // static Unregister(WifiDataUpdateCallback * callback)43bool WifiDataProvider::Unregister(WifiDataUpdateCallback* callback) { 44 DCHECK(instance_); 45 DCHECK(instance_->has_callbacks()); 46 if (!instance_->RemoveCallback(callback)) { 47 return false; 48 } 49 if (!instance_->has_callbacks()) { 50 // Must stop the data provider (and any implementation threads) before 51 // destroying to avoid any race conditions in access to the provider in 52 // the destructor chain. 53 instance_->StopDataProvider(); 54 delete instance_; 55 instance_ = NULL; 56 } 57 return true; 58 } 59 WifiDataProviderImplBase()60WifiDataProviderImplBase::WifiDataProviderImplBase() 61 : container_(NULL), 62 client_loop_(base::MessageLoop::current()) { 63 DCHECK(client_loop_); 64 } 65 ~WifiDataProviderImplBase()66WifiDataProviderImplBase::~WifiDataProviderImplBase() { 67 } 68 SetContainer(WifiDataProvider * container)69void WifiDataProviderImplBase::SetContainer(WifiDataProvider* container) { 70 container_ = container; 71 } 72 AddCallback(WifiDataUpdateCallback * callback)73void WifiDataProviderImplBase::AddCallback(WifiDataUpdateCallback* callback) { 74 callbacks_.insert(callback); 75 } 76 RemoveCallback(WifiDataUpdateCallback * callback)77bool WifiDataProviderImplBase::RemoveCallback( 78 WifiDataUpdateCallback* callback) { 79 return callbacks_.erase(callback) == 1; 80 } 81 has_callbacks() const82bool WifiDataProviderImplBase::has_callbacks() const { 83 return !callbacks_.empty(); 84 } 85 RunCallbacks()86void WifiDataProviderImplBase::RunCallbacks() { 87 client_loop_->PostTask(FROM_HERE, base::Bind( 88 &WifiDataProviderImplBase::DoRunCallbacks, 89 this)); 90 } 91 CalledOnClientThread() const92bool WifiDataProviderImplBase::CalledOnClientThread() const { 93 return base::MessageLoop::current() == this->client_loop_; 94 } 95 client_loop() const96base::MessageLoop* WifiDataProviderImplBase::client_loop() const { 97 return client_loop_; 98 } 99 DoRunCallbacks()100void WifiDataProviderImplBase::DoRunCallbacks() { 101 // It's possible that all the callbacks (and the container) went away 102 // whilst this task was pending. This is fine; the loop will be a no-op. 103 CallbackSet::const_iterator iter = callbacks_.begin(); 104 while (iter != callbacks_.end()) { 105 WifiDataUpdateCallback* callback = *iter; 106 ++iter; // Advance iter before running, in case callback unregisters. 107 callback->Run(container_); 108 } 109 } 110 WifiDataProvider()111WifiDataProvider::WifiDataProvider() { 112 DCHECK(factory_function_); 113 impl_ = (*factory_function_)(); 114 DCHECK(impl_.get()); 115 impl_->SetContainer(this); 116 } 117 ~WifiDataProvider()118WifiDataProvider::~WifiDataProvider() { 119 DCHECK(impl_.get()); 120 impl_->SetContainer(NULL); 121 } 122 GetData(WifiData * data)123bool WifiDataProvider::GetData(WifiData* data) { 124 return impl_->GetData(data); 125 } 126 AddCallback(WifiDataUpdateCallback * callback)127void WifiDataProvider::AddCallback(WifiDataUpdateCallback* callback) { 128 impl_->AddCallback(callback); 129 } 130 RemoveCallback(WifiDataUpdateCallback * callback)131bool WifiDataProvider::RemoveCallback(WifiDataUpdateCallback* callback) { 132 return impl_->RemoveCallback(callback); 133 } 134 has_callbacks() const135bool WifiDataProvider::has_callbacks() const { 136 return impl_->has_callbacks(); 137 } 138 StartDataProvider()139void WifiDataProvider::StartDataProvider() { 140 impl_->StartDataProvider(); 141 } 142 StopDataProvider()143void WifiDataProvider::StopDataProvider() { 144 impl_->StopDataProvider(); 145 } 146 147 } // namespace content 148