Commit 952e6e08 authored by Olya Kalitova's avatar Olya Kalitova Committed by Commit Bot

Add unzipping functionality to PluginVmImageManager

After PluginVm image is successfully downloaded it needs to be unzipped to a specific location. This CL adds unzipping functionality to the PluginVmImageManager so unzipping of the downloaded image could be called using manager and observer could receive events regarding status of the unzipping.

Bug: 904851
Test: unit_tests --gtest_filter="PluginVmImageManagerTest.*"
Change-Id: I005929fccbeec191951a054e303bc816e853285a
Reviewed-on: https://chromium-review.googlesource.com/c/1443171
Commit-Queue: Olya Kalitova <okalitova@chromium.org>
Reviewed-by: default avatarIgor <igorcov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#629931}
parent 7d8cbfa9
...@@ -4,40 +4,79 @@ ...@@ -4,40 +4,79 @@
#include "chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.h"
#include <memory>
#include <string> #include <string>
#include "base/bind.h" #include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/guid.h" #include "base/guid.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h"
#include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/download/download_service_factory.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "components/download/public/background_service/download_service.h" #include "components/download/public/background_service/download_service.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/traffic_annotation/network_traffic_annotation.h"
#include "third_party/zlib/google/zip.h"
namespace plugin_vm { namespace plugin_vm {
bool PluginVmImageManager::IsDownloading() { bool PluginVmImageManager::IsProcessingImage() {
return processing_download_; return processing_image_;
} }
void PluginVmImageManager::StartDownload() { void PluginVmImageManager::StartDownload() {
if (IsDownloading()) if (IsProcessingImage()) {
return OnDownloadFailed(); LOG(ERROR) << "Download of a PluginVm image couldn't be started as"
processing_download_ = true; << " another PluginVm image is currently being processed";
OnDownloadFailed();
return;
}
processing_image_ = true;
download_service_->StartDownload(GetDownloadParams()); download_service_->StartDownload(GetDownloadParams());
} }
void PluginVmImageManager::CancelDownload() { void PluginVmImageManager::CancelDownload() {
DCHECK(!current_download_guid_.empty());
download_service_->CancelDownload(current_download_guid_); download_service_->CancelDownload(current_download_guid_);
} }
void PluginVmImageManager::StartUnzipping() {
if (IsDownloading()) {
LOG(ERROR) << "Unzipping of PluginVm image couldn't be proceeded "
<< "as image is still being downloaded";
OnUnzipped(false);
return;
}
if (!EnsureDirectoryForPluginVmImageIsPresent() ||
!EnsureDownloadedPluginVmImageArchiveIsPresent()) {
LOG(ERROR) << "Unzipping of PluginVm image couldn't be proceeded";
OnUnzipped(false);
return;
}
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
base::BindOnce(&PluginVmImageManager::UnzipDownloadedPluginVmImageArchive,
base::Unretained(this)),
base::BindOnce(&PluginVmImageManager::OnUnzipped,
weak_ptr_factory_.GetWeakPtr()));
}
void PluginVmImageManager::CancelUnzipping() {
unzipping_cancelled_ = true;
}
void PluginVmImageManager::SetObserver(Observer* observer) { void PluginVmImageManager::SetObserver(Observer* observer) {
observer_ = observer; observer_ = observer;
} }
void PluginVmImageManager::RemoveObserver() {
observer_ = nullptr;
}
void PluginVmImageManager::OnDownloadStarted() { void PluginVmImageManager::OnDownloadStarted() {
if (observer_) if (observer_)
observer_->OnDownloadStarted(); observer_->OnDownloadStarted();
...@@ -50,24 +89,26 @@ void PluginVmImageManager::OnProgressUpdated( ...@@ -50,24 +89,26 @@ void PluginVmImageManager::OnProgressUpdated(
} }
void PluginVmImageManager::OnDownloadCompleted(base::FilePath file_path) { void PluginVmImageManager::OnDownloadCompleted(base::FilePath file_path) {
if (observer_) downloaded_plugin_vm_image_archive_ = file_path;
observer_->OnDownloadCompleted(file_path);
current_download_guid_.clear(); current_download_guid_.clear();
processing_download_ = false; if (observer_)
observer_->OnDownloadCompleted();
} }
void PluginVmImageManager::OnDownloadCancelled() { void PluginVmImageManager::OnDownloadCancelled() {
RemoveTemporaryPluginVmImageArchiveIfExists();
current_download_guid_.clear();
processing_image_ = false;
if (observer_) if (observer_)
observer_->OnDownloadCancelled(); observer_->OnDownloadCancelled();
current_download_guid_.clear();
processing_download_ = false;
} }
void PluginVmImageManager::OnDownloadFailed() { void PluginVmImageManager::OnDownloadFailed() {
RemoveTemporaryPluginVmImageArchiveIfExists();
current_download_guid_.clear();
processing_image_ = false;
if (observer_) if (observer_)
observer_->OnDownloadFailed(); observer_->OnDownloadFailed();
current_download_guid_.clear();
processing_download_ = false;
} }
void PluginVmImageManager::SetDownloadServiceForTesting( void PluginVmImageManager::SetDownloadServiceForTesting(
...@@ -75,14 +116,19 @@ void PluginVmImageManager::SetDownloadServiceForTesting( ...@@ -75,14 +116,19 @@ void PluginVmImageManager::SetDownloadServiceForTesting(
download_service_ = download_service; download_service_ = download_service;
} }
void PluginVmImageManager::SetDownloadedPluginVmImageArchiveForTesting(
base::FilePath downloaded_plugin_vm_image_archive) {
downloaded_plugin_vm_image_archive_ = downloaded_plugin_vm_image_archive;
}
std::string PluginVmImageManager::GetCurrentDownloadGuidForTesting() { std::string PluginVmImageManager::GetCurrentDownloadGuidForTesting() {
return current_download_guid_; return current_download_guid_;
} }
PluginVmImageManager::PluginVmImageManager(Profile* profile) PluginVmImageManager::PluginVmImageManager(Profile* profile)
: profile_(profile), : profile_(profile),
download_service_(DownloadServiceFactory::GetForBrowserContext(profile)) { download_service_(DownloadServiceFactory::GetForBrowserContext(profile)),
} weak_ptr_factory_(this) {}
PluginVmImageManager::~PluginVmImageManager() = default; PluginVmImageManager::~PluginVmImageManager() = default;
download::DownloadParams PluginVmImageManager::GetDownloadParams() { download::DownloadParams PluginVmImageManager::GetDownloadParams() {
...@@ -91,8 +137,8 @@ download::DownloadParams PluginVmImageManager::GetDownloadParams() { ...@@ -91,8 +137,8 @@ download::DownloadParams PluginVmImageManager::GetDownloadParams() {
// DownloadParams // DownloadParams
params.client = download::DownloadClient::PLUGIN_VM_IMAGE; params.client = download::DownloadClient::PLUGIN_VM_IMAGE;
params.guid = base::GenerateGUID(); params.guid = base::GenerateGUID();
params.callback = base::BindRepeating(&PluginVmImageManager::OnStarted, params.callback = base::BindRepeating(&PluginVmImageManager::OnStartDownload,
base::Unretained(this)); weak_ptr_factory_.GetWeakPtr());
// TODO(okalitova): Create annotation. // TODO(okalitova): Create annotation.
params.traffic_annotation = params.traffic_annotation =
net::MutableNetworkTrafficAnnotationTag(NO_TRAFFIC_ANNOTATION_YET); net::MutableNetworkTrafficAnnotationTag(NO_TRAFFIC_ANNOTATION_YET);
...@@ -117,7 +163,7 @@ download::DownloadParams PluginVmImageManager::GetDownloadParams() { ...@@ -117,7 +163,7 @@ download::DownloadParams PluginVmImageManager::GetDownloadParams() {
return params; return params;
} }
void PluginVmImageManager::OnStarted( void PluginVmImageManager::OnStartDownload(
const std::string& download_guid, const std::string& download_guid,
download::DownloadParams::StartResult start_result) { download::DownloadParams::StartResult start_result) {
if (start_result == download::DownloadParams::ACCEPTED) if (start_result == download::DownloadParams::ACCEPTED)
...@@ -126,4 +172,137 @@ void PluginVmImageManager::OnStarted( ...@@ -126,4 +172,137 @@ void PluginVmImageManager::OnStarted(
OnDownloadFailed(); OnDownloadFailed();
} }
bool PluginVmImageManager::IsDownloading() {
return !current_download_guid_.empty();
}
bool PluginVmImageManager::UnzipDownloadedPluginVmImageArchive() {
base::File file(downloaded_plugin_vm_image_archive_,
base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!file.IsValid()) {
LOG(ERROR) << "Failed to open "
<< downloaded_plugin_vm_image_archive_.value();
return false;
}
bool success = zip::UnzipWithFilterAndWriters(
file.GetPlatformFile(),
base::BindRepeating(
&PluginVmImageManager::CreatePluginVmImageWriterDelegate,
base::Unretained(this)),
base::BindRepeating(&PluginVmImageManager::CreateDirectory,
base::Unretained(this)),
base::BindRepeating(
&PluginVmImageManager::FilterFilesInPluginVmImageArchive,
base::Unretained(this)),
true /* log_skipped_files */);
return success;
}
bool PluginVmImageManager::IsUnzippingCancelled() {
return unzipping_cancelled_;
}
PluginVmImageManager::PluginVmImageWriterDelegate::PluginVmImageWriterDelegate(
PluginVmImageManager* manager,
const base::FilePath& output_file_path)
: manager_(manager), output_file_path_(output_file_path) {}
bool PluginVmImageManager::PluginVmImageWriterDelegate::PrepareOutput() {
// We can't rely on parent directory entries being specified in the
// zip, so we make sure they are created.
if (!base::CreateDirectory(output_file_path_.DirName()))
return false;
output_file_.Initialize(output_file_path_, base::File::FLAG_CREATE_ALWAYS |
base::File::FLAG_WRITE);
return output_file_.IsValid();
}
bool PluginVmImageManager::PluginVmImageWriterDelegate::WriteBytes(
const char* data,
int num_bytes) {
return !manager_->IsUnzippingCancelled() &&
num_bytes == output_file_.WriteAtCurrentPos(data, num_bytes);
}
void PluginVmImageManager::PluginVmImageWriterDelegate::SetTimeModified(
const base::Time& time) {
output_file_.Close();
base::TouchFile(output_file_path_, base::Time::Now(), time);
}
std::unique_ptr<zip::WriterDelegate>
PluginVmImageManager::CreatePluginVmImageWriterDelegate(
const base::FilePath& entry_path) {
return std::make_unique<PluginVmImageWriterDelegate>(
this, plugin_vm_image_dir_.Append(entry_path));
}
bool PluginVmImageManager::CreateDirectory(const base::FilePath& entry_path) {
return base::CreateDirectory(plugin_vm_image_dir_.Append(entry_path));
}
bool PluginVmImageManager::FilterFilesInPluginVmImageArchive(
const base::FilePath& file) {
return true;
}
void PluginVmImageManager::OnUnzipped(bool success) {
unzipping_cancelled_ = false;
RemoveTemporaryPluginVmImageArchiveIfExists();
if (!success) {
if (observer_)
observer_->OnUnzippingFailed();
RemovePluginVmImageDirectoryIfExists();
processing_image_ = false;
return;
}
if (observer_)
observer_->OnUnzipped();
processing_image_ = false;
// TODO(okalitova): Populate necessary preferences with information about
// PluginVm image that has been successfully downloaded and extracted.
}
bool PluginVmImageManager::EnsureDownloadedPluginVmImageArchiveIsPresent() {
return !downloaded_plugin_vm_image_archive_.empty();
}
bool PluginVmImageManager::EnsureDirectoryForPluginVmImageIsPresent() {
plugin_vm_image_dir_ = profile_->GetPath()
.AppendASCII(kCrosvmDir)
.AppendASCII(kPvmDir)
.AppendASCII(kPluginVmImageDir);
if (!base::CreateDirectory(plugin_vm_image_dir_)) {
LOG(ERROR) << "Directory " << plugin_vm_image_dir_.value()
<< " failed to be created";
plugin_vm_image_dir_.clear();
return false;
}
return true;
}
void PluginVmImageManager::RemoveTemporaryPluginVmImageArchiveIfExists() {
if (!downloaded_plugin_vm_image_archive_.empty()) {
if (!base::DeleteFile(downloaded_plugin_vm_image_archive_,
false /* recursive */)) {
LOG(ERROR) << "Downloaded PluginVm image archive located in "
<< downloaded_plugin_vm_image_archive_.value()
<< " failed to be deleted";
}
downloaded_plugin_vm_image_archive_.clear();
}
}
void PluginVmImageManager::RemovePluginVmImageDirectoryIfExists() {
if (!plugin_vm_image_dir_.empty()) {
if (!base::DeleteFile(plugin_vm_image_dir_, true /* recursive */)) {
LOG(ERROR) << "Directory with PluginVm image "
<< plugin_vm_image_dir_.value() << " failed to be deleted";
}
plugin_vm_image_dir_.clear();
}
}
} // namespace plugin_vm } // namespace plugin_vm
...@@ -5,11 +5,14 @@ ...@@ -5,11 +5,14 @@
#ifndef CHROME_BROWSER_CHROMEOS_PLUGIN_VM_PLUGIN_VM_IMAGE_MANAGER_H_ #ifndef CHROME_BROWSER_CHROMEOS_PLUGIN_VM_PLUGIN_VM_IMAGE_MANAGER_H_
#define CHROME_BROWSER_CHROMEOS_PLUGIN_VM_PLUGIN_VM_IMAGE_MANAGER_H_ #define CHROME_BROWSER_CHROMEOS_PLUGIN_VM_PLUGIN_VM_IMAGE_MANAGER_H_
#include <memory>
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/download/public/background_service/download_params.h" #include "components/download/public/background_service/download_params.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
#include "third_party/zlib/google/zip_reader.h"
namespace base { namespace base {
template <typename T> template <typename T>
...@@ -24,13 +27,17 @@ class Profile; ...@@ -24,13 +27,17 @@ class Profile;
namespace plugin_vm { namespace plugin_vm {
constexpr char kCrosvmDir[] = "crosvm";
constexpr char kPvmDir[] = "pvm";
constexpr char kPluginVmImageDir[] = "default";
// PluginVmImageManager is responsible for management of PluginVm image // PluginVmImageManager is responsible for management of PluginVm image
// including downloading this image from url specified by user policy and // including downloading this image from url specified by user policy and
// unzipping downloaded image to the specified location. // unzipping downloaded image archive to the specified location.
// //
// Only one download of PluginVm image at a time is allowed. // Only one PluginVm image at a time is allowed to be processed.
// IsDownloading() should be called to check whether the manager is downloading // IsProcessingImage() should be called to check whether any image is being
// PluginVm image at the moment. // processed at the moment.
class PluginVmImageManager : public KeyedService { class PluginVmImageManager : public KeyedService {
public: public:
// Observer class for the PluginVm image related events. // Observer class for the PluginVm image related events.
...@@ -40,23 +47,37 @@ class PluginVmImageManager : public KeyedService { ...@@ -40,23 +47,37 @@ class PluginVmImageManager : public KeyedService {
virtual void OnDownloadStarted() = 0; virtual void OnDownloadStarted() = 0;
virtual void OnProgressUpdated( virtual void OnProgressUpdated(
base::Optional<double> fraction_complete) = 0; base::Optional<double> fraction_complete) = 0;
virtual void OnDownloadCompleted(base::FilePath file_path) = 0; virtual void OnDownloadCompleted() = 0;
virtual void OnDownloadCancelled() = 0; virtual void OnDownloadCancelled() = 0;
// TODO(https://crbug.com/904851): Add failure reasons. // TODO(https://crbug.com/904851): Add failure reasons.
virtual void OnDownloadFailed() = 0; virtual void OnDownloadFailed() = 0;
virtual void OnUnzipped() = 0;
virtual void OnUnzippingFailed() = 0;
}; };
explicit PluginVmImageManager(Profile* profile); explicit PluginVmImageManager(Profile* profile);
// Returns true if manager is downloading PluginVm image at the moment. // Returns true if manager is processing PluginVm image at the moment.
bool IsDownloading(); bool IsProcessingImage();
// Fails download in case IsDownloading() returns true otherwise starts a new // Doesn't start to download PluginVm image and calls OnDownloadFailed() in
// download of PluginVm image. // case IsProcessingImage() returns true otherwise starts processing PluginVm
// image by downloading it.
void StartDownload(); void StartDownload();
// Cancels the download of PluginVm image. // Cancels the download of PluginVm image finishing the image processing.
// Downloaded PluginVm image archive is being deleted.
void CancelDownload(); void CancelDownload();
// Should be called when download of PluginVm image has been completed
// successfully. If called in other cases - unzipping is not started
// and OnUnzipped(false /* success */) is called.
void StartUnzipping();
// Sets flag that indicates that unzipping is cancelled. This flag is further
// checked in PluginVmImageWriterDelegate and in cases it is set to true
// OnUnzipped(false /* success */) called.
void CancelUnzipping();
void SetObserver(Observer* observer); void SetObserver(Observer* observer);
void RemoveObserver();
// Called by PluginVmImageDownloadClient. // Called by PluginVmImageDownloadClient.
void OnDownloadStarted(); void OnDownloadStarted();
...@@ -67,21 +88,69 @@ class PluginVmImageManager : public KeyedService { ...@@ -67,21 +88,69 @@ class PluginVmImageManager : public KeyedService {
void SetDownloadServiceForTesting( void SetDownloadServiceForTesting(
download::DownloadService* download_service); download::DownloadService* download_service);
void SetDownloadedPluginVmImageArchiveForTesting(
base::FilePath downloaded_plugin_vm_image_archive);
std::string GetCurrentDownloadGuidForTesting(); std::string GetCurrentDownloadGuidForTesting();
private: private:
Profile* profile_ = nullptr; Profile* profile_ = nullptr;
download::DownloadService* download_service_ = nullptr;
Observer* observer_ = nullptr; Observer* observer_ = nullptr;
bool processing_download_ = false; download::DownloadService* download_service_ = nullptr;
bool processing_image_ = false;
bool unzipping_cancelled_ = false;
std::string current_download_guid_; std::string current_download_guid_;
base::FilePath downloaded_plugin_vm_image_archive_;
base::FilePath plugin_vm_image_dir_;
class PluginVmImageWriterDelegate : public zip::WriterDelegate {
public:
explicit PluginVmImageWriterDelegate(
PluginVmImageManager* manager,
const base::FilePath& output_file_path);
// zip::WriterDelegate implementation.
bool PrepareOutput() override;
// If unzipping is cancelled returns false so unzipping would fail.
bool WriteBytes(const char* data, int num_bytes) override;
void SetTimeModified(const base::Time& time) override;
private:
PluginVmImageManager* manager_;
base::FilePath output_file_path_;
base::File output_file_;
DISALLOW_COPY_AND_ASSIGN(PluginVmImageWriterDelegate);
};
~PluginVmImageManager() override; ~PluginVmImageManager() override;
download::DownloadParams GetDownloadParams(); download::DownloadParams GetDownloadParams();
void OnStarted(const std::string& download_guid, void OnStartDownload(const std::string& download_guid,
download::DownloadParams::StartResult start_result); download::DownloadParams::StartResult start_result);
bool IsDownloading();
bool UnzipDownloadedPluginVmImageArchive();
bool IsUnzippingCancelled();
// Callback arguments for unzipping function.
std::unique_ptr<zip::WriterDelegate> CreatePluginVmImageWriterDelegate(
const base::FilePath& entry_path);
bool CreateDirectory(const base::FilePath& entry_path);
bool FilterFilesInPluginVmImageArchive(const base::FilePath& file);
// Finishes the processing of PluginVm image. Deletes downloaded PluginVm
// image archive. In case success is false also deletes PluginVm image.
void OnUnzipped(bool success);
bool EnsureDownloadedPluginVmImageArchiveIsPresent();
// Creates directory for PluginVm image if one doesn't exists.
// Returns true in case directory has already existed or was successfully
// created and false otherwise.
bool EnsureDirectoryForPluginVmImageIsPresent();
void RemoveTemporaryPluginVmImageArchiveIfExists();
void RemovePluginVmImageDirectoryIfExists();
base::WeakPtrFactory<PluginVmImageManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PluginVmImageManager); DISALLOW_COPY_AND_ASSIGN(PluginVmImageManager);
}; };
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h" #include "base/files/scoped_temp_dir.h"
#include "base/optional.h" #include "base/optional.h"
#include "chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.h"
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
#include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/zlib/google/zip.h"
namespace plugin_vm { namespace plugin_vm {
...@@ -30,6 +32,11 @@ const char kProfileName[] = "p1"; ...@@ -30,6 +32,11 @@ const char kProfileName[] = "p1";
const char kUrl[] = "http://example.com"; const char kUrl[] = "http://example.com";
const char kHash[] = const char kHash[] =
"842841a4c75a55ad050d686f4ea5f77e83ae059877fe9b6946aa63d3d057ed32"; "842841a4c75a55ad050d686f4ea5f77e83ae059877fe9b6946aa63d3d057ed32";
const char kPluginVmImageUnzipped[] = "plugin_vm_image_unzipped";
const char kPluginVmImageFile1[] = "plugin_vm_image_file_1";
const char kContent1[] = "This is content #1.";
const char kPluginVmImageFile2[] = "plugin_vm_image_file_2";
const char kContent2[] = "This is content #2.";
} // namespace } // namespace
...@@ -38,9 +45,11 @@ class MockObserver : public PluginVmImageManager::Observer { ...@@ -38,9 +45,11 @@ class MockObserver : public PluginVmImageManager::Observer {
MOCK_METHOD0(OnDownloadStarted, void()); MOCK_METHOD0(OnDownloadStarted, void());
MOCK_METHOD1(OnProgressUpdated, MOCK_METHOD1(OnProgressUpdated,
void(base::Optional<double> fraction_complete)); void(base::Optional<double> fraction_complete));
MOCK_METHOD1(OnDownloadCompleted, void(base::FilePath file_path)); MOCK_METHOD0(OnDownloadCompleted, void());
MOCK_METHOD0(OnDownloadCancelled, void()); MOCK_METHOD0(OnDownloadCancelled, void());
MOCK_METHOD0(OnDownloadFailed, void()); MOCK_METHOD0(OnDownloadFailed, void());
MOCK_METHOD0(OnUnzipped, void());
MOCK_METHOD0(OnUnzippingFailed, void());
}; };
class PluginVmImageManagerTest : public testing::Test { class PluginVmImageManagerTest : public testing::Test {
...@@ -54,6 +63,7 @@ class PluginVmImageManagerTest : public testing::Test { ...@@ -54,6 +63,7 @@ class PluginVmImageManagerTest : public testing::Test {
PluginVmImageManager* manager_; PluginVmImageManager* manager_;
download::test::TestDownloadService* download_service_; download::test::TestDownloadService* download_service_;
std::unique_ptr<MockObserver> download_observer_; std::unique_ptr<MockObserver> download_observer_;
base::FilePath fake_downloaded_plugin_vm_image_archive_;
void SetUp() override { void SetUp() override {
ASSERT_TRUE(profiles_dir_.CreateUniqueTempDir()); ASSERT_TRUE(profiles_dir_.CreateUniqueTempDir());
...@@ -67,6 +77,8 @@ class PluginVmImageManagerTest : public testing::Test { ...@@ -67,6 +77,8 @@ class PluginVmImageManagerTest : public testing::Test {
manager_->SetDownloadServiceForTesting(download_service_); manager_->SetDownloadServiceForTesting(download_service_);
download_observer_ = std::make_unique<MockObserver>(); download_observer_ = std::make_unique<MockObserver>();
manager_->SetObserver(download_observer_.get()); manager_->SetObserver(download_observer_.get());
fake_downloaded_plugin_vm_image_archive_ = CreateZipFile();
} }
void TearDown() override { void TearDown() override {
...@@ -82,6 +94,37 @@ class PluginVmImageManagerTest : public testing::Test { ...@@ -82,6 +94,37 @@ class PluginVmImageManagerTest : public testing::Test {
plugin_vm_image->SetKey("hash", base::Value(hash)); plugin_vm_image->SetKey("hash", base::Value(hash));
} }
void ProcessImage() {
manager_->StartDownload();
test_browser_thread_bundle_.RunUntilIdle();
// Faking downloaded file for testing.
manager_->SetDownloadedPluginVmImageArchiveForTesting(
fake_downloaded_plugin_vm_image_archive_);
manager_->StartUnzipping();
test_browser_thread_bundle_.RunUntilIdle();
}
base::FilePath CreateZipFile() {
base::FilePath src_dir = profile_->GetPath().AppendASCII("src");
base::CreateDirectory(src_dir);
base::FilePath dest_dir = profile_->GetPath().AppendASCII("dest");
base::CreateDirectory(dest_dir);
base::FilePath zip_file = dest_dir.Append("out");
base::FilePath plugin_vm_image_unzipped =
src_dir.Append(kPluginVmImageUnzipped);
base::CreateDirectory(plugin_vm_image_unzipped);
base::FilePath plugin_vm_image_file_1 =
plugin_vm_image_unzipped.Append(kPluginVmImageFile1);
base::FilePath plugin_vm_image_file_2 =
plugin_vm_image_unzipped.Append(kPluginVmImageFile2);
base::WriteFile(plugin_vm_image_file_1, kContent1, strlen(kContent1));
base::WriteFile(plugin_vm_image_file_2, kContent2, strlen(kContent2));
zip::Zip(src_dir, zip_file, true /* include_hidden_files */);
return zip_file;
}
private: private:
base::ScopedTempDir profiles_dir_; base::ScopedTempDir profiles_dir_;
...@@ -100,7 +143,8 @@ class PluginVmImageManagerTest : public testing::Test { ...@@ -100,7 +143,8 @@ class PluginVmImageManagerTest : public testing::Test {
}; };
TEST_F(PluginVmImageManagerTest, DownloadPluginVmImageParamsTest) { TEST_F(PluginVmImageManagerTest, DownloadPluginVmImageParamsTest) {
EXPECT_CALL(*download_observer_, OnDownloadCompleted(testing::_)); EXPECT_CALL(*download_observer_, OnDownloadCompleted());
EXPECT_CALL(*download_observer_, OnUnzipped());
manager_->StartDownload(); manager_->StartDownload();
...@@ -112,54 +156,139 @@ TEST_F(PluginVmImageManagerTest, DownloadPluginVmImageParamsTest) { ...@@ -112,54 +156,139 @@ TEST_F(PluginVmImageManagerTest, DownloadPluginVmImageParamsTest) {
EXPECT_EQ(download::DownloadClient::PLUGIN_VM_IMAGE, params->client); EXPECT_EQ(download::DownloadClient::PLUGIN_VM_IMAGE, params->client);
EXPECT_EQ(GURL(kUrl), params->request_params.url); EXPECT_EQ(GURL(kUrl), params->request_params.url);
base::RunLoop().RunUntilIdle(); // Finishing image processing.
test_browser_thread_bundle_.RunUntilIdle();
// Faking downloaded file for testing. Creates one additional call to
// OnDownloadCompleted().
manager_->SetDownloadedPluginVmImageArchiveForTesting(
fake_downloaded_plugin_vm_image_archive_);
manager_->StartUnzipping();
test_browser_thread_bundle_.RunUntilIdle();
} }
TEST_F(PluginVmImageManagerTest, OnlyOneDownloadAtATimeIsAllowedTest) { TEST_F(PluginVmImageManagerTest, OnlyOneImageIsProcessedTest) {
EXPECT_CALL(*download_observer_, OnDownloadCompleted(testing::_)).Times(1); EXPECT_CALL(*download_observer_, OnDownloadCompleted());
EXPECT_CALL(*download_observer_, OnDownloadFailed()).Times(1); EXPECT_CALL(*download_observer_, OnUnzipped());
manager_->StartDownload(); manager_->StartDownload();
EXPECT_TRUE(manager_->IsDownloading()); EXPECT_TRUE(manager_->IsProcessingImage());
manager_->StartDownload(); test_browser_thread_bundle_.RunUntilIdle();
base::RunLoop().RunUntilIdle(); // Faking downloaded file for testing.
manager_->SetDownloadedPluginVmImageArchiveForTesting(
fake_downloaded_plugin_vm_image_archive_);
manager_->StartUnzipping();
EXPECT_TRUE(manager_->IsProcessingImage());
test_browser_thread_bundle_.RunUntilIdle();
} }
TEST_F(PluginVmImageManagerTest, CanStartSecondDownloadWhenSucceededTest) { TEST_F(PluginVmImageManagerTest, CanProceedWithANewImageWhenSucceededTest) {
EXPECT_CALL(*download_observer_, OnDownloadCompleted(testing::_)).Times(2); EXPECT_CALL(*download_observer_, OnDownloadCompleted()).Times(2);
EXPECT_CALL(*download_observer_, OnUnzipped()).Times(2);
manager_->StartDownload(); ProcessImage();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(manager_->IsDownloading()); EXPECT_FALSE(manager_->IsProcessingImage());
manager_->StartDownload(); // As it is deleted after successful unzipping.
base::RunLoop().RunUntilIdle(); fake_downloaded_plugin_vm_image_archive_ = CreateZipFile();
ProcessImage();
} }
TEST_F(PluginVmImageManagerTest, CanStartSecondDownloadWhenFailedTest) { TEST_F(PluginVmImageManagerTest, CanProceedWithANewImageWhenFailedTest) {
EXPECT_CALL(*download_observer_, OnDownloadFailed()).Times(1); EXPECT_CALL(*download_observer_, OnDownloadFailed());
EXPECT_CALL(*download_observer_, OnDownloadCompleted(testing::_)).Times(1); EXPECT_CALL(*download_observer_, OnDownloadCompleted());
EXPECT_CALL(*download_observer_, OnUnzipped());
manager_->StartDownload(); manager_->StartDownload();
std::string guid = manager_->GetCurrentDownloadGuidForTesting(); std::string guid = manager_->GetCurrentDownloadGuidForTesting();
download_service_->SetFailedDownload(guid, false); download_service_->SetFailedDownload(guid, false);
base::RunLoop().RunUntilIdle(); test_browser_thread_bundle_.RunUntilIdle();
EXPECT_FALSE(manager_->IsDownloading()); EXPECT_FALSE(manager_->IsProcessingImage());
manager_->StartDownload(); ProcessImage();
base::RunLoop().RunUntilIdle();
} }
TEST_F(PluginVmImageManagerTest, CancelledDownloadTest) { TEST_F(PluginVmImageManagerTest, CancelledDownloadTest) {
EXPECT_CALL(*download_observer_, OnDownloadCompleted(testing::_)).Times(0); EXPECT_CALL(*download_observer_, OnDownloadCompleted()).Times(0);
EXPECT_CALL(*download_observer_, OnDownloadCancelled());
manager_->StartDownload(); manager_->StartDownload();
manager_->CancelDownload(); manager_->CancelDownload();
base::RunLoop().RunUntilIdle(); test_browser_thread_bundle_.RunUntilIdle();
// Finishing image processing as it should really happen.
manager_->OnDownloadCancelled();
}
TEST_F(PluginVmImageManagerTest, UnzipDownloadedImageTest) {
EXPECT_CALL(*download_observer_, OnDownloadCompleted());
EXPECT_CALL(*download_observer_, OnUnzipped());
ProcessImage();
// Checking that all files are in place.
base::FilePath plugin_vm_image_unzipped =
profile_->GetPath()
.AppendASCII(kCrosvmDir)
.AppendASCII(kPvmDir)
.AppendASCII(kPluginVmImageDir)
.AppendASCII(kPluginVmImageUnzipped);
EXPECT_TRUE(base::DirectoryExists(plugin_vm_image_unzipped));
base::FilePath plugin_vm_image_file_1 =
plugin_vm_image_unzipped.AppendASCII(kPluginVmImageFile1);
EXPECT_TRUE(base::PathExists(plugin_vm_image_file_1));
EXPECT_FALSE(base::DirectoryExists(plugin_vm_image_file_1));
std::string plugin_vm_image_file_1_content;
EXPECT_TRUE(base::ReadFileToString(plugin_vm_image_file_1,
&plugin_vm_image_file_1_content));
EXPECT_EQ(kContent1, plugin_vm_image_file_1_content);
base::FilePath plugin_vm_image_file_2 =
plugin_vm_image_unzipped.AppendASCII(kPluginVmImageFile2);
EXPECT_TRUE(base::PathExists(plugin_vm_image_file_2));
EXPECT_FALSE(base::DirectoryExists(plugin_vm_image_file_2));
std::string plugin_vm_image_file_2_content;
EXPECT_TRUE(base::ReadFileToString(plugin_vm_image_file_2,
&plugin_vm_image_file_2_content));
EXPECT_EQ(kContent2, plugin_vm_image_file_2_content);
}
TEST_F(PluginVmImageManagerTest, UnzipNonExistingImageTest) {
EXPECT_CALL(*download_observer_, OnDownloadCompleted());
EXPECT_CALL(*download_observer_, OnUnzippingFailed());
manager_->StartDownload();
test_browser_thread_bundle_.RunUntilIdle();
manager_->StartUnzipping();
test_browser_thread_bundle_.RunUntilIdle();
// Checking that directory with PluginVm image has been deleted.
base::FilePath plugin_vm_image_unzipped = profile_->GetPath()
.AppendASCII(kCrosvmDir)
.AppendASCII(kPvmDir)
.AppendASCII(kPluginVmImageDir);
EXPECT_FALSE(base::DirectoryExists(plugin_vm_image_unzipped));
}
TEST_F(PluginVmImageManagerTest, CancelUnzippingTest) {
// Faking downloaded file for testing.
manager_->SetDownloadedPluginVmImageArchiveForTesting(
fake_downloaded_plugin_vm_image_archive_);
manager_->StartUnzipping();
manager_->CancelUnzipping();
test_browser_thread_bundle_.RunUntilIdle();
// Checking that directory with PluginVm image has been deleted.
base::FilePath plugin_vm_image_unzipped = profile_->GetPath()
.AppendASCII(kCrosvmDir)
.AppendASCII(kPvmDir)
.AppendASCII(kPluginVmImageDir);
EXPECT_FALSE(base::DirectoryExists(plugin_vm_image_unzipped));
} }
} // namespace plugin_vm } // namespace plugin_vm
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