Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / api / mdns / dns_sd_registry.cc
blob1a809ff78bcff5ca4549b600694af84db6e40702
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 {
16 namespace {
17 // Predicate to test if two discovered services have the same service_name.
18 class IsSameServiceName {
19 public:
20 explicit IsSameServiceName(const DnsSdService& service) : service_(service) {}
21 bool operator()(const DnsSdService& other) const {
22 return service_.service_name == other.service_name;
25 private:
26 const DnsSdService& service_;
28 } // namespace
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() {
37 ref_count++;
40 bool DnsSdRegistry::ServiceTypeData::ListenerRemoved() {
41 return --ref_count == 0;
44 int DnsSdRegistry::ServiceTypeData::GetListenerCount() {
45 return ref_count;
48 bool DnsSdRegistry::ServiceTypeData::UpdateService(
49 bool added, const DnsSdService& service) {
50 DnsSdRegistry::DnsSdServiceList::iterator it =
51 std::find_if(service_list_.begin(),
52 service_list_.end(),
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());
57 if (known) {
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!
60 DCHECK(!added);
61 if (*it != service) {
62 *it = service;
63 updated_or_added = true;
65 } else if (added) {
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);
82 return true;
85 return false;
88 void DnsSdRegistry::ServiceTypeData::ForceDiscovery() {
89 lister_->Discover(false);
92 bool DnsSdRegistry::ServiceTypeData::ClearServices() {
93 lister_->Discover(false);
95 if (service_list_.empty())
96 return false;
98 service_list_.clear();
99 return true;
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();
110 #endif
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())
148 return;
150 if (IsRegistered(service_type)) {
151 service_data_map_[service_type]->ListenerAdded();
152 DispatchApiEvent(service_type);
153 return;
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())
170 return;
172 if (service_data_map_[service_type]->ListenerRemoved())
173 service_data_map_.erase(it);
176 void DnsSdRegistry::ServiceChanged(const std::string& service_type,
177 bool added,
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)) {
184 return;
187 bool is_updated =
188 service_data_map_[service_type]->UpdateService(added, service);
189 VLOG(1) << "ServiceChanged: is_updated: " << is_updated;
191 if (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)) {
202 return;
205 bool is_removed =
206 service_data_map_[service_type]->RemoveService(service_name);
207 VLOG(1) << "ServiceRemoved: is_removed: " << is_removed;
209 if (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)) {
217 return;
220 bool is_cleared = service_data_map_[service_type]->ClearServices();
221 VLOG(1) << "ServicesFlushed: is_cleared: " << is_cleared;
223 if (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