Home | History | Annotate | Download | only in geolocation
      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
     17 void WifiDataProvider::SetFactory(ImplFactoryFunction factory_function_in) {
     18   factory_function_ = factory_function_in;
     19 }
     20 
     21 // static
     22 void WifiDataProvider::ResetFactory() {
     23   factory_function_ = DefaultFactoryFunction;
     24 }
     25 
     26 // static
     27 WifiDataProvider* 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
     43 bool 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 
     60 WifiDataProviderImplBase::WifiDataProviderImplBase()
     61     : container_(NULL),
     62       client_loop_(base::MessageLoop::current()) {
     63   DCHECK(client_loop_);
     64 }
     65 
     66 WifiDataProviderImplBase::~WifiDataProviderImplBase() {
     67 }
     68 
     69 void WifiDataProviderImplBase::SetContainer(WifiDataProvider* container) {
     70   container_ = container;
     71 }
     72 
     73 void WifiDataProviderImplBase::AddCallback(WifiDataUpdateCallback* callback) {
     74   callbacks_.insert(callback);
     75 }
     76 
     77 bool WifiDataProviderImplBase::RemoveCallback(
     78     WifiDataUpdateCallback* callback) {
     79   return callbacks_.erase(callback) == 1;
     80 }
     81 
     82 bool WifiDataProviderImplBase::has_callbacks() const {
     83   return !callbacks_.empty();
     84 }
     85 
     86 void WifiDataProviderImplBase::RunCallbacks() {
     87   client_loop_->PostTask(FROM_HERE, base::Bind(
     88       &WifiDataProviderImplBase::DoRunCallbacks,
     89       this));
     90 }
     91 
     92 bool WifiDataProviderImplBase::CalledOnClientThread() const {
     93   return base::MessageLoop::current() == this->client_loop_;
     94 }
     95 
     96 base::MessageLoop* WifiDataProviderImplBase::client_loop() const {
     97   return client_loop_;
     98 }
     99 
    100 void 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 
    111 WifiDataProvider::WifiDataProvider() {
    112   DCHECK(factory_function_);
    113   impl_ = (*factory_function_)();
    114   DCHECK(impl_.get());
    115   impl_->SetContainer(this);
    116 }
    117 
    118 WifiDataProvider::~WifiDataProvider() {
    119   DCHECK(impl_.get());
    120   impl_->SetContainer(NULL);
    121 }
    122 
    123 bool WifiDataProvider::GetData(WifiData* data) {
    124   return impl_->GetData(data);
    125 }
    126 
    127 void WifiDataProvider::AddCallback(WifiDataUpdateCallback* callback) {
    128   impl_->AddCallback(callback);
    129 }
    130 
    131 bool WifiDataProvider::RemoveCallback(WifiDataUpdateCallback* callback) {
    132   return impl_->RemoveCallback(callback);
    133 }
    134 
    135 bool WifiDataProvider::has_callbacks() const {
    136   return impl_->has_callbacks();
    137 }
    138 
    139 void WifiDataProvider::StartDataProvider() {
    140   impl_->StartDataProvider();
    141 }
    142 
    143 void WifiDataProvider::StopDataProvider() {
    144   impl_->StopDataProvider();
    145 }
    146 
    147 }  // namespace content
    148