service_discovery_host_client.cc revision bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3
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_host_client.h" 6 7#include "chrome/common/local_discovery/local_discovery_messages.h" 8#include "content/public/browser/browser_thread.h" 9#include "content/public/browser/utility_process_host.h" 10 11namespace local_discovery { 12 13using content::BrowserThread; 14using content::UtilityProcessHost; 15 16class ServiceDiscoveryHostClient::ServiceWatcherProxy : public ServiceWatcher { 17 public: 18 ServiceWatcherProxy(ServiceDiscoveryHostClient* host, 19 const std::string& service_type, 20 const ServiceWatcher::UpdatedCallback& callback) 21 : host_(host), 22 service_type_(service_type), 23 id_(host_->RegisterWatcherCallback(callback)), 24 started_(false) { 25 } 26 27 virtual ~ServiceWatcherProxy() { 28 host_->UnregisterWatcherCallback(id_); 29 if (started_) 30 host_->Send(new LocalDiscoveryMsg_DestroyWatcher(id_)); 31 } 32 33 virtual void Start() OVERRIDE { 34 DCHECK(!started_); 35 host_->Send(new LocalDiscoveryMsg_StartWatcher(id_, service_type_)); 36 started_ = true; 37 } 38 39 virtual void DiscoverNewServices(bool force_update) OVERRIDE { 40 DCHECK(started_); 41 host_->Send(new LocalDiscoveryMsg_DiscoverServices(id_, force_update)); 42 } 43 44 virtual std::string GetServiceType() const OVERRIDE { 45 return service_type_; 46 } 47 48 private: 49 scoped_refptr<ServiceDiscoveryHostClient> host_; 50 const std::string service_type_; 51 const uint64 id_; 52 bool started_; 53}; 54 55class ServiceDiscoveryHostClient::ServiceResolverProxy 56 : public ServiceResolver { 57 public: 58 ServiceResolverProxy(ServiceDiscoveryHostClient* host, 59 const std::string& service_name, 60 const ServiceResolver::ResolveCompleteCallback& callback) 61 : host_(host), 62 service_name_(service_name), 63 id_(host->RegisterResolverCallback(callback)), 64 started_(false) { 65 } 66 67 virtual ~ServiceResolverProxy() { 68 host_->UnregisterResolverCallback(id_); 69 if (started_) 70 host_->Send(new LocalDiscoveryMsg_DestroyResolver(id_)); 71 } 72 73 virtual void StartResolving() OVERRIDE { 74 DCHECK(!started_); 75 host_->Send(new LocalDiscoveryMsg_ResolveService(id_, service_name_)); 76 started_ = true; 77 } 78 79 virtual std::string GetName() const OVERRIDE { 80 return service_name_; 81 } 82 83 private: 84 scoped_refptr<ServiceDiscoveryHostClient> host_; 85 const std::string service_name_; 86 const uint64 id_; 87 bool started_; 88}; 89 90class ServiceDiscoveryHostClient::LocalDomainResolverProxy 91 : public LocalDomainResolver { 92 public: 93 LocalDomainResolverProxy(ServiceDiscoveryHostClient* host, 94 const std::string& domain, 95 net::AddressFamily address_family, 96 const LocalDomainResolver::IPAddressCallback& callback) 97 : host_(host), 98 domain_(domain), 99 address_family_(address_family), 100 id_(host->RegisterLocalDomainResolverCallback(callback)), 101 started_(false) { 102 } 103 104 virtual ~LocalDomainResolverProxy() { 105 host_->UnregisterLocalDomainResolverCallback(id_); 106 if (started_) 107 host_->Send(new LocalDiscoveryMsg_DestroyLocalDomainResolver(id_)); 108 } 109 110 virtual void Start() OVERRIDE { 111 DCHECK(!started_); 112 host_->Send(new LocalDiscoveryMsg_ResolveLocalDomain(id_, domain_, 113 address_family_)); 114 started_ = true; 115 } 116 117 private: 118 scoped_refptr<ServiceDiscoveryHostClient> host_; 119 std::string domain_; 120 net::AddressFamily address_family_; 121 const uint64 id_; 122 bool started_; 123}; 124 125ServiceDiscoveryHostClient::ServiceDiscoveryHostClient() : current_id_(0) { 126 callback_runner_ = base::MessageLoop::current()->message_loop_proxy(); 127} 128 129ServiceDiscoveryHostClient::~ServiceDiscoveryHostClient() { 130 DCHECK(CalledOnValidThread()); 131 DCHECK(service_watcher_callbacks_.empty()); 132 DCHECK(service_resolver_callbacks_.empty()); 133} 134 135scoped_ptr<ServiceWatcher> ServiceDiscoveryHostClient::CreateServiceWatcher( 136 const std::string& service_type, 137 const ServiceWatcher::UpdatedCallback& callback) { 138 DCHECK(CalledOnValidThread()); 139 return scoped_ptr<ServiceWatcher>( 140 new ServiceWatcherProxy(this, service_type, callback)); 141} 142 143scoped_ptr<ServiceResolver> ServiceDiscoveryHostClient::CreateServiceResolver( 144 const std::string& service_name, 145 const ServiceResolver::ResolveCompleteCallback& callback) { 146 DCHECK(CalledOnValidThread()); 147 return scoped_ptr<ServiceResolver>( 148 new ServiceResolverProxy(this, service_name, callback)); 149} 150 151scoped_ptr<LocalDomainResolver> 152ServiceDiscoveryHostClient::CreateLocalDomainResolver( 153 const std::string& domain, 154 net::AddressFamily address_family, 155 const LocalDomainResolver::IPAddressCallback& callback) { 156 DCHECK(CalledOnValidThread()); 157 return scoped_ptr<LocalDomainResolver>(new LocalDomainResolverProxy( 158 this, domain, address_family, callback)); 159} 160 161uint64 ServiceDiscoveryHostClient::RegisterWatcherCallback( 162 const ServiceWatcher::UpdatedCallback& callback) { 163 DCHECK(CalledOnValidThread()); 164 DCHECK(!ContainsKey(service_watcher_callbacks_, current_id_ + 1)); 165 service_watcher_callbacks_[++current_id_] = callback; 166 return current_id_; 167} 168 169uint64 ServiceDiscoveryHostClient::RegisterResolverCallback( 170 const ServiceResolver::ResolveCompleteCallback& callback) { 171 DCHECK(CalledOnValidThread()); 172 DCHECK(!ContainsKey(service_resolver_callbacks_, current_id_ + 1)); 173 service_resolver_callbacks_[++current_id_] = callback; 174 return current_id_; 175} 176 177uint64 ServiceDiscoveryHostClient::RegisterLocalDomainResolverCallback( 178 const LocalDomainResolver::IPAddressCallback& callback) { 179 DCHECK(CalledOnValidThread()); 180 DCHECK(!ContainsKey(domain_resolver_callbacks_, current_id_ + 1)); 181 domain_resolver_callbacks_[++current_id_] = callback; 182 return current_id_; 183} 184 185void ServiceDiscoveryHostClient::UnregisterWatcherCallback(uint64 id) { 186 DCHECK(CalledOnValidThread()); 187 DCHECK(ContainsKey(service_watcher_callbacks_, id)); 188 service_watcher_callbacks_.erase(id); 189} 190 191void ServiceDiscoveryHostClient::UnregisterResolverCallback(uint64 id) { 192 DCHECK(CalledOnValidThread()); 193 DCHECK(ContainsKey(service_resolver_callbacks_, id)); 194 service_resolver_callbacks_.erase(id); 195} 196 197void ServiceDiscoveryHostClient::UnregisterLocalDomainResolverCallback( 198 uint64 id) { 199 DCHECK(CalledOnValidThread()); 200 DCHECK(ContainsKey(domain_resolver_callbacks_, id)); 201 domain_resolver_callbacks_.erase(id); 202} 203 204void ServiceDiscoveryHostClient::Start() { 205 DCHECK(CalledOnValidThread()); 206 BrowserThread::PostTask( 207 BrowserThread::IO, 208 FROM_HERE, 209 base::Bind(&ServiceDiscoveryHostClient::StartOnIOThread, this)); 210} 211 212void ServiceDiscoveryHostClient::Shutdown() { 213 DCHECK(CalledOnValidThread()); 214 BrowserThread::PostTask( 215 BrowserThread::IO, 216 FROM_HERE, 217 base::Bind(&ServiceDiscoveryHostClient::ShutdownOnIOThread, this)); 218} 219 220void ServiceDiscoveryHostClient::StartOnIOThread() { 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 222 utility_host_ = UtilityProcessHost::Create( 223 this, base::MessageLoopProxy::current().get())->AsWeakPtr(); 224 if (utility_host_) { 225 utility_host_->EnableZygote(); 226 utility_host_->EnableMDns(); 227 utility_host_->StartBatchMode(); 228 } 229} 230 231void ServiceDiscoveryHostClient::ShutdownOnIOThread() { 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 233 if (utility_host_) 234 utility_host_->EndBatchMode(); 235} 236 237void ServiceDiscoveryHostClient::Send(IPC::Message* msg) { 238 DCHECK(CalledOnValidThread()); 239 BrowserThread::PostTask( 240 BrowserThread::IO, 241 FROM_HERE, 242 base::Bind(&ServiceDiscoveryHostClient::SendOnIOThread, this, msg)); 243} 244 245void ServiceDiscoveryHostClient::SendOnIOThread(IPC::Message* msg) { 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 247 if (utility_host_) 248 utility_host_->Send(msg); 249} 250 251bool ServiceDiscoveryHostClient::OnMessageReceived( 252 const IPC::Message& message) { 253 bool handled = true; 254 IPC_BEGIN_MESSAGE_MAP(ServiceDiscoveryHostClient, message) 255 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_WatcherCallback, 256 OnWatcherCallback) 257 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_ResolverCallback, 258 OnResolverCallback) 259 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_LocalDomainResolverCallback, 260 OnLocalDomainResolverCallback) 261 IPC_MESSAGE_UNHANDLED(handled = false) 262 IPC_END_MESSAGE_MAP() 263 return handled; 264} 265 266void ServiceDiscoveryHostClient::OnWatcherCallback( 267 uint64 id, 268 ServiceWatcher::UpdateType update, 269 const std::string& service_name) { 270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 271 callback_runner_->PostTask( 272 FROM_HERE, 273 base::Bind(&ServiceDiscoveryHostClient::RunWatcherCallback, this, id, 274 update, service_name)); 275} 276 277void ServiceDiscoveryHostClient::OnResolverCallback( 278 uint64 id, 279 ServiceResolver::RequestStatus status, 280 const ServiceDescription& description) { 281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 282 callback_runner_->PostTask( 283 FROM_HERE, 284 base::Bind(&ServiceDiscoveryHostClient::RunResolverCallback, this, id, 285 status, description)); 286} 287 288void ServiceDiscoveryHostClient::OnLocalDomainResolverCallback( 289 uint64 id, 290 bool success, 291 const net::IPAddressNumber& ip_address) { 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 293 callback_runner_->PostTask( 294 FROM_HERE, 295 base::Bind(&ServiceDiscoveryHostClient::RunLocalDomainResolverCallback, 296 this, id, success, ip_address)); 297} 298 299void ServiceDiscoveryHostClient::RunWatcherCallback( 300 uint64 id, 301 ServiceWatcher::UpdateType update, 302 const std::string& service_name) { 303 DCHECK(CalledOnValidThread()); 304 WatcherCallbacks::iterator it = service_watcher_callbacks_.find(id); 305 if (it != service_watcher_callbacks_.end() && !it->second.is_null()) 306 it->second.Run(update, service_name); 307} 308 309void ServiceDiscoveryHostClient::RunResolverCallback( 310 uint64 id, 311 ServiceResolver::RequestStatus status, 312 const ServiceDescription& description) { 313 DCHECK(CalledOnValidThread()); 314 ResolverCallbacks::iterator it = service_resolver_callbacks_.find(id); 315 if (it != service_resolver_callbacks_.end() && !it->second.is_null()) 316 it->second.Run(status, description); 317} 318 319void ServiceDiscoveryHostClient::RunLocalDomainResolverCallback( 320 uint64 id, 321 bool success, 322 const net::IPAddressNumber& ip_address) { 323 DCHECK(CalledOnValidThread()); 324 DomainResolverCallbacks::iterator it = domain_resolver_callbacks_.find(id); 325 if (it != domain_resolver_callbacks_.end() && !it->second.is_null()) 326 it->second.Run(success, ip_address); 327} 328 329} // namespace local_discovery 330