chromium/chrome/browser/ash/printing/oauth2/ipp_endpoint_token_fetcher.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_IPP_ENDPOINT_TOKEN_FETCHER_H_
#define CHROME_BROWSER_ASH_PRINTING_OAUTH2_IPP_ENDPOINT_TOKEN_FETCHER_H_

#include <string>
#include <vector>

#include "base/containers/flat_set.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "chrome/browser/ash/printing/oauth2/http_exchange.h"
#include "chrome/browser/ash/printing/oauth2/status_code.h"
#include "chromeos/printing/uri.h"
#include "url/gurl.h"

namespace network {
class SharedURLLoaderFactory;
}  // namespace network

namespace ash {
namespace printing {
namespace oauth2 {

// This class represents an OAuth2 session for a single IPP Endpoint. Objects
// of this class are responsible for:
// * storing basic data: endpoint's URI and scope;
// * storing current value of endpoint access token (empty string if missing);
// * storing a list of callbacks waiting for the endpoint access token;
// * sending Token Exchange Request and interpreting the response.
class IppEndpointTokenFetcher {
 public:
  // Constructor.
  IppEndpointTokenFetcher(
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
      const GURL& token_endpoint_uri,
      const chromeos::Uri& ipp_endpoint,
      base::flat_set<std::string>&& scope);
  // Not copyable.
  IppEndpointTokenFetcher(const IppEndpointTokenFetcher&) = delete;
  IppEndpointTokenFetcher& operator=(const IppEndpointTokenFetcher&) = delete;
  // Destructor.
  ~IppEndpointTokenFetcher();

  const chromeos::Uri& ipp_endpoint_uri() const { return ipp_endpoint_uri_; }
  const base::flat_set<std::string>& scope() const { return scope_; }

  // Returns the current endpoint access token or an empty string if the token
  // is not known yet.
  const std::string& endpoint_access_token() const {
    return endpoint_access_token_;
  }

  // Adds `callback` to the end of the waiting list. These callbacks are not
  // called internally. Instead, they can be retrieved with TakeWaitingList().
  void AddToWaitingList(StatusCallback callback);
  // Returns the waiting list by moving it. After calling this method
  // the waiting list is empty.
  std::vector<StatusCallback> TakeWaitingList();

  // Prepares and sends Token Exchange Request using `access_token`. Results are
  // returned by `callback`. If the request is successful, the callback returns
  // StatusCode::kOK and the endpoint access token as the second parameter.
  // If the server rejected the `access_token` (e.g. is expired or invalid)
  // the status StatusCode::kInvalidAccessToken is returned and the rejected
  // access token is returned in the second parameter. Otherwise, the error code
  // with a message is returned.
  void SendTokenExchangeRequest(const std::string& access_token,
                                StatusCallback callback);

 private:
  // Analyzes response for Token Exchange Request.
  void OnTokenExchangeResponse(const std::string& access_token,
                               StatusCallback callback,
                               StatusCode status);

  const GURL token_endpoint_uri_;
  const chromeos::Uri ipp_endpoint_uri_;
  const base::flat_set<std::string> scope_;

  std::string endpoint_access_token_;

  // The waiting list - a vector of waiting callbacks.
  std::vector<StatusCallback> callbacks_;

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

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

#endif  // CHROME_BROWSER_ASH_PRINTING_OAUTH2_IPP_ENDPOINT_TOKEN_FETCHER_H_