chromium/chrome/browser/local_discovery/service_discovery_client_mac.h

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_H_
#define CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_H_

#import <Foundation/Foundation.h>
#import <Network/Network.h>

#include <memory>
#include <string>

#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "chrome/browser/local_discovery/service_discovery_shared_client.h"

namespace base {
class Thread;
}

@class NetServiceBrowser;
@class NetServiceResolver;

namespace local_discovery {

// Implementation of ServiceDiscoveryClient that uses the Bonjour SDK.
// https://developer.apple.com/library/mac/documentation/Networking/Conceptual/
// NSNetServiceProgGuide/Articles/BrowsingForServices.html
class ServiceDiscoveryClientMac : public ServiceDiscoverySharedClient {
 public:
  ServiceDiscoveryClientMac();

  ServiceDiscoveryClientMac(const ServiceDiscoveryClientMac&) = delete;
  ServiceDiscoveryClientMac& operator=(const ServiceDiscoveryClientMac&) =
      delete;

 private:
  friend class ServiceDiscoveryClientMacTest;

  ~ServiceDiscoveryClientMac() override;

  // ServiceDiscoveryClient implementation.
  std::unique_ptr<ServiceWatcher> CreateServiceWatcher(
      const std::string& service_type,
      ServiceWatcher::UpdatedCallback callback) override;
  std::unique_ptr<ServiceResolver> CreateServiceResolver(
      const std::string& service_name,
      ServiceResolver::ResolveCompleteCallback callback) override;
  std::unique_ptr<LocalDomainResolver> CreateLocalDomainResolver(
      const std::string& domain,
      net::AddressFamily address_family,
      LocalDomainResolver::IPAddressCallback callback) override;

  void StartThreadIfNotStarted();

  std::unique_ptr<base::Thread> service_discovery_thread_;
};

class ServiceWatcherImplMac : public ServiceWatcher {
 public:
  ServiceWatcherImplMac(
      const std::string& service_type,
      ServiceWatcher::UpdatedCallback callback,
      scoped_refptr<base::SingleThreadTaskRunner> service_discovery_runner);

  ServiceWatcherImplMac(const ServiceWatcherImplMac&) = delete;
  ServiceWatcherImplMac& operator=(const ServiceWatcherImplMac&) = delete;

  ~ServiceWatcherImplMac() override;

  void OnServicesUpdate(ServiceWatcher::UpdateType update,
                        const std::string& service);
  void RecordPermissionState(bool permission_granted);

 private:
  void Start() override;
  void DiscoverNewServices() override;
  void SetActivelyRefreshServices(bool actively_refresh_services) override;
  std::string GetServiceType() const override;

  // These members should only be accessed on the object creator's sequence.
  const std::string service_type_;
  ServiceWatcher::UpdatedCallback callback_;
  bool started_ = false;

  scoped_refptr<base::SingleThreadTaskRunner> service_discovery_runner_;

  // TODO(crbug.com/354231463): Remove usage of NetServiceBrowser once the
  // feature media_router::kUseNetworkFrameworkForLocalDiscovery is enabled by
  // default. `nw_browser_` and `browser_` lives on the
  // `service_discovery_runner_`, though they are initialized on the object
  // creator's sequence. They are cleaned up in `StopServiceBrowser()`.
  nw_browser_t __strong nw_browser_;
  NetServiceBrowser* __strong browser_;

  base::WeakPtrFactory<ServiceWatcherImplMac> weak_factory_{this};
};

class ServiceResolverImplMac : public ServiceResolver {
 public:
  ServiceResolverImplMac(
      const std::string& service_name,
      ServiceResolver::ResolveCompleteCallback callback,
      scoped_refptr<base::SingleThreadTaskRunner> service_discovery_runner);

  ServiceResolverImplMac(const ServiceResolverImplMac&) = delete;
  ServiceResolverImplMac& operator=(const ServiceResolverImplMac&) = delete;

  ~ServiceResolverImplMac() override;

 private:
  void StartResolving() override;
  std::string GetName() const override;

  void OnResolveComplete(RequestStatus status,
                         const ServiceDescription& description);

  void StopResolving();

  // These members should only be accessed on the object creator's sequence.
  const std::string service_name_;
  ServiceResolver::ResolveCompleteCallback callback_;
  bool has_resolved_ = false;

  scoped_refptr<base::SingleThreadTaskRunner> service_discovery_runner_;
  // |resolver_| lives on the |service_discovery_runner_|, though it is
  // initialized on the object creator's sequence. It is released in
  // StopResolving().
  NetServiceResolver* __strong resolver_;

  base::WeakPtrFactory<ServiceResolverImplMac> weak_factory_{this};
};

// Parses the data out of the |service|, updating the |description| with the
// results.
void ParseNetService(NSNetService* service, ServiceDescription& description);

}  // namespace local_discovery

#endif  // CHROME_BROWSER_LOCAL_DISCOVERY_SERVICE_DISCOVERY_CLIENT_MAC_H_