chromium/chrome/browser/ash/printing/oauth2/authorization_server_data.h

// Copyright 2022 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_PRINTING_OAUTH2_AUTHORIZATION_SERVER_DATA_H_
#define CHROME_BROWSER_ASH_PRINTING_OAUTH2_AUTHORIZATION_SERVER_DATA_H_

#include <memory>
#include <optional>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ash/printing/oauth2/http_exchange.h"
#include "chrome/browser/ash/printing/oauth2/status_code.h"
#include "url/gurl.h"

namespace network {
class SharedURLLoaderFactory;
}  // namespace network

namespace ash {
namespace printing {
namespace oauth2 {

class ClientIdsDatabase;

// This class is responsible for the initial communication with the
// Authorization Server specified in the constructor. The method Initialize(...)
// retrieves metadata from the server and tries to register to it as a new
// client if necessary.
class AuthorizationServerData {
 public:
  // `client_ids_database` cannot be nullptr and must outlive this object.
  AuthorizationServerData(
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
      const GURL& authorization_server_uri,
      ClientIdsDatabase* client_ids_database);

  AuthorizationServerData(const AuthorizationServerData&) = delete;
  AuthorizationServerData& operator=(const AuthorizationServerData&) = delete;
  ~AuthorizationServerData();

  // Accessors to the server's metadata.
  const GURL& AuthorizationServerURI() const {
    return authorization_server_uri_;
  }
  std::string ClientId() const { return client_id_.value_or(""); }
  const GURL& AuthorizationEndpointURI() const {
    return authorization_endpoint_uri_;
  }
  const GURL& TokenEndpointURI() const { return token_endpoint_uri_; }
  const GURL& RegistrationEndpointURI() const {
    return registration_endpoint_uri_;
  }
  const GURL& RevocationEndpointURI() const { return revocation_endpoint_uri_; }

  // Returns true <=> the connection with the server was successfully
  // initialized. It is true <=> the method Initialize(...) was called earlier
  // and its callback returned StatusCode::kOK.
  bool IsReady() const {
    return !(!client_id_ || authorization_endpoint_uri_.is_empty() ||
             token_endpoint_uri_.is_empty() || client_id_->empty());
  }

  // Downloads metadata from the server. It also tries to register a new client
  // to the server if the server is not present in `client_ids_database_` (see
  // the constructor). If the client is not registered (i.e. the server is not
  // present in the database) and the server does not support dynamic
  // registration the callback returns StatusCode::kClientNotRegistered. If the
  // registration succeeds the obtained `client_id_` along with
  // `authorization_endpoint_uri_` is saved in `client_ids_database_`.
  // `callback` must be non-empty. This method cannot be called again before the
  // `callback` returns.
  void Initialize(StatusCallback callback);

 private:
  // Loads metadata from the server if `authorization_endpoint_uri_` or
  // `token_endpoint_uri_` are empty. Also tries to register the client to the
  // server if `client_id_` is empty. Calls `callback_` with results.
  void InitializationProcedure();
  // Sets `client_id_` to the value fetched from `client_ids_database_`.
  void OnClientIdFetched(StatusCode status, std::string data);
  // Prepares and sends Metadata Request.
  void SendMetadataRequest();
  // Analyzes response for Metadata Request.
  void OnMetadataResponse(StatusCode status);
  // Prepares and sends Registration Request.
  void SendRegistrationRequest();
  // Analyzes response for Registration Request.
  void OnRegistrationResponse(StatusCode status);

  // Basic information about the Authorization Server.
  const GURL authorization_server_uri_;
  std::optional<std::string> client_id_;

  // Metadata read from the Authorization Server.
  GURL authorization_endpoint_uri_;
  GURL token_endpoint_uri_;
  GURL registration_endpoint_uri_;
  GURL revocation_endpoint_uri_;

  StatusCallback callback_;

  // The object used to fetch and store client_id.
  raw_ptr<ClientIdsDatabase> client_ids_database_;

  // The object used for communication with the Authorization Server.
  HttpExchange http_exchange_;

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

}  // namespace oauth2
}  // namespace printing
}  // namespace ash

#endif  // CHROME_BROWSER_ASH_PRINTING_OAUTH2_AUTHORIZATION_SERVER_DATA_H_