service_discovery_device_lister.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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 "chrome/browser/local_discovery/service_discovery_device_lister.h"
6
7#include <utility>
8#include <vector>
9
10#include "base/bind.h"
11
12namespace local_discovery {
13
14ServiceDiscoveryDeviceLister::ServiceDiscoveryDeviceLister(
15    Delegate* delegate,
16    ServiceDiscoveryClient* service_discovery_client,
17    const std::string& service_type)
18    : delegate_(delegate),
19      service_discovery_client_(service_discovery_client),
20      service_type_(service_type) {
21}
22
23ServiceDiscoveryDeviceLister::~ServiceDiscoveryDeviceLister() {
24}
25
26void ServiceDiscoveryDeviceLister::Start() {
27  CreateServiceWatcher();
28}
29
30void ServiceDiscoveryDeviceLister::DiscoverNewDevices(bool force_update) {
31  service_watcher_->DiscoverNewServices(force_update);
32}
33
34void ServiceDiscoveryDeviceLister::OnServiceUpdated(
35    ServiceWatcher::UpdateType update,
36    const std::string& service_name) {
37  if (update == ServiceWatcher::UPDATE_INVALIDATED) {
38    resolvers_.clear();
39    CreateServiceWatcher();
40
41    delegate_->OnDeviceCacheFlushed();
42    return;
43  }
44
45  if (update != ServiceWatcher::UPDATE_REMOVED) {
46    bool added = (update == ServiceWatcher::UPDATE_ADDED);
47    std::pair<ServiceResolverMap::iterator, bool> insert_result =
48        resolvers_.insert(make_pair(service_name,
49                                    linked_ptr<ServiceResolver>(NULL)));
50
51    // If there is already a resolver working on this service, don't add one.
52    if (insert_result.second) {
53      scoped_ptr<ServiceResolver> resolver =
54          service_discovery_client_->CreateServiceResolver(
55          service_name, base::Bind(
56              &ServiceDiscoveryDeviceLister::OnResolveComplete,
57              base::Unretained(this),
58              added));
59
60      insert_result.first->second.reset(resolver.release());
61      insert_result.first->second->StartResolving();
62    }
63  } else {
64    delegate_->OnDeviceRemoved(service_name);
65  }
66}
67
68void ServiceDiscoveryDeviceLister::OnResolveComplete(
69    bool added,
70    ServiceResolver::RequestStatus status,
71    const ServiceDescription& service_description) {
72  if (status != ServiceResolver::STATUS_SUCCESS) {
73    resolvers_.erase(service_description.service_name);
74
75    // TODO(noamsml): Add retry logic.
76    return;
77  }
78
79  delegate_->OnDeviceChanged(added, service_description);
80  resolvers_.erase(service_description.service_name);
81}
82
83void ServiceDiscoveryDeviceLister::CreateServiceWatcher() {
84  service_watcher_ =
85      service_discovery_client_->CreateServiceWatcher(
86          service_type_,
87          base::Bind(&ServiceDiscoveryDeviceLister::OnServiceUpdated,
88                     base::Unretained(this)));
89  service_watcher_->Start();
90}
91
92}  // namespace local_discovery
93