diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-09-29 16:16:15 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-11-09 10:04:06 +0000 |
commit | a95a7417ad456115a1ef2da4bb8320531c0821f1 (patch) | |
tree | edcd59279e486d2fd4a8f88a7ed025bcf925c6e6 /chromium/components/services/unzip | |
parent | 33fc33aa94d4add0878ec30dc818e34e1dd3cc2a (diff) | |
download | qtwebengine-chromium-a95a7417ad456115a1ef2da4bb8320531c0821f1.tar.gz |
BASELINE: Update Chromium to 106.0.5249.126
Change-Id: Ib0bb21c437a7d1686e21c33f2d329f2ac425b7ab
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/438936
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/services/unzip')
7 files changed, 242 insertions, 38 deletions
diff --git a/chromium/components/services/unzip/BUILD.gn b/chromium/components/services/unzip/BUILD.gn index 101ad663dc1..6a74da3d3e7 100644 --- a/chromium/components/services/unzip/BUILD.gn +++ b/chromium/components/services/unzip/BUILD.gn @@ -46,6 +46,7 @@ bundle_data("unit_tests_bundle_data") { visibility = [ ":unit_tests" ] testonly = true sources = [ + "//components/test/data/unzip_service/DifferentEncryptions.zip", "//components/test/data/unzip_service/Duplicate Filenames.zip", "//components/test/data/unzip_service/SJIS 00.zip", "//components/test/data/unzip_service/SJIS 01.zip", diff --git a/chromium/components/services/unzip/public/cpp/unzip.cc b/chromium/components/services/unzip/public/cpp/unzip.cc index 90e753613fe..c2c7c28351e 100644 --- a/chromium/components/services/unzip/public/cpp/unzip.cc +++ b/chromium/components/services/unzip/public/cpp/unzip.cc @@ -16,13 +16,13 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" +#include "base/synchronization/atomic_flag.h" #include "base/task/bind_post_task.h" #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "components/services/filesystem/directory_impl.h" -#include "components/services/filesystem/lock_table.h" #include "components/services/unzip/public/mojom/unzipper.mojom.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -69,6 +69,9 @@ class UnzipParams : public base::RefCounted<UnzipParams>, return &listener_receiver_; } + // Set by the task runner when it resets the UnzipParams object. + base::AtomicFlag clean_up_is_done; + private: friend class base::RefCounted<UnzipParams>; @@ -157,48 +160,69 @@ class GetExtractedInfoParams : public base::RefCounted<GetExtractedInfoParams> { GetExtractedInfoCallback callback_; }; -void DoUnzip(mojo::PendingRemote<mojom::Unzipper> unzipper, - const base::FilePath& zip_path, - const base::FilePath& output_dir, - UnzipFilterCallback filter_callback, - UnzipListenerCallback listener_callback, - mojom::UnzipOptionsPtr options, - UnzipCallback result_callback) { - base::File zip_file(zip_path, base::File::FLAG_OPEN | base::File::FLAG_READ); +bool CheckZipFileValid(const base::FilePath& zip_path, + const base::File& zip_file) { if (!zip_file.IsValid()) { LOG(ERROR) << "Cannot open ZIP archive " << Redact(zip_path) << ": " << base::File::ErrorToString(zip_file.error_details()); - std::move(result_callback).Run(false); - return; + return false; } + return true; +} - mojo::PendingRemote<filesystem::mojom::Directory> directory_remote; +void PrepareUnzipParams( + scoped_refptr<UnzipParams> unzip_params, + const base::FilePath& output_dir, + UnzipFilterCallback filter_callback, + UnzipListenerCallback listener_callback, + mojo::PendingRemote<filesystem::mojom::Directory>& directory_remote, + mojo::PendingRemote<unzip::mojom::UnzipFilter>& filter_remote, + mojo::PendingRemote<unzip::mojom::UnzipListener>& listener_remote) { mojo::MakeSelfOwnedReceiver( - std::make_unique<filesystem::DirectoryImpl>(output_dir, nullptr, nullptr), + std::make_unique<filesystem::DirectoryImpl>(output_dir, nullptr), directory_remote.InitWithNewPipeAndPassReceiver()); - // |result_callback| is shared between the connection error handler and the - // Unzip call using a refcounted UnzipParams object that owns - // |result_callback|. - auto unzip_params = base::MakeRefCounted<UnzipParams>( - std::move(unzipper), std::move(result_callback)); - unzip_params->unzipper().set_disconnect_handler( base::BindOnce(&UnzipParams::InvokeCallback, unzip_params, false)); - mojo::PendingRemote<unzip::mojom::UnzipFilter> filter_remote; if (filter_callback) { unzip_params->SetFilter(filter_remote.InitWithNewPipeAndPassReceiver(), std::move(filter_callback)); } - mojo::PendingRemote<unzip::mojom::UnzipListener> listener_remote; if (listener_callback) { mojo::Receiver<unzip::mojom::UnzipListener>* listener = unzip_params->GetListenerReceiver(); unzip_params->SetListener(std::move(listener_callback)); listener_remote = listener->BindNewPipeAndPassRemote(); } +} + +void DoUnzip(mojo::PendingRemote<mojom::Unzipper> unzipper, + const base::FilePath& zip_path, + const base::FilePath& output_dir, + UnzipFilterCallback filter_callback, + UnzipListenerCallback listener_callback, + mojom::UnzipOptionsPtr options, + UnzipCallback result_callback) { + base::File zip_file(zip_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!CheckZipFileValid(zip_path, zip_file)) { + std::move(result_callback).Run(false); + return; + } + + // |result_callback| is shared between the connection error handler and the + // Unzip call using a refcounted UnzipParams object that owns + // |result_callback|. + auto unzip_params = base::MakeRefCounted<UnzipParams>( + std::move(unzipper), std::move(result_callback)); + + mojo::PendingRemote<filesystem::mojom::Directory> directory_remote; + mojo::PendingRemote<unzip::mojom::UnzipFilter> filter_remote; + mojo::PendingRemote<unzip::mojom::UnzipListener> listener_remote; + PrepareUnzipParams(unzip_params, output_dir, filter_callback, + listener_callback, directory_remote, filter_remote, + listener_remote); unzip_params->unzipper()->Unzip( std::move(zip_file), std::move(directory_remote), std::move(options), @@ -235,7 +259,7 @@ void DoGetExtractedInfo(mojo::PendingRemote<mojom::Unzipper> unzipper, const base::FilePath& zip_path, GetExtractedInfoCallback result_callback) { base::File zip_file(zip_path, base::File::FLAG_OPEN | base::File::FLAG_READ); - unzip::mojom::InfoPtr info = unzip::mojom::Info::New(false, 0, false); + unzip::mojom::InfoPtr info = unzip::mojom::Info::New(false, 0, false, false); if (!zip_file.IsValid()) { LOG(ERROR) << "Cannot open ZIP archive " << Redact(zip_path) << ": " << base::File::ErrorToString(zip_file.error_details()); @@ -338,4 +362,91 @@ void GetExtractedInfo(mojo::PendingRemote<mojom::Unzipper> unzipper, std::move(result_callback)))); } +ZipFileUnpacker::ZipFileUnpacker() = default; + +ZipFileUnpacker::~ZipFileUnpacker() = default; + +void DoUnzipWithParams(mojo::PendingRemote<mojom::Unzipper> unzipper, + scoped_refptr<UnzipParams>& unzip_params, + const base::FilePath& zip_path, + const base::FilePath& output_dir, + UnzipFilterCallback filter_callback, + UnzipListenerCallback listener_callback, + mojom::UnzipOptionsPtr options, + UnzipCallback result_callback) { + base::File zip_file(zip_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!CheckZipFileValid(zip_path, zip_file)) { + std::move(result_callback).Run(false); + return; + } + + // |result_callback| is shared between the connection error handler and the + // Unzip call using a refcounted UnzipParams object that owns + // |result_callback|. + unzip_params = base::MakeRefCounted<UnzipParams>(std::move(unzipper), + std::move(result_callback)); + + mojo::PendingRemote<filesystem::mojom::Directory> directory_remote; + mojo::PendingRemote<unzip::mojom::UnzipFilter> filter_remote; + mojo::PendingRemote<unzip::mojom::UnzipListener> listener_remote; + PrepareUnzipParams(unzip_params, output_dir, filter_callback, + listener_callback, directory_remote, filter_remote, + listener_remote); + + unzip_params->unzipper()->Unzip( + std::move(zip_file), std::move(directory_remote), std::move(options), + std::move(filter_remote), std::move(listener_remote), + base::BindOnce(&UnzipParams::InvokeCallback, unzip_params)); +} + +void ZipFileUnpacker::Unpack(mojo::PendingRemote<mojom::Unzipper> unzipper, + const base::FilePath& zip_file, + const base::FilePath& output_dir, + mojom::UnzipOptionsPtr options, + UnzipListenerCallback listener_callback, + UnzipCallback result_callback) { + DCHECK(!result_callback.is_null()); + + runner_->PostTask( + FROM_HERE, + base::BindOnce(&::unzip::DoUnzipWithParams, std::move(unzipper), + std::ref(params_), zip_file, output_dir, + UnzipFilterCallback(), + base::BindPostTask(base::SequencedTaskRunnerHandle::Get(), + std::move(listener_callback)), + std::move(options), + base::BindPostTask(base::SequencedTaskRunnerHandle::Get(), + std::move(result_callback)))); +} + +void ReleaseParams(scoped_refptr<UnzipParams>& unzip_params) { + if (unzip_params) { + unzip_params->clean_up_is_done.Set(); + unzip_params.reset(); + } +} + +void EndUnpack(scoped_refptr<UnzipParams>& unzip_params) { + if (unzip_params) { + unzip_params->InvokeCallback(false); + ReleaseParams(unzip_params); + } +} + +void ZipFileUnpacker::Stop() { + runner_->PostTask(FROM_HERE, base::BindOnce(&EndUnpack, std::ref(params_))); +} + +bool ZipFileUnpacker::CleanUpDone() { + if (params_) { + return params_->clean_up_is_done.IsSet(); + } + return true; +} + +void ZipFileUnpacker::CleanUp() { + runner_->PostTask(FROM_HERE, + base::BindOnce(&ReleaseParams, std::ref(params_))); +} + } // namespace unzip diff --git a/chromium/components/services/unzip/public/cpp/unzip.h b/chromium/components/services/unzip/public/cpp/unzip.h index ead7290a051..a9f21eccec7 100644 --- a/chromium/components/services/unzip/public/cpp/unzip.h +++ b/chromium/components/services/unzip/public/cpp/unzip.h @@ -6,6 +6,7 @@ #define COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_UNZIP_H_ #include "base/callback_forward.h" +#include "base/task/thread_pool.h" #include "components/services/unzip/public/mojom/unzipper.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/ced/src/util/encodings/encodings.h" @@ -51,6 +52,45 @@ void GetExtractedInfo(mojo::PendingRemote<mojom::Unzipper> unzipper, const base::FilePath& zip_file, GetExtractedInfoCallback result_callback); +namespace { +class UnzipParams; +} + +// Class that wraps the unzip service to manage the lifetime of its +// mojo conncections to enable cancellation, etc. +class ZipFileUnpacker : public base::RefCountedThreadSafe<ZipFileUnpacker> { + public: + ZipFileUnpacker(); + void Unpack(mojo::PendingRemote<mojom::Unzipper> unzipper, + const base::FilePath& zip_file, + const base::FilePath& output_dir, + mojom::UnzipOptionsPtr options, + UnzipListenerCallback listener_callback, + UnzipCallback result_callback); + + void Stop(); + + bool CleanUpDone(); + + void CleanUp(); + + private: + friend class base::RefCountedThreadSafe<ZipFileUnpacker>; + + ~ZipFileUnpacker(); + + const scoped_refptr<base::SequencedTaskRunner> runner_ = + base::ThreadPool::CreateSequencedTaskRunner( + {base::TaskPriority::USER_VISIBLE, base::MayBlock(), + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); + + base::File zip_file_; + scoped_refptr<UnzipParams> params_; + mojo::PendingRemote<filesystem::mojom::Directory> directory_remote_; + mojo::PendingRemote<unzip::mojom::UnzipFilter> filter_remote_; + mojo::PendingRemote<unzip::mojom::UnzipListener> listener_remote_; +}; + } // namespace unzip #endif // COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_UNZIP_H_ diff --git a/chromium/components/services/unzip/public/cpp/unzip_unittest.cc b/chromium/components/services/unzip/public/cpp/unzip_unittest.cc index db4db7d2158..3630b0f1c1b 100644 --- a/chromium/components/services/unzip/public/cpp/unzip_unittest.cc +++ b/chromium/components/services/unzip/public/cpp/unzip_unittest.cc @@ -332,5 +332,11 @@ TEST_F(UnzipTest, ExtractEncrypted) { EXPECT_EQ(5, CountFiles(unzip_dir_, &some_files_empty)); } +TEST_F(UnzipTest, DetectAESArchive) { + mojom::Info result = + DoGetExtractedInfo(GetArchivePath("DifferentEncryptions.zip")); + EXPECT_TRUE(result.uses_aes_encryption); +} + } // namespace } // namespace unzip diff --git a/chromium/components/services/unzip/public/mojom/unzipper.mojom b/chromium/components/services/unzip/public/mojom/unzipper.mojom index 1ed647f1365..620c6844592 100644 --- a/chromium/components/services/unzip/public/mojom/unzipper.mojom +++ b/chromium/components/services/unzip/public/mojom/unzipper.mojom @@ -24,6 +24,8 @@ struct Info { uint64 size; // Boolean set to true if the ZIP contains encrypted content. bool is_encrypted; + // Boolean set to true if the ZIP encrypted content uses AES. + bool uses_aes_encryption; }; // UnzipFilter is used to call back into the caller to check if diff --git a/chromium/components/services/unzip/unzipper_impl.cc b/chromium/components/services/unzip/unzipper_impl.cc index a0f5ba9fbb5..af74ee09ad4 100644 --- a/chromium/components/services/unzip/unzipper_impl.cc +++ b/chromium/components/services/unzip/unzipper_impl.cc @@ -150,7 +150,10 @@ std::string GetRawFileNamesFromZip(const base::File& zip_file) { UnzipperImpl::UnzipperImpl() = default; UnzipperImpl::UnzipperImpl(mojo::PendingReceiver<mojom::Unzipper> receiver) - : receiver_(this, std::move(receiver)) {} + : receiver_(this, std::move(receiver)) { + receiver_.set_disconnect_handler(base::BindOnce( + &UnzipperImpl::OnReceiverDisconnect, weak_ptr_factory_.GetWeakPtr())); +} UnzipperImpl::~UnzipperImpl() = default; @@ -202,15 +205,13 @@ bool DoUnzip(base::File zip_file, .password = std::move(password)}); } -void UnzipperImpl::Unzip( +bool RunUnzip( base::File zip_file, mojo::PendingRemote<filesystem::mojom::Directory> output_dir_remote, - mojom::UnzipOptionsPtr set_options, + std::string encoding_name, + std::string password, mojo::PendingRemote<mojom::UnzipFilter> filter_remote, - mojo::PendingRemote<mojom::UnzipListener> listener_remote, - UnzipCallback callback) { - DCHECK(zip_file.IsValid()); - + mojo::PendingRemote<mojom::UnzipListener> listener_remote) { mojo::Remote<filesystem::mojom::Directory> output_dir( std::move(output_dir_remote)); @@ -226,6 +227,24 @@ void UnzipperImpl::Unzip( progress_cb = base::BindRepeating(&UnzipperImpl::Listener, std::move(listener)); } + return zip::Unzip( + zip_file.GetPlatformFile(), + base::BindRepeating(&MakeFileWriterDelegate, output_dir.get()), + base::BindRepeating(&CreateDirectory, output_dir.get()), + {.encoding = std::move(encoding_name), + .filter = std::move(filter_cb), + .progress = std::move(progress_cb), + .password = std::move(password)}); +} + +void UnzipperImpl::Unzip( + base::File zip_file, + mojo::PendingRemote<filesystem::mojom::Directory> output_dir_remote, + mojom::UnzipOptionsPtr set_options, + mojo::PendingRemote<mojom::UnzipFilter> filter_remote, + mojo::PendingRemote<mojom::UnzipListener> listener_remote, + UnzipCallback callback) { + DCHECK(zip_file.IsValid()); std::string encoding_name; if (set_options->encoding == "auto") { @@ -237,11 +256,12 @@ void UnzipperImpl::Unzip( encoding_name = set_options->encoding; } - base::SequencedTaskRunnerHandle::Get()->PostTaskAndReplyWithResult( + runner_->PostTaskAndReplyWithResult( FROM_HERE, - base::BindOnce(&DoUnzip, std::move(zip_file), std::move(output_dir), - std::move(encoding_name), std::move(set_options->password), - std::move(filter_cb), std::move(progress_cb)), + base::BindOnce(&RunUnzip, std::move(zip_file), + std::move(output_dir_remote), std::move(encoding_name), + std::move(set_options->password), std::move(filter_remote), + std::move(listener_remote)), base::BindOnce(std::move(callback))); } @@ -262,7 +282,8 @@ void UnzipperImpl::GetExtractedInfo(base::File zip_file, if (!reader.OpenFromPlatformFile(zip_file.GetPlatformFile())) { LOG(ERROR) << "Cannot decode ZIP archive from file handle " << zip_file.GetPlatformFile(); - unzip::mojom::InfoPtr info = unzip::mojom::Info::New(false, 0, false); + unzip::mojom::InfoPtr info = + unzip::mojom::Info::New(false, 0, false, false); std::move(callback).Run(std::move(info)); return; } @@ -270,6 +291,7 @@ void UnzipperImpl::GetExtractedInfo(base::File zip_file, int64_t size = 0; bool valid = true; bool has_encrypted_content = false; + bool uses_aes_encryption = false; // Iterate over file entries of the ZIP archive. while (const zip::ZipReader::Entry* const entry = reader.Next()) { @@ -287,11 +309,19 @@ void UnzipperImpl::GetExtractedInfo(base::File zip_file, } if (entry->is_encrypted) { has_encrypted_content = true; + if (entry->uses_aes_encryption) { + uses_aes_encryption = true; + } } } - unzip::mojom::InfoPtr info = - unzip::mojom::Info::New(valid, size, has_encrypted_content); + unzip::mojom::InfoPtr info = unzip::mojom::Info::New( + valid, size, has_encrypted_content, uses_aes_encryption); std::move(callback).Run(std::move(info)); } +void UnzipperImpl::OnReceiverDisconnect() { + DCHECK(receiver_.is_bound()); + receiver_.reset(); +} + } // namespace unzip diff --git a/chromium/components/services/unzip/unzipper_impl.h b/chromium/components/services/unzip/unzipper_impl.h index 89f132addbf..2bd9541727f 100644 --- a/chromium/components/services/unzip/unzipper_impl.h +++ b/chromium/components/services/unzip/unzipper_impl.h @@ -6,6 +6,8 @@ #define COMPONENTS_SERVICES_UNZIP_UNZIPPER_IMPL_H_ #include "base/files/file.h" +#include "base/memory/weak_ptr.h" +#include "base/task/thread_pool.h" #include "components/services/unzip/public/mojom/unzipper.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -26,6 +28,9 @@ class UnzipperImpl : public mojom::Unzipper { UnzipperImpl(const UnzipperImpl&) = delete; UnzipperImpl& operator=(const UnzipperImpl&) = delete; + static void Listener(const mojo::Remote<mojom::UnzipListener>& listener, + uint64_t bytes); + ~UnzipperImpl() override; private: @@ -44,10 +49,19 @@ class UnzipperImpl : public mojom::Unzipper { void GetExtractedInfo(base::File zip_file, GetExtractedInfoCallback callback) override; - static void Listener(const mojo::Remote<mojom::UnzipListener>& listener, - uint64_t bytes); + // Disconnect handler for the receiver. + void OnReceiverDisconnect(); + + // Task runner for ZIP extraction. + using RunnerPtr = scoped_refptr<base::SequencedTaskRunner>; + const RunnerPtr runner_ = base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::WithBaseSyncPrimitives(), + base::TaskPriority::USER_BLOCKING, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); mojo::Receiver<mojom::Unzipper> receiver_{this}; + + base::WeakPtrFactory<UnzipperImpl> weak_ptr_factory_{this}; }; } // namespace unzip |