blob: af1dc05ae6240aca957402f1b609fb9c1f8b3703 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/external_pref_loader.h"
#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/task/post_task.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/sync/profile_sync_test_util.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "extensions/common/extension.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
namespace {
class TestSyncService : public browser_sync::ProfileSyncServiceMock {
public:
enum class SyncedTypes { ALL, NONE };
explicit TestSyncService(Profile* profile)
: browser_sync::ProfileSyncServiceMock(
CreateProfileSyncServiceParamsForTest(profile)),
synced_types_(SyncedTypes::NONE) {}
~TestSyncService() override {}
// FakeSyncService:
int GetDisableReasons() const override { return disable_reasons_; }
syncer::ModelTypeSet GetActiveDataTypes() const override {
switch (synced_types_) {
case SyncedTypes::ALL:
return syncer::ModelTypeSet::All();
case SyncedTypes::NONE:
return syncer::ModelTypeSet();
}
NOTREACHED();
return syncer::ModelTypeSet();
}
void AddObserver(syncer::SyncServiceObserver* observer) override {
ASSERT_FALSE(observer_);
observer_ = observer;
}
void RemoveObserver(syncer::SyncServiceObserver* observer) override {
EXPECT_EQ(observer_, observer);
}
void SetDisableReasons(int disable_reasons) {
disable_reasons_ = disable_reasons;
}
void FireOnStateChanged(browser_sync::ProfileSyncService* service) {
ASSERT_TRUE(observer_);
observer_->OnStateChanged(service);
}
private:
syncer::SyncServiceObserver* observer_ = nullptr;
int disable_reasons_ = DISABLE_REASON_NONE;
SyncedTypes synced_types_;
DISALLOW_COPY_AND_ASSIGN(TestSyncService);
};
std::unique_ptr<KeyedService> TestingSyncFactoryFunction(
content::BrowserContext* context) {
return std::make_unique<TestSyncService>(static_cast<Profile*>(context));
}
} // namespace
// Test version of ExternalPrefLoader that doesn't do any IO.
class TestExternalPrefLoader : public ExternalPrefLoader {
public:
TestExternalPrefLoader(Profile* profile, base::OnceClosure load_callback)
: ExternalPrefLoader(
// Invalid value, doesn't matter since it's not used.
-1,
// Make sure ExternalPrefLoader waits for priority sync.
ExternalPrefLoader::DELAY_LOAD_UNTIL_PRIORITY_SYNC,
profile),
load_callback_(std::move(load_callback)) {}
void LoadOnFileThread() override {
base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
std::move(load_callback_));
}
private:
~TestExternalPrefLoader() override {}
base::OnceClosure load_callback_;
DISALLOW_COPY_AND_ASSIGN(TestExternalPrefLoader);
};
class ExternalPrefLoaderTest : public testing::Test {
public:
ExternalPrefLoaderTest() {}
~ExternalPrefLoaderTest() override {}
void SetUp() override { profile_ = std::make_unique<TestingProfile>(); }
void TearDown() override { profile_.reset(); }
Profile* profile() { return profile_.get(); }
private:
content::TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<TestingProfile> profile_;
DISALLOW_COPY_AND_ASSIGN(ExternalPrefLoaderTest);
};
// TODO(lazyboy): Add a test to cover
// PrioritySyncReadyWaiter::OnIsSyncingChanged().
// Tests that we fire pref reading correctly after priority sync state
// is resolved by ExternalPrefLoader.
TEST_F(ExternalPrefLoaderTest, PrefReadInitiatesCorrectly) {
TestSyncService* test_service = static_cast<TestSyncService*>(
ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
profile(), base::BindRepeating(&TestingSyncFactoryFunction)));
ON_CALL(*test_service->GetUserSettingsMock(), IsFirstSetupComplete())
.WillByDefault(testing::Return(true));
base::RunLoop run_loop;
scoped_refptr<ExternalPrefLoader> loader(
new TestExternalPrefLoader(profile(), run_loop.QuitWhenIdleClosure()));
ExternalProviderImpl provider(
nullptr, loader, profile(), Manifest::INVALID_LOCATION,
Manifest::INVALID_LOCATION, Extension::NO_FLAGS);
provider.VisitRegisteredExtension();
// Initially CanSyncFeatureStart() returns true, returning false will let
// |loader| proceed.
test_service->SetDisableReasons(
syncer::SyncService::DISABLE_REASON_USER_CHOICE);
ASSERT_FALSE(test_service->CanSyncFeatureStart());
test_service->FireOnStateChanged(test_service);
run_loop.Run();
}
} // namespace extensions