chromium/chrome/browser/ash/policy/core/user_cloud_policy_token_forwarder.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_ASH_POLICY_CORE_USER_CLOUD_POLICY_TOKEN_FORWARDER_H_
#define CHROME_BROWSER_ASH_POLICY_CORE_USER_CLOUD_POLICY_TOKEN_FORWARDER_H_

#include <memory>
#include <optional>

#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/policy/core/common/cloud/cloud_policy_service.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/base/backoff_entry.h"

namespace base {
class Clock;
class RepeatingTimer;
class SequencedTaskRunner;
class TimeDelta;
}  // namespace base

namespace signin {
class PrimaryAccountAccessTokenFetcher;
}

namespace policy {

class UserCloudPolicyManagerAsh;

// A PKS that observes an IdentityManager and mints the policy access
// token for the UserCloudPolicyManagerAsh. First token is fetched when the
// token service becomes ready. After that if needed a new token is fetched when
// the previous one is expected to expire. This service decouples the
// UserCloudPolicyManagerAsh from depending directly on the
// IdentityManager, since it is initialized much earlier.
class UserCloudPolicyTokenForwarder : public KeyedService,
                                      public CloudPolicyService::Observer {
 public:
  // Backoff policy for token fetch retry attempts in case token fetch failed or
  // returned invalid data.
  static const net::BackoffEntry::Policy kFetchTokenRetryBackoffPolicy;

  // Histogram to log errors occurred while fetching OAuth token for child user.
  static constexpr char kUMAChildUserOAuthTokenError[] =
      "Enterprise.UserPolicyChromeOS.ChildUser.OAuthTokenError";

  // The factory of this PKS depends on the factories of these two arguments,
  // so this object will be Shutdown() first and these pointers can be used
  // until that point.
  UserCloudPolicyTokenForwarder(UserCloudPolicyManagerAsh* manager,
                                signin::IdentityManager* identity_manager);

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

  ~UserCloudPolicyTokenForwarder() override;

  // KeyedService:
  void Shutdown() override;

  // CloudPolicyService::Observer:
  void OnCloudPolicyServiceInitializationCompleted() override;
  std::string_view name() const override;

  // Returns whether OAuth token fetch is currently in progress.
  bool IsTokenFetchInProgressForTesting() const;

  // Returns whether next OAuth token refresh is scheduled.
  bool IsTokenRefreshScheduledForTesting() const;

  // Returns delay to next token refresh if it is scheduled.
  std::optional<base::TimeDelta> GetTokenRefreshDelayForTesting() const;

  // Overrides elements responsible for time progression to allow testing.
  // Affects time calculation and timer objects.
  void OverrideTimeForTesting(
      const base::Clock* clock,
      const base::TickClock* tick_clock,
      scoped_refptr<base::SequencedTaskRunner> task_runner);

 private:
  void StartRequest();
  void OnAccessTokenFetchCompleted(GoogleServiceAuthError error,
                                   signin::AccessTokenInfo token_info);

  raw_ptr<UserCloudPolicyManagerAsh> manager_;
  raw_ptr<signin::IdentityManager, DanglingUntriaged> identity_manager_;
  std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
      access_token_fetcher_;

  // Last fetched OAuth token.
  std::optional<signin::AccessTokenInfo> oauth_token_;

  // Timer that measures time to the next OAuth token refresh. Not initialized
  // if token refresh is not scheduled.
  std::unique_ptr<base::RepeatingTimer> refresh_oauth_token_timer_;

  // Backoff for fetch token retry attempts.
  std::unique_ptr<net::BackoffEntry> retry_backoff_;

  // Points to the base::DefaultClock by default.
  raw_ptr<const base::Clock> clock_;

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

}  // namespace policy

#endif  // CHROME_BROWSER_ASH_POLICY_CORE_USER_CLOUD_POLICY_TOKEN_FORWARDER_H_