- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / local_discovery / service_discovery_device_lister.cc
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 #include "base/message_loop/message_loop.h"
12
13 namespace local_discovery {
14
15 namespace {
16 #if defined(OS_MACOSX)
17 const int kMacServiceResolvingIntervalSecs = 60;
18 #endif
19 }  // namespace
20
21 ServiceDiscoveryDeviceLister::ServiceDiscoveryDeviceLister(
22     Delegate* delegate,
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),
28       weak_factory_(this) {
29 }
30
31 ServiceDiscoveryDeviceLister::~ServiceDiscoveryDeviceLister() {
32 }
33
34 void ServiceDiscoveryDeviceLister::Start() {
35   CreateServiceWatcher();
36 }
37
38 void ServiceDiscoveryDeviceLister::DiscoverNewDevices(bool force_update) {
39   service_watcher_->DiscoverNewServices(force_update);
40 }
41
42 void ServiceDiscoveryDeviceLister::OnServiceUpdated(
43     ServiceWatcher::UpdateType update,
44     const std::string& service_name) {
45   if (update == ServiceWatcher::UPDATE_INVALIDATED) {
46     resolvers_.clear();
47     CreateServiceWatcher();
48
49     delegate_->OnDeviceCacheFlushed();
50     return;
51   }
52
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)));
58
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(),
66               added,
67               service_name));
68
69       insert_result.first->second.reset(resolver.release());
70       insert_result.first->second->StartResolving();
71     }
72   } else {
73     delegate_->OnDeviceRemoved(service_name);
74   }
75 }
76
77 // TODO(noamsml): Update ServiceDiscoveryClient interface to match this.
78 void ServiceDiscoveryDeviceLister::OnResolveComplete(
79     bool added,
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);
85
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(
91         FROM_HERE,
92         base::Bind(&ServiceDiscoveryDeviceLister::OnServiceUpdated,
93                    weak_factory_.GetWeakPtr(),
94                    ServiceWatcher::UPDATE_CHANGED,
95                    service_description.service_name),
96         base::TimeDelta::FromSeconds(kMacServiceResolvingIntervalSecs));
97 #endif
98   } else {
99     // TODO(noamsml): Add retry logic.
100   }
101   resolvers_.erase(service_name);
102 }
103
104 void ServiceDiscoveryDeviceLister::CreateServiceWatcher() {
105   service_watcher_ =
106       service_discovery_client_->CreateServiceWatcher(
107           service_type_,
108           base::Bind(&ServiceDiscoveryDeviceLister::OnServiceUpdated,
109                      weak_factory_.GetWeakPtr()));
110   service_watcher_->Start();
111 }
112
113 }  // namespace local_discovery