chromium/chromeos/ash/components/network/shill_property_handler.h

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

#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_SHILL_PROPERTY_HANDLER_H_
#define CHROMEOS_ASH_COMPONENTS_NETWORK_SHILL_PROPERTY_HANDLER_H_

#include <map>
#include <optional>
#include <set>
#include <string>
#include <vector>

#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "chromeos/ash/components/dbus/shill/shill_property_changed_observer.h"
#include "chromeos/ash/components/dbus/shill/shill_service_client.h"
#include "chromeos/ash/components/network/managed_state.h"
#include "chromeos/ash/components/network/network_handler_callbacks.h"
#include "chromeos/dbus/common/dbus_callback.h"

namespace ash {

class ShillManagerClient;

namespace internal {

class ShillPropertyObserver;

// This class handles Shill calls and observers to reflect the state of the
// Shill Manager and its services and devices. It observes Shill.Manager and
// requests properties for new devices/networks. It takes a Listener in its
// constructor (e.g. NetworkStateHandler) that it calls when properties change
// (including once to set their initial state after Init() gets called).
// It also observes Shill.Service for all services in Manager.ServiceWatchList.
// This class must not outlive the ShillManagerClient instance.
class COMPONENT_EXPORT(CHROMEOS_NETWORK) ShillPropertyHandler final
    : public ShillPropertyChangedObserver {
 public:
  typedef std::map<std::string, std::unique_ptr<ShillPropertyObserver>>
      ShillPropertyObserverMap;

  class COMPONENT_EXPORT(CHROMEOS_NETWORK) Listener {
   public:
    // Called when the entries in a managed list have changed.
    virtual void UpdateManagedList(ManagedState::ManagedType type,
                                   const base::Value::List& entries) = 0;

    // Called when the properties for a managed state have changed.
    virtual void UpdateManagedStateProperties(
        ManagedState::ManagedType type,
        const std::string& path,
        const base::Value::Dict& properties) = 0;

    // Called when the list of profiles changes.
    virtual void ProfileListChanged(const base::Value::List& profile_list) = 0;

    // Called when a property for a watched network service has changed.
    virtual void UpdateNetworkServiceProperty(const std::string& service_path,
                                              const std::string& key,
                                              const base::Value& value) = 0;

    // Called when a property for a watched device has changed.
    virtual void UpdateDeviceProperty(const std::string& device_path,
                                      const std::string& key,
                                      const base::Value& value) = 0;

    // Called when a watched network or device IPConfig property changes.
    virtual void UpdateIPConfigProperties(ManagedState::ManagedType type,
                                          const std::string& path,
                                          const std::string& ip_config_path,
                                          base::Value::Dict properties) = 0;

    // Called when the list of devices with portal check enabled changes.
    virtual void CheckPortalListChanged(
        const std::string& check_portal_list) = 0;

    // Called when the DHCP Hostname property changes.
    virtual void HostnameChanged(const std::string& hostname) = 0;

    // Called when a technology list changes.
    virtual void TechnologyListChanged() = 0;

    // Called when a managed state list has changed, after properties for any
    // new entries in the list have been received and
    // UpdateManagedStateProperties has been called for each new entry.
    virtual void ManagedStateListChanged(ManagedState::ManagedType type) = 0;

    // Called when the default network service changes.
    virtual void DefaultNetworkServiceChanged(
        const std::string& service_path) = 0;

   protected:
    virtual ~Listener() {}
  };

  explicit ShillPropertyHandler(Listener* listener);

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

  ~ShillPropertyHandler() override;

  // Sets up the observer and calls UpdateManagerProperties().
  void Init();

  // Requests all Manager properties. Called from Init() and any time
  // properties that do not signal changes might have been updated (e.g.
  // ServiceCompleteList).
  void UpdateManagerProperties();

  // Returns true if |technology| is available, enabled, etc.
  bool IsTechnologyAvailable(const std::string& technology) const;
  bool IsTechnologyEnabled(const std::string& technology) const;
  bool IsTechnologyEnabling(const std::string& technology) const;
  bool IsTechnologyDisabling(const std::string& technology) const;
  bool IsTechnologyProhibited(const std::string& technology) const;
  bool IsTechnologyUninitialized(const std::string& technology) const;

  // Asynchronously sets the enabled state for |technology|.
  // Note: Modifies Manager state. Calls |error_callback| on failure.
  void SetTechnologyEnabled(
      const std::string& technology,
      bool enabled,
      network_handler::ErrorCallback error_callback,
      base::OnceClosure success_callback = base::DoNothing());

  // Asynchronously sets the prohibited state for every network technology
  // listed in |technologies|. Note: Modifies Manager state.
  void SetProhibitedTechnologies(const std::vector<std::string>& technologies);

  // Sets the Manager.WakeOnLan property. Note: we do not track this state, we
  // only set it.
  void SetWakeOnLanEnabled(bool enabled);

  // Sets the HostName property. Note: we do not track this property, we
  // only set it.
  void SetHostname(const std::string& hostname);

  // Calls shill to enable/disable network bandwidth throttling. If |enabled|
  // is true, |upload_rate_kbits| and |download_rate_kbits| specify the rate
  // in kbits/s to throttle to. If |enabled| is false, throttling is disabled
  // and the rates are ignored.
  void SetNetworkThrottlingStatus(bool enabled,
                                  uint32_t upload_rate_kbits,
                                  uint32_t download_rate_kbits);

  // Sets Fast Transition status.
  void SetFastTransitionStatus(bool enabled);

  // Requests an immediate network scan for |type|.
  void RequestScanByType(const std::string& type) const;

  // Requests all properties for the service or device (called for new items).
  void RequestProperties(ManagedState::ManagedType type,
                         const std::string& path);

  // Requests portal detection for |service_path|.
  void RequestPortalDetection(const std::string& service_path);

  // Requests traffic counters for a Service denoted by |service_path|.
  // Traffic counters are returned via |callback|.
  void RequestTrafficCounters(
      const std::string& service_path,
      chromeos::DBusMethodCallback<base::Value> callback);

  // Resets traffic counters for a Service denoted by |service_path|.
  void ResetTrafficCounters(const std::string& service_path);

  // ShillPropertyChangedObserver overrides
  void OnPropertyChanged(const std::string& key,
                         const base::Value& value) override;

 private:
  typedef std::map<ManagedState::ManagedType, std::set<std::string>>
      TypeRequestMap;

  // Callback for dbus method fetching properties.
  void ManagerPropertiesCallback(std::optional<base::Value::Dict> properties);

  // Notifies the listener when a ManagedStateList has changed and all pending
  // updates have been received. |key| can either identify the list that
  // has changed or an empty string if multiple lists may have changed.
  void CheckPendingStateListUpdates(const std::string& key);

  // Called form OnPropertyChanged() and ManagerPropertiesCallback().
  void ManagerPropertyChanged(const std::string& key, const base::Value& value);

  // Requests properties for new entries in the list for |type|.
  void UpdateProperties(ManagedState::ManagedType type,
                        const base::Value& entries);

  // Updates the Shill property observers to observe any entries for |type|.
  void UpdateObserved(ManagedState::ManagedType type,
                      const base::Value& entries);

  // Sets |*_technologies_| to contain only entries in |technologies|.
  void UpdateAvailableTechnologies(const base::Value& technologies);
  void UpdateEnabledTechnologies(const base::Value& technologies);
  void UpdateUninitializedTechnologies(const base::Value& technologies);
  void UpdateProhibitedTechnologies(const std::string& technologies);

  void EnableTechnologySuccess(const std::string& technology,
                               base::OnceClosure success_callback);

  void EnableTechnologyFailed(const std::string& technology,
                              network_handler::ErrorCallback error_callback,
                              const std::string& dbus_error_name,
                              const std::string& dbus_error_message);

  void DisableTechnologySuccess(const std::string& technology,
                                base::OnceClosure success_callback);

  void DisableTechnologyFailed(const std::string& technology,
                               network_handler::ErrorCallback error_callback,
                               const std::string& dbus_error_name,
                               const std::string& dbus_error_message);

  // Called when Shill returns the properties for a service or device.
  void GetPropertiesCallback(ManagedState::ManagedType type,
                             const std::string& path,
                             std::optional<base::Value::Dict> properties);

  // Callback invoked when a watched property changes. Calls appropriate
  // handlers and signals observers.
  void PropertyChangedCallback(ManagedState::ManagedType type,
                               const std::string& path,
                               const std::string& key,
                               const base::Value& value);

  // Request a single IPConfig object corresponding to |ip_config_path_value|
  // from Shill.IPConfigClient and trigger a call to UpdateIPConfigProperties
  // for the network or device corresponding to |type| and |path|.
  void RequestIPConfig(ManagedState::ManagedType type,
                       const std::string& path,
                       const base::Value& ip_config_path_value);

  // Request the IPConfig objects corresponding to entries in
  // |ip_config_list_value| from Shill.IPConfigClient and trigger a call to
  // UpdateIPConfigProperties with each object for the network or device
  // corresponding to |type| and |path|.
  void RequestIPConfigsList(ManagedState::ManagedType type,
                            const std::string& path,
                            const base::Value& ip_config_list_value);

  // Callback for getting the IPConfig property of a network or device. Handled
  // here instead of in NetworkState so that all asynchronous requests are done
  // in a single place (also simplifies NetworkState considerably).
  void GetIPConfigCallback(ManagedState::ManagedType type,
                           const std::string& path,
                           const std::string& ip_config_path,
                           std::optional<base::Value::Dict> properties);

  void SetProhibitedTechnologiesEnforced(bool enforced);

  // Pointer to containing class (owns this)
  raw_ptr<Listener> listener_;

  // Convenience pointer for ShillManagerClient
  raw_ptr<ShillManagerClient> shill_manager_;

  // Pending update list for each managed state type
  TypeRequestMap pending_updates_;

  // List of states for which properties have been requested, for each managed
  // state type
  TypeRequestMap requested_updates_;

  // List of network services with Shill property changed observers
  ShillPropertyObserverMap observed_networks_;

  // List of network devices with Shill property changed observers
  ShillPropertyObserverMap observed_devices_;

  // Lists of available / enabled / uninitialized technologies
  std::set<std::string> available_technologies_;
  std::set<std::string> enabled_technologies_;
  std::set<std::string> enabling_technologies_;
  std::set<std::string> disabling_technologies_;
  std::set<std::string> prohibited_technologies_;
  std::set<std::string> uninitialized_technologies_;

  base::WeakPtrFactory<ShillPropertyHandler> weak_ptr_factory_{this};
};

}  // namespace internal
}  // namespace ash

#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_SHILL_PROPERTY_HANDLER_H_