blob: a6c025ac5ef1761a1653421aa5d8d95a05f7fb5a [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 "chrome/browser/local_discovery/service_discovery_device_lister.h"
#include <utility>
#include <vector>
#include "base/bind.h"
namespace local_discovery {
ServiceDiscoveryDeviceLister::ServiceDiscoveryDeviceLister(
Delegate* delegate,
ServiceDiscoveryClient* service_discovery_client,
const std::string& service_type)
: delegate_(delegate),
service_discovery_client_(service_discovery_client),
service_type_(service_type) {
}
ServiceDiscoveryDeviceLister::~ServiceDiscoveryDeviceLister() {
}
void ServiceDiscoveryDeviceLister::Start() {
CreateServiceWatcher();
}
void ServiceDiscoveryDeviceLister::DiscoverNewDevices(bool force_update) {
service_watcher_->DiscoverNewServices(force_update);
}
void ServiceDiscoveryDeviceLister::OnServiceUpdated(
ServiceWatcher::UpdateType update,
const std::string& service_name) {
if (update == ServiceWatcher::UPDATE_INVALIDATED) {
resolvers_.clear();
CreateServiceWatcher();
delegate_->OnDeviceCacheFlushed();
return;
}
if (update != ServiceWatcher::UPDATE_REMOVED) {
bool added = (update == ServiceWatcher::UPDATE_ADDED);
std::pair<ServiceResolverMap::iterator, bool> insert_result =
resolvers_.insert(make_pair(service_name,
linked_ptr<ServiceResolver>(NULL)));
// If there is already a resolver working on this service, don't add one.
if (insert_result.second) {
scoped_ptr<ServiceResolver> resolver =
service_discovery_client_->CreateServiceResolver(
service_name, base::Bind(
&ServiceDiscoveryDeviceLister::OnResolveComplete,
base::Unretained(this),
added));
insert_result.first->second.reset(resolver.release());
insert_result.first->second->StartResolving();
}
} else {
delegate_->OnDeviceRemoved(service_name);
}
}
void ServiceDiscoveryDeviceLister::OnResolveComplete(
bool added,
ServiceResolver::RequestStatus status,
const ServiceDescription& service_description) {
if (status != ServiceResolver::STATUS_SUCCESS) {
resolvers_.erase(service_description.service_name);
// TODO(noamsml): Add retry logic.
return;
}
delegate_->OnDeviceChanged(added, service_description);
resolvers_.erase(service_description.service_name);
}
void ServiceDiscoveryDeviceLister::CreateServiceWatcher() {
service_watcher_ =
service_discovery_client_->CreateServiceWatcher(
service_type_,
base::Bind(&ServiceDiscoveryDeviceLister::OnServiceUpdated,
base::Unretained(this)));
service_watcher_->Start();
}
} // namespace local_discovery