blob: d7eb982ace49a5fa47cedf78669b3141a51c0bbb [file] [log] [blame]
// Copyright 2023 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_AMBIENT_AMBIENT_MANAGED_PHOTO_CONTROLLER_H_
#define ASH_AMBIENT_AMBIENT_MANAGED_PHOTO_CONTROLLER_H_
#include <vector>
#include "ash/ambient/model/ambient_backend_model.h"
#include "ash/ambient/model/ambient_photo_config.h"
#include "ash/ambient/ui/ambient_view_delegate.h"
#include "ash/ash_export.h"
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
namespace gfx {
class ImageSkia;
} // namespace gfx
namespace ash {
// Class to handle policy-set photos in ambient mode. This is a barebones
// controller which takes in a list of file paths and adds them to the backend
// model one by one.
class ASH_EXPORT AmbientManagedPhotoController
: public AmbientViewDelegateObserver {
public:
class ASH_EXPORT Observer {
public:
virtual void OnErrorStateChanged() {}
};
AmbientManagedPhotoController(AmbientViewDelegate& view_delegate,
AmbientPhotoConfig photo_config);
AmbientManagedPhotoController(const AmbientManagedPhotoController&) = delete;
AmbientManagedPhotoController& operator=(
const AmbientManagedPhotoController&) = delete;
~AmbientManagedPhotoController() override;
// Start/stop updating the screen contents.
void StartScreenUpdate();
void StopScreenUpdate();
bool IsScreenUpdateActive() const;
bool HasScreenUpdateErrors() const;
void SetObserver(Observer* observer);
// Updates the image file paths, if controller is active, this method will
// also load these files from disk and put them in backend model in case the
// controller is in the active state.
void UpdateImageFilePaths(const std::vector<base::FilePath>& path_to_images);
AmbientBackendModel* ambient_backend_model() {
return &ambient_backend_model_;
}
// AmbientViewDelegateObserver:
void OnMarkerHit(AmbientPhotoConfig::Marker marker) override;
private:
// The controller `state_` is reset on dismissing the screensaver (when
// StopScreenUpdate is called) so if the error states are not treated
// differently they will be cleared on dismissing the screensaver and we will
// waste CPU cycles going in and out of this Started->Error state.
// Treating the error state separately allows the error state to be sticky and
// lets us know when there are still errors when the data doesn't change.
enum class ErrorState {
kNone,
// The controller was started with an insufficient number of images.
kInsufficientImages,
// The controller was started but we failed to load a sufficient number of
// images to continue even after trying to load all the provided images from
// disk.
kPhotoLoadFailure,
};
// Load and decode images
void LoadImages();
size_t GetMaxImageAttempts() const;
// Loads `images_to_load` no of images in an asynchronous but sequential
// manner and waits for the previous image to load before starting to load the
// next image. `success` denotes that the previous load was successful. Note:
// In case `success` is false or `images_to_load` is 0 this method will be a
// no-op.
void LoadImagesInternal(size_t images_to_load, bool success);
void LoadNextImage(base::OnceCallback<void(bool success)> callback);
void OnPhotoDecoded(base::OnceCallback<void(bool success)> callback,
const gfx::ImageSkia& image);
void HandlePhotoDecodingFailure(
base::OnceCallback<void(bool success)> callback);
// Sets and notifies whenever the `error_state_` is changed.
void SetErrorState(ErrorState error_state);
AmbientBackendModel ambient_backend_model_;
// The current number of tries for loading the next image, once it reaches the
// max tries, we will log an error and stop retrying. This is reset as soon as
// an image is decoded successfully.
size_t image_attempt_no_ = 0;
// Current index of cached file to read and display.
size_t current_image_index_ = 0;
// Flag used to determine whether the screen update is active. The screen
// update is considered to be active when the `StartScreenUpdate` method has
// been called. And it stops being active when the `StopScreenUpdate` method
// is called.
bool is_active_ = false;
// State used to determine whether the controller has encountered any errors.
// Note: This is sticky and cleared when sufficient new data is added to the
// controller.
ErrorState error_state_ = ErrorState::kNone;
// The list of image filepaths that are used as the sources for the images to
// show.
std::vector<base::FilePath> images_file_paths_;
raw_ptr<Observer> observer_ = nullptr;
base::ScopedObservation<AmbientViewDelegate, AmbientViewDelegateObserver>
scoped_view_delegate_observation_{this};
base::WeakPtrFactory<AmbientManagedPhotoController> weak_factory_{this};
};
} // namespace ash
#endif // ASH_AMBIENT_AMBIENT_MANAGED_PHOTO_CONTROLLER_H_