blob: 02891c8e610c49a83013c3675e4ddd0e3e119641 [file] [log] [blame] [edit]
// Copyright 2024 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_SCANNER_SCANNER_CONTROLLER_H_
#define ASH_SCANNER_SCANNER_CONTROLLER_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "ash/ash_export.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/scanner/scanner_action_view_model.h"
#include "ash/scanner/scanner_session.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
class PrefRegistrySimple;
namespace manta::proto {
class ScannerAction;
}
namespace ash {
class ScannerCommandDelegateImpl;
class ScannerDelegate;
class ScreenPinningController;
class SessionControllerImpl;
// This is the top level controller used for Scanner. It acts as a mediator
// between Scanner and any consuming features.
class ASH_EXPORT ScannerController : public SessionObserver {
public:
using OnActionFinishedCallback = base::OnceCallback<void(bool success)>;
// `screen_pinning_controller` must outlive this class.
// It must only be null in tests.
explicit ScannerController(
std::unique_ptr<ScannerDelegate> delegate,
SessionControllerImpl& session_controller,
const ScreenPinningController* screen_pinning_controller);
ScannerController(const ScannerController&) = delete;
ScannerController& operator=(const ScannerController&) = delete;
~ScannerController() override;
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
// Returns whether Scanner-related UI can be shown. This function checks
// `CanShowUi` for the `Shell`-global `ScannerController`.
//
// Do NOT use this method if your feature is using
// `SunfishScannerFeatureWatcher`, use its `CanShowScannerUi` method instead.
static bool CanShowUiForShell();
// SessionObserver:
void OnActiveUserSessionChanged(const AccountId& account_id) override;
// Checks system level constraints (e.g. feature flags) and returns
// true if the constraints allow the scanner UI to show.
// Note that this ignores consent status.
bool CanShowUi();
// Checks system level constraints (e.g. feature flags) and returns
// true if the constraints allow a Scanner settings toggle to be shown.
bool CanShowFeatureSettingsToggle();
// Checks system level constraints (e.g. prefs, feature flags) and returns
// true if the constraints allow a Scanner session to be created.
bool CanStartSession();
// Creates a new ScannerSession and returns a pointer to the created session.
// If the Scanner cannot be initialized due to system level constraints (e.g.
// pref disabled, feature not allowed), then no session is created and
// `nullptr` is returned instead. Note that calling `StartNewSession` will end
// the current session if there is one.
ScannerSession* StartNewSession();
// Fetches Scanner actions that are available based on the current
// `scanner_session_` and the contents of `jpeg_bytes`, and returns whether a
// session was active. The actions are returned via `callback`. If no session
// is active, then `callback` will be run with an empty list of actions.
bool FetchActionsForImage(scoped_refptr<base::RefCountedMemory> jpeg_bytes,
ScannerSession::FetchActionsCallback callback);
// Should be called when the user has finished interacting with a Scanner
// session. This will trigger relevant cleanup and eventually destroy the
// scanner session.
void OnSessionUIClosed();
// Executes the action described by `scanner_action`.
void ExecuteAction(const ScannerActionViewModel& scanner_action);
// Opens a feedback dialog for an action that has been performed, and the
// (resized) screenshot which initiated the action.
// WARNING: This function does not check whether the account has feedback
// enabled or not!
void OpenFeedbackDialog(const AccountId& account_id,
manta::proto::ScannerAction action,
scoped_refptr<base::RefCountedMemory> screenshot);
// Sets mock ScannerOutput data for testing.
void SetScannerResponsesForTesting(const std::vector<std::string> responses);
bool HasActiveSessionForTesting() const;
ScannerDelegate* delegate_for_testing() { return delegate_.get(); }
void SetOnActionFinishedForTesting(OnActionFinishedCallback callback);
private:
// Should be called when an action finishes execution.
void OnActionFinished(
manta::proto::ScannerAction::ActionCase action_case,
scoped_refptr<base::RefCountedMemory> downscaled_jpeg_bytes,
manta::proto::ScannerAction populated_action,
bool success);
std::unique_ptr<ScannerDelegate> delegate_;
// Delegate to handle Scanner commands for actions fetched during a session.
// `command_delegate_` should outlive `scanner_session_`, to allow commands to
// be completed in the background after the session UI has been closed.
std::unique_ptr<ScannerCommandDelegateImpl> command_delegate_;
// May hold an active Scanner session, to allow access to the Scanner feature.
std::unique_ptr<ScannerSession> scanner_session_;
OnActionFinishedCallback on_action_finished_for_testing_;
// External dependencies not owned by this class:
// Session controller, stored in `Shell`. Always outlives this class.
raw_ref<SessionControllerImpl> session_controller_;
// Screen pinning controller, stored in `Shell`. Always outlives this class.
// If this pointer is null, then we are in a test.
const raw_ptr<const ScreenPinningController> screen_pinning_controller_;
// Holds mock ScannerOutput data for testing.
std::vector<std::string> mock_scanner_responses_for_testing_;
ScopedSessionObserver session_observer_{this};
base::WeakPtrFactory<ScannerController> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_SCANNER_SCANNER_CONTROLLER_H_