diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/components/paint_preview/browser | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-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')
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_ |