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#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_H_
6#define CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_H_
7
8#include <string>
9
10#include "base/mac/scoped_nsobject.h"
11#include "base/memory/weak_ptr.h"
12#include "chrome/browser/local_discovery/service_discovery_shared_client.h"
13#include "content/public/browser/browser_thread.h"
14
15namespace base {
16class Thread;
17}
18
19namespace local_discovery {
20
21template <class T>
22class ServiceDiscoveryThreadDeleter {
23 public:
24  inline void operator()(T* t) { t->DeleteSoon(); }
25};
26
27// Implementation of ServiceDiscoveryClient that uses the Bonjour SDK.
28// https://developer.apple.com/library/mac/documentation/Networking/Conceptual/
29// NSNetServiceProgGuide/Articles/BrowsingForServices.html
30class ServiceDiscoveryClientMac : public ServiceDiscoverySharedClient {
31 public:
32  ServiceDiscoveryClientMac();
33
34 private:
35  virtual ~ServiceDiscoveryClientMac();
36
37  // ServiceDiscoveryClient implementation.
38  virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher(
39      const std::string& service_type,
40      const ServiceWatcher::UpdatedCallback& callback) OVERRIDE;
41  virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
42      const std::string& service_name,
43      const ServiceResolver::ResolveCompleteCallback& callback) OVERRIDE;
44  virtual scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver(
45      const std::string& domain,
46      net::AddressFamily address_family,
47      const LocalDomainResolver::IPAddressCallback& callback) OVERRIDE;
48
49  void StartThreadIfNotStarted();
50
51  scoped_ptr<base::Thread> service_discovery_thread_;
52
53  DISALLOW_COPY_AND_ASSIGN(ServiceDiscoveryClientMac);
54};
55
56class ServiceWatcherImplMac : public ServiceWatcher {
57 public:
58  class NetServiceBrowserContainer {
59   public:
60    NetServiceBrowserContainer(
61        const std::string& service_type,
62        const ServiceWatcher::UpdatedCallback& callback,
63        scoped_refptr<base::MessageLoopProxy> service_discovery_runner);
64    ~NetServiceBrowserContainer();
65
66    void Start();
67    void DiscoverNewServices();
68
69    void OnServicesUpdate(ServiceWatcher::UpdateType update,
70                          const std::string& service);
71
72    void DeleteSoon();
73
74   private:
75    void StartOnDiscoveryThread();
76    void DiscoverOnDiscoveryThread();
77
78    bool IsOnServiceDiscoveryThread() {
79      return base::MessageLoopProxy::current() ==
80             service_discovery_runner_.get();
81    }
82
83    std::string service_type_;
84    ServiceWatcher::UpdatedCallback callback_;
85
86    scoped_refptr<base::MessageLoopProxy> callback_runner_;
87    scoped_refptr<base::MessageLoopProxy> service_discovery_runner_;
88
89    base::scoped_nsobject<id> delegate_;
90    base::scoped_nsobject<NSNetServiceBrowser> browser_;
91    base::WeakPtrFactory<NetServiceBrowserContainer> weak_factory_;
92  };
93
94  ServiceWatcherImplMac(
95      const std::string& service_type,
96      const ServiceWatcher::UpdatedCallback& callback,
97      scoped_refptr<base::MessageLoopProxy> service_discovery_runner);
98
99  void OnServicesUpdate(ServiceWatcher::UpdateType update,
100                        const std::string& service);
101
102 private:
103  virtual ~ServiceWatcherImplMac();
104
105  virtual void Start() OVERRIDE;
106  virtual void DiscoverNewServices(bool force_update) OVERRIDE;
107  virtual void SetActivelyRefreshServices(
108      bool actively_refresh_services) OVERRIDE;
109  virtual std::string GetServiceType() const OVERRIDE;
110
111  std::string service_type_;
112  ServiceWatcher::UpdatedCallback callback_;
113  bool started_;
114
115  scoped_ptr<NetServiceBrowserContainer,
116             ServiceDiscoveryThreadDeleter<NetServiceBrowserContainer> >
117      container_;
118  base::WeakPtrFactory<ServiceWatcherImplMac> weak_factory_;
119
120  DISALLOW_COPY_AND_ASSIGN(ServiceWatcherImplMac);
121};
122
123class ServiceResolverImplMac : public ServiceResolver {
124 public:
125  class NetServiceContainer {
126   public:
127    NetServiceContainer(
128        const std::string& service_name,
129        const ServiceResolver::ResolveCompleteCallback& callback,
130        scoped_refptr<base::MessageLoopProxy> service_discovery_runner);
131
132    virtual ~NetServiceContainer();
133
134    void StartResolving();
135
136    void OnResolveUpdate(RequestStatus);
137
138    void SetServiceForTesting(base::scoped_nsobject<NSNetService> service);
139
140    void DeleteSoon();
141
142   private:
143    void StartResolvingOnDiscoveryThread();
144
145    bool IsOnServiceDiscoveryThread() {
146      return base::MessageLoopProxy::current() ==
147             service_discovery_runner_.get();
148    }
149
150    const std::string service_name_;
151    ServiceResolver::ResolveCompleteCallback callback_;
152
153    scoped_refptr<base::MessageLoopProxy> callback_runner_;
154    scoped_refptr<base::MessageLoopProxy> service_discovery_runner_;
155
156    base::scoped_nsobject<id> delegate_;
157    base::scoped_nsobject<NSNetService> service_;
158    ServiceDescription service_description_;
159    base::WeakPtrFactory<NetServiceContainer> weak_factory_;
160  };
161
162  ServiceResolverImplMac(
163      const std::string& service_name,
164      const ServiceResolver::ResolveCompleteCallback& callback,
165      scoped_refptr<base::MessageLoopProxy> service_discovery_runner);
166
167  // Testing methods.
168  NetServiceContainer* GetContainerForTesting();
169
170 private:
171  virtual ~ServiceResolverImplMac();
172
173  virtual void StartResolving() OVERRIDE;
174  virtual std::string GetName() const OVERRIDE;
175
176  void OnResolveComplete(RequestStatus status,
177                         const ServiceDescription& description);
178
179  const std::string service_name_;
180  ServiceResolver::ResolveCompleteCallback callback_;
181  bool has_resolved_;
182
183  scoped_ptr<NetServiceContainer,
184             ServiceDiscoveryThreadDeleter<NetServiceContainer> > container_;
185  base::WeakPtrFactory<ServiceResolverImplMac> weak_factory_;
186
187  DISALLOW_COPY_AND_ASSIGN(ServiceResolverImplMac);
188};
189
190}  // namespace local_discovery
191
192#endif  // CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_H_
193