Commit cb4431a3 authored by Sorin Jianu's avatar Sorin Jianu Committed by Commit Bot

Allow for Chrome components to be not present while an update check occurs.

Bug: 837371

Change-Id: Ifc2aa0c3b9a8e75d44dad32136d172d58380f1b4
Reviewed-on: https://chromium-review.googlesource.com/1033468Reviewed-by: default avatarJoshua Pawlicki <waffles@chromium.org>
Commit-Queue: Sorin Jianu <sorin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#554870}
parent 9db896d5
...@@ -345,8 +345,13 @@ void Component::StateNew::DoHandle() { ...@@ -345,8 +345,13 @@ void Component::StateNew::DoHandle() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
auto& component = State::component(); auto& component = State::component();
if (component.crx_component()) {
TransitionState(std::make_unique<StateChecking>(&component)); TransitionState(std::make_unique<StateChecking>(&component));
} else {
component.error_code_ = static_cast<int>(Error::CRX_NOT_FOUND);
component.error_category_ = static_cast<int>(ErrorCategory::kServiceError);
TransitionState(std::make_unique<StateUpdateError>(&component));
}
} }
Component::StateChecking::StateChecking(Component* component) Component::StateChecking::StateChecking(Component* component)
......
...@@ -17,6 +17,7 @@ enum class Error { ...@@ -17,6 +17,7 @@ enum class Error {
RETRY_LATER = 3, RETRY_LATER = 3,
SERVICE_ERROR = 4, SERVICE_ERROR = 4,
UPDATE_CHECK_ERROR = 5, UPDATE_CHECK_ERROR = 5,
CRX_NOT_FOUND = 6,
}; };
// These errors are sent in pings. Add new values only to the bottom of // These errors are sent in pings. Add new values only to the bottom of
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/task_scheduler/post_task.h" #include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h" #include "base/task_scheduler/task_traits.h"
#include "base/test/scoped_path_override.h" #include "base/test/scoped_path_override.h"
...@@ -217,7 +218,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdate) { ...@@ -217,7 +218,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdate) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx->name = "test_jebg"; crx->name = "test_jebg";
crx->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx->version = base::Version("0.9"); crx->version = base::Version("0.9");
crx->installer = base::MakeRefCounted<TestInstaller>(); crx->installer = base::MakeRefCounted<TestInstaller>();
std::vector<std::unique_ptr<CrxComponent>> component; std::vector<std::unique_ptr<CrxComponent>> component;
...@@ -325,13 +326,13 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) { ...@@ -325,13 +326,13 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx1 = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx1 = std::make_unique<CrxComponent>();
crx1->name = "test_jebg"; crx1->name = "test_jebg";
crx1->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx1->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx1->version = base::Version("0.9"); crx1->version = base::Version("0.9");
crx1->installer = base::MakeRefCounted<TestInstaller>(); crx1->installer = base::MakeRefCounted<TestInstaller>();
std::unique_ptr<CrxComponent> crx2 = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx2 = std::make_unique<CrxComponent>();
crx2->name = "test_abag"; crx2->name = "test_abag";
crx2->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash)); crx2->pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
crx2->version = base::Version("2.2"); crx2->version = base::Version("2.2");
crx2->installer = base::MakeRefCounted<TestInstaller>(); crx2->installer = base::MakeRefCounted<TestInstaller>();
...@@ -532,27 +533,25 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) { ...@@ -532,27 +533,25 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
update_client->RemoveObserver(&observer); update_client->RemoveObserver(&observer);
} }
// Tests the update check for two CRXs scenario. Both CRXs have updates. // Tests the update check for two CRXs scenario when the second CRX does not
TEST_F(UpdateClientTest, TwoCrxUpdate) { // provide a CrxComponent instance. In this case, the update is handled as
// if only one component were provided as an argument to the |Update| call
// with the exception that the second component still fires an event such as
// |COMPONENT_UPDATE_ERROR|.
TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) {
class DataCallbackMock { class DataCallbackMock {
public: public:
static std::vector<std::unique_ptr<CrxComponent>> Callback( static std::vector<std::unique_ptr<CrxComponent>> Callback(
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx1 = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx1->name = "test_jebg"; crx->name = "test_jebg";
crx1->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx1->version = base::Version("0.9"); crx->version = base::Version("0.9");
crx1->installer = base::MakeRefCounted<TestInstaller>(); crx->installer = base::MakeRefCounted<TestInstaller>();
std::unique_ptr<CrxComponent> crx2 = std::make_unique<CrxComponent>();
crx2->name = "test_ihfo";
crx2->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
crx2->version = base::Version("0.8");
crx2->installer = base::MakeRefCounted<TestInstaller>();
std::vector<std::unique_ptr<CrxComponent>> component; std::vector<std::unique_ptr<CrxComponent>> component;
component.push_back(std::move(crx1)); component.push_back(std::move(crx));
component.push_back(std::move(crx2)); component.push_back(std::move(nullptr));
return component; return component;
} }
}; };
...@@ -598,25 +597,11 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) { ...@@ -598,25 +597,11 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
</manifest> </manifest>
</updatecheck> </updatecheck>
</app> </app>
<app appid='ihfokbkgjpifnbbojhneepfflplebdkc'>
<updatecheck status='ok'>
<urls>
<url codebase='http://localhost/download/'/>
</urls>
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
hash_sha256='813c59747e139a608b3b5fc49633affc6db574373f
309f156ea6d27229c0b3f9'/>
</packages>
</manifest>
</updatecheck>
</app>
</response> </response>
*/ */
EXPECT_FALSE(session_id.empty()); EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates); EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(2u, ids_to_check.size()); EXPECT_EQ(1u, ids_to_check.size());
{ {
const std::string id = "jebgalgnebhfojomionfpkfelancnnkf"; const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
...@@ -642,30 +627,6 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) { ...@@ -642,30 +627,6 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
EXPECT_FALSE(component->is_foreground()); EXPECT_FALSE(component->is_foreground());
} }
{
const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
EXPECT_EQ(id, ids_to_check[1]);
EXPECT_EQ(1u, components.count(id));
ProtocolParser::Result::Manifest::Package package;
package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
package.hash_sha256 =
"813c59747e139a608b3b5fc49633affc6db574373f309f156ea6d27229c0b3f9";
ProtocolParser::Result result;
result.extension_id = id;
result.status = "ok";
result.crx_urls.push_back(GURL("http://localhost/download/"));
result.manifest.version = "1.0";
result.manifest.browser_min_version = "11.0.1.0";
result.manifest.packages.push_back(package);
auto& component = components.at(id);
component->SetParseResult(result);
EXPECT_FALSE(component->is_foreground());
}
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(update_check_callback), 0, 0)); FROM_HERE, base::BindOnce(std::move(update_check_callback), 0, 0));
} }
...@@ -701,22 +662,6 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) { ...@@ -701,22 +662,6 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
result.response = path; result.response = path;
result.downloaded_bytes = 1843; result.downloaded_bytes = 1843;
result.total_bytes = 1843; result.total_bytes = 1843;
} else if (url.path() ==
"/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") {
download_metrics.url = url;
download_metrics.downloader = DownloadMetrics::kNone;
download_metrics.error = 0;
download_metrics.downloaded_bytes = 53638;
download_metrics.total_bytes = 53638;
download_metrics.download_time_ms = 2000;
EXPECT_TRUE(MakeTestFile(
TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path));
result.error = 0;
result.response = path;
result.downloaded_bytes = 53638;
result.total_bytes = 53638;
} else { } else {
NOTREACHED(); NOTREACHED();
} }
...@@ -740,17 +685,12 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) { ...@@ -740,17 +685,12 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
protected: protected:
~MockPingManager() override { ~MockPingManager() override {
const auto ping_data = MockPingManagerImpl::ping_data(); const auto ping_data = MockPingManagerImpl::ping_data();
EXPECT_EQ(2u, ping_data.size()); EXPECT_EQ(1u, ping_data.size());
EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id); EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_data[0].id);
EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version); EXPECT_EQ(base::Version("0.9"), ping_data[0].previous_version);
EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version); EXPECT_EQ(base::Version("1.0"), ping_data[0].next_version);
EXPECT_EQ(0, ping_data[0].error_category); EXPECT_EQ(0, ping_data[0].error_category);
EXPECT_EQ(0, ping_data[0].error_code); EXPECT_EQ(0, ping_data[0].error_code);
EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_data[1].id);
EXPECT_EQ(base::Version("0.8"), ping_data[1].previous_version);
EXPECT_EQ(base::Version("1.0"), ping_data[1].next_version);
EXPECT_EQ(0, ping_data[1].error_category);
EXPECT_EQ(0, ping_data[1].error_code);
} }
}; };
...@@ -776,19 +716,104 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) { ...@@ -776,19 +716,104 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
} }
{ {
InSequence seq; InSequence seq;
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
"ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
"ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_WAIT,
"ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
"ihfokbkgjpifnbbojhneepfflplebdkc")) "ihfokbkgjpifnbbojhneepfflplebdkc"))
.Times(AtLeast(1)); .Times(1);
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, }
"ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, update_client->AddObserver(&observer);
"ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1);
const std::vector<std::string> ids = {"jebgalgnebhfojomionfpkfelancnnkf",
"ihfokbkgjpifnbbojhneepfflplebdkc"};
update_client->Update(
ids, base::BindOnce(&DataCallbackMock::Callback), false,
base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
RunThreads();
update_client->RemoveObserver(&observer);
}
// Tests the update check for two CRXs scenario when no CrxComponent data is
// provided for either component. In this case, no update check occurs, and
// |COMPONENT_UPDATE_ERROR| event fires for both components.
TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentDataAtAll) {
class DataCallbackMock {
public:
static std::vector<std::unique_ptr<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
std::vector<std::unique_ptr<CrxComponent>> component;
component.push_back(std::move(nullptr));
component.push_back(std::move(nullptr));
return component;
}
};
class CompletionCallbackMock {
public:
static void Callback(base::OnceClosure quit_closure, Error error) {
EXPECT_EQ(Error::NONE, error);
std::move(quit_closure).Run();
}
};
class MockUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<MockUpdateChecker>();
}
void CheckForUpdates(const std::string& session_id,
const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
UpdateCheckCallback update_check_callback) override {
NOTREACHED();
}
};
class MockCrxDownloader : public CrxDownloader {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<MockCrxDownloader>();
}
MockCrxDownloader() : CrxDownloader(nullptr) {}
private:
void DoStartDownload(const GURL& url) override { NOTREACHED(); }
};
class MockPingManager : public MockPingManagerImpl {
public:
explicit MockPingManager(scoped_refptr<Configurator> config)
: MockPingManagerImpl(config) {}
protected:
~MockPingManager() override {
EXPECT_EQ(0u, MockPingManagerImpl::ping_data().size());
}
};
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
config(), base::MakeRefCounted<MockPingManager>(config()),
&MockUpdateChecker::Create, &MockCrxDownloader::Create);
MockObserver observer;
{
InSequence seq;
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
"jebgalgnebhfojomionfpkfelancnnkf"))
.Times(1);
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
"ihfokbkgjpifnbbojhneepfflplebdkc"))
.Times(1);
} }
update_client->AddObserver(&observer); update_client->AddObserver(&observer);
...@@ -814,13 +839,13 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) { ...@@ -814,13 +839,13 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx1 = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx1 = std::make_unique<CrxComponent>();
crx1->name = "test_jebg"; crx1->name = "test_jebg";
crx1->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx1->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx1->version = base::Version("0.9"); crx1->version = base::Version("0.9");
crx1->installer = base::MakeRefCounted<TestInstaller>(); crx1->installer = base::MakeRefCounted<TestInstaller>();
std::unique_ptr<CrxComponent> crx2 = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx2 = std::make_unique<CrxComponent>();
crx2->name = "test_ihfo"; crx2->name = "test_ihfo";
crx2->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); crx2->pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
crx2->version = base::Version("0.8"); crx2->version = base::Version("0.8");
crx2->installer = base::MakeRefCounted<TestInstaller>(); crx2->installer = base::MakeRefCounted<TestInstaller>();
...@@ -1088,7 +1113,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) { ...@@ -1088,7 +1113,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx->name = "test_ihfo"; crx->name = "test_ihfo";
crx->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); crx->pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
crx->installer = installer; crx->installer = installer;
if (num_calls == 1) { if (num_calls == 1) {
crx->version = base::Version("0.8"); crx->version = base::Version("0.8");
...@@ -1430,7 +1455,7 @@ TEST_F(UpdateClientTest, OneCrxInstallError) { ...@@ -1430,7 +1455,7 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx->name = "test_jebg"; crx->name = "test_jebg";
crx->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx->version = base::Version("0.9"); crx->version = base::Version("0.9");
crx->installer = installer; crx->installer = installer;
...@@ -1618,7 +1643,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) { ...@@ -1618,7 +1643,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx->name = "test_ihfo"; crx->name = "test_ihfo";
crx->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); crx->pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
crx->installer = installer; crx->installer = installer;
if (num_calls == 1) { if (num_calls == 1) {
crx->version = base::Version("0.8"); crx->version = base::Version("0.8");
...@@ -1930,7 +1955,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) { ...@@ -1930,7 +1955,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx->name = "test_jebg"; crx->name = "test_jebg";
crx->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx->version = base::Version("0.9"); crx->version = base::Version("0.9");
crx->installer = base::MakeRefCounted<TestInstaller>(); crx->installer = base::MakeRefCounted<TestInstaller>();
std::vector<std::unique_ptr<CrxComponent>> component; std::vector<std::unique_ptr<CrxComponent>> component;
...@@ -2049,7 +2074,7 @@ TEST_F(UpdateClientTest, OneCrxInstall) { ...@@ -2049,7 +2074,7 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx->name = "test_jebg"; crx->name = "test_jebg";
crx->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx->version = base::Version("0.0"); crx->version = base::Version("0.0");
crx->installer = base::MakeRefCounted<TestInstaller>(); crx->installer = base::MakeRefCounted<TestInstaller>();
...@@ -2227,6 +2252,93 @@ TEST_F(UpdateClientTest, OneCrxInstall) { ...@@ -2227,6 +2252,93 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
update_client->RemoveObserver(&observer); update_client->RemoveObserver(&observer);
} }
// Tests the install of one CRX when no component data is provided. This
// results in an install error.
TEST_F(UpdateClientTest, OneCrxInstallNoCrxComponentData) {
class DataCallbackMock {
public:
static std::vector<std::unique_ptr<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
std::vector<std::unique_ptr<CrxComponent>> component;
component.push_back(nullptr);
return component;
}
};
class CompletionCallbackMock {
public:
static void Callback(base::OnceClosure quit_closure, Error error) {
EXPECT_EQ(Error::NONE, error);
std::move(quit_closure).Run();
}
};
class MockUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<MockUpdateChecker>();
}
void CheckForUpdates(const std::string& session_id,
const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
UpdateCheckCallback update_check_callback) override {
NOTREACHED();
}
};
class MockCrxDownloader : public CrxDownloader {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<MockCrxDownloader>();
}
MockCrxDownloader() : CrxDownloader(nullptr) {}
private:
void DoStartDownload(const GURL& url) override { NOTREACHED(); }
};
class MockPingManager : public MockPingManagerImpl {
public:
explicit MockPingManager(scoped_refptr<Configurator> config)
: MockPingManagerImpl(config) {}
protected:
~MockPingManager() override {
EXPECT_EQ(0u, MockPingManagerImpl::ping_data().size());
}
};
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
config(), base::MakeRefCounted<MockPingManager>(config()),
&MockUpdateChecker::Create, &MockCrxDownloader::Create);
MockObserver observer;
InSequence seq;
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
"jebgalgnebhfojomionfpkfelancnnkf"))
.Times(1);
update_client->AddObserver(&observer);
update_client->Install(
std::string("jebgalgnebhfojomionfpkfelancnnkf"),
base::BindOnce(&DataCallbackMock::Callback),
base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
RunThreads();
update_client->RemoveObserver(&observer);
}
// Tests that overlapping installs of the same CRX result in an error. // Tests that overlapping installs of the same CRX result in an error.
TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) { TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
class DataCallbackMock { class DataCallbackMock {
...@@ -2235,7 +2347,7 @@ TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) { ...@@ -2235,7 +2347,7 @@ TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx->name = "test_jebg"; crx->name = "test_jebg";
crx->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx->version = base::Version("0.0"); crx->version = base::Version("0.0");
crx->installer = base::MakeRefCounted<TestInstaller>(); crx->installer = base::MakeRefCounted<TestInstaller>();
std::vector<std::unique_ptr<CrxComponent>> component; std::vector<std::unique_ptr<CrxComponent>> component;
...@@ -2500,7 +2612,7 @@ TEST_F(UpdateClientTest, RetryAfter) { ...@@ -2500,7 +2612,7 @@ TEST_F(UpdateClientTest, RetryAfter) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx->name = "test_jebg"; crx->name = "test_jebg";
crx->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx->version = base::Version("0.9"); crx->version = base::Version("0.9");
crx->installer = base::MakeRefCounted<TestInstaller>(); crx->installer = base::MakeRefCounted<TestInstaller>();
std::vector<std::unique_ptr<CrxComponent>> component; std::vector<std::unique_ptr<CrxComponent>> component;
...@@ -2694,14 +2806,14 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) { ...@@ -2694,14 +2806,14 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx1 = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx1 = std::make_unique<CrxComponent>();
crx1->name = "test_jebg"; crx1->name = "test_jebg";
crx1->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx1->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx1->version = base::Version("0.9"); crx1->version = base::Version("0.9");
crx1->installer = base::MakeRefCounted<TestInstaller>(); crx1->installer = base::MakeRefCounted<TestInstaller>();
crx1->supports_group_policy_enable_component_updates = true; crx1->supports_group_policy_enable_component_updates = true;
std::unique_ptr<CrxComponent> crx2 = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx2 = std::make_unique<CrxComponent>();
crx2->name = "test_ihfo"; crx2->name = "test_ihfo";
crx2->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); crx2->pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
crx2->version = base::Version("0.8"); crx2->version = base::Version("0.8");
crx2->installer = base::MakeRefCounted<TestInstaller>(); crx2->installer = base::MakeRefCounted<TestInstaller>();
...@@ -2954,7 +3066,7 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) { ...@@ -2954,7 +3066,7 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>(); std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
crx->name = "test_jebg"; crx->name = "test_jebg";
crx->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); crx->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx->version = base::Version("0.9"); crx->version = base::Version("0.9");
crx->installer = base::MakeRefCounted<TestInstaller>(); crx->installer = base::MakeRefCounted<TestInstaller>();
std::vector<std::unique_ptr<CrxComponent>> component; std::vector<std::unique_ptr<CrxComponent>> component;
...@@ -3201,7 +3313,7 @@ TEST_F(UpdateClientTest, ActionRun_Install) { ...@@ -3201,7 +3313,7 @@ TEST_F(UpdateClientTest, ActionRun_Install) {
base::BindOnce([](const std::vector<std::string>& ids) { base::BindOnce([](const std::vector<std::string>& ids) {
auto crx = std::make_unique<CrxComponent>(); auto crx = std::make_unique<CrxComponent>();
crx->name = "test_niea"; crx->name = "test_niea";
crx->pk_hash.assign(gjpm_hash, gjpm_hash + arraysize(gjpm_hash)); crx->pk_hash.assign(gjpm_hash, gjpm_hash + base::size(gjpm_hash));
crx->version = base::Version("0.0"); crx->version = base::Version("0.0");
crx->installer = base::MakeRefCounted<VersionedTestInstaller>(); crx->installer = base::MakeRefCounted<VersionedTestInstaller>();
std::vector<std::unique_ptr<CrxComponent>> component; std::vector<std::unique_ptr<CrxComponent>> component;
...@@ -3349,7 +3461,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) { ...@@ -3349,7 +3461,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
const std::vector<std::string>& ids) { const std::vector<std::string>& ids) {
auto crx = std::make_unique<CrxComponent>(); auto crx = std::make_unique<CrxComponent>();
crx->name = "test_niea"; crx->name = "test_niea";
crx->pk_hash.assign(gjpm_hash, gjpm_hash + arraysize(gjpm_hash)); crx->pk_hash.assign(gjpm_hash, gjpm_hash + base::size(gjpm_hash));
crx->version = base::Version("1.0"); crx->version = base::Version("1.0");
crx->installer = crx->installer =
base::MakeRefCounted<ReadOnlyTestInstaller>(unpack_path); base::MakeRefCounted<ReadOnlyTestInstaller>(unpack_path);
......
...@@ -97,8 +97,6 @@ void UpdateEngine::Update(bool is_foreground, ...@@ -97,8 +97,6 @@ void UpdateEngine::Update(bool is_foreground,
// Calls out to get the corresponding CrxComponent data for the CRXs in this // Calls out to get the corresponding CrxComponent data for the CRXs in this
// update context. // update context.
DCHECK_EQ(ids.size(), update_context->ids.size());
DCHECK_EQ(update_context->ids.size(), update_context->components.size());
std::vector<std::unique_ptr<CrxComponent>> crx_components = std::vector<std::unique_ptr<CrxComponent>> crx_components =
std::move(update_context->crx_data_callback).Run(update_context->ids); std::move(update_context->crx_data_callback).Run(update_context->ids);
DCHECK_EQ(update_context->ids.size(), crx_components.size()); DCHECK_EQ(update_context->ids.size(), crx_components.size());
...@@ -106,20 +104,37 @@ void UpdateEngine::Update(bool is_foreground, ...@@ -106,20 +104,37 @@ void UpdateEngine::Update(bool is_foreground,
for (size_t i = 0; i != update_context->ids.size(); ++i) { for (size_t i = 0; i != update_context->ids.size(); ++i) {
const auto& id = update_context->ids[i]; const auto& id = update_context->ids[i];
DCHECK_EQ(id, GetCrxComponentID(*crx_components[i])); DCHECK(update_context->components[id]->state() == ComponentState::kNew);
DCHECK_EQ(1u, update_context->components.count(id));
DCHECK(update_context->components.at(id)); auto& crx_component = crx_components[i];
if (crx_component) {
// This component can be checked for updates.
DCHECK_EQ(id, GetCrxComponentID(*crx_component));
auto& component = update_context->components[id];
component->set_crx_component(std::move(crx_component));
component->set_previous_version(component->crx_component()->version);
component->set_previous_fp(component->crx_component()->fingerprint);
update_context->components_to_check_for_updates.push_back(id);
} else {
// |CrxDataCallback| did not return a CrxComponent instance for this
// component, which most likely, has been uninstalled. This component
// is going to be transitioned to an error state when the its |Handle|
// method is called later on by the engine.
update_context->component_queue.push(id);
}
}
auto& component = *update_context->components.at(id); if (update_context->components_to_check_for_updates.empty()) {
component.set_crx_component(std::move(crx_components[i])); base::ThreadTaskRunnerHandle::Get()->PostTask(
component.set_previous_version(component.crx_component()->version); FROM_HERE, base::BindOnce(&UpdateEngine::HandleComponent,
component.set_previous_fp(component.crx_component()->fingerprint); base::Unretained(this), update_context));
return;
}
// Handle |kNew| state. This will transition the components to |kChecking|. for (const auto& id : update_context->components_to_check_for_updates)
component.Handle( update_context->components[id]->Handle(
base::BindOnce(&UpdateEngine::ComponentCheckingForUpdatesStart, base::BindOnce(&UpdateEngine::ComponentCheckingForUpdatesStart,
base::Unretained(this), update_context, id)); base::Unretained(this), update_context, id));
}
} }
void UpdateEngine::ComponentCheckingForUpdatesStart( void UpdateEngine::ComponentCheckingForUpdatesStart(
...@@ -139,7 +154,7 @@ void UpdateEngine::ComponentCheckingForUpdatesStart( ...@@ -139,7 +154,7 @@ void UpdateEngine::ComponentCheckingForUpdatesStart(
++update_context->num_components_ready_to_check; ++update_context->num_components_ready_to_check;
if (update_context->num_components_ready_to_check < if (update_context->num_components_ready_to_check <
update_context->ids.size()) { update_context->components_to_check_for_updates.size()) {
return; return;
} }
...@@ -156,7 +171,8 @@ void UpdateEngine::DoUpdateCheck(scoped_refptr<UpdateContext> update_context) { ...@@ -156,7 +171,8 @@ void UpdateEngine::DoUpdateCheck(scoped_refptr<UpdateContext> update_context) {
update_checker_factory_(config_, metadata_.get()); update_checker_factory_(config_, metadata_.get());
update_context->update_checker->CheckForUpdates( update_context->update_checker->CheckForUpdates(
update_context->session_id, update_context->ids, update_context->session_id,
update_context->components_to_check_for_updates,
update_context->components, config_->ExtraRequestParams(), update_context->components, config_->ExtraRequestParams(),
update_context->enabled_component_updates, update_context->enabled_component_updates,
base::BindOnce(&UpdateEngine::UpdateCheckDone, base::Unretained(this), base::BindOnce(&UpdateEngine::UpdateCheckDone, base::Unretained(this),
...@@ -186,7 +202,7 @@ void UpdateEngine::UpdateCheckDone(scoped_refptr<UpdateContext> update_context, ...@@ -186,7 +202,7 @@ void UpdateEngine::UpdateCheckDone(scoped_refptr<UpdateContext> update_context,
update_context->update_check_error = error; update_context->update_check_error = error;
for (const auto& id : update_context->ids) { for (const auto& id : update_context->components_to_check_for_updates) {
DCHECK_EQ(1u, update_context->components.count(id)); DCHECK_EQ(1u, update_context->components.count(id));
DCHECK(update_context->components.at(id)); DCHECK(update_context->components.at(id));
...@@ -201,7 +217,8 @@ void UpdateEngine::ComponentCheckingForUpdatesComplete( ...@@ -201,7 +217,8 @@ void UpdateEngine::ComponentCheckingForUpdatesComplete(
DCHECK(update_context); DCHECK(update_context);
++update_context->num_components_checked; ++update_context->num_components_checked;
if (update_context->num_components_checked < update_context->ids.size()) { if (update_context->num_components_checked <
update_context->components_to_check_for_updates.size()) {
return; return;
} }
...@@ -215,7 +232,7 @@ void UpdateEngine::UpdateCheckComplete( ...@@ -215,7 +232,7 @@ void UpdateEngine::UpdateCheckComplete(
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(update_context); DCHECK(update_context);
for (const auto& id : update_context->ids) for (const auto& id : update_context->components_to_check_for_updates)
update_context->component_queue.push(id); update_context->component_queue.push(id);
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
...@@ -312,7 +329,7 @@ bool UpdateEngine::GetUpdateState(const std::string& id, ...@@ -312,7 +329,7 @@ bool UpdateEngine::GetUpdateState(const std::string& id,
for (const auto& context : update_contexts_) { for (const auto& context : update_contexts_) {
const auto& components = context.second->components; const auto& components = context.second->components;
const auto it = components.find(id); const auto it = components.find(id);
if (it != components.end()) { if (it != components.end() && it->second->crx_component()) {
*update_item = it->second->GetCrxUpdateItem(); *update_item = it->second->GetCrxUpdateItem();
return true; return true;
} }
......
...@@ -157,10 +157,18 @@ struct UpdateContext : public base::RefCounted<UpdateContext> { ...@@ -157,10 +157,18 @@ struct UpdateContext : public base::RefCounted<UpdateContext> {
// The time in seconds to wait until doing further update checks. // The time in seconds to wait until doing further update checks.
int retry_after_sec = 0; int retry_after_sec = 0;
// Contains the ids of the components to check for updates. It is possible
// for a component to be uninstalled after it has been added in this context
// but before an update check is made. When this happens, the component won't
// have a CrxComponent instance, therefore, it can't be included in an
// update check.
std::vector<std::string> components_to_check_for_updates;
int update_check_error = 0; int update_check_error = 0;
size_t num_components_ready_to_check = 0; size_t num_components_ready_to_check = 0;
size_t num_components_checked = 0; size_t num_components_checked = 0;
// Contains the ids of the components that the state machine must handle.
base::queue<std::string> component_queue; base::queue<std::string> component_queue;
// The time to wait before handling the update for a component. // The time to wait before handling the update for a component.
......
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