chromium/chrome/browser/ash/smb_client/smb_share_finder.h

// Copyright 2018 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_ASH_SMB_CLIENT_SMB_SHARE_FINDER_H_
#define CHROME_BROWSER_ASH_SMB_CLIENT_SMB_SHARE_FINDER_H_

#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ash/smb_client/discovery/host_locator.h"
#include "chrome/browser/ash/smb_client/discovery/network_scanner.h"
#include "chrome/browser/ash/smb_client/smb_url.h"
#include "chromeos/ash/components/dbus/smbprovider/smb_provider_client.h"

namespace ash::smb_client {

// The callback run to indicate the scan for hosts on the network is complete.
using HostDiscoveryResponse = base::OnceClosure;

// This class is responsible for finding hosts in a network and getting the
// available shares for each host found.
class SmbShareFinder final {
 public:
  // The callback that will be passed to GatherSharesInNetwork.
  using GatherSharesInNetworkResponse =
      base::OnceCallback<void(const std::vector<SmbUrl>& shares_gathered)>;

  explicit SmbShareFinder(SmbProviderClient* client);
  SmbShareFinder(const SmbShareFinder&) = delete;
  SmbShareFinder& operator=(const SmbShareFinder&) = delete;
  ~SmbShareFinder();

  // Gathers the hosts in the network using |scanner_| and gets the shares for
  // each of the hosts found. |discovery_callback| runs once when host
  // disovery is complete. |shares_callback| only runs once when all entries
  // from hosts are stored to |shares| and will contain the paths to the shares
  // found (e.g. "smb://host/share").
  void GatherSharesInNetwork(HostDiscoveryResponse discovery_callback,
                             GatherSharesInNetworkResponse shares_callback);

  // Gathers the hosts in the network using |scanner_|. Runs
  // |discovery_callback| upon completion. No data is returned to the caller,
  // but hosts are cached in |scanner_| and can be used for name resolution.
  void DiscoverHostsInNetwork(HostDiscoveryResponse discovery_callback);

  // Registers HostLocator |locator| to |scanner_|.
  void RegisterHostLocator(std::unique_ptr<HostLocator> locator);

  // Attempts to resolve |url|. Returns the resolved url if successful,
  // otherwise returns |url|.
  SmbUrl GetResolvedUrl(const SmbUrl& url) const;

  // Returns the IP address of |host|. |host| MUST be non-empty. If |host|
  // cannot be resolved, returns the empty/invalid IPAddress.
  net::IPAddress GetResolvedHost(const std::string& host) const;

  // Attempts to resolve |url|. If able to resolve |url|, returns true and sets
  // |resolved_url| the the resolved url. If unable, returns false and sets
  // |resolved_url| to |url|.
  bool TryResolveUrl(const SmbUrl& url, SmbUrl* updated_url) const;

 private:
  // Handles the response from finding hosts in the network.
  void OnHostsFound(bool success, const HostMap& hosts);

  // Handles the response from getting shares for a given host.
  void OnSharesFound(const std::string& host_name,
                     smbprovider::ErrorType error,
                     const smbprovider::DirectoryEntryListProto& entries);

  // Executes all the DiscoveryCallbacks inside |discovery_callbacks_|.
  void RunDiscoveryCallbacks();

  // Executes all the SharesCallback inside |shares_callback_|.
  void RunSharesCallbacks(const std::vector<SmbUrl>& shares);

  // Executes all the SharesCallback inside |shares_callback_| with an empty
  // vector of SmbUrl.
  void RunEmptySharesCallbacks();

  // Inserts HostDiscoveryResponse in |discovery_callbacks_| and inserts
  // GatherSharesInNetworkResponse in |shares_callbacks_|.
  void InsertDiscoveryAndShareCallbacks(
      HostDiscoveryResponse discovery_callback,
      GatherSharesInNetworkResponse shares_callback);

  // Inserts |shares_callback| to |share_callbacks_|.
  void InsertShareCallback(GatherSharesInNetworkResponse shares_callback);

  // Inserts |discovery_callback| to |discovery_callbacks_|.
  void InsertDiscoveryCallback(HostDiscoveryResponse discovery_callback);

  NetworkScanner scanner_;

  raw_ptr<SmbProviderClient, DanglingUntriaged> client_;  // Not owned.

  uint32_t host_counter_ = 0u;

  std::vector<HostDiscoveryResponse> discovery_callbacks_;
  std::vector<GatherSharesInNetworkResponse> share_callbacks_;

  std::vector<SmbUrl> shares_;
  base::WeakPtrFactory<SmbShareFinder> weak_ptr_factory_{this};
};

}  // namespace ash::smb_client

#endif  // CHROME_BROWSER_ASH_SMB_CLIENT_SMB_SHARE_FINDER_H_