OLD | NEW |
| (Empty) |
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/extensions/api/mdns/dns_sd_registry.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "base/memory/ptr_util.h" | |
10 #include "base/stl_util.h" | |
11 #include "chrome/browser/extensions/api/mdns/dns_sd_device_lister.h" | |
12 #include "chrome/browser/local_discovery/service_discovery_shared_client.h" | |
13 #include "chrome/common/features.h" | |
14 | |
15 using local_discovery::ServiceDiscoveryClient; | |
16 using local_discovery::ServiceDiscoverySharedClient; | |
17 | |
18 namespace extensions { | |
19 | |
20 namespace { | |
21 // Predicate to test if two discovered services have the same service_name. | |
22 class IsSameServiceName { | |
23 public: | |
24 explicit IsSameServiceName(const DnsSdService& service) : service_(service) {} | |
25 bool operator()(const DnsSdService& other) const { | |
26 return service_.service_name == other.service_name; | |
27 } | |
28 | |
29 private: | |
30 const DnsSdService& service_; | |
31 }; | |
32 } // namespace | |
33 | |
34 DnsSdRegistry::ServiceTypeData::ServiceTypeData( | |
35 std::unique_ptr<DnsSdDeviceLister> lister) | |
36 : ref_count(1), lister_(std::move(lister)) {} | |
37 | |
38 DnsSdRegistry::ServiceTypeData::~ServiceTypeData() {} | |
39 | |
40 void DnsSdRegistry::ServiceTypeData::ListenerAdded() { | |
41 ref_count++; | |
42 } | |
43 | |
44 bool DnsSdRegistry::ServiceTypeData::ListenerRemoved() { | |
45 return --ref_count == 0; | |
46 } | |
47 | |
48 int DnsSdRegistry::ServiceTypeData::GetListenerCount() { | |
49 return ref_count; | |
50 } | |
51 | |
52 bool DnsSdRegistry::ServiceTypeData::UpdateService( | |
53 bool added, const DnsSdService& service) { | |
54 DnsSdRegistry::DnsSdServiceList::iterator it = | |
55 std::find_if(service_list_.begin(), | |
56 service_list_.end(), | |
57 IsSameServiceName(service)); | |
58 // Set to true when a service is updated in or added to the registry. | |
59 bool updated_or_added = added; | |
60 bool known = (it != service_list_.end()); | |
61 if (known) { | |
62 // If added == true, but we still found the service in our cache, then just | |
63 // update the existing entry, but this should not happen! | |
64 DCHECK(!added); | |
65 if (*it != service) { | |
66 *it = service; | |
67 updated_or_added = true; | |
68 } | |
69 } else if (added) { | |
70 service_list_.push_back(service); | |
71 } | |
72 | |
73 VLOG(1) << "UpdateService: " << service.service_name | |
74 << ", added: " << added | |
75 << ", known: " << known | |
76 << ", updated or added: " << updated_or_added; | |
77 return updated_or_added; | |
78 } | |
79 | |
80 bool DnsSdRegistry::ServiceTypeData::RemoveService( | |
81 const std::string& service_name) { | |
82 for (DnsSdRegistry::DnsSdServiceList::iterator it = service_list_.begin(); | |
83 it != service_list_.end(); ++it) { | |
84 if ((*it).service_name == service_name) { | |
85 service_list_.erase(it); | |
86 return true; | |
87 } | |
88 } | |
89 return false; | |
90 } | |
91 | |
92 void DnsSdRegistry::ServiceTypeData::ForceDiscovery() { | |
93 lister_->Discover(false); | |
94 } | |
95 | |
96 bool DnsSdRegistry::ServiceTypeData::ClearServices() { | |
97 lister_->Discover(false); | |
98 | |
99 if (service_list_.empty()) | |
100 return false; | |
101 | |
102 service_list_.clear(); | |
103 return true; | |
104 } | |
105 | |
106 const DnsSdRegistry::DnsSdServiceList& | |
107 DnsSdRegistry::ServiceTypeData::GetServiceList() { | |
108 return service_list_; | |
109 } | |
110 | |
111 DnsSdRegistry::DnsSdRegistry() { | |
112 #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) | |
113 service_discovery_client_ = ServiceDiscoverySharedClient::GetInstance(); | |
114 #endif | |
115 } | |
116 | |
117 DnsSdRegistry::DnsSdRegistry(ServiceDiscoverySharedClient* client) { | |
118 service_discovery_client_ = client; | |
119 } | |
120 | |
121 DnsSdRegistry::~DnsSdRegistry() {} | |
122 | |
123 void DnsSdRegistry::AddObserver(DnsSdObserver* observer) { | |
124 observers_.AddObserver(observer); | |
125 } | |
126 | |
127 void DnsSdRegistry::RemoveObserver(DnsSdObserver* observer) { | |
128 observers_.RemoveObserver(observer); | |
129 } | |
130 | |
131 DnsSdDeviceLister* DnsSdRegistry::CreateDnsSdDeviceLister( | |
132 DnsSdDelegate* delegate, | |
133 const std::string& service_type, | |
134 local_discovery::ServiceDiscoverySharedClient* discovery_client) { | |
135 return new DnsSdDeviceLister(discovery_client, delegate, service_type); | |
136 } | |
137 | |
138 void DnsSdRegistry::Publish(const std::string& service_type) { | |
139 DispatchApiEvent(service_type); | |
140 } | |
141 | |
142 void DnsSdRegistry::ForceDiscovery() { | |
143 for (const auto& next_service : service_data_map_) { | |
144 next_service.second->ForceDiscovery(); | |
145 } | |
146 } | |
147 | |
148 void DnsSdRegistry::RegisterDnsSdListener(const std::string& service_type) { | |
149 VLOG(1) << "RegisterDnsSdListener: " << service_type | |
150 << ", registered: " << IsRegistered(service_type); | |
151 if (service_type.empty()) | |
152 return; | |
153 | |
154 if (IsRegistered(service_type)) { | |
155 service_data_map_[service_type]->ListenerAdded(); | |
156 DispatchApiEvent(service_type); | |
157 return; | |
158 } | |
159 | |
160 std::unique_ptr<DnsSdDeviceLister> dns_sd_device_lister( | |
161 CreateDnsSdDeviceLister(this, service_type, | |
162 service_discovery_client_.get())); | |
163 dns_sd_device_lister->Discover(false); | |
164 service_data_map_[service_type] = | |
165 base::MakeUnique<ServiceTypeData>(std::move(dns_sd_device_lister)); | |
166 DispatchApiEvent(service_type); | |
167 } | |
168 | |
169 void DnsSdRegistry::UnregisterDnsSdListener(const std::string& service_type) { | |
170 VLOG(1) << "UnregisterDnsSdListener: " << service_type; | |
171 auto it = service_data_map_.find(service_type); | |
172 if (it == service_data_map_.end()) | |
173 return; | |
174 | |
175 if (service_data_map_[service_type]->ListenerRemoved()) | |
176 service_data_map_.erase(it); | |
177 } | |
178 | |
179 void DnsSdRegistry::ServiceChanged(const std::string& service_type, | |
180 bool added, | |
181 const DnsSdService& service) { | |
182 VLOG(1) << "ServiceChanged: service_type: " << service_type | |
183 << ", known: " << IsRegistered(service_type) | |
184 << ", service: " << service.service_name | |
185 << ", added: " << added; | |
186 if (!IsRegistered(service_type)) { | |
187 return; | |
188 } | |
189 | |
190 bool is_updated = | |
191 service_data_map_[service_type]->UpdateService(added, service); | |
192 VLOG(1) << "ServiceChanged: is_updated: " << is_updated; | |
193 | |
194 if (is_updated) { | |
195 DispatchApiEvent(service_type); | |
196 } | |
197 } | |
198 | |
199 void DnsSdRegistry::ServiceRemoved(const std::string& service_type, | |
200 const std::string& service_name) { | |
201 VLOG(1) << "ServiceRemoved: service_type: " << service_type | |
202 << ", known: " << IsRegistered(service_type) | |
203 << ", service: " << service_name; | |
204 if (!IsRegistered(service_type)) { | |
205 return; | |
206 } | |
207 | |
208 bool is_removed = | |
209 service_data_map_[service_type]->RemoveService(service_name); | |
210 VLOG(1) << "ServiceRemoved: is_removed: " << is_removed; | |
211 | |
212 if (is_removed) | |
213 DispatchApiEvent(service_type); | |
214 } | |
215 | |
216 void DnsSdRegistry::ServicesFlushed(const std::string& service_type) { | |
217 VLOG(1) << "ServicesFlushed: service_type: " << service_type | |
218 << ", known: " << IsRegistered(service_type); | |
219 if (!IsRegistered(service_type)) { | |
220 return; | |
221 } | |
222 | |
223 bool is_cleared = service_data_map_[service_type]->ClearServices(); | |
224 VLOG(1) << "ServicesFlushed: is_cleared: " << is_cleared; | |
225 | |
226 if (is_cleared) | |
227 DispatchApiEvent(service_type); | |
228 } | |
229 | |
230 void DnsSdRegistry::DispatchApiEvent(const std::string& service_type) { | |
231 VLOG(1) << "DispatchApiEvent: service_type: " << service_type; | |
232 for (auto& observer : observers_) { | |
233 observer.OnDnsSdEvent(service_type, | |
234 service_data_map_[service_type]->GetServiceList()); | |
235 } | |
236 } | |
237 | |
238 bool DnsSdRegistry::IsRegistered(const std::string& service_type) { | |
239 return service_data_map_.find(service_type) != service_data_map_.end(); | |
240 } | |
241 | |
242 } // namespace extensions | |
OLD | NEW |