Upstream version 11.40.277.0
[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   VLOG(1) << "DeviceListerStart: service_type: " << service_type_;
36   CreateServiceWatcher();
37 }
38
39 void ServiceDiscoveryDeviceLister::DiscoverNewDevices(bool force_update) {
40   VLOG(1) << "DiscoverNewDevices: service_type: " << service_type_;
41   service_watcher_->DiscoverNewServices(force_update);
42 }
43
44 void ServiceDiscoveryDeviceLister::OnServiceUpdated(
45     ServiceWatcher::UpdateType update,
46     const std::string& service_name) {
47   VLOG(1) << "OnServiceUpdated: service_type: " << service_type_
48           << ", service_name: " << service_name
49           << ", update: " << update;
50   if (update == ServiceWatcher::UPDATE_INVALIDATED) {
51     resolvers_.clear();
52     CreateServiceWatcher();
53
54     delegate_->OnDeviceCacheFlushed();
55     return;
56   }
57
58   if (update != ServiceWatcher::UPDATE_REMOVED) {
59     bool added = (update == ServiceWatcher::UPDATE_ADDED);
60     std::pair<ServiceResolverMap::iterator, bool> insert_result =
61         resolvers_.insert(make_pair(service_name,
62                                     linked_ptr<ServiceResolver>(NULL)));
63
64     // If there is already a resolver working on this service, don't add one.
65     if (insert_result.second) {
66       VLOG(1) << "Adding resolver for service_name: " << service_name;
67       scoped_ptr<ServiceResolver> resolver =
68           service_discovery_client_->CreateServiceResolver(
69           service_name, base::Bind(
70               &ServiceDiscoveryDeviceLister::OnResolveComplete,
71               weak_factory_.GetWeakPtr(),
72               added,
73               service_name));
74
75       insert_result.first->second.reset(resolver.release());
76       insert_result.first->second->StartResolving();
77     } else {
78       VLOG(1) << "Resolver already exists, service_name: " << service_name;
79     }
80   } else {
81     delegate_->OnDeviceRemoved(service_name);
82   }
83 }
84
85 // TODO(noamsml): Update ServiceDiscoveryClient interface to match this.
86 void ServiceDiscoveryDeviceLister::OnResolveComplete(
87     bool added,
88     std::string service_name,
89     ServiceResolver::RequestStatus status,
90     const ServiceDescription& service_description) {
91   VLOG(1) << "OnResolveComplete: service_type: " << service_type_
92           << ", service_name: " << service_name
93           << ", status: " << status;
94   if (status == ServiceResolver::STATUS_SUCCESS) {
95     delegate_->OnDeviceChanged(added, service_description);
96
97 #if defined(OS_MACOSX)
98     // On Mac, the Bonjour service does not seem to ever evict a service if a
99     // device is unplugged, so we need to continuously try to resolve the
100     // service to detect non-graceful shutdowns.
101     base::MessageLoop::current()->PostDelayedTask(
102         FROM_HERE,
103         base::Bind(&ServiceDiscoveryDeviceLister::OnServiceUpdated,
104                    weak_factory_.GetWeakPtr(),
105                    ServiceWatcher::UPDATE_CHANGED,
106                    service_description.service_name),
107         base::TimeDelta::FromSeconds(kMacServiceResolvingIntervalSecs));
108 #endif
109   } else {
110     // TODO(noamsml): Add retry logic.
111   }
112   resolvers_.erase(service_name);
113 }
114
115 void ServiceDiscoveryDeviceLister::CreateServiceWatcher() {
116   service_watcher_ =
117       service_discovery_client_->CreateServiceWatcher(
118           service_type_,
119           base::Bind(&ServiceDiscoveryDeviceLister::OnServiceUpdated,
120                      weak_factory_.GetWeakPtr()));
121   service_watcher_->Start();
122 }
123
124 }  // namespace local_discovery