Commit 4fe6241c authored by ckitagawa's avatar ckitagawa Committed by Commit Bot

[Paint Preview] Expire old previews

This CL expires old captures after 72 hours in order to allow for
previews to be reasonably current.

Bug: TODO
Change-Id: I0c86c928dc73564e3721d4d8f79b8b7693931619
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2386223Reviewed-by: default avatarMehran Mahmoudi <mahmoudi@chromium.org>
Commit-Queue: Calder Kitagawa <ckitagawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803946}
parent fc124e67
...@@ -30,6 +30,8 @@ namespace { ...@@ -30,6 +30,8 @@ namespace {
constexpr size_t kMaxPerCaptureSizeBytes = 5 * 1000L * 1000L; // 5 MB. constexpr size_t kMaxPerCaptureSizeBytes = 5 * 1000L * 1000L; // 5 MB.
constexpr size_t kMaximumTotalCaptureSize = 25 * 1000L * 1000L; // 25 MB. constexpr size_t kMaximumTotalCaptureSize = 25 * 1000L * 1000L; // 25 MB.
// The time horizon after which unused paint previews will be deleted.
constexpr int kExpiryHorizonHrs = 72;
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
void JavaBooleanCallbackAdapter(base::OnceCallback<void(bool)> callback, void JavaBooleanCallbackAdapter(base::OnceCallback<void(bool)> callback,
...@@ -153,6 +155,18 @@ void PaintPreviewTabService::AuditArtifacts( ...@@ -153,6 +155,18 @@ void PaintPreviewTabService::AuditArtifacts(
weak_ptr_factory_.GetWeakPtr(), active_tab_ids)); weak_ptr_factory_.GetWeakPtr(), active_tab_ids));
} }
void PaintPreviewTabService::GetCapturedPaintPreviewProto(
const DirectoryKey& key,
base::Optional<base::TimeDelta> expiry_horizon,
PaintPreviewBaseService::OnReadProtoCallback on_read_proto_callback) {
PaintPreviewBaseService::GetCapturedPaintPreviewProto(
key,
expiry_horizon.has_value()
? expiry_horizon.value()
: base::TimeDelta::FromHours(kExpiryHorizonHrs),
std::move(on_read_proto_callback));
}
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
void PaintPreviewTabService::CaptureTabAndroid( void PaintPreviewTabService::CaptureTabAndroid(
JNIEnv* env, JNIEnv* env,
...@@ -273,7 +287,8 @@ void PaintPreviewTabService::OnFinished(int tab_id, ...@@ -273,7 +287,8 @@ void PaintPreviewTabService::OnFinished(int tab_id,
GetTaskRunner()->PostTaskAndReplyWithResult( GetTaskRunner()->PostTaskAndReplyWithResult(
FROM_HERE, FROM_HERE,
base::BindOnce(&FileManager::GetOldestArtifactsForCleanup, file_manager, base::BindOnce(&FileManager::GetOldestArtifactsForCleanup, file_manager,
kMaximumTotalCaptureSize), kMaximumTotalCaptureSize,
base::TimeDelta::FromHours(kExpiryHorizonHrs)),
base::BindOnce(&PaintPreviewTabService::CleanupOldestFiles, base::BindOnce(&PaintPreviewTabService::CleanupOldestFiles,
weak_ptr_factory_.GetWeakPtr(), tab_id)); weak_ptr_factory_.GetWeakPtr(), tab_id));
} }
......
...@@ -78,6 +78,14 @@ class PaintPreviewTabService : public PaintPreviewBaseService { ...@@ -78,6 +78,14 @@ class PaintPreviewTabService : public PaintPreviewBaseService {
// occurred. // occurred.
void AuditArtifacts(const std::vector<int>& active_tab_ids); void AuditArtifacts(const std::vector<int>& active_tab_ids);
// Override for GetCapturedPaintPreviewProto. Defaults expiry horizon to 72
// hrs if not specified.
void GetCapturedPaintPreviewProto(
const DirectoryKey& key,
base::Optional<base::TimeDelta> expiry_horizon,
PaintPreviewBaseService::OnReadProtoCallback on_read_proto_callback)
override;
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
// JNI wrapped versions of the above methods // JNI wrapped versions of the above methods
void CaptureTabAndroid( void CaptureTabAndroid(
......
...@@ -218,13 +218,22 @@ bool FileManager::SerializePaintPreviewProto(const DirectoryKey& key, ...@@ -218,13 +218,22 @@ bool FileManager::SerializePaintPreviewProto(const DirectoryKey& key,
return result; return result;
} }
std::unique_ptr<PaintPreviewProto> FileManager::DeserializePaintPreviewProto( std::pair<FileManager::ProtoReadStatus, std::unique_ptr<PaintPreviewProto>>
const DirectoryKey& key) const { FileManager::DeserializePaintPreviewProto(const DirectoryKey& key) const {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
auto path = CreateOrGetDirectory(key, false); auto path = CreateOrGetDirectory(key, false);
if (!path.has_value()) if (!path.has_value())
return nullptr; return std::make_pair(ProtoReadStatus::kNoProto, nullptr);
return ReadProtoFromFile(path->AppendASCII(kProtoName));
auto proto_path = path->AppendASCII(kProtoName);
if (!base::PathExists(proto_path))
return std::make_pair(ProtoReadStatus::kNoProto, nullptr);
auto proto = ReadProtoFromFile(path->AppendASCII(kProtoName));
if (proto == nullptr)
return std::make_pair(ProtoReadStatus::kDeserializationError, nullptr);
return std::make_pair(ProtoReadStatus::kOk, std::move(proto));
} }
base::flat_set<DirectoryKey> FileManager::ListUsedKeys() const { base::flat_set<DirectoryKey> FileManager::ListUsedKeys() const {
...@@ -242,13 +251,8 @@ base::flat_set<DirectoryKey> FileManager::ListUsedKeys() const { ...@@ -242,13 +251,8 @@ base::flat_set<DirectoryKey> FileManager::ListUsedKeys() const {
} }
std::vector<DirectoryKey> FileManager::GetOldestArtifactsForCleanup( std::vector<DirectoryKey> FileManager::GetOldestArtifactsForCleanup(
size_t max_size) { size_t max_size,
// The rest of this function is expensive so cleanup should exit early if not base::TimeDelta expiry_horizon) {
// required.
size_t size = base::ComputeDirectorySize(root_directory_);
if (size <= max_size)
return std::vector<DirectoryKey>();
base::FileEnumerator file_enum( base::FileEnumerator file_enum(
root_directory_, false, root_directory_, false,
base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
...@@ -260,22 +264,29 @@ std::vector<DirectoryKey> FileManager::GetOldestArtifactsForCleanup( ...@@ -260,22 +264,29 @@ std::vector<DirectoryKey> FileManager::GetOldestArtifactsForCleanup(
std::sort(file_infos.begin(), file_infos.end(), CompareByLastModified); std::sort(file_infos.begin(), file_infos.end(), CompareByLastModified);
// If the oldest file doesn't need to expire attempt to early exit.
base::Time expiry_threshold =
base::Time::NowFromSystemTime() - expiry_horizon;
size_t size = base::ComputeDirectorySize(root_directory_);
std::vector<DirectoryKey> keys_to_remove; std::vector<DirectoryKey> keys_to_remove;
for (const auto& file_info : file_infos) { for (const auto& file_info : file_infos) {
base::FilePath full_path = root_directory_.Append(file_info.GetName()); // Stop when both the max size and expiry threshold requirements are met.
if (size <= max_size && file_info.GetLastModifiedTime() > expiry_threshold)
break;
size_t size_delta = file_info.GetSize(); size_t size_delta = file_info.GetSize();
// Computing a directory size is expensive. Most files should hopefully be // Computing a directory size is expensive. Most files should hopefully be
// compressed already. // compressed already.
if (file_info.IsDirectory()) if (file_info.IsDirectory()) {
base::FilePath full_path = root_directory_.Append(file_info.GetName());
size_delta = base::ComputeDirectorySize(full_path); size_delta = base::ComputeDirectorySize(full_path);
}
// Directory names should always be ASCII. // Directory names should always be ASCII.
keys_to_remove.emplace_back( keys_to_remove.emplace_back(
file_info.GetName().RemoveExtension().MaybeAsASCII()); file_info.GetName().RemoveExtension().MaybeAsASCII());
size -= size_delta; size -= size_delta;
if (size <= max_size)
break;
} }
return keys_to_remove; return keys_to_remove;
} }
......
...@@ -24,6 +24,12 @@ class PaintPreviewTabService; ...@@ -24,6 +24,12 @@ class PaintPreviewTabService;
// This class is refcounted so scheduled tasks may continue during shutdown. // This class is refcounted so scheduled tasks may continue during shutdown.
class FileManager : public base::RefCountedThreadSafe<FileManager> { class FileManager : public base::RefCountedThreadSafe<FileManager> {
public: public:
enum class ProtoReadStatus : int {
kOk = 0,
kNoProto,
kDeserializationError,
};
// Create a file manager for |root_directory|. Top level items in // Create a file manager for |root_directory|. Top level items in
// |root_directoy| should be exclusively managed by this class. Items within // |root_directoy| should be exclusively managed by this class. Items within
// the subdirectories it creates can be freely modified. All methods will be // the subdirectories it creates can be freely modified. All methods will be
...@@ -83,10 +89,10 @@ class FileManager : public base::RefCountedThreadSafe<FileManager> { ...@@ -83,10 +89,10 @@ class FileManager : public base::RefCountedThreadSafe<FileManager> {
const PaintPreviewProto& proto, const PaintPreviewProto& proto,
bool compress) const; bool compress) const;
// Deserializes PaintPreviewProto stored in |key|. Returns nullptr if not // Deserializes PaintPreviewProto stored in |key|. Returns a status and the
// found or the proto cannot be parsed. // proto. The proto will be nullptr if the ProtoReadStatus != kOk.
std::unique_ptr<PaintPreviewProto> DeserializePaintPreviewProto( std::pair<ProtoReadStatus, std::unique_ptr<PaintPreviewProto>>
const DirectoryKey& key) const; DeserializePaintPreviewProto(const DirectoryKey& key) const;
// Lists the current set of in-use DirectoryKeys. // Lists the current set of in-use DirectoryKeys.
base::flat_set<DirectoryKey> ListUsedKeys() const; base::flat_set<DirectoryKey> ListUsedKeys() const;
...@@ -94,7 +100,9 @@ class FileManager : public base::RefCountedThreadSafe<FileManager> { ...@@ -94,7 +100,9 @@ class FileManager : public base::RefCountedThreadSafe<FileManager> {
// Returns a list of the least recently modified artifact sets until which // Returns a list of the least recently modified artifact sets until which
// when deleted would result in a total capture size on disk that is less than // when deleted would result in a total capture size on disk that is less than
// |max_size|. // |max_size|.
std::vector<DirectoryKey> GetOldestArtifactsForCleanup(size_t max_size); std::vector<DirectoryKey> GetOldestArtifactsForCleanup(
size_t max_size,
base::TimeDelta expiry_horizon);
private: private:
friend class base::RefCountedThreadSafe<FileManager>; friend class base::RefCountedThreadSafe<FileManager>;
......
...@@ -252,8 +252,9 @@ TEST_F(FileManagerTest, HandleProto) { ...@@ -252,8 +252,9 @@ TEST_F(FileManagerTest, HandleProto) {
EXPECT_TRUE(manager->SerializePaintPreviewProto(key, original_proto, false)); EXPECT_TRUE(manager->SerializePaintPreviewProto(key, original_proto, false));
EXPECT_TRUE(base::PathExists(path.AppendASCII("proto.pb"))); EXPECT_TRUE(base::PathExists(path.AppendASCII("proto.pb")));
auto out_proto = manager->DeserializePaintPreviewProto(key); auto out_proto = manager->DeserializePaintPreviewProto(key);
EXPECT_NE(out_proto, nullptr); EXPECT_EQ(out_proto.first, FileManager::ProtoReadStatus::kOk);
EXPECT_THAT(*out_proto, EqualsProto(original_proto)); EXPECT_NE(out_proto.second, nullptr);
EXPECT_THAT(*(out_proto.second), EqualsProto(original_proto));
} }
TEST_F(FileManagerTest, HandleProtoCompressed) { TEST_F(FileManagerTest, HandleProtoCompressed) {
...@@ -280,8 +281,9 @@ TEST_F(FileManagerTest, HandleProtoCompressed) { ...@@ -280,8 +281,9 @@ TEST_F(FileManagerTest, HandleProtoCompressed) {
EXPECT_TRUE(base::PathExists(path.AddExtensionASCII(".zip"))); EXPECT_TRUE(base::PathExists(path.AddExtensionASCII(".zip")));
auto out_proto = manager->DeserializePaintPreviewProto(key); auto out_proto = manager->DeserializePaintPreviewProto(key);
EXPECT_NE(out_proto, nullptr); EXPECT_EQ(out_proto.first, FileManager::ProtoReadStatus::kOk);
EXPECT_THAT(*out_proto, EqualsProto(original_proto)); EXPECT_NE(out_proto.second, nullptr);
EXPECT_THAT(*(out_proto.second), EqualsProto(original_proto));
EXPECT_TRUE(manager->CaptureExists(key)); EXPECT_TRUE(manager->CaptureExists(key));
} }
...@@ -297,14 +299,19 @@ TEST_F(FileManagerTest, OldestFilesForCleanup) { ...@@ -297,14 +299,19 @@ TEST_F(FileManagerTest, OldestFilesForCleanup) {
auto key_0 = manager->CreateKey(0U); auto key_0 = manager->CreateKey(0U);
base::FilePath path_0 = base::FilePath path_0 =
manager->CreateOrGetDirectory(key_0, true).value_or(base::FilePath()); manager->CreateOrGetDirectory(key_0, true).value_or(base::FilePath());
base::WriteFile(path_0.AppendASCII("0.txt"), data.data(), data.size()); auto path_0_file = path_0.AppendASCII("0.txt");
base::WriteFile(path_0_file, data.data(), data.size());
base::Time modified_time = base::Time::NowFromSystemTime();
base::TouchFile(path_0_file, modified_time, modified_time);
{ {
auto to_delete = manager->GetOldestArtifactsForCleanup(0U); auto to_delete = manager->GetOldestArtifactsForCleanup(
0U, base::TimeDelta::FromMinutes(20));
ASSERT_EQ(to_delete.size(), 1U); ASSERT_EQ(to_delete.size(), 1U);
EXPECT_EQ(to_delete[0], key_0); EXPECT_EQ(to_delete[0], key_0);
} }
{ {
auto to_delete = manager->GetOldestArtifactsForCleanup(50U); auto to_delete = manager->GetOldestArtifactsForCleanup(
50U, base::TimeDelta::FromMinutes(20));
EXPECT_EQ(to_delete.size(), 0U); EXPECT_EQ(to_delete.size(), 0U);
} }
...@@ -313,14 +320,15 @@ TEST_F(FileManagerTest, OldestFilesForCleanup) { ...@@ -313,14 +320,15 @@ TEST_F(FileManagerTest, OldestFilesForCleanup) {
manager->CreateOrGetDirectory(key_1, true).value_or(base::FilePath()); manager->CreateOrGetDirectory(key_1, true).value_or(base::FilePath());
base::WriteFile(path_1.AppendASCII("1.txt"), data.data(), data.size()); base::WriteFile(path_1.AppendASCII("1.txt"), data.data(), data.size());
manager->CompressDirectory(key_1); manager->CompressDirectory(key_1);
base::Time modified_time = base::Time::Now(); modified_time = base::Time::NowFromSystemTime();
auto path_1_zip = path_1.AddExtensionASCII(".zip"); auto path_1_zip = path_1.AddExtensionASCII(".zip");
base::TouchFile(path_0, modified_time - base::TimeDelta::FromSeconds(10), base::TouchFile(path_0, modified_time - base::TimeDelta::FromSeconds(10),
modified_time - base::TimeDelta::FromSeconds(10)); modified_time - base::TimeDelta::FromSeconds(10));
base::TouchFile(path_1_zip, modified_time, modified_time); base::TouchFile(path_1_zip, modified_time, modified_time);
{ {
auto to_delete = manager->GetOldestArtifactsForCleanup(0U); auto to_delete = manager->GetOldestArtifactsForCleanup(
0U, base::TimeDelta::FromMinutes(20));
ASSERT_EQ(to_delete.size(), 2U); ASSERT_EQ(to_delete.size(), 2U);
// Elements should be ordered in oldest to newest. // Elements should be ordered in oldest to newest.
EXPECT_EQ(to_delete[0], key_0); EXPECT_EQ(to_delete[0], key_0);
...@@ -328,12 +336,14 @@ TEST_F(FileManagerTest, OldestFilesForCleanup) { ...@@ -328,12 +336,14 @@ TEST_F(FileManagerTest, OldestFilesForCleanup) {
} }
{ {
// Zip is ~116 bytes. // Zip is ~116 bytes.
auto to_delete = manager->GetOldestArtifactsForCleanup(120U); auto to_delete = manager->GetOldestArtifactsForCleanup(
120U, base::TimeDelta::FromMinutes(20));
ASSERT_EQ(to_delete.size(), 1U); ASSERT_EQ(to_delete.size(), 1U);
EXPECT_EQ(to_delete[0], key_0); EXPECT_EQ(to_delete[0], key_0);
} }
{ {
auto to_delete = manager->GetOldestArtifactsForCleanup(150U); auto to_delete = manager->GetOldestArtifactsForCleanup(
150U, base::TimeDelta::FromMinutes(20));
EXPECT_EQ(to_delete.size(), 0U); EXPECT_EQ(to_delete.size(), 0U);
} }
} }
......
...@@ -50,12 +50,51 @@ PaintPreviewBaseService::~PaintPreviewBaseService() = default; ...@@ -50,12 +50,51 @@ PaintPreviewBaseService::~PaintPreviewBaseService() = default;
void PaintPreviewBaseService::GetCapturedPaintPreviewProto( void PaintPreviewBaseService::GetCapturedPaintPreviewProto(
const DirectoryKey& key, const DirectoryKey& key,
base::Optional<base::TimeDelta> expiry_horizon,
OnReadProtoCallback on_read_proto_callback) { OnReadProtoCallback on_read_proto_callback) {
task_runner_->PostTaskAndReplyWithResult( task_runner_->PostTaskAndReplyWithResult(
FROM_HERE, FROM_HERE,
base::BindOnce(&FileManager::DeserializePaintPreviewProto, file_manager_, base::BindOnce(
key), [](scoped_refptr<FileManager> file_manager, const DirectoryKey& key,
std::move(on_read_proto_callback)); base::Optional<base::TimeDelta> expiry_horizon)
-> std::pair<PaintPreviewBaseService::ProtoReadStatus,
std::unique_ptr<PaintPreviewProto>> {
if (expiry_horizon.has_value()) {
auto file_info = file_manager->GetInfo(key);
if (!file_info.has_value())
return std::make_pair(ProtoReadStatus::kNoProto, nullptr);
if (file_info->last_modified + expiry_horizon.value() <
base::Time::NowFromSystemTime()) {
return std::make_pair(ProtoReadStatus::kExpired, nullptr);
}
}
auto result = file_manager->DeserializePaintPreviewProto(key);
PaintPreviewBaseService::ProtoReadStatus status =
ProtoReadStatus::kNoProto;
switch (result.first) {
case FileManager::ProtoReadStatus::kOk:
status = ProtoReadStatus::kOk;
break;
case FileManager::ProtoReadStatus::kNoProto:
status = ProtoReadStatus::kNoProto;
break;
case FileManager::ProtoReadStatus::kDeserializationError:
status = ProtoReadStatus::kDeserializationError;
break;
default:
NOTREACHED();
}
return std::make_pair(status, std::move(result.second));
},
file_manager_, key, expiry_horizon),
base::BindOnce(
[](OnReadProtoCallback callback,
std::pair<PaintPreviewBaseService::ProtoReadStatus,
std::unique_ptr<PaintPreviewProto>> result) {
std::move(callback).Run(result.first, std::move(result.second));
},
std::move(on_read_proto_callback)));
} }
void PaintPreviewBaseService::CapturePaintPreview( void PaintPreviewBaseService::CapturePaintPreview(
...@@ -80,14 +119,14 @@ void PaintPreviewBaseService::CapturePaintPreview( ...@@ -80,14 +119,14 @@ void PaintPreviewBaseService::CapturePaintPreview(
OnCapturedCallback callback) { OnCapturedCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (policy_ && !policy_->SupportedForContents(web_contents)) { if (policy_ && !policy_->SupportedForContents(web_contents)) {
std::move(callback).Run(kContentUnsupported, {}); std::move(callback).Run(CaptureStatus::kContentUnsupported, {});
return; return;
} }
PaintPreviewClient::CreateForWebContents(web_contents); // Is a singleton. PaintPreviewClient::CreateForWebContents(web_contents); // Is a singleton.
auto* client = PaintPreviewClient::FromWebContents(web_contents); auto* client = PaintPreviewClient::FromWebContents(web_contents);
if (!client) { if (!client) {
std::move(callback).Run(kClientCreationFailed, {}); std::move(callback).Run(CaptureStatus::kClientCreationFailed, {});
return; return;
} }
...@@ -131,12 +170,12 @@ void PaintPreviewBaseService::OnCaptured( ...@@ -131,12 +170,12 @@ void PaintPreviewBaseService::OnCaptured(
!result->capture_success) { !result->capture_success) {
DVLOG(1) << "ERROR: Paint Preview failed to capture for document " DVLOG(1) << "ERROR: Paint Preview failed to capture for document "
<< guid.ToString() << " with error " << status; << guid.ToString() << " with error " << status;
std::move(callback).Run(kCaptureFailed, {}); std::move(callback).Run(CaptureStatus::kCaptureFailed, {});
return; return;
} }
base::UmaHistogramTimes("Browser.PaintPreview.Capture.TotalCaptureDuration", base::UmaHistogramTimes("Browser.PaintPreview.Capture.TotalCaptureDuration",
base::TimeTicks::Now() - start_time); base::TimeTicks::Now() - start_time);
std::move(callback).Run(kOk, std::move(result)); std::move(callback).Run(CaptureStatus::kOk, std::move(result));
} }
} // namespace paint_preview } // namespace paint_preview
...@@ -41,18 +41,26 @@ namespace paint_preview { ...@@ -41,18 +41,26 @@ namespace paint_preview {
// - SimpleKeyedServiceFactory // - SimpleKeyedServiceFactory
class PaintPreviewBaseService : public KeyedService { class PaintPreviewBaseService : public KeyedService {
public: public:
enum CaptureStatus { enum class CaptureStatus : int {
kOk = 0, kOk = 0,
kContentUnsupported, kContentUnsupported,
kClientCreationFailed, kClientCreationFailed,
kCaptureFailed, kCaptureFailed,
}; };
enum class ProtoReadStatus : int {
kOk = 0,
kNoProto,
kDeserializationError,
kExpired,
};
using OnCapturedCallback = using OnCapturedCallback =
base::OnceCallback<void(CaptureStatus, std::unique_ptr<CaptureResult>)>; base::OnceCallback<void(CaptureStatus, std::unique_ptr<CaptureResult>)>;
using OnReadProtoCallback = using OnReadProtoCallback =
base::OnceCallback<void(std::unique_ptr<PaintPreviewProto>)>; base::OnceCallback<void(ProtoReadStatus,
std::unique_ptr<PaintPreviewProto>)>;
// Creates a service instance for a feature. Artifacts produced will live in // Creates a service instance for a feature. Artifacts produced will live in
// |profile_dir|/paint_preview/|ascii_feature_name|. Implementers of the // |profile_dir|/paint_preview/|ascii_feature_name|. Implementers of the
...@@ -79,10 +87,15 @@ class PaintPreviewBaseService : public KeyedService { ...@@ -79,10 +87,15 @@ class PaintPreviewBaseService : public KeyedService {
// Acquires the PaintPreviewProto that is associated with |key| and sends it // Acquires the PaintPreviewProto that is associated with |key| and sends it
// to |on_read_proto_callback|. The default implementation attempts to invoke // to |on_read_proto_callback|. The default implementation attempts to invoke
// GetFileManager()->DeserializePaintPreviewProto(). Derived classes may // GetFileManager()->DeserializePaintPreviewProto(). If |expiry_horizon| is
// override this function; for example, the proto is cached in memory. // provided a proto that was last modified earlier than |now - expiry_horizon|
// will return the kExpired status.
//
// Derived classes may override this function; for example, the proto is
// cached in memory.
virtual void GetCapturedPaintPreviewProto( virtual void GetCapturedPaintPreviewProto(
const DirectoryKey& key, const DirectoryKey& key,
base::Optional<base::TimeDelta> expiry_horizon,
OnReadProtoCallback on_read_proto_callback); OnReadProtoCallback on_read_proto_callback);
// Captures need to run on the Browser UI thread! Captures may involve child // Captures need to run on the Browser UI thread! Captures may involve child
......
...@@ -23,6 +23,8 @@ enum class CompositorStatus : int { ...@@ -23,6 +23,8 @@ enum class CompositorStatus : int {
INVALID_REQUEST, INVALID_REQUEST,
OLD_VERSION, OLD_VERSION,
UNEXPECTED_VERSION, UNEXPECTED_VERSION,
CAPTURE_EXPIRED,
NO_CAPTURE,
COUNT, COUNT,
}; };
......
...@@ -112,8 +112,9 @@ PlayerCompositorDelegate::PlayerCompositorDelegate( ...@@ -112,8 +112,9 @@ PlayerCompositorDelegate::PlayerCompositorDelegate(
base::OnTaskRunnerDeleter(nullptr)) { base::OnTaskRunnerDeleter(nullptr)) {
if (skip_service_launch) { if (skip_service_launch) {
paint_preview_service_->GetCapturedPaintPreviewProto( paint_preview_service_->GetCapturedPaintPreviewProto(
key, base::BindOnce(&PlayerCompositorDelegate::OnProtoAvailable, key, base::nullopt,
weak_factory_.GetWeakPtr(), expected_url)); base::BindOnce(&PlayerCompositorDelegate::OnProtoAvailable,
weak_factory_.GetWeakPtr(), expected_url));
return; return;
} }
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("paint_preview", TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("paint_preview",
...@@ -179,15 +180,29 @@ void PlayerCompositorDelegate::OnCompositorClientCreated( ...@@ -179,15 +180,29 @@ void PlayerCompositorDelegate::OnCompositorClientCreated(
"PlayerCompositorDelegate CreateCompositor", "PlayerCompositorDelegate CreateCompositor",
TRACE_ID_LOCAL(this)); TRACE_ID_LOCAL(this));
paint_preview_service_->GetCapturedPaintPreviewProto( paint_preview_service_->GetCapturedPaintPreviewProto(
key, base::BindOnce(&PlayerCompositorDelegate::OnProtoAvailable, key, base::nullopt,
weak_factory_.GetWeakPtr(), expected_url)); base::BindOnce(&PlayerCompositorDelegate::OnProtoAvailable,
weak_factory_.GetWeakPtr(), expected_url));
} }
void PlayerCompositorDelegate::OnProtoAvailable( void PlayerCompositorDelegate::OnProtoAvailable(
const GURL& expected_url, const GURL& expected_url,
PaintPreviewBaseService::ProtoReadStatus proto_status,
std::unique_ptr<PaintPreviewProto> proto) { std::unique_ptr<PaintPreviewProto> proto) {
if (!proto || !proto->IsInitialized()) { // TODO(crbug.com/1021590): Handle initialization errors.
// TODO(crbug.com/1021590): Handle initialization errors. if (proto_status == PaintPreviewBaseService::ProtoReadStatus::kExpired) {
OnCompositorReady(CompositorStatus::CAPTURE_EXPIRED, nullptr);
return;
}
if (proto_status == PaintPreviewBaseService::ProtoReadStatus::kNoProto) {
OnCompositorReady(CompositorStatus::NO_CAPTURE, nullptr);
return;
}
if (proto_status ==
PaintPreviewBaseService::ProtoReadStatus::kDeserializationError ||
!proto || !proto->IsInitialized()) {
OnCompositorReady(CompositorStatus::PROTOBUF_DESERIALIZATION_ERROR, OnCompositorReady(CompositorStatus::PROTOBUF_DESERIALIZATION_ERROR,
nullptr); nullptr);
return; return;
......
...@@ -76,6 +76,7 @@ class PlayerCompositorDelegate { ...@@ -76,6 +76,7 @@ class PlayerCompositorDelegate {
void OnCompositorClientDisconnected(); void OnCompositorClientDisconnected();
void OnProtoAvailable(const GURL& expected_url, void OnProtoAvailable(const GURL& expected_url,
PaintPreviewBaseService::ProtoReadStatus proto_status,
std::unique_ptr<PaintPreviewProto> proto); std::unique_ptr<PaintPreviewProto> proto);
void SendCompositeRequest( void SendCompositeRequest(
mojom::PaintPreviewBeginCompositeRequestPtr begin_composite_request); mojom::PaintPreviewBeginCompositeRequestPtr begin_composite_request);
......
...@@ -69572,6 +69572,8 @@ would be helpful to identify which type is being sent. ...@@ -69572,6 +69572,8 @@ would be helpful to identify which type is being sent.
<int value="7" label="Invalid Request"/> <int value="7" label="Invalid Request"/>
<int value="8" label="Old Version"/> <int value="8" label="Old Version"/>
<int value="9" label="Unexpected Version"/> <int value="9" label="Unexpected Version"/>
<int value="10" label="Capture Expired"/>
<int value="11" label="No Capture"/>
</enum> </enum>
<enum name="TabbedPaintPreviewExitCause"> <enum name="TabbedPaintPreviewExitCause">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment