blob: 66f50b75061a820465f84985665453ad0757d486 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS 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 "shill/dbus_manager.h"
#include <base/bind.h>
#include "shill/dbus_service_proxy_interface.h"
#include "shill/error.h"
#include "shill/logging.h"
#include "shill/proxy_factory.h"
using base::Bind;
using base::Unretained;
using std::list;
using std::map;
using std::string;
namespace shill {
namespace {
const int kDefaultRPCTimeoutMS = 30000;
} // namespace
DBusManager::DBusManager()
: proxy_factory_(ProxyFactory::GetInstance()) {}
DBusManager::~DBusManager() {}
void DBusManager::Start() {
SLOG(DBus, 2) << __func__;
if (proxy_.get()) {
return;
}
proxy_.reset(proxy_factory_->CreateDBusServiceProxy());
proxy_->set_name_owner_changed_callback(
Bind(&DBusManager::OnNameOwnerChanged, Unretained(this)));
}
void DBusManager::Stop() {
SLOG(DBus, 2) << __func__;
proxy_.reset();
name_watchers_.clear();
}
void DBusManager::WatchName(const string &name,
const AppearedCallback &on_appear,
const VanishedCallback &on_vanish) {
LOG(INFO) << "DBus watch: " << name;
NameWatcher watcher(on_appear, on_vanish);
name_watchers_[name].push_back(watcher);
Error error;
proxy_->GetNameOwner(
name,
&error,
Bind(&DBusManager::OnGetNameOwnerComplete, Unretained(this), watcher),
kDefaultRPCTimeoutMS);
// Ensures that the watcher gets an initial appear/vanish notification
// regardless of the outcome of the GetNameOwner call.
if (error.IsFailure()) {
OnGetNameOwnerComplete(watcher, string(), error);
}
}
void DBusManager::OnNameOwnerChanged(
const string &name, const string &old_owner, const string &new_owner) {
map<string, list<NameWatcher> >::const_iterator find_it =
name_watchers_.find(name);
if (find_it == name_watchers_.end()) {
return;
}
LOG(INFO) << "DBus name owner changed: " << name
<< "(" << old_owner << "->" << new_owner << ")";
for (list<NameWatcher>::const_iterator it = find_it->second.begin();
it != find_it->second.end(); ++it) {
NotifyNameWatcher(*it, new_owner);
}
}
void DBusManager::OnGetNameOwnerComplete(const NameWatcher &watcher,
const string &unique_name,
const Error &error) {
LOG(INFO) << "DBus name owner: " << unique_name
<< "(" << error.message() << ")";
NotifyNameWatcher(watcher, error.IsSuccess() ? unique_name : string());
}
// static
void DBusManager::NotifyNameWatcher(const NameWatcher &watcher,
const string &owner) {
SLOG(DBus, 2) << __func__ << "(" << owner << ")";
if (owner.empty()) {
if (!watcher.on_vanish.is_null()) {
watcher.on_vanish.Run();
}
} else if (!watcher.on_appear.is_null()) {
watcher.on_appear.Run(owner);
}
}
} // namespace shill