summaryrefslogtreecommitdiff
path: root/chromium/components/services/unzip
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-09-29 16:16:15 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-11-09 10:04:06 +0000
commita95a7417ad456115a1ef2da4bb8320531c0821f1 (patch)
treeedcd59279e486d2fd4a8f88a7ed025bcf925c6e6 /chromium/components/services/unzip
parent33fc33aa94d4add0878ec30dc818e34e1dd3cc2a (diff)
downloadqtwebengine-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')
-rw-r--r--chromium/components/services/unzip/BUILD.gn1
-rw-r--r--chromium/components/services/unzip/public/cpp/unzip.cc155
-rw-r--r--chromium/components/services/unzip/public/cpp/unzip.h40
-rw-r--r--chromium/components/services/unzip/public/cpp/unzip_unittest.cc6
-rw-r--r--chromium/components/services/unzip/public/mojom/unzipper.mojom2
-rw-r--r--chromium/components/services/unzip/unzipper_impl.cc58
-rw-r--r--chromium/components/services/unzip/unzipper_impl.h18
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