blob: c319ff6ea94a3bc9573dcf8ef7f24154ac438f84 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_FEED_CORE_FEED_IMAGE_DATABASE_H_
#define COMPONENTS_FEED_CORE_FEED_IMAGE_DATABASE_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "components/leveldb_proto/proto_database.h"
namespace base {
class Clock;
} // namespace base
namespace feed {
class CachedImageProto;
// FeedImageDatabase is leveldb backed store for feed's image data.
// FeedImageDatabase keeps images identified by URLs.
// Save and Load operations are asynchronous, every load operation will update
// last_used_time for the image for garbage collection purpose.
class FeedImageDatabase {
public:
enum State {
UNINITIALIZED,
INITIALIZED,
INIT_FAILURE,
};
// Returns the resulting raw image data as std::string of a |LoadImage| call.
using FeedImageDatabaseCallback =
base::OnceCallback<void(const std::string&)>;
using FeedImageDatabaseOperationCallback = base::OnceCallback<void(bool)>;
// Initializes the database with |database_dir|.
explicit FeedImageDatabase(const base::FilePath& database_dir);
// Initializes the database with |database_dir|. Creates storage using the
// given |image_database| for local storage. Useful for testing.
FeedImageDatabase(
const base::FilePath& database_dir,
std::unique_ptr<leveldb_proto::ProtoDatabase<CachedImageProto>>
image_database,
base::Clock* clock);
~FeedImageDatabase();
// Returns true if initialization has finished successfully, else false.
// While this is false, initialization may already started, or initialization
// failed.
bool IsInitialized();
// Adds or updates the image data for the |url|.
// If the database is not initialized or in some error status, the call will
// be ignored.
void SaveImage(const std::string& url, const std::string& image_data);
// Loads the image data for the |url| and passes it to |callback|.
// |callback| will be called in the same thread as this function called.
// If the image cannot be found in database, or database error, returns an
// empty CachedImageProto. If the database is not initialized yet, the
// request will be pending until the database has been initialized.
void LoadImage(const std::string& url, FeedImageDatabaseCallback callback);
// Deletes the image data for the |url|.
void DeleteImage(const std::string& url);
// Delete all images whose |last_used_time| is older than |expired_time| and
// passes the result to |callback|. |callback| will be called in the same
// thread as this function called. If database is not initialized, or failed
// to delete expired entry, false will be passed to |callback|.
void GarbageCollectImages(base::Time expired_time,
FeedImageDatabaseOperationCallback callback);
private:
friend class FeedImageDatabaseTest;
using ImageKeyEntryVector =
leveldb_proto::ProtoDatabase<CachedImageProto>::KeyEntryVector;
// Initialization
void OnDatabaseInitialized(bool success);
void ProcessPendingImageLoads();
// Saving
void SaveImageImpl(std::string url, const CachedImageProto& image_proto);
void OnImageUpdated(bool success);
// Loading
void LoadImageImpl(const std::string& url,
FeedImageDatabaseCallback callback);
void OnImageLoaded(std::string url,
FeedImageDatabaseCallback callback,
bool success,
std::unique_ptr<CachedImageProto> entry);
// Deleting
void DeleteImageImpl(const std::string& url,
FeedImageDatabaseOperationCallback callback);
// Garbage collection
void GarbageCollectImagesImpl(
base::Time expired_time,
FeedImageDatabaseOperationCallback callback,
bool load_entries_success,
std::unique_ptr<std::vector<CachedImageProto>> image_entries);
void OnGarbageCollectionDone(FeedImageDatabaseOperationCallback callback,
bool success);
State database_status_;
std::unique_ptr<leveldb_proto::ProtoDatabase<CachedImageProto>>
image_database_;
// Used to access current time, injected for testing.
base::Clock* clock_;
std::vector<std::pair<std::string, FeedImageDatabaseCallback>>
pending_image_callbacks_;
// Used to check that functions are called on the correct sequence.
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<FeedImageDatabase> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(FeedImageDatabase);
};
} // namespace feed
#endif // COMPONENTS_FEED_CORE_FEED_IMAGE_DATABASE_H_