blob: faf17c2c3fb2f60ac8971bcc158f267e2f7b3cad [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include <utility>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "components/update_client/update_client.h"
#include "components/update_client/update_client_errors.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/extensions_test.h"
#include "extensions/browser/updater/extension_installer.h"
#include "extensions/common/extension_id.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
namespace {
class ExtensionInstallerTest : public ExtensionsTest {
public:
using UpdateClientCallback =
extensions::ExtensionInstaller::UpdateClientCallback;
using ExtensionInstallerCallback =
ExtensionInstaller::ExtensionInstallerCallback;
using Result = update_client::CrxInstaller::Result;
using InstallError = update_client::InstallError;
ExtensionInstallerTest();
ExtensionInstallerTest(const ExtensionInstallerTest&) = delete;
ExtensionInstallerTest& operator=(const ExtensionInstallerTest&) = delete;
~ExtensionInstallerTest() override;
void InstallCompleteCallback(const Result& result);
protected:
void RunThreads();
protected:
const std::string kExtensionId = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
const std::string kPublicKey =
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8c4fBSPZ6utYoZ8NiWF/"
"DSaimBhihjwgOsskyleFGaurhi3TDClTVSGPxNkgCzrz0wACML7M4aNjpd05qupdbR2d294j"
"kDuI7caxEGUucpP7GJRRHnm8Sx+"
"y0ury28n8jbN0PnInKKWcxpIXXmNQyC19HBuO3QIeUq9Dqc+7YFQIDAQAB";
base::RunLoop run_loop_;
Result result_;
bool executed_;
};
ExtensionInstallerTest::ExtensionInstallerTest()
: result_(-1), executed_(false) {}
ExtensionInstallerTest::~ExtensionInstallerTest() = default;
void ExtensionInstallerTest::InstallCompleteCallback(const Result& result) {
result_ = result;
executed_ = true;
run_loop_.Quit();
}
void ExtensionInstallerTest::RunThreads() {
run_loop_.Run();
}
TEST_F(ExtensionInstallerTest, GetInstalledFile) {
base::ScopedTempDir root_dir;
ASSERT_TRUE(root_dir.CreateUniqueTempDir());
ASSERT_FALSE(base::MakeRefCounted<ExtensionInstaller>(
kExtensionId, root_dir.GetPath(),
false /*install_immediately*/, ExtensionInstallerCallback())
->GetInstalledFile("f"));
}
TEST_F(ExtensionInstallerTest, Install_InvalidUnpackedDir) {
// The unpacked folder is not valid, the installer will return an error.
base::ScopedTempDir root_dir;
ASSERT_TRUE(root_dir.CreateUniqueTempDir());
ASSERT_TRUE(base::PathExists(root_dir.GetPath()));
scoped_refptr<ExtensionInstaller> installer =
base::MakeRefCounted<ExtensionInstaller>(
kExtensionId, root_dir.GetPath(), true /*install_immediately*/,
base::BindRepeating(
[](const ExtensionId& extension_id, const std::string& public_key,
const base::FilePath& unpacked_dir, bool install_immediately,
UpdateClientCallback update_client_callback) {
// This function should never be executed.
EXPECT_TRUE(false);
}));
// Non-existing unpacked dir
base::ScopedTempDir unpacked_dir;
ASSERT_TRUE(unpacked_dir.CreateUniqueTempDir());
ASSERT_TRUE(base::PathExists(unpacked_dir.GetPath()));
ASSERT_TRUE(base::DeletePathRecursively(unpacked_dir.GetPath()));
ASSERT_FALSE(base::PathExists(unpacked_dir.GetPath()));
installer->Install(
unpacked_dir.GetPath(), kPublicKey, nullptr, base::DoNothing(),
base::BindOnce(&ExtensionInstallerTest::InstallCompleteCallback,
base::Unretained(this)));
RunThreads();
EXPECT_TRUE(executed_);
EXPECT_EQ(static_cast<int>(InstallError::GENERIC_ERROR), result_.result.code);
}
TEST_F(ExtensionInstallerTest, Install_BasicInstallOperation_Error) {
base::ScopedTempDir root_dir;
ASSERT_TRUE(root_dir.CreateUniqueTempDir());
ASSERT_TRUE(base::PathExists(root_dir.GetPath()));
scoped_refptr<ExtensionInstaller> installer =
base::MakeRefCounted<ExtensionInstaller>(
kExtensionId, root_dir.GetPath(), false /*install_immediately*/,
base::BindRepeating([](const ExtensionId& extension_id,
const std::string& public_key,
const base::FilePath& unpacked_dir,
bool install_immediately,
UpdateClientCallback update_client_callback) {
EXPECT_FALSE(install_immediately);
std::move(update_client_callback)
.Run(Result(InstallError::GENERIC_ERROR));
}));
base::ScopedTempDir unpacked_dir;
ASSERT_TRUE(unpacked_dir.CreateUniqueTempDir());
ASSERT_TRUE(base::PathExists(unpacked_dir.GetPath()));
installer->Install(
unpacked_dir.GetPath(), kPublicKey, nullptr, base::DoNothing(),
base::BindOnce(&ExtensionInstallerTest::InstallCompleteCallback,
base::Unretained(this)));
RunThreads();
EXPECT_TRUE(executed_);
EXPECT_EQ(static_cast<int>(InstallError::GENERIC_ERROR), result_.result.code);
}
TEST_F(ExtensionInstallerTest, Install_BasicInstallOperation_Success) {
base::ScopedTempDir root_dir;
ASSERT_TRUE(root_dir.CreateUniqueTempDir());
ASSERT_TRUE(base::PathExists(root_dir.GetPath()));
scoped_refptr<ExtensionInstaller> installer =
base::MakeRefCounted<ExtensionInstaller>(
kExtensionId, root_dir.GetPath(), true /*install_immediately*/,
base::BindRepeating([](const ExtensionId& extension_id,
const std::string& public_key,
const base::FilePath& unpacked_dir,
bool install_immediately,
UpdateClientCallback update_client_callback) {
EXPECT_TRUE(install_immediately);
std::move(update_client_callback).Run(Result(InstallError::NONE));
}));
base::ScopedTempDir unpacked_dir;
ASSERT_TRUE(unpacked_dir.CreateUniqueTempDir());
ASSERT_TRUE(base::PathExists(unpacked_dir.GetPath()));
installer->Install(
unpacked_dir.GetPath(), kPublicKey, nullptr, base::DoNothing(),
base::BindOnce(&ExtensionInstallerTest::InstallCompleteCallback,
base::Unretained(this)));
RunThreads();
EXPECT_TRUE(executed_);
EXPECT_EQ(static_cast<int>(InstallError::NONE), result_.result.code);
}
} // namespace
} // namespace extensions