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/extensions/api/mdns/dns_sd_registry.h"
7 #include "base/stl_util.h"
8 #include "chrome/browser/extensions/api/mdns/dns_sd_device_lister.h"
9 #include "chrome/browser/local_discovery/service_discovery_shared_client.h"
11 using local_discovery::ServiceDiscoveryClient
;
12 using local_discovery::ServiceDiscoverySharedClient
;
14 namespace extensions
{
17 // Predicate to test if two discovered services have the same service_name.
18 class IsSameServiceName
{
20 explicit IsSameServiceName(const DnsSdService
& service
) : service_(service
) {}
21 bool operator()(const DnsSdService
& other
) const {
22 return service_
.service_name
== other
.service_name
;
26 const DnsSdService
& service_
;
30 DnsSdRegistry::ServiceTypeData::ServiceTypeData(
31 scoped_ptr
<DnsSdDeviceLister
> lister
)
32 : ref_count(1), lister_(lister
.Pass()) {}
34 DnsSdRegistry::ServiceTypeData::~ServiceTypeData() {}
36 void DnsSdRegistry::ServiceTypeData::ListenerAdded() {
40 bool DnsSdRegistry::ServiceTypeData::ListenerRemoved() {
41 return --ref_count
== 0;
44 int DnsSdRegistry::ServiceTypeData::GetListenerCount() {
48 bool DnsSdRegistry::ServiceTypeData::UpdateService(
49 bool added
, const DnsSdService
& service
) {
50 DnsSdRegistry::DnsSdServiceList::iterator it
=
51 std::find_if(service_list_
.begin(),
53 IsSameServiceName(service
));
54 // Set to true when a service is updated in or added to the registry.
55 bool updated_or_added
= added
;
56 bool known
= (it
!= service_list_
.end());
58 // If added == true, but we still found the service in our cache, then just
59 // update the existing entry, but this should not happen!
63 updated_or_added
= true;
66 service_list_
.push_back(service
);
69 VLOG(1) << "UpdateService: " << service
.service_name
70 << ", added: " << added
71 << ", known: " << known
72 << ", updated or added: " << updated_or_added
;
73 return updated_or_added
;
76 bool DnsSdRegistry::ServiceTypeData::RemoveService(
77 const std::string
& service_name
) {
78 for (DnsSdRegistry::DnsSdServiceList::iterator it
= service_list_
.begin();
79 it
!= service_list_
.end(); ++it
) {
80 if ((*it
).service_name
== service_name
) {
81 service_list_
.erase(it
);
88 void DnsSdRegistry::ServiceTypeData::ForceDiscovery() {
89 lister_
->Discover(false);
92 bool DnsSdRegistry::ServiceTypeData::ClearServices() {
93 lister_
->Discover(false);
95 if (service_list_
.empty())
98 service_list_
.clear();
102 const DnsSdRegistry::DnsSdServiceList
&
103 DnsSdRegistry::ServiceTypeData::GetServiceList() {
104 return service_list_
;
107 DnsSdRegistry::DnsSdRegistry() {
108 #if defined(ENABLE_SERVICE_DISCOVERY)
109 service_discovery_client_
= ServiceDiscoverySharedClient::GetInstance();
113 DnsSdRegistry::DnsSdRegistry(ServiceDiscoverySharedClient
* client
) {
114 service_discovery_client_
= client
;
117 DnsSdRegistry::~DnsSdRegistry() {}
119 void DnsSdRegistry::AddObserver(DnsSdObserver
* observer
) {
120 observers_
.AddObserver(observer
);
123 void DnsSdRegistry::RemoveObserver(DnsSdObserver
* observer
) {
124 observers_
.RemoveObserver(observer
);
127 DnsSdDeviceLister
* DnsSdRegistry::CreateDnsSdDeviceLister(
128 DnsSdDelegate
* delegate
,
129 const std::string
& service_type
,
130 local_discovery::ServiceDiscoverySharedClient
* discovery_client
) {
131 return new DnsSdDeviceLister(discovery_client
, delegate
, service_type
);
134 void DnsSdRegistry::Publish(const std::string
& service_type
) {
135 DispatchApiEvent(service_type
);
138 void DnsSdRegistry::ForceDiscovery() {
139 for (const auto& next_service
: service_data_map_
) {
140 next_service
.second
->ForceDiscovery();
144 void DnsSdRegistry::RegisterDnsSdListener(const std::string
& service_type
) {
145 VLOG(1) << "RegisterDnsSdListener: " << service_type
146 << ", registered: " << IsRegistered(service_type
);
147 if (service_type
.empty())
150 if (IsRegistered(service_type
)) {
151 service_data_map_
[service_type
]->ListenerAdded();
152 DispatchApiEvent(service_type
);
156 scoped_ptr
<DnsSdDeviceLister
> dns_sd_device_lister(CreateDnsSdDeviceLister(
157 this, service_type
, service_discovery_client_
.get()));
158 dns_sd_device_lister
->Discover(false);
159 linked_ptr
<ServiceTypeData
> service_type_data(
160 new ServiceTypeData(dns_sd_device_lister
.Pass()));
161 service_data_map_
[service_type
] = service_type_data
;
162 DispatchApiEvent(service_type
);
165 void DnsSdRegistry::UnregisterDnsSdListener(const std::string
& service_type
) {
166 VLOG(1) << "UnregisterDnsSdListener: " << service_type
;
167 DnsSdRegistry::DnsSdServiceTypeDataMap::iterator it
=
168 service_data_map_
.find(service_type
);
169 if (it
== service_data_map_
.end())
172 if (service_data_map_
[service_type
]->ListenerRemoved())
173 service_data_map_
.erase(it
);
176 void DnsSdRegistry::ServiceChanged(const std::string
& service_type
,
178 const DnsSdService
& service
) {
179 VLOG(1) << "ServiceChanged: service_type: " << service_type
180 << ", known: " << IsRegistered(service_type
)
181 << ", service: " << service
.service_name
182 << ", added: " << added
;
183 if (!IsRegistered(service_type
)) {
188 service_data_map_
[service_type
]->UpdateService(added
, service
);
189 VLOG(1) << "ServiceChanged: is_updated: " << is_updated
;
192 DispatchApiEvent(service_type
);
196 void DnsSdRegistry::ServiceRemoved(const std::string
& service_type
,
197 const std::string
& service_name
) {
198 VLOG(1) << "ServiceRemoved: service_type: " << service_type
199 << ", known: " << IsRegistered(service_type
)
200 << ", service: " << service_name
;
201 if (!IsRegistered(service_type
)) {
206 service_data_map_
[service_type
]->RemoveService(service_name
);
207 VLOG(1) << "ServiceRemoved: is_removed: " << is_removed
;
210 DispatchApiEvent(service_type
);
213 void DnsSdRegistry::ServicesFlushed(const std::string
& service_type
) {
214 VLOG(1) << "ServicesFlushed: service_type: " << service_type
215 << ", known: " << IsRegistered(service_type
);
216 if (!IsRegistered(service_type
)) {
220 bool is_cleared
= service_data_map_
[service_type
]->ClearServices();
221 VLOG(1) << "ServicesFlushed: is_cleared: " << is_cleared
;
224 DispatchApiEvent(service_type
);
227 void DnsSdRegistry::DispatchApiEvent(const std::string
& service_type
) {
228 VLOG(1) << "DispatchApiEvent: service_type: " << service_type
;
229 FOR_EACH_OBSERVER(DnsSdObserver
, observers_
, OnDnsSdEvent(
230 service_type
, service_data_map_
[service_type
]->GetServiceList()));
233 bool DnsSdRegistry::IsRegistered(const std::string
& service_type
) {
234 return service_data_map_
.find(service_type
) != service_data_map_
.end();
237 } // namespace extensions