blob: cdf96a5ae915871c22e4ee428cdcb12a545a08ae [file] [log] [blame]
// Copyright (c) 2012 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/themes/theme_syncable_service.h"
#include <memory>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/test/base/testing_profile.h"
#include "components/sync/model/fake_sync_change_processor.h"
#include "components/sync/model/sync_change_processor_wrapper_for_test.h"
#include "components/sync/model/sync_error.h"
#include "components/sync/model/sync_error_factory_mock.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync/protocol/theme_specifics.pb.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_url_handlers.h"
#include "extensions/common/permissions/api_permission_set.h"
#include "extensions/common/permissions/permission_set.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
#endif
using std::string;
namespace {
static const char kCustomThemeName[] = "name";
static const char kCustomThemeUrl[] = "http://update.url/foo";
#if defined(OS_WIN)
const base::FilePath::CharType kExtensionFilePath[] =
FILE_PATH_LITERAL("c:\\foo");
#elif defined(OS_POSIX)
const base::FilePath::CharType kExtensionFilePath[] = FILE_PATH_LITERAL("/oo");
#endif
class FakeThemeService : public ThemeService {
public:
FakeThemeService() {}
// ThemeService implementation
void DoSetTheme(const extensions::Extension* extension,
bool suppress_infobar) override {
is_dirty_ = true;
theme_extension_ = extension;
using_system_theme_ = false;
using_default_theme_ = false;
might_show_infobar_ = !suppress_infobar;
}
void UseDefaultTheme() override {
is_dirty_ = true;
using_default_theme_ = true;
using_system_theme_ = false;
theme_extension_ = NULL;
}
void UseSystemTheme() override {
is_dirty_ = true;
using_system_theme_ = true;
using_default_theme_ = false;
theme_extension_ = NULL;
}
bool IsSystemThemeDistinctFromDefaultTheme() const override {
return distinct_from_default_theme_;
}
void set_distinct_from_default_theme(bool is_distinct) {
distinct_from_default_theme_ = is_distinct;
}
bool UsingDefaultTheme() const override { return using_default_theme_; }
bool UsingSystemTheme() const override { return using_system_theme_; }
string GetThemeID() const override {
if (theme_extension_.get())
return theme_extension_->id();
else
return std::string();
}
const extensions::Extension* theme_extension() const {
return theme_extension_.get();
}
bool is_dirty() const { return is_dirty_; }
void MarkClean() { is_dirty_ = false; }
bool might_show_infobar() const { return might_show_infobar_; }
private:
bool using_system_theme_ = false;
bool using_default_theme_ = false;
bool distinct_from_default_theme_ = false;
scoped_refptr<const extensions::Extension> theme_extension_;
bool is_dirty_ = false;
bool might_show_infobar_ = false;
};
std::unique_ptr<KeyedService> BuildMockThemeService(
content::BrowserContext* profile) {
return base::WrapUnique(new FakeThemeService);
}
scoped_refptr<extensions::Extension> MakeThemeExtension(
const base::FilePath& extension_path,
const string& name,
extensions::Manifest::Location location,
const string& update_url) {
base::DictionaryValue source;
source.SetString(extensions::manifest_keys::kName, name);
source.Set(extensions::manifest_keys::kTheme,
std::make_unique<base::DictionaryValue>());
source.SetString(extensions::manifest_keys::kUpdateURL, update_url);
source.SetString(extensions::manifest_keys::kVersion, "0.0.0.0");
string error;
scoped_refptr<extensions::Extension> extension =
extensions::Extension::Create(
extension_path, location, source,
extensions::Extension::NO_FLAGS, &error);
EXPECT_TRUE(extension.get());
EXPECT_EQ("", error);
return extension;
}
} // namespace
class ThemeSyncableServiceTest : public testing::Test {
protected:
ThemeSyncableServiceTest() : fake_theme_service_(NULL) {}
~ThemeSyncableServiceTest() override {}
void SetUp() override {
// Setting a matching update URL is necessary to make the test theme
// considered syncable.
extension_test_util::SetGalleryUpdateURL(GURL(kCustomThemeUrl));
profile_.reset(new TestingProfile);
fake_theme_service_ = BuildForProfile(profile_.get());
theme_sync_service_.reset(new ThemeSyncableService(profile_.get(),
fake_theme_service_));
fake_change_processor_.reset(new syncer::FakeSyncChangeProcessor);
SetUpExtension();
}
void TearDown() override {
profile_.reset();
base::RunLoop().RunUntilIdle();
}
void SetUpExtension() {
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
extensions::TestExtensionSystem* test_ext_system =
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile_.get()));
extensions::ExtensionService* service =
test_ext_system->CreateExtensionService(
&command_line, base::FilePath(kExtensionFilePath), false);
EXPECT_TRUE(service->extensions_enabled());
service->Init();
base::RunLoop().RunUntilIdle();
// Create and add custom theme extension so the ThemeSyncableService can
// find it.
theme_extension_ = MakeThemeExtension(base::FilePath(kExtensionFilePath),
kCustomThemeName,
GetThemeLocation(),
kCustomThemeUrl);
extensions::ExtensionPrefs::Get(profile_.get())
->AddGrantedPermissions(theme_extension_->id(),
extensions::PermissionSet());
service->AddExtension(theme_extension_.get());
extensions::ExtensionRegistry* registry =
extensions::ExtensionRegistry::Get(profile_.get());
ASSERT_EQ(1u, registry->enabled_extensions().size());
}
// Overridden in PolicyInstalledThemeTest below.
virtual extensions::Manifest::Location GetThemeLocation() {
return extensions::Manifest::INTERNAL;
}
FakeThemeService* BuildForProfile(Profile* profile) {
return static_cast<FakeThemeService*>(
ThemeServiceFactory::GetInstance()->SetTestingFactoryAndUse(
profile, base::BindRepeating(&BuildMockThemeService)));
}
syncer::SyncDataList MakeThemeDataList(
const sync_pb::ThemeSpecifics& theme_specifics) {
syncer::SyncDataList list;
sync_pb::EntitySpecifics entity_specifics;
entity_specifics.mutable_theme()->CopyFrom(theme_specifics);
list.push_back(syncer::SyncData::CreateLocalData(
ThemeSyncableService::kCurrentThemeClientTag,
ThemeSyncableService::kCurrentThemeNodeTitle,
entity_specifics));
return list;
}
// Needed for setting up extension service.
content::TestBrowserThreadBundle test_browser_thread_bundle_;
#if defined OS_CHROMEOS
chromeos::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
chromeos::ScopedTestUserManager test_user_manager_;
#endif
std::unique_ptr<TestingProfile> profile_;
FakeThemeService* fake_theme_service_;
scoped_refptr<extensions::Extension> theme_extension_;
std::unique_ptr<ThemeSyncableService> theme_sync_service_;
std::unique_ptr<syncer::FakeSyncChangeProcessor> fake_change_processor_;
};
class PolicyInstalledThemeTest : public ThemeSyncableServiceTest {
extensions::Manifest::Location GetThemeLocation() override {
return extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD;
}
};
TEST_F(ThemeSyncableServiceTest, AreThemeSpecificsEqual) {
sync_pb::ThemeSpecifics a, b;
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
// Custom vs. non-custom.
a.set_use_custom_theme(true);
EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
// Custom theme equality.
b.set_use_custom_theme(true);
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
a.set_custom_theme_id("id");
EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
b.set_custom_theme_id("id");
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
a.set_custom_theme_update_url("http://update.url");
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
a.set_custom_theme_name("name");
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
// Non-custom theme equality.
a.set_use_custom_theme(false);
b.set_use_custom_theme(false);
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
a.set_use_system_theme_by_default(true);
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
b.set_use_system_theme_by_default(true);
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
}
TEST_F(ThemeSyncableServiceTest, SetCurrentThemeDefaultTheme) {
// Set up theme service to use custom theme.
fake_theme_service_->SetTheme(theme_extension_.get());
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(sync_pb::ThemeSpecifics()),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_FALSE(error.IsSet()) << error.message();
EXPECT_FALSE(fake_theme_service_->UsingDefaultTheme());
EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
}
TEST_F(ThemeSyncableServiceTest, SetCurrentThemeSystemTheme) {
sync_pb::ThemeSpecifics theme_specifics;
theme_specifics.set_use_system_theme_by_default(true);
// Set up theme service to use custom theme.
fake_theme_service_->SetTheme(theme_extension_.get());
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(theme_specifics),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_FALSE(error.IsSet()) << error.message();
EXPECT_FALSE(fake_theme_service_->UsingSystemTheme());
EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
}
TEST_F(ThemeSyncableServiceTest, SetCurrentThemeCustomTheme) {
sync_pb::ThemeSpecifics theme_specifics;
theme_specifics.set_use_custom_theme(true);
theme_specifics.set_custom_theme_id(theme_extension_->id());
theme_specifics.set_custom_theme_name(kCustomThemeName);
theme_specifics.set_custom_theme_name(kCustomThemeUrl);
// Set up theme service to use default theme.
fake_theme_service_->UseDefaultTheme();
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(theme_specifics),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_FALSE(error.IsSet()) << error.message();
EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
}
TEST_F(ThemeSyncableServiceTest, DontResetThemeWhenSpecificsAreEqual) {
// Set up theme service to use default theme and expect no changes.
fake_theme_service_->UseDefaultTheme();
fake_theme_service_->MarkClean();
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(sync_pb::ThemeSpecifics()),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_FALSE(error.IsSet()) << error.message();
EXPECT_FALSE(fake_theme_service_->is_dirty());
}
TEST_F(ThemeSyncableServiceTest, UpdateThemeSpecificsFromCurrentTheme) {
// Set up theme service to use custom theme.
fake_theme_service_->SetTheme(theme_extension_.get());
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, syncer::SyncDataList(),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_FALSE(error.IsSet()) << error.message();
const syncer::SyncChangeList& changes = fake_change_processor_->changes();
ASSERT_EQ(1u, changes.size());
EXPECT_TRUE(changes[0].IsValid());
EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
EXPECT_EQ(syncer::THEMES, changes[0].sync_data().GetDataType());
const sync_pb::ThemeSpecifics& theme_specifics =
changes[0].sync_data().GetSpecifics().theme();
EXPECT_TRUE(theme_specifics.use_custom_theme());
EXPECT_EQ(theme_extension_->id(), theme_specifics.custom_theme_id());
EXPECT_EQ(theme_extension_->name(), theme_specifics.custom_theme_name());
EXPECT_EQ(
extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(),
theme_specifics.custom_theme_update_url());
}
TEST_F(ThemeSyncableServiceTest, GetAllSyncData) {
// Set up theme service to use custom theme.
fake_theme_service_->SetTheme(theme_extension_.get());
syncer::SyncDataList data_list =
theme_sync_service_->GetAllSyncData(syncer::THEMES);
ASSERT_EQ(1u, data_list.size());
const sync_pb::ThemeSpecifics& theme_specifics =
data_list[0].GetSpecifics().theme();
EXPECT_TRUE(theme_specifics.use_custom_theme());
EXPECT_EQ(theme_extension_->id(), theme_specifics.custom_theme_id());
EXPECT_EQ(theme_extension_->name(), theme_specifics.custom_theme_name());
EXPECT_EQ(
extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(),
theme_specifics.custom_theme_update_url());
}
TEST_F(ThemeSyncableServiceTest, ProcessSyncThemeChange) {
// Set up theme service to use default theme.
fake_theme_service_->UseDefaultTheme();
fake_theme_service_->MarkClean();
// Start syncing.
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(sync_pb::ThemeSpecifics()),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_FALSE(error.IsSet()) << error.message();
// Don't expect theme change initially because specifics are equal.
EXPECT_FALSE(fake_theme_service_->is_dirty());
// Change specifics to use custom theme and update.
sync_pb::ThemeSpecifics theme_specifics;
theme_specifics.set_use_custom_theme(true);
theme_specifics.set_custom_theme_id(theme_extension_->id());
theme_specifics.set_custom_theme_name(kCustomThemeName);
theme_specifics.set_custom_theme_name(kCustomThemeUrl);
sync_pb::EntitySpecifics entity_specifics;
entity_specifics.mutable_theme()->CopyFrom(theme_specifics);
syncer::SyncChangeList change_list;
change_list.push_back(syncer::SyncChange(
FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
syncer::SyncData::CreateRemoteData(1, entity_specifics)));
error = theme_sync_service_->ProcessSyncChanges(FROM_HERE, change_list);
EXPECT_FALSE(error.IsSet()) << error.message();
EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
// Don't show an infobar for theme installation. Regression test for
// crbug.com/731688
EXPECT_FALSE(fake_theme_service_->might_show_infobar());
}
TEST_F(ThemeSyncableServiceTest, OnThemeChangeByUser) {
// Set up theme service to use default theme.
fake_theme_service_->UseDefaultTheme();
// Start syncing.
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(sync_pb::ThemeSpecifics()),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_FALSE(error.IsSet()) << error.message();
const syncer::SyncChangeList& changes = fake_change_processor_->changes();
EXPECT_EQ(0u, changes.size());
// Change current theme to custom theme and notify theme_sync_service_.
fake_theme_service_->SetTheme(theme_extension_.get());
theme_sync_service_->OnThemeChange();
EXPECT_EQ(1u, changes.size());
const sync_pb::ThemeSpecifics& change_specifics =
changes[0].sync_data().GetSpecifics().theme();
EXPECT_TRUE(change_specifics.use_custom_theme());
EXPECT_EQ(theme_extension_->id(), change_specifics.custom_theme_id());
EXPECT_EQ(theme_extension_->name(), change_specifics.custom_theme_name());
EXPECT_EQ(
extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(),
change_specifics.custom_theme_update_url());
}
TEST_F(ThemeSyncableServiceTest, StopSync) {
// Set up theme service to use default theme.
fake_theme_service_->UseDefaultTheme();
// Start syncing.
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(sync_pb::ThemeSpecifics()),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_FALSE(error.IsSet()) << error.message();
const syncer::SyncChangeList& changes = fake_change_processor_->changes();
EXPECT_EQ(0u, changes.size());
// Stop syncing.
theme_sync_service_->StopSyncing(syncer::THEMES);
// Change current theme to custom theme and notify theme_sync_service_.
// No change is output because sync has stopped.
fake_theme_service_->SetTheme(theme_extension_.get());
theme_sync_service_->OnThemeChange();
EXPECT_EQ(0u, changes.size());
// ProcessSyncChanges() should return error when sync has stopped.
error = theme_sync_service_->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_TRUE(error.IsSet());
EXPECT_EQ(syncer::THEMES, error.model_type());
EXPECT_EQ("Theme syncable service is not started.", error.message());
}
TEST_F(ThemeSyncableServiceTest, RestoreSystemThemeBitWhenChangeToCustomTheme) {
// Initialize to use system theme.
fake_theme_service_->UseDefaultTheme();
sync_pb::ThemeSpecifics theme_specifics;
theme_specifics.set_use_system_theme_by_default(true);
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(theme_specifics),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
// Change to custom theme and notify theme_sync_service_.
// use_system_theme_by_default bit should be preserved.
fake_theme_service_->SetTheme(theme_extension_.get());
theme_sync_service_->OnThemeChange();
const syncer::SyncChangeList& changes = fake_change_processor_->changes();
EXPECT_EQ(1u, changes.size());
const sync_pb::ThemeSpecifics& change_specifics =
changes[0].sync_data().GetSpecifics().theme();
EXPECT_TRUE(change_specifics.use_system_theme_by_default());
}
TEST_F(ThemeSyncableServiceTest, DistinctSystemTheme) {
fake_theme_service_->set_distinct_from_default_theme(true);
// Initialize to use native theme.
fake_theme_service_->UseSystemTheme();
fake_theme_service_->MarkClean();
sync_pb::ThemeSpecifics theme_specifics;
theme_specifics.set_use_system_theme_by_default(true);
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(theme_specifics),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_FALSE(fake_theme_service_->is_dirty());
// Change to default theme and notify theme_sync_service_.
// use_system_theme_by_default bit should be false.
fake_theme_service_->UseDefaultTheme();
theme_sync_service_->OnThemeChange();
syncer::SyncChangeList& changes = fake_change_processor_->changes();
EXPECT_EQ(1u, changes.size());
EXPECT_FALSE(changes[0]
.sync_data()
.GetSpecifics()
.theme()
.use_system_theme_by_default());
// Change to native theme and notify theme_sync_service_.
// use_system_theme_by_default bit should be true.
changes.clear();
fake_theme_service_->UseSystemTheme();
theme_sync_service_->OnThemeChange();
EXPECT_EQ(1u, changes.size());
EXPECT_TRUE(changes[0]
.sync_data()
.GetSpecifics()
.theme()
.use_system_theme_by_default());
}
TEST_F(ThemeSyncableServiceTest, SystemThemeSameAsDefaultTheme) {
fake_theme_service_->set_distinct_from_default_theme(false);
// Set up theme service to use default theme.
fake_theme_service_->UseDefaultTheme();
// Initialize to use custom theme with use_system_theme_by_default set true.
sync_pb::ThemeSpecifics theme_specifics;
theme_specifics.set_use_custom_theme(true);
theme_specifics.set_custom_theme_id(theme_extension_->id());
theme_specifics.set_custom_theme_name(kCustomThemeName);
theme_specifics.set_custom_theme_name(kCustomThemeUrl);
theme_specifics.set_use_system_theme_by_default(true);
syncer::SyncError error =
theme_sync_service_
->MergeDataAndStartSyncing(
syncer::THEMES, MakeThemeDataList(theme_specifics),
std::unique_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
fake_change_processor_.get())),
std::unique_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock()))
.error();
EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
// Change to default theme and notify theme_sync_service_.
// use_system_theme_by_default bit should be preserved.
fake_theme_service_->UseDefaultTheme();
theme_sync_service_->OnThemeChange();
const syncer::SyncChangeList& changes = fake_change_processor_->changes();
EXPECT_EQ(1u, changes.size());
const sync_pb::ThemeSpecifics& change_specifics =
changes[0].sync_data().GetSpecifics().theme();
EXPECT_FALSE(change_specifics.use_custom_theme());
EXPECT_TRUE(change_specifics.use_system_theme_by_default());
}
TEST_F(PolicyInstalledThemeTest, InstallThemeByPolicy) {
// Set up theme service to use custom theme that was installed by policy.
fake_theme_service_->SetTheme(theme_extension_.get());
syncer::SyncDataList data_list =
theme_sync_service_->GetAllSyncData(syncer::THEMES);
ASSERT_EQ(0u, data_list.size());
}