blob: 416ecb8e52f1cea08ba091cdd9cb43769a2ba8da [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/geolocation/wifi_data_provider.h"
namespace content {
// static
WifiDataProvider* WifiDataProvider::instance_ = NULL;
// static
WifiDataProvider::ImplFactoryFunction WifiDataProvider::factory_function_ =
DefaultFactoryFunction;
// static
WifiDataProvider* WifiDataProvider::Register(WifiDataUpdateCallback* callback) {
bool need_to_start_data_provider = false;
if (!instance_) {
instance_ = new WifiDataProvider();
need_to_start_data_provider = true;
}
DCHECK(instance_);
instance_->AddCallback(callback);
// Start the provider after adding the callback, to avoid any race in
// it running early.
if (need_to_start_data_provider)
instance_->StartDataProvider();
return instance_;
}
WifiDataProviderImplBase::WifiDataProviderImplBase()
: container_(NULL),
client_loop_(base::MessageLoop::current()) {
DCHECK(client_loop_);
}
WifiDataProviderImplBase::~WifiDataProviderImplBase() {
}
void WifiDataProviderImplBase::SetContainer(WifiDataProvider* container) {
container_ = container;
}
void WifiDataProviderImplBase::AddCallback(WifiDataUpdateCallback* callback) {
callbacks_.insert(callback);
}
bool WifiDataProviderImplBase::RemoveCallback(
WifiDataUpdateCallback* callback) {
return callbacks_.erase(callback) == 1;
}
bool WifiDataProviderImplBase::has_callbacks() const {
return !callbacks_.empty();
}
void WifiDataProviderImplBase::RunCallbacks() {
client_loop_->PostTask(FROM_HERE, base::Bind(
&WifiDataProviderImplBase::DoRunCallbacks,
this));
}
bool WifiDataProviderImplBase::CalledOnClientThread() const {
return base::MessageLoop::current() == this->client_loop_;
}
base::MessageLoop* WifiDataProviderImplBase::client_loop() const {
return client_loop_;
}
void WifiDataProviderImplBase::DoRunCallbacks() {
// It's possible that all the callbacks (and the container) went away
// whilst this task was pending. This is fine; the loop will be a no-op.
CallbackSet::const_iterator iter = callbacks_.begin();
while (iter != callbacks_.end()) {
WifiDataUpdateCallback* callback = *iter;
++iter; // Advance iter before running, in case callback unregisters.
callback->Run(container_);
}
}
WifiDataProvider::WifiDataProvider() {
DCHECK(factory_function_);
impl_ = (*factory_function_)();
DCHECK(impl_.get());
impl_->SetContainer(this);
}
WifiDataProvider::~WifiDataProvider() {
DCHECK(impl_.get());
impl_->SetContainer(NULL);
}
} // namespace content