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.
5 #include "chrome/browser/local_discovery/service_discovery_device_lister.h"
10 #include "base/bind.h"
11 #include "base/message_loop/message_loop.h"
13 namespace local_discovery {
16 #if defined(OS_MACOSX)
17 const int kMacServiceResolvingIntervalSecs = 60;
21 ServiceDiscoveryDeviceLister::ServiceDiscoveryDeviceLister(
23 ServiceDiscoveryClient* service_discovery_client,
24 const std::string& service_type)
25 : delegate_(delegate),
26 service_discovery_client_(service_discovery_client),
27 service_type_(service_type),
31 ServiceDiscoveryDeviceLister::~ServiceDiscoveryDeviceLister() {
34 void ServiceDiscoveryDeviceLister::Start() {
35 CreateServiceWatcher();
38 void ServiceDiscoveryDeviceLister::DiscoverNewDevices(bool force_update) {
39 service_watcher_->DiscoverNewServices(force_update);
42 void ServiceDiscoveryDeviceLister::OnServiceUpdated(
43 ServiceWatcher::UpdateType update,
44 const std::string& service_name) {
45 if (update == ServiceWatcher::UPDATE_INVALIDATED) {
47 CreateServiceWatcher();
49 delegate_->OnDeviceCacheFlushed();
53 if (update != ServiceWatcher::UPDATE_REMOVED) {
54 bool added = (update == ServiceWatcher::UPDATE_ADDED);
55 std::pair<ServiceResolverMap::iterator, bool> insert_result =
56 resolvers_.insert(make_pair(service_name,
57 linked_ptr<ServiceResolver>(NULL)));
59 // If there is already a resolver working on this service, don't add one.
60 if (insert_result.second) {
61 scoped_ptr<ServiceResolver> resolver =
62 service_discovery_client_->CreateServiceResolver(
63 service_name, base::Bind(
64 &ServiceDiscoveryDeviceLister::OnResolveComplete,
65 weak_factory_.GetWeakPtr(),
69 insert_result.first->second.reset(resolver.release());
70 insert_result.first->second->StartResolving();
73 delegate_->OnDeviceRemoved(service_name);
77 // TODO(noamsml): Update ServiceDiscoveryClient interface to match this.
78 void ServiceDiscoveryDeviceLister::OnResolveComplete(
80 std::string service_name,
81 ServiceResolver::RequestStatus status,
82 const ServiceDescription& service_description) {
83 if (status == ServiceResolver::STATUS_SUCCESS) {
84 delegate_->OnDeviceChanged(added, service_description);
86 #if defined(OS_MACOSX)
87 // On Mac, the Bonjour service does not seem to ever evict a service if a
88 // device is unplugged, so we need to continuously try to resolve the
89 // service to detect non-graceful shutdowns.
90 base::MessageLoop::current()->PostDelayedTask(
92 base::Bind(&ServiceDiscoveryDeviceLister::OnServiceUpdated,
93 weak_factory_.GetWeakPtr(),
94 ServiceWatcher::UPDATE_CHANGED,
95 service_description.service_name),
96 base::TimeDelta::FromSeconds(kMacServiceResolvingIntervalSecs));
99 // TODO(noamsml): Add retry logic.
101 resolvers_.erase(service_name);
104 void ServiceDiscoveryDeviceLister::CreateServiceWatcher() {
106 service_discovery_client_->CreateServiceWatcher(
108 base::Bind(&ServiceDiscoveryDeviceLister::OnServiceUpdated,
109 weak_factory_.GetWeakPtr()));
110 service_watcher_->Start();
113 } // namespace local_discovery