chromium/ash/webui/eche_app_ui/apps_access_manager.h

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

#ifndef ASH_WEBUI_ECHE_APP_UI_APPS_ACCESS_MANAGER_H_
#define ASH_WEBUI_ECHE_APP_UI_APPS_ACCESS_MANAGER_H_

#include <ostream>

#include "ash/webui/eche_app_ui/apps_access_setup_operation.h"
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "chromeos/ash/components/phonehub/multidevice_feature_access_manager.h"

namespace ash {
namespace eche_app {

// Histogram for tracking Phone Hub Apps setup requests.
constexpr char kEcheOnboardingHistogramName[] = "Eche.Onboarding.UserAction";

using AccessStatus =
    ash::phonehub::MultideviceFeatureAccessManager::AccessStatus;
// Tracks the status of whether the user has enabled apps access on
// their phones.
class AppsAccessManager {
 public:
  // Note: Numerical values should not be changed, they are persisted to logs
  // and should not be renumbered or re-used. See
  // tools/metrics/histograms/enums.xml.
  enum class OnboardingUserActionMetric {
    // Initial state.
    kUserActionUnknown = 0,

    // Onboarding is started by user action.
    kUserActionStartClicked = 1,

    // The permission is granted by user action.
    kUserActionPermissionGranted = 2,

    // Users explicitly decline the permission request.
    kUserActionPermissionRejected = 3,

    // The permission request time out after 20 seconds.
    kUserActionTimeout = 4,

    // The permission request is canceled from the remote device, e.g. device
    // screen off.
    kUserActionRemoteInterrupt = 5,

    // System exceptions thrown out.
    kSystemError = 6,

    // The permission request is canceled from the onboarding UI.
    kUserActionCanceled = 7,

    // The permission request is canceled when the device is disconnected.
    kFailedConnection = 8,

    // The permission request is delivered to phone's Exo package.
    kAckByExo = 9,

    kMaxValue = kAckByExo
  };

  class Observer : public base::CheckedObserver {
   public:
    ~Observer() override = default;

    // Called when apps access has changed; use OnAppsAccessChanged()
    // for the new status.
    virtual void OnAppsAccessChanged() = 0;
  };

  AppsAccessManager(const AppsAccessManager&) = delete;
  AppsAccessManager& operator=(const AppsAccessManager&) = delete;
  virtual ~AppsAccessManager();

  virtual AccessStatus GetAccessStatus() const = 0;
  virtual void NotifyAppsAccessCanceled() = 0;

  // Starts an attempt to enable the apps access.
  std::unique_ptr<AppsAccessSetupOperation> AttemptAppsAccessSetup(
      AppsAccessSetupOperation::Delegate* delegate);
  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);
  void NotifyAppsAccessChanged();

 protected:
  AppsAccessManager();

  void SetAppsSetupOperationStatus(AppsAccessSetupOperation::Status new_status);

  bool IsSetupOperationInProgress() const;
  virtual void OnSetupRequested() = 0;

 private:
  friend class AppsAccessManagerImplTest;
  virtual void SetAccessStatusInternal(AccessStatus access_status) = 0;
  void OnSetupOperationDeleted(int operation_id);

  int next_operation_id_ = 0;
  base::flat_map<int, AppsAccessSetupOperation*> id_to_operation_map_;
  base::ObserverList<Observer> observer_list_;
  base::WeakPtrFactory<AppsAccessManager> weak_ptr_factory_{this};
};

}  // namespace eche_app
}  // namespace ash

#endif  // ASH_WEBUI_ECHE_APP_UI_APPS_ACCESS_MANAGER_H_