1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/themes/theme_syncable_service.h"
7 #include "base/command_line.h"
8 #include "base/compiler_specific.h"
9 #include "base/files/file_path.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/test_extension_system.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/themes/theme_service.h"
16 #include "chrome/browser/themes/theme_service_factory.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "content/public/test/test_browser_thread.h"
19 #include "extensions/browser/extension_prefs.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/common/manifest_constants.h"
23 #include "extensions/common/manifest_url_handlers.h"
24 #include "extensions/common/permissions/api_permission_set.h"
25 #include "extensions/common/permissions/permission_set.h"
26 #include "sync/api/attachments/attachment_id.h"
27 #include "sync/api/fake_sync_change_processor.h"
28 #include "sync/api/sync_change_processor_wrapper_for_test.h"
29 #include "sync/api/sync_error.h"
30 #include "sync/api/sync_error_factory_mock.h"
31 #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h"
32 #include "sync/protocol/sync.pb.h"
33 #include "sync/protocol/theme_specifics.pb.h"
34 #include "testing/gtest/include/gtest/gtest.h"
36 #if defined(OS_CHROMEOS)
37 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
38 #include "chrome/browser/chromeos/settings/cros_settings.h"
39 #include "chrome/browser/chromeos/settings/device_settings_service.h"
46 static const char kCustomThemeName
[] = "name";
47 static const char kCustomThemeUrl
[] = "http://update.url/foo";
50 const base::FilePath::CharType kExtensionFilePath
[] =
51 FILE_PATH_LITERAL("c:\\foo");
52 #elif defined(OS_POSIX)
53 const base::FilePath::CharType kExtensionFilePath
[] = FILE_PATH_LITERAL("/oo");
56 class FakeThemeService
: public ThemeService
{
59 using_system_theme_(false),
60 using_default_theme_(false),
61 theme_extension_(NULL
),
64 // ThemeService implementation
65 void SetTheme(const extensions::Extension
* extension
) override
{
67 theme_extension_
= extension
;
68 using_system_theme_
= false;
69 using_default_theme_
= false;
72 void UseDefaultTheme() override
{
74 using_default_theme_
= true;
75 using_system_theme_
= false;
76 theme_extension_
= NULL
;
79 void UseSystemTheme() override
{
81 using_system_theme_
= true;
82 using_default_theme_
= false;
83 theme_extension_
= NULL
;
86 bool UsingDefaultTheme() const override
{ return using_default_theme_
; }
88 bool UsingSystemTheme() const override
{ return using_system_theme_
; }
90 string
GetThemeID() const override
{
91 if (theme_extension_
.get())
92 return theme_extension_
->id();
97 const extensions::Extension
* theme_extension() const {
98 return theme_extension_
.get();
101 bool is_dirty() const {
110 bool using_system_theme_
;
111 bool using_default_theme_
;
112 scoped_refptr
<const extensions::Extension
> theme_extension_
;
116 scoped_ptr
<KeyedService
> BuildMockThemeService(
117 content::BrowserContext
* profile
) {
118 return make_scoped_ptr(new FakeThemeService
);
121 scoped_refptr
<extensions::Extension
> MakeThemeExtension(
122 const base::FilePath
& extension_path
,
124 extensions::Manifest::Location location
,
125 const string
& update_url
) {
126 base::DictionaryValue source
;
127 source
.SetString(extensions::manifest_keys::kName
, name
);
128 source
.Set(extensions::manifest_keys::kTheme
, new base::DictionaryValue());
129 source
.SetString(extensions::manifest_keys::kUpdateURL
, update_url
);
130 source
.SetString(extensions::manifest_keys::kVersion
, "0.0.0.0");
132 scoped_refptr
<extensions::Extension
> extension
=
133 extensions::Extension::Create(
134 extension_path
, location
, source
,
135 extensions::Extension::NO_FLAGS
, &error
);
136 EXPECT_TRUE(extension
.get());
137 EXPECT_EQ("", error
);
143 class ThemeSyncableServiceTest
: public testing::Test
{
145 ThemeSyncableServiceTest()
146 : ui_thread_(content::BrowserThread::UI
, &loop_
),
147 file_thread_(content::BrowserThread::FILE, &loop_
),
148 fake_theme_service_(NULL
) {}
150 ~ThemeSyncableServiceTest() override
{}
152 void SetUp() override
{
153 profile_
.reset(new TestingProfile
);
154 fake_theme_service_
= BuildForProfile(profile_
.get());
155 theme_sync_service_
.reset(new ThemeSyncableService(profile_
.get(),
156 fake_theme_service_
));
157 fake_change_processor_
.reset(new syncer::FakeSyncChangeProcessor
);
161 void TearDown() override
{
163 loop_
.RunUntilIdle();
166 void SetUpExtension() {
167 base::CommandLine
command_line(base::CommandLine::NO_PROGRAM
);
168 extensions::TestExtensionSystem
* test_ext_system
=
169 static_cast<extensions::TestExtensionSystem
*>(
170 extensions::ExtensionSystem::Get(profile_
.get()));
171 ExtensionService
* service
= test_ext_system
->CreateExtensionService(
172 &command_line
, base::FilePath(kExtensionFilePath
), false);
173 EXPECT_TRUE(service
->extensions_enabled());
175 loop_
.RunUntilIdle();
177 // Create and add custom theme extension so the ThemeSyncableService can
179 theme_extension_
= MakeThemeExtension(base::FilePath(kExtensionFilePath
),
183 extensions::APIPermissionSet empty_set
;
184 extensions::ManifestPermissionSet empty_manifest_permissions
;
185 extensions::URLPatternSet empty_extent
;
186 scoped_refptr
<extensions::PermissionSet
> permissions
=
187 new extensions::PermissionSet(empty_set
, empty_manifest_permissions
,
188 empty_extent
, empty_extent
);
189 extensions::ExtensionPrefs::Get(profile_
.get())
190 ->AddGrantedPermissions(theme_extension_
->id(), permissions
.get());
191 service
->AddExtension(theme_extension_
.get());
192 extensions::ExtensionRegistry
* registry
=
193 extensions::ExtensionRegistry::Get(profile_
.get());
194 ASSERT_EQ(1u, registry
->enabled_extensions().size());
197 // Overridden in PolicyInstalledThemeTest below.
198 virtual extensions::Manifest::Location
GetThemeLocation() {
199 return extensions::Manifest::INTERNAL
;
202 FakeThemeService
* BuildForProfile(Profile
* profile
) {
203 return static_cast<FakeThemeService
*>(
204 ThemeServiceFactory::GetInstance()->SetTestingFactoryAndUse(
205 profile
, &BuildMockThemeService
));
208 syncer::SyncDataList
MakeThemeDataList(
209 const sync_pb::ThemeSpecifics
& theme_specifics
) {
210 syncer::SyncDataList list
;
211 sync_pb::EntitySpecifics entity_specifics
;
212 entity_specifics
.mutable_theme()->CopyFrom(theme_specifics
);
213 list
.push_back(syncer::SyncData::CreateLocalData(
214 ThemeSyncableService::kCurrentThemeClientTag
,
215 ThemeSyncableService::kCurrentThemeNodeTitle
,
220 // Needed for setting up extension service.
221 base::MessageLoop loop_
;
222 content::TestBrowserThread ui_thread_
;
223 content::TestBrowserThread file_thread_
;
225 #if defined OS_CHROMEOS
226 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_
;
227 chromeos::ScopedTestCrosSettings test_cros_settings_
;
228 chromeos::ScopedTestUserManager test_user_manager_
;
231 scoped_ptr
<TestingProfile
> profile_
;
232 FakeThemeService
* fake_theme_service_
;
233 scoped_refptr
<extensions::Extension
> theme_extension_
;
234 scoped_ptr
<ThemeSyncableService
> theme_sync_service_
;
235 scoped_ptr
<syncer::FakeSyncChangeProcessor
> fake_change_processor_
;
238 class PolicyInstalledThemeTest
: public ThemeSyncableServiceTest
{
239 extensions::Manifest::Location
GetThemeLocation() override
{
240 return extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD
;
244 TEST_F(ThemeSyncableServiceTest
, AreThemeSpecificsEqual
) {
245 sync_pb::ThemeSpecifics a
, b
;
246 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
247 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
249 // Custom vs. non-custom.
251 a
.set_use_custom_theme(true);
252 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
253 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
255 // Custom theme equality.
257 b
.set_use_custom_theme(true);
258 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
259 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
261 a
.set_custom_theme_id("id");
262 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
263 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
265 b
.set_custom_theme_id("id");
266 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
267 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
269 a
.set_custom_theme_update_url("http://update.url");
270 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
271 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
273 a
.set_custom_theme_name("name");
274 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
275 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
277 // Non-custom theme equality.
279 a
.set_use_custom_theme(false);
280 b
.set_use_custom_theme(false);
281 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
282 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
284 a
.set_use_system_theme_by_default(true);
285 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
286 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
288 b
.set_use_system_theme_by_default(true);
289 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
290 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
293 TEST_F(ThemeSyncableServiceTest
, SetCurrentThemeDefaultTheme
) {
294 // Set up theme service to use custom theme.
295 fake_theme_service_
->SetTheme(theme_extension_
.get());
297 syncer::SyncError error
=
299 ->MergeDataAndStartSyncing(
301 MakeThemeDataList(sync_pb::ThemeSpecifics()),
302 scoped_ptr
<syncer::SyncChangeProcessor
>(
303 new syncer::SyncChangeProcessorWrapperForTest(
304 fake_change_processor_
.get())),
305 scoped_ptr
<syncer::SyncErrorFactory
>(
306 new syncer::SyncErrorFactoryMock()))
308 EXPECT_FALSE(error
.IsSet()) << error
.message();
309 EXPECT_TRUE(fake_theme_service_
->UsingDefaultTheme());
312 TEST_F(ThemeSyncableServiceTest
, SetCurrentThemeSystemTheme
) {
313 sync_pb::ThemeSpecifics theme_specifics
;
314 theme_specifics
.set_use_system_theme_by_default(true);
316 // Set up theme service to use custom theme.
317 fake_theme_service_
->SetTheme(theme_extension_
.get());
318 syncer::SyncError error
=
320 ->MergeDataAndStartSyncing(
322 MakeThemeDataList(theme_specifics
),
323 scoped_ptr
<syncer::SyncChangeProcessor
>(
324 new syncer::SyncChangeProcessorWrapperForTest(
325 fake_change_processor_
.get())),
326 scoped_ptr
<syncer::SyncErrorFactory
>(
327 new syncer::SyncErrorFactoryMock()))
329 EXPECT_FALSE(error
.IsSet()) << error
.message();
330 EXPECT_TRUE(fake_theme_service_
->UsingSystemTheme());
333 TEST_F(ThemeSyncableServiceTest
, SetCurrentThemeCustomTheme
) {
334 sync_pb::ThemeSpecifics theme_specifics
;
335 theme_specifics
.set_use_custom_theme(true);
336 theme_specifics
.set_custom_theme_id(theme_extension_
->id());
337 theme_specifics
.set_custom_theme_name(kCustomThemeName
);
338 theme_specifics
.set_custom_theme_name(kCustomThemeUrl
);
340 // Set up theme service to use default theme.
341 fake_theme_service_
->UseDefaultTheme();
342 syncer::SyncError error
=
344 ->MergeDataAndStartSyncing(
346 MakeThemeDataList(theme_specifics
),
347 scoped_ptr
<syncer::SyncChangeProcessor
>(
348 new syncer::SyncChangeProcessorWrapperForTest(
349 fake_change_processor_
.get())),
350 scoped_ptr
<syncer::SyncErrorFactory
>(
351 new syncer::SyncErrorFactoryMock()))
353 EXPECT_FALSE(error
.IsSet()) << error
.message();
354 EXPECT_EQ(fake_theme_service_
->theme_extension(), theme_extension_
.get());
357 TEST_F(ThemeSyncableServiceTest
, DontResetThemeWhenSpecificsAreEqual
) {
358 // Set up theme service to use default theme and expect no changes.
359 fake_theme_service_
->UseDefaultTheme();
360 fake_theme_service_
->MarkClean();
361 syncer::SyncError error
=
363 ->MergeDataAndStartSyncing(
365 MakeThemeDataList(sync_pb::ThemeSpecifics()),
366 scoped_ptr
<syncer::SyncChangeProcessor
>(
367 new syncer::SyncChangeProcessorWrapperForTest(
368 fake_change_processor_
.get())),
369 scoped_ptr
<syncer::SyncErrorFactory
>(
370 new syncer::SyncErrorFactoryMock()))
372 EXPECT_FALSE(error
.IsSet()) << error
.message();
373 EXPECT_FALSE(fake_theme_service_
->is_dirty());
376 TEST_F(ThemeSyncableServiceTest
, UpdateThemeSpecificsFromCurrentTheme
) {
377 // Set up theme service to use custom theme.
378 fake_theme_service_
->SetTheme(theme_extension_
.get());
380 syncer::SyncError error
=
382 ->MergeDataAndStartSyncing(
384 syncer::SyncDataList(),
385 scoped_ptr
<syncer::SyncChangeProcessor
>(
386 new syncer::SyncChangeProcessorWrapperForTest(
387 fake_change_processor_
.get())),
388 scoped_ptr
<syncer::SyncErrorFactory
>(
389 new syncer::SyncErrorFactoryMock()))
391 EXPECT_FALSE(error
.IsSet()) << error
.message();
392 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
393 ASSERT_EQ(1u, changes
.size());
394 EXPECT_TRUE(changes
[0].IsValid());
395 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, changes
[0].change_type());
396 EXPECT_EQ(syncer::THEMES
, changes
[0].sync_data().GetDataType());
398 const sync_pb::ThemeSpecifics
& theme_specifics
=
399 changes
[0].sync_data().GetSpecifics().theme();
400 EXPECT_TRUE(theme_specifics
.use_custom_theme());
401 EXPECT_EQ(theme_extension_
->id(), theme_specifics
.custom_theme_id());
402 EXPECT_EQ(theme_extension_
->name(), theme_specifics
.custom_theme_name());
404 extensions::ManifestURL::GetUpdateURL(theme_extension_
.get()).spec(),
405 theme_specifics
.custom_theme_update_url());
408 TEST_F(ThemeSyncableServiceTest
, GetAllSyncData
) {
409 // Set up theme service to use custom theme.
410 fake_theme_service_
->SetTheme(theme_extension_
.get());
412 syncer::SyncDataList data_list
=
413 theme_sync_service_
->GetAllSyncData(syncer::THEMES
);
415 ASSERT_EQ(1u, data_list
.size());
416 const sync_pb::ThemeSpecifics
& theme_specifics
=
417 data_list
[0].GetSpecifics().theme();
418 EXPECT_TRUE(theme_specifics
.use_custom_theme());
419 EXPECT_EQ(theme_extension_
->id(), theme_specifics
.custom_theme_id());
420 EXPECT_EQ(theme_extension_
->name(), theme_specifics
.custom_theme_name());
422 extensions::ManifestURL::GetUpdateURL(theme_extension_
.get()).spec(),
423 theme_specifics
.custom_theme_update_url());
426 TEST_F(ThemeSyncableServiceTest
, ProcessSyncThemeChange
) {
427 // Set up theme service to use default theme.
428 fake_theme_service_
->UseDefaultTheme();
429 fake_theme_service_
->MarkClean();
432 syncer::SyncError error
=
434 ->MergeDataAndStartSyncing(
436 MakeThemeDataList(sync_pb::ThemeSpecifics()),
437 scoped_ptr
<syncer::SyncChangeProcessor
>(
438 new syncer::SyncChangeProcessorWrapperForTest(
439 fake_change_processor_
.get())),
440 scoped_ptr
<syncer::SyncErrorFactory
>(
441 new syncer::SyncErrorFactoryMock()))
443 EXPECT_FALSE(error
.IsSet()) << error
.message();
444 // Don't expect theme change initially because specifics are equal.
445 EXPECT_FALSE(fake_theme_service_
->is_dirty());
447 // Change specifics to use custom theme and update.
448 sync_pb::ThemeSpecifics theme_specifics
;
449 theme_specifics
.set_use_custom_theme(true);
450 theme_specifics
.set_custom_theme_id(theme_extension_
->id());
451 theme_specifics
.set_custom_theme_name(kCustomThemeName
);
452 theme_specifics
.set_custom_theme_name(kCustomThemeUrl
);
453 sync_pb::EntitySpecifics entity_specifics
;
454 entity_specifics
.mutable_theme()->CopyFrom(theme_specifics
);
455 syncer::SyncChangeList change_list
;
456 change_list
.push_back(
457 syncer::SyncChange(FROM_HERE
,
458 syncer::SyncChange::ACTION_UPDATE
,
459 syncer::SyncData::CreateRemoteData(
463 syncer::AttachmentIdList(),
464 syncer::AttachmentServiceProxyForTest::Create())));
465 error
= theme_sync_service_
->ProcessSyncChanges(FROM_HERE
, change_list
);
466 EXPECT_FALSE(error
.IsSet()) << error
.message();
467 EXPECT_EQ(fake_theme_service_
->theme_extension(), theme_extension_
.get());
470 TEST_F(ThemeSyncableServiceTest
, OnThemeChangeByUser
) {
471 // Set up theme service to use default theme.
472 fake_theme_service_
->UseDefaultTheme();
475 syncer::SyncError error
=
477 ->MergeDataAndStartSyncing(
479 MakeThemeDataList(sync_pb::ThemeSpecifics()),
480 scoped_ptr
<syncer::SyncChangeProcessor
>(
481 new syncer::SyncChangeProcessorWrapperForTest(
482 fake_change_processor_
.get())),
483 scoped_ptr
<syncer::SyncErrorFactory
>(
484 new syncer::SyncErrorFactoryMock()))
486 EXPECT_FALSE(error
.IsSet()) << error
.message();
487 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
488 EXPECT_EQ(0u, changes
.size());
490 // Change current theme to custom theme and notify theme_sync_service_.
491 fake_theme_service_
->SetTheme(theme_extension_
.get());
492 theme_sync_service_
->OnThemeChange();
493 EXPECT_EQ(1u, changes
.size());
494 const sync_pb::ThemeSpecifics
& change_specifics
=
495 changes
[0].sync_data().GetSpecifics().theme();
496 EXPECT_TRUE(change_specifics
.use_custom_theme());
497 EXPECT_EQ(theme_extension_
->id(), change_specifics
.custom_theme_id());
498 EXPECT_EQ(theme_extension_
->name(), change_specifics
.custom_theme_name());
500 extensions::ManifestURL::GetUpdateURL(theme_extension_
.get()).spec(),
501 change_specifics
.custom_theme_update_url());
504 TEST_F(ThemeSyncableServiceTest
, StopSync
) {
505 // Set up theme service to use default theme.
506 fake_theme_service_
->UseDefaultTheme();
509 syncer::SyncError error
=
511 ->MergeDataAndStartSyncing(
513 MakeThemeDataList(sync_pb::ThemeSpecifics()),
514 scoped_ptr
<syncer::SyncChangeProcessor
>(
515 new syncer::SyncChangeProcessorWrapperForTest(
516 fake_change_processor_
.get())),
517 scoped_ptr
<syncer::SyncErrorFactory
>(
518 new syncer::SyncErrorFactoryMock()))
520 EXPECT_FALSE(error
.IsSet()) << error
.message();
521 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
522 EXPECT_EQ(0u, changes
.size());
525 theme_sync_service_
->StopSyncing(syncer::THEMES
);
527 // Change current theme to custom theme and notify theme_sync_service_.
528 // No change is output because sync has stopped.
529 fake_theme_service_
->SetTheme(theme_extension_
.get());
530 theme_sync_service_
->OnThemeChange();
531 EXPECT_EQ(0u, changes
.size());
533 // ProcessSyncChanges() should return error when sync has stopped.
534 error
= theme_sync_service_
->ProcessSyncChanges(FROM_HERE
, changes
);
535 EXPECT_TRUE(error
.IsSet());
536 EXPECT_EQ(syncer::THEMES
, error
.model_type());
537 EXPECT_EQ("Theme syncable service is not started.", error
.message());
540 TEST_F(ThemeSyncableServiceTest
, RestoreSystemThemeBitWhenChangeToCustomTheme
) {
541 // Initialize to use system theme.
542 fake_theme_service_
->UseDefaultTheme();
543 sync_pb::ThemeSpecifics theme_specifics
;
544 theme_specifics
.set_use_system_theme_by_default(true);
545 syncer::SyncError error
=
547 ->MergeDataAndStartSyncing(
549 MakeThemeDataList(theme_specifics
),
550 scoped_ptr
<syncer::SyncChangeProcessor
>(
551 new syncer::SyncChangeProcessorWrapperForTest(
552 fake_change_processor_
.get())),
553 scoped_ptr
<syncer::SyncErrorFactory
>(
554 new syncer::SyncErrorFactoryMock()))
557 // Change to custom theme and notify theme_sync_service_.
558 // use_system_theme_by_default bit should be preserved.
559 fake_theme_service_
->SetTheme(theme_extension_
.get());
560 theme_sync_service_
->OnThemeChange();
561 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
562 EXPECT_EQ(1u, changes
.size());
563 const sync_pb::ThemeSpecifics
& change_specifics
=
564 changes
[0].sync_data().GetSpecifics().theme();
565 EXPECT_TRUE(change_specifics
.use_system_theme_by_default());
568 #if defined(TOOLKIT_GTK)
569 TEST_F(ThemeSyncableServiceTest
,
570 GtkUpdateSystemThemeBitWhenChangeBetweenSystemAndDefault
) {
571 // Initialize to use native theme.
572 fake_theme_service_
->UseSystemTheme();
573 fake_theme_service_
->MarkClean();
574 sync_pb::ThemeSpecifics theme_specifics
;
575 theme_specifics
.set_use_system_theme_by_default(true);
576 syncer::SyncError error
=
578 ->MergeDataAndStartSyncing(
580 MakeThemeDataList(theme_specifics
),
581 scoped_ptr
<syncer::SyncChangeProcessor
>(
582 new syncer::SyncChangeProcessorWrapperForTest(
583 fake_change_processor_
.get())),
584 scoped_ptr
<syncer::SyncErrorFactory
>(
585 new syncer::SyncErrorFactoryMock()))
587 EXPECT_FALSE(fake_theme_service_
->is_dirty());
589 // Change to default theme and notify theme_sync_service_.
590 // use_system_theme_by_default bit should be false.
591 fake_theme_service_
->UseDefaultTheme();
592 theme_sync_service_
->OnThemeChange();
593 syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
594 EXPECT_EQ(1u, changes
.size());
595 EXPECT_FALSE(changes
[0]
599 .use_system_theme_by_default());
601 // Change to native theme and notify theme_sync_service_.
602 // use_system_theme_by_default bit should be true.
604 fake_theme_service_
->UseSystemTheme();
605 theme_sync_service_
->OnThemeChange();
606 EXPECT_EQ(1u, changes
.size());
607 EXPECT_TRUE(changes
[0]
611 .use_system_theme_by_default());
616 TEST_F(ThemeSyncableServiceTest
,
617 NonGtkPreserveSystemThemeBitWhenChangeToDefaultTheme
) {
618 // Set up theme service to use default theme.
619 fake_theme_service_
->UseDefaultTheme();
621 // Initialize to use custom theme with use_system_theme_by_default set true.
622 sync_pb::ThemeSpecifics theme_specifics
;
623 theme_specifics
.set_use_custom_theme(true);
624 theme_specifics
.set_custom_theme_id(theme_extension_
->id());
625 theme_specifics
.set_custom_theme_name(kCustomThemeName
);
626 theme_specifics
.set_custom_theme_name(kCustomThemeUrl
);
627 theme_specifics
.set_use_system_theme_by_default(true);
628 syncer::SyncError error
=
630 ->MergeDataAndStartSyncing(
632 MakeThemeDataList(theme_specifics
),
633 scoped_ptr
<syncer::SyncChangeProcessor
>(
634 new syncer::SyncChangeProcessorWrapperForTest(
635 fake_change_processor_
.get())),
636 scoped_ptr
<syncer::SyncErrorFactory
>(
637 new syncer::SyncErrorFactoryMock()))
639 EXPECT_EQ(fake_theme_service_
->theme_extension(), theme_extension_
.get());
641 // Change to default theme and notify theme_sync_service_.
642 // use_system_theme_by_default bit should be preserved.
643 fake_theme_service_
->UseDefaultTheme();
644 theme_sync_service_
->OnThemeChange();
645 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
646 EXPECT_EQ(1u, changes
.size());
647 const sync_pb::ThemeSpecifics
& change_specifics
=
648 changes
[0].sync_data().GetSpecifics().theme();
649 EXPECT_FALSE(change_specifics
.use_custom_theme());
650 EXPECT_TRUE(change_specifics
.use_system_theme_by_default());
654 TEST_F(PolicyInstalledThemeTest
, InstallThemeByPolicy
) {
655 // Set up theme service to use custom theme that was installed by policy.
656 fake_theme_service_
->SetTheme(theme_extension_
.get());
658 syncer::SyncDataList data_list
=
659 theme_sync_service_
->GetAllSyncData(syncer::THEMES
);
661 ASSERT_EQ(0u, data_list
.size());