chromium/chrome/browser/ash/printing/printer_authenticator.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_PRINTER_AUTHENTICATOR_H_
#define CHROME_BROWSER_ASH_PRINTING_PRINTER_AUTHENTICATOR_H_

#include <optional>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ash/printing/oauth2/status_code.h"
#include "chromeos/printing/cups_printer_status.h"
#include "chromeos/printing/printer_configuration.h"
#include "chromeos/printing/uri.h"
#include "url/gurl.h"

namespace ash {
class CupsPrintersManager;
}  // namespace ash

namespace chromeos {
class Printer;
}  // namespace chromeos

namespace ash::printing {

namespace oauth2 {
class AuthorizationZonesManager;
}  // namespace oauth2

class PrinterAuthenticator {
 public:
  // No nullptrs are allowed (DCHECK).
  PrinterAuthenticator(CupsPrintersManager* printers_manager,
                       oauth2::AuthorizationZonesManager* auth_manager,
                       const chromeos::Printer& printer);

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

  ~PrinterAuthenticator();

  // Starts the procedure of obtainig access to the printer. It may involve
  // showing dialogs to the user and waiting for his reaction. `callback` is
  // called when the procedure is completed. Three types of responses (sent as
  // callback's parameters) are possible:
  //  * `status` == StatusCode::kOK && `data` == "": access granted, no access
  //    tokens are needed;
  //  * `status` == StatusCode::kOK && `data` != "": access granted, `data` must
  //    be used as an access token during communication with the printer;
  //  * `status` != StatusCode::kOK: access denied or an error occurred, use the
  //    `status` to choose an error message shown to the user.
  void ObtainAccessTokenIfNeeded(oauth2::StatusCallback callback);

  // Instead of showing UI dialogs to user, statuses from
  // `is_trusted_dialog_response` and `signin_dialog_response` are
  // returned.
  void SetUIResponsesForTesting(oauth2::StatusCode is_trusted_dialog_response,
                                oauth2::StatusCode signin_dialog_response);

 private:
  // Enumerates steps of an authorization procedure.
  enum class Step {
    kGetAccessToken,
    kShowIsTrustedDialog,
    kInitAuthorization,
    kShowSigninDialog,
    kFinishAuthorization
  };

  // This is called when the status of the printer is obtained.
  void OnGetPrinterStatus(const chromeos::CupsPrinterStatus& printer_status);
  // Returns a callback that must be called when the given `step` is completed.
  oauth2::StatusCallback OnComplete(Step step);
  // Proceeds to the next action when `current_step` is completed. `status` and
  // `data` contain result of the completed step (`current_step`).
  void ToNextStep(Step current_step,
                  oauth2::StatusCode status,
                  std::string data);
  // Shows a dialog to the user asking if the given `auth_url` is a trusted
  // Authorization Server. Calls `callback` when the dialog is closed.
  void ShowIsTrustedDialog(const GURL& auth_url,
                           oauth2::StatusCallback callback);

  // Shows a dialog to the user with the webpage provided by the Authorization
  // Server at `auth_url` and calls `callback` when the authorization procedure
  // is completed or when the dialog is closed by the user.
  void ShowSigninDialog(const std::string& auth_url,
                        oauth2::StatusCallback callback);

  raw_ptr<CupsPrintersManager> cups_manager_;
  raw_ptr<oauth2::AuthorizationZonesManager> auth_manager_;
  chromeos::Printer printer_;
  GURL oauth_server_;
  std::string oauth_scope_;
  oauth2::StatusCallback callback_;

  // These fields are used to avoid showing UI elements when the class is
  // tested in unit tests.
  std::optional<oauth2::StatusCode> is_trusted_dialog_response_for_testing_;
  std::optional<oauth2::StatusCode> signin_dialog_response_for_testing_;

  base::WeakPtrFactory<PrinterAuthenticator> weak_factory_{this};
};

}  // namespace ash::printing

#endif  // CHROME_BROWSER_ASH_PRINTING_PRINTER_AUTHENTICATOR_H_