summaryrefslogtreecommitdiff
path: root/chromium/components/paint_preview/browser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/components/paint_preview/browser
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/paint_preview/browser')
-rw-r--r--chromium/components/paint_preview/browser/BUILD.gn1
-rw-r--r--chromium/components/paint_preview/browser/compositor_utils.cc8
-rw-r--r--chromium/components/paint_preview/browser/directory_key.cc4
-rw-r--r--chromium/components/paint_preview/browser/directory_key.h2
-rw-r--r--chromium/components/paint_preview/browser/file_manager.cc72
-rw-r--r--chromium/components/paint_preview/browser/file_manager.h12
-rw-r--r--chromium/components/paint_preview/browser/file_manager_unittest.cc57
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_base_service.cc4
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_client.cc19
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_client_unittest.cc6
-rw-r--r--chromium/components/paint_preview/browser/service_sandbox_type.h29
11 files changed, 205 insertions, 9 deletions
diff --git a/chromium/components/paint_preview/browser/BUILD.gn b/chromium/components/paint_preview/browser/BUILD.gn
index 90ebaf83615..3712dfeccb2 100644
--- a/chromium/components/paint_preview/browser/BUILD.gn
+++ b/chromium/components/paint_preview/browser/BUILD.gn
@@ -25,6 +25,7 @@ source_set("browser") {
"paint_preview_compositor_service_impl.cc",
"paint_preview_compositor_service_impl.h",
"paint_preview_policy.h",
+ "service_sandbox_type.h",
]
deps = [
diff --git a/chromium/components/paint_preview/browser/compositor_utils.cc b/chromium/components/paint_preview/browser/compositor_utils.cc
index c8e342b96dc..120d2434685 100644
--- a/chromium/components/paint_preview/browser/compositor_utils.cc
+++ b/chromium/components/paint_preview/browser/compositor_utils.cc
@@ -7,9 +7,9 @@
#include <utility>
#include "base/bind.h"
-#include "base/task/post_task.h"
#include "build/build_config.h"
#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
+#include "components/paint_preview/browser/service_sandbox_type.h"
#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/browser_task_traits.h"
@@ -41,12 +41,10 @@ CreateCompositorCollection() {
void CreateCompositorCollectionPending(
mojo::PendingReceiver<mojom::PaintPreviewCompositorCollection> collection) {
- // TODO(crbug/1074323): Investigate using a different SandboxType.
content::ServiceProcessHost::Launch<mojom::PaintPreviewCompositorCollection>(
std::move(collection),
content::ServiceProcessHost::Options()
.WithDisplayName(IDS_PAINT_PREVIEW_COMPOSITOR_SERVICE_DISPLAY_NAME)
- .WithSandboxType(service_manager::SandboxType::kPrintCompositor)
.Pass());
}
@@ -56,8 +54,8 @@ void BindDiscardableSharedMemoryManager(
discardable_memory_manager;
// Set up the discardable memory manager.
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&BindDiscardableSharedMemoryManagerOnIOThread,
discardable_memory_manager.InitWithNewPipeAndPassReceiver()));
diff --git a/chromium/components/paint_preview/browser/directory_key.cc b/chromium/components/paint_preview/browser/directory_key.cc
index 819e98c4bb9..45e07acdb7f 100644
--- a/chromium/components/paint_preview/browser/directory_key.cc
+++ b/chromium/components/paint_preview/browser/directory_key.cc
@@ -10,4 +10,8 @@ bool operator<(const DirectoryKey& a, const DirectoryKey& b) {
return a.AsciiDirname() < b.AsciiDirname();
}
+bool operator==(const DirectoryKey& a, const DirectoryKey& b) {
+ return a.AsciiDirname() == b.AsciiDirname();
+}
+
} // namespace paint_preview
diff --git a/chromium/components/paint_preview/browser/directory_key.h b/chromium/components/paint_preview/browser/directory_key.h
index a24b66afa29..bed4752f370 100644
--- a/chromium/components/paint_preview/browser/directory_key.h
+++ b/chromium/components/paint_preview/browser/directory_key.h
@@ -27,6 +27,8 @@ class DirectoryKey {
bool operator<(const DirectoryKey& a, const DirectoryKey& b);
+bool operator==(const DirectoryKey& a, const DirectoryKey& b);
+
} // namespace paint_preview
#endif // COMPONENTS_PAINT_PREVIEW_BROWSER_DIRECTORY_KEY_H_
diff --git a/chromium/components/paint_preview/browser/file_manager.cc b/chromium/components/paint_preview/browser/file_manager.cc
index 70fc611b3f2..8566302a2df 100644
--- a/chromium/components/paint_preview/browser/file_manager.cc
+++ b/chromium/components/paint_preview/browser/file_manager.cc
@@ -4,9 +4,14 @@
#include "components/paint_preview/browser/file_manager.h"
+#include <algorithm>
+#include <vector>
+
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/hash/hash.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
#include "base/strings/string_number_conversions.h"
#include "components/paint_preview/common/file_utils.h"
#include "third_party/zlib/google/zip.h"
@@ -18,6 +23,11 @@ namespace {
constexpr char kProtoName[] = "proto.pb";
constexpr char kZipExt[] = ".zip";
+bool CompareByLastModified(const base::FileEnumerator::FileInfo& a,
+ const base::FileEnumerator::FileInfo& b) {
+ return a.GetLastModifiedTime() < b.GetLastModifiedTime();
+}
+
} // namespace
FileManager::FileManager(
@@ -70,6 +80,10 @@ base::Optional<base::File::Info> FileManager::GetInfo(
return info;
}
+size_t FileManager::GetTotalDiskUsage() const {
+ return base::ComputeDirectorySize(root_directory_);
+}
+
bool FileManager::DirectoryExists(const DirectoryKey& key) const {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
base::FilePath path;
@@ -185,8 +199,23 @@ bool FileManager::SerializePaintPreviewProto(const DirectoryKey& key,
auto path = CreateOrGetDirectory(key, false);
if (!path.has_value())
return false;
- return WriteProtoToFile(path->AppendASCII(kProtoName), proto) &&
- (!compress || CompressDirectory(key));
+ bool result = WriteProtoToFile(path->AppendASCII(kProtoName), proto) &&
+ (!compress || CompressDirectory(key));
+
+ if (compress) {
+ auto info = GetInfo(key);
+ if (info.has_value()) {
+ base::UmaHistogramMemoryKB(
+ "Browser.PaintPreview.Capture.CompressedOnDiskSize",
+ info->size / 1000);
+ }
+ } else {
+ size_t size_bytes = base::ComputeDirectorySize(path.value());
+ base::UmaHistogramMemoryKB(
+ "Browser.PaintPreview.Capture.UncompressedOnDiskSize",
+ size_bytes / 1000);
+ }
+ return result;
}
std::unique_ptr<PaintPreviewProto> FileManager::DeserializePaintPreviewProto(
@@ -212,6 +241,45 @@ base::flat_set<DirectoryKey> FileManager::ListUsedKeys() const {
return base::flat_set<DirectoryKey>(std::move(keys));
}
+std::vector<DirectoryKey> FileManager::GetOldestArtifactsForCleanup(
+ size_t max_size) {
+ // The rest of this function is expensive so cleanup should exit early if not
+ // required.
+ size_t size = base::ComputeDirectorySize(root_directory_);
+ if (size <= max_size)
+ return std::vector<DirectoryKey>();
+
+ base::FileEnumerator file_enum(
+ root_directory_, false,
+ base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
+ std::vector<base::FileEnumerator::FileInfo> file_infos;
+ for (base::FilePath name = file_enum.Next(); !name.empty();
+ name = file_enum.Next()) {
+ file_infos.push_back(file_enum.GetInfo());
+ }
+
+ std::sort(file_infos.begin(), file_infos.end(), CompareByLastModified);
+
+ std::vector<DirectoryKey> keys_to_remove;
+ for (const auto& file_info : file_infos) {
+ base::FilePath full_path = root_directory_.Append(file_info.GetName());
+
+ size_t size_delta = file_info.GetSize();
+ // Computing a directory size is expensive. Most files should hopefully be
+ // compressed already.
+ if (file_info.IsDirectory())
+ size_delta = base::ComputeDirectorySize(full_path);
+
+ // Directory names should always be ASCII.
+ keys_to_remove.emplace_back(
+ file_info.GetName().RemoveExtension().MaybeAsASCII());
+ size -= size_delta;
+ if (size <= max_size)
+ break;
+ }
+ return keys_to_remove;
+}
+
FileManager::StorageType FileManager::GetPathForKey(
const DirectoryKey& key,
base::FilePath* path) const {
diff --git a/chromium/components/paint_preview/browser/file_manager.h b/chromium/components/paint_preview/browser/file_manager.h
index 3d9173e4ce4..126e418fd96 100644
--- a/chromium/components/paint_preview/browser/file_manager.h
+++ b/chromium/components/paint_preview/browser/file_manager.h
@@ -16,6 +16,7 @@
#include "url/gurl.h"
namespace paint_preview {
+class PaintPreviewTabService;
// FileManager manages paint preview files associated with a root directory.
// Typically the root directory is <profile_dir>/paint_previews/<feature>.
@@ -47,6 +48,9 @@ class FileManager : public base::RefCountedThreadSafe<FileManager> {
size_t GetSizeOfArtifacts(const DirectoryKey& key) const;
base::Optional<base::File::Info> GetInfo(const DirectoryKey& key) const;
+ // Returns the total disk usage of all paint previews.
+ size_t GetTotalDiskUsage() const;
+
// Returns true if the directory for |key| exists.
bool DirectoryExists(const DirectoryKey& key) const;
@@ -87,10 +91,18 @@ class FileManager : public base::RefCountedThreadSafe<FileManager> {
// Lists the current set of in-use DirectoryKeys.
base::flat_set<DirectoryKey> ListUsedKeys() const;
+ // 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
+ // |max_size|.
+ std::vector<DirectoryKey> GetOldestArtifactsForCleanup(size_t max_size);
+
private:
friend class base::RefCountedThreadSafe<FileManager>;
~FileManager();
+ friend class PaintPreviewTabService;
+ base::FilePath GetPath() const { return root_directory_; }
+
enum StorageType {
kNone = 0,
kDirectory = 1,
diff --git a/chromium/components/paint_preview/browser/file_manager_unittest.cc b/chromium/components/paint_preview/browser/file_manager_unittest.cc
index cacb0ce55e8..0ee9043e5ca 100644
--- a/chromium/components/paint_preview/browser/file_manager_unittest.cc
+++ b/chromium/components/paint_preview/browser/file_manager_unittest.cc
@@ -138,6 +138,7 @@ TEST_F(FileManagerTest, TestCompression) {
// Compress.
base::FilePath zip_path = directory.AddExtensionASCII(".zip");
EXPECT_TRUE(manager->CompressDirectory(key));
+ EXPECT_TRUE(manager->CompressDirectory(key)); // no-op
EXPECT_GT(manager->GetSizeOfArtifacts(key), 0U);
EXPECT_FALSE(base::PathExists(directory));
EXPECT_FALSE(base::PathExists(test_file));
@@ -275,10 +276,66 @@ TEST_F(FileManagerTest, HandleProtoCompressed) {
metadata->set_url(GURL("www.chromium.org").spec());
EXPECT_TRUE(manager->SerializePaintPreviewProto(key, original_proto, true));
+ EXPECT_TRUE(manager->CaptureExists(key));
+
EXPECT_TRUE(base::PathExists(path.AddExtensionASCII(".zip")));
auto out_proto = manager->DeserializePaintPreviewProto(key);
EXPECT_NE(out_proto, nullptr);
EXPECT_THAT(*out_proto, EqualsProto(original_proto));
+
+ EXPECT_TRUE(manager->CaptureExists(key));
+}
+
+TEST_F(FileManagerTest, OldestFilesForCleanup) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ auto manager =
+ base::MakeRefCounted<FileManager>(temp_dir.GetPath(), MainTaskRunner());
+
+ const std::string data = "Foobar";
+
+ auto key_0 = manager->CreateKey(0U);
+ base::FilePath path_0 =
+ manager->CreateOrGetDirectory(key_0, true).value_or(base::FilePath());
+ base::WriteFile(path_0.AppendASCII("0.txt"), data.data(), data.size());
+ {
+ auto to_delete = manager->GetOldestArtifactsForCleanup(0U);
+ ASSERT_EQ(to_delete.size(), 1U);
+ EXPECT_EQ(to_delete[0], key_0);
+ }
+ {
+ auto to_delete = manager->GetOldestArtifactsForCleanup(50U);
+ EXPECT_EQ(to_delete.size(), 0U);
+ }
+
+ auto key_1 = manager->CreateKey(1U);
+ base::FilePath path_1 =
+ manager->CreateOrGetDirectory(key_1, true).value_or(base::FilePath());
+ base::WriteFile(path_1.AppendASCII("1.txt"), data.data(), data.size());
+ manager->CompressDirectory(key_1);
+ base::Time modified_time = base::Time::Now();
+ auto path_1_zip = path_1.AddExtensionASCII(".zip");
+ base::TouchFile(path_0, modified_time - base::TimeDelta::FromSeconds(10),
+ modified_time - base::TimeDelta::FromSeconds(10));
+ base::TouchFile(path_1_zip, modified_time, modified_time);
+
+ {
+ auto to_delete = manager->GetOldestArtifactsForCleanup(0U);
+ ASSERT_EQ(to_delete.size(), 2U);
+ // Elements should be ordered in oldest to newest.
+ EXPECT_EQ(to_delete[0], key_0);
+ EXPECT_EQ(to_delete[1], key_1);
+ }
+ {
+ // Zip is ~116 bytes.
+ auto to_delete = manager->GetOldestArtifactsForCleanup(120U);
+ ASSERT_EQ(to_delete.size(), 1U);
+ EXPECT_EQ(to_delete[0], key_0);
+ }
+ {
+ auto to_delete = manager->GetOldestArtifactsForCleanup(150U);
+ EXPECT_EQ(to_delete.size(), 0U);
+ }
}
} // namespace paint_preview
diff --git a/chromium/components/paint_preview/browser/paint_preview_base_service.cc b/chromium/components/paint_preview/browser/paint_preview_base_service.cc
index 7b54b73c970..d99dce23ff4 100644
--- a/chromium/components/paint_preview/browser/paint_preview_base_service.cc
+++ b/chromium/components/paint_preview/browser/paint_preview_base_service.cc
@@ -148,7 +148,9 @@ void PaintPreviewBaseService::OnCaptured(
if (web_contents)
web_contents->DecrementCapturerCount(true);
- if (status != mojom::PaintPreviewStatus::kOk || !proto) {
+ if (!(status == mojom::PaintPreviewStatus::kOk ||
+ status == mojom::PaintPreviewStatus::kPartialSuccess) ||
+ !proto) {
DVLOG(1) << "ERROR: Paint Preview failed to capture for document "
<< guid.ToString() << " with error " << status;
std::move(callback).Run(kCaptureFailed, nullptr);
diff --git a/chromium/components/paint_preview/browser/paint_preview_client.cc b/chromium/components/paint_preview/browser/paint_preview_client.cc
index 35dec779664..d18772758fd 100644
--- a/chromium/components/paint_preview/browser/paint_preview_client.cc
+++ b/chromium/components/paint_preview/browser/paint_preview_client.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/files/file_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
@@ -57,6 +58,8 @@ PaintPreviewCaptureResponseToPaintPreviewFrameProto(
PaintPreviewFrameProto* proto) {
proto->set_embedding_token_high(frame_guid.GetHighForSerialization());
proto->set_embedding_token_low(frame_guid.GetLowForSerialization());
+ proto->set_scroll_offset_x(response->scroll_offsets.width());
+ proto->set_scroll_offset_y(response->scroll_offsets.height());
std::vector<base::UnguessableToken> frame_guids;
for (const auto& id_pair : response->content_id_to_embedding_token) {
@@ -332,9 +335,23 @@ void PaintPreviewClient::OnPaintPreviewCapturedCallback(
// |status|
MarkFrameAsProcessed(guid, frame_guid);
- if (status == mojom::PaintPreviewStatus::kOk)
+ if (status == mojom::PaintPreviewStatus::kOk) {
status = RecordFrame(guid, frame_guid, is_main_frame, filename,
render_frame_id, std::move(response));
+ } else {
+ // If the capture failed then cleanup the file.
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(base::GetDeleteFileCallback(), filename));
+
+ // If this is the main frame we should just abort the capture.
+ if (is_main_frame) {
+ auto it = all_document_data_.find(guid);
+ if (it != all_document_data_.end())
+ OnFinished(guid, &it->second);
+ }
+ }
+
auto it = all_document_data_.find(guid);
if (it == all_document_data_.end())
return;
diff --git a/chromium/components/paint_preview/browser/paint_preview_client_unittest.cc b/chromium/components/paint_preview/browser/paint_preview_client_unittest.cc
index 91962004fd7..ad6126749bb 100644
--- a/chromium/components/paint_preview/browser/paint_preview_client_unittest.cc
+++ b/chromium/components/paint_preview/browser/paint_preview_client_unittest.cc
@@ -18,6 +18,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_renderer_host.h"
+#include "content/public/test/test_utils.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
@@ -138,11 +139,14 @@ TEST_F(PaintPreviewClientRenderViewHostTest, CaptureMainFrameMock) {
auto response = mojom::PaintPreviewCaptureResponse::New();
response->embedding_token = base::nullopt;
+ response->scroll_offsets = gfx::Size(5, 10);
PaintPreviewProto expected_proto;
expected_proto.mutable_metadata()->set_url(expected_url.spec());
PaintPreviewFrameProto* main_frame = expected_proto.mutable_root_frame();
main_frame->set_is_main_frame(true);
+ main_frame->set_scroll_offset_x(5);
+ main_frame->set_scroll_offset_y(10);
base::RunLoop loop;
auto callback = base::BindOnce(
@@ -223,6 +227,8 @@ TEST_F(PaintPreviewClientRenderViewHostTest, CaptureFailureMock) {
ASSERT_NE(client, nullptr);
client->CapturePaintPreview(params, main_rfh(), std::move(callback));
loop.Run();
+ content::RunAllTasksUntilIdle();
+ EXPECT_TRUE(base::IsDirectoryEmpty(temp_dir_.GetPath()));
}
TEST_F(PaintPreviewClientRenderViewHostTest, RenderFrameDeletedNotCapturing) {
diff --git a/chromium/components/paint_preview/browser/service_sandbox_type.h b/chromium/components/paint_preview/browser/service_sandbox_type.h
new file mode 100644
index 00000000000..f955efc4a33
--- /dev/null
+++ b/chromium/components/paint_preview/browser/service_sandbox_type.h
@@ -0,0 +1,29 @@
+// Copyright 2020 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_PAINT_PREVIEW_BROWSER_SERVICE_SANDBOX_TYPE_H_
+#define COMPONENTS_PAINT_PREVIEW_BROWSER_SERVICE_SANDBOX_TYPE_H_
+
+#include "content/public/browser/sandbox_type.h"
+#include "content/public/browser/service_process_host.h"
+
+// This file maps service classes to sandbox types. Services which
+// require a non-utility sandbox can be added here. See
+// ServiceProcessHost::Launch() for how these templates are consumed.
+
+// paint_preview::mojom::PaintPreviewCompositorCollection
+namespace paint_preview {
+namespace mojom {
+class PaintPreviewCompositorCollection;
+}
+} // namespace paint_preview
+
+template <>
+inline content::SandboxType content::GetServiceSandboxType<
+ paint_preview::mojom::PaintPreviewCompositorCollection>() {
+ // TODO(crbug/1074323): Investigate using a different SandboxType.
+ return content::SandboxType::kPrintCompositor;
+}
+
+#endif // COMPONENTS_PAINT_PREVIEW_BROWSER_SERVICE_SANDBOX_TYPE_H_