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 KeyedService
* BuildMockThemeService(content::BrowserContext
* profile
) {
117 return new FakeThemeService
;
120 scoped_refptr
<extensions::Extension
> MakeThemeExtension(
121 const base::FilePath
& extension_path
,
123 extensions::Manifest::Location location
,
124 const string
& update_url
) {
125 base::DictionaryValue source
;
126 source
.SetString(extensions::manifest_keys::kName
, name
);
127 source
.Set(extensions::manifest_keys::kTheme
, new base::DictionaryValue());
128 source
.SetString(extensions::manifest_keys::kUpdateURL
, update_url
);
129 source
.SetString(extensions::manifest_keys::kVersion
, "0.0.0.0");
131 scoped_refptr
<extensions::Extension
> extension
=
132 extensions::Extension::Create(
133 extension_path
, location
, source
,
134 extensions::Extension::NO_FLAGS
, &error
);
135 EXPECT_TRUE(extension
.get());
136 EXPECT_EQ("", error
);
142 class ThemeSyncableServiceTest
: public testing::Test
{
144 ThemeSyncableServiceTest()
145 : ui_thread_(content::BrowserThread::UI
, &loop_
),
146 file_thread_(content::BrowserThread::FILE, &loop_
),
147 fake_theme_service_(NULL
) {}
149 ~ThemeSyncableServiceTest() override
{}
151 void SetUp() override
{
152 profile_
.reset(new TestingProfile
);
153 fake_theme_service_
= BuildForProfile(profile_
.get());
154 theme_sync_service_
.reset(new ThemeSyncableService(profile_
.get(),
155 fake_theme_service_
));
156 fake_change_processor_
.reset(new syncer::FakeSyncChangeProcessor
);
160 void TearDown() override
{
162 loop_
.RunUntilIdle();
165 void SetUpExtension() {
166 base::CommandLine
command_line(base::CommandLine::NO_PROGRAM
);
167 extensions::TestExtensionSystem
* test_ext_system
=
168 static_cast<extensions::TestExtensionSystem
*>(
169 extensions::ExtensionSystem::Get(profile_
.get()));
170 ExtensionService
* service
= test_ext_system
->CreateExtensionService(
171 &command_line
, base::FilePath(kExtensionFilePath
), false);
172 EXPECT_TRUE(service
->extensions_enabled());
174 loop_
.RunUntilIdle();
176 // Create and add custom theme extension so the ThemeSyncableService can
178 theme_extension_
= MakeThemeExtension(base::FilePath(kExtensionFilePath
),
182 extensions::APIPermissionSet empty_set
;
183 extensions::ManifestPermissionSet empty_manifest_permissions
;
184 extensions::URLPatternSet empty_extent
;
185 scoped_refptr
<extensions::PermissionSet
> permissions
=
186 new extensions::PermissionSet(empty_set
, empty_manifest_permissions
,
187 empty_extent
, empty_extent
);
188 extensions::ExtensionPrefs::Get(profile_
.get())
189 ->AddGrantedPermissions(theme_extension_
->id(), permissions
.get());
190 service
->AddExtension(theme_extension_
.get());
191 extensions::ExtensionRegistry
* registry
=
192 extensions::ExtensionRegistry::Get(profile_
.get());
193 ASSERT_EQ(1u, registry
->enabled_extensions().size());
196 // Overridden in PolicyInstalledThemeTest below.
197 virtual extensions::Manifest::Location
GetThemeLocation() {
198 return extensions::Manifest::INTERNAL
;
201 FakeThemeService
* BuildForProfile(Profile
* profile
) {
202 return static_cast<FakeThemeService
*>(
203 ThemeServiceFactory::GetInstance()->SetTestingFactoryAndUse(
204 profile
, &BuildMockThemeService
));
207 syncer::SyncDataList
MakeThemeDataList(
208 const sync_pb::ThemeSpecifics
& theme_specifics
) {
209 syncer::SyncDataList list
;
210 sync_pb::EntitySpecifics entity_specifics
;
211 entity_specifics
.mutable_theme()->CopyFrom(theme_specifics
);
212 list
.push_back(syncer::SyncData::CreateLocalData(
213 ThemeSyncableService::kCurrentThemeClientTag
,
214 ThemeSyncableService::kCurrentThemeNodeTitle
,
219 // Needed for setting up extension service.
220 base::MessageLoop loop_
;
221 content::TestBrowserThread ui_thread_
;
222 content::TestBrowserThread file_thread_
;
224 #if defined OS_CHROMEOS
225 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_
;
226 chromeos::ScopedTestCrosSettings test_cros_settings_
;
227 chromeos::ScopedTestUserManager test_user_manager_
;
230 scoped_ptr
<TestingProfile
> profile_
;
231 FakeThemeService
* fake_theme_service_
;
232 scoped_refptr
<extensions::Extension
> theme_extension_
;
233 scoped_ptr
<ThemeSyncableService
> theme_sync_service_
;
234 scoped_ptr
<syncer::FakeSyncChangeProcessor
> fake_change_processor_
;
237 class PolicyInstalledThemeTest
: public ThemeSyncableServiceTest
{
238 extensions::Manifest::Location
GetThemeLocation() override
{
239 return extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD
;
243 TEST_F(ThemeSyncableServiceTest
, AreThemeSpecificsEqual
) {
244 sync_pb::ThemeSpecifics a
, b
;
245 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
246 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
248 // Custom vs. non-custom.
250 a
.set_use_custom_theme(true);
251 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
252 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
254 // Custom theme equality.
256 b
.set_use_custom_theme(true);
257 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
258 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
260 a
.set_custom_theme_id("id");
261 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
262 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
264 b
.set_custom_theme_id("id");
265 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
266 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
268 a
.set_custom_theme_update_url("http://update.url");
269 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
270 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
272 a
.set_custom_theme_name("name");
273 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
274 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
276 // Non-custom theme equality.
278 a
.set_use_custom_theme(false);
279 b
.set_use_custom_theme(false);
280 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
281 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
283 a
.set_use_system_theme_by_default(true);
284 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
285 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
287 b
.set_use_system_theme_by_default(true);
288 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
289 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
292 TEST_F(ThemeSyncableServiceTest
, SetCurrentThemeDefaultTheme
) {
293 // Set up theme service to use custom theme.
294 fake_theme_service_
->SetTheme(theme_extension_
.get());
296 syncer::SyncError error
=
298 ->MergeDataAndStartSyncing(
300 MakeThemeDataList(sync_pb::ThemeSpecifics()),
301 scoped_ptr
<syncer::SyncChangeProcessor
>(
302 new syncer::SyncChangeProcessorWrapperForTest(
303 fake_change_processor_
.get())),
304 scoped_ptr
<syncer::SyncErrorFactory
>(
305 new syncer::SyncErrorFactoryMock()))
307 EXPECT_FALSE(error
.IsSet()) << error
.message();
308 EXPECT_TRUE(fake_theme_service_
->UsingDefaultTheme());
311 TEST_F(ThemeSyncableServiceTest
, SetCurrentThemeSystemTheme
) {
312 sync_pb::ThemeSpecifics theme_specifics
;
313 theme_specifics
.set_use_system_theme_by_default(true);
315 // Set up theme service to use custom theme.
316 fake_theme_service_
->SetTheme(theme_extension_
.get());
317 syncer::SyncError error
=
319 ->MergeDataAndStartSyncing(
321 MakeThemeDataList(theme_specifics
),
322 scoped_ptr
<syncer::SyncChangeProcessor
>(
323 new syncer::SyncChangeProcessorWrapperForTest(
324 fake_change_processor_
.get())),
325 scoped_ptr
<syncer::SyncErrorFactory
>(
326 new syncer::SyncErrorFactoryMock()))
328 EXPECT_FALSE(error
.IsSet()) << error
.message();
329 EXPECT_TRUE(fake_theme_service_
->UsingSystemTheme());
332 TEST_F(ThemeSyncableServiceTest
, SetCurrentThemeCustomTheme
) {
333 sync_pb::ThemeSpecifics theme_specifics
;
334 theme_specifics
.set_use_custom_theme(true);
335 theme_specifics
.set_custom_theme_id(theme_extension_
->id());
336 theme_specifics
.set_custom_theme_name(kCustomThemeName
);
337 theme_specifics
.set_custom_theme_name(kCustomThemeUrl
);
339 // Set up theme service to use default theme.
340 fake_theme_service_
->UseDefaultTheme();
341 syncer::SyncError error
=
343 ->MergeDataAndStartSyncing(
345 MakeThemeDataList(theme_specifics
),
346 scoped_ptr
<syncer::SyncChangeProcessor
>(
347 new syncer::SyncChangeProcessorWrapperForTest(
348 fake_change_processor_
.get())),
349 scoped_ptr
<syncer::SyncErrorFactory
>(
350 new syncer::SyncErrorFactoryMock()))
352 EXPECT_FALSE(error
.IsSet()) << error
.message();
353 EXPECT_EQ(fake_theme_service_
->theme_extension(), theme_extension_
.get());
356 TEST_F(ThemeSyncableServiceTest
, DontResetThemeWhenSpecificsAreEqual
) {
357 // Set up theme service to use default theme and expect no changes.
358 fake_theme_service_
->UseDefaultTheme();
359 fake_theme_service_
->MarkClean();
360 syncer::SyncError error
=
362 ->MergeDataAndStartSyncing(
364 MakeThemeDataList(sync_pb::ThemeSpecifics()),
365 scoped_ptr
<syncer::SyncChangeProcessor
>(
366 new syncer::SyncChangeProcessorWrapperForTest(
367 fake_change_processor_
.get())),
368 scoped_ptr
<syncer::SyncErrorFactory
>(
369 new syncer::SyncErrorFactoryMock()))
371 EXPECT_FALSE(error
.IsSet()) << error
.message();
372 EXPECT_FALSE(fake_theme_service_
->is_dirty());
375 TEST_F(ThemeSyncableServiceTest
, UpdateThemeSpecificsFromCurrentTheme
) {
376 // Set up theme service to use custom theme.
377 fake_theme_service_
->SetTheme(theme_extension_
.get());
379 syncer::SyncError error
=
381 ->MergeDataAndStartSyncing(
383 syncer::SyncDataList(),
384 scoped_ptr
<syncer::SyncChangeProcessor
>(
385 new syncer::SyncChangeProcessorWrapperForTest(
386 fake_change_processor_
.get())),
387 scoped_ptr
<syncer::SyncErrorFactory
>(
388 new syncer::SyncErrorFactoryMock()))
390 EXPECT_FALSE(error
.IsSet()) << error
.message();
391 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
392 ASSERT_EQ(1u, changes
.size());
393 EXPECT_TRUE(changes
[0].IsValid());
394 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, changes
[0].change_type());
395 EXPECT_EQ(syncer::THEMES
, changes
[0].sync_data().GetDataType());
397 const sync_pb::ThemeSpecifics
& theme_specifics
=
398 changes
[0].sync_data().GetSpecifics().theme();
399 EXPECT_TRUE(theme_specifics
.use_custom_theme());
400 EXPECT_EQ(theme_extension_
->id(), theme_specifics
.custom_theme_id());
401 EXPECT_EQ(theme_extension_
->name(), theme_specifics
.custom_theme_name());
403 extensions::ManifestURL::GetUpdateURL(theme_extension_
.get()).spec(),
404 theme_specifics
.custom_theme_update_url());
407 TEST_F(ThemeSyncableServiceTest
, GetAllSyncData
) {
408 // Set up theme service to use custom theme.
409 fake_theme_service_
->SetTheme(theme_extension_
.get());
411 syncer::SyncDataList data_list
=
412 theme_sync_service_
->GetAllSyncData(syncer::THEMES
);
414 ASSERT_EQ(1u, data_list
.size());
415 const sync_pb::ThemeSpecifics
& theme_specifics
=
416 data_list
[0].GetSpecifics().theme();
417 EXPECT_TRUE(theme_specifics
.use_custom_theme());
418 EXPECT_EQ(theme_extension_
->id(), theme_specifics
.custom_theme_id());
419 EXPECT_EQ(theme_extension_
->name(), theme_specifics
.custom_theme_name());
421 extensions::ManifestURL::GetUpdateURL(theme_extension_
.get()).spec(),
422 theme_specifics
.custom_theme_update_url());
425 TEST_F(ThemeSyncableServiceTest
, ProcessSyncThemeChange
) {
426 // Set up theme service to use default theme.
427 fake_theme_service_
->UseDefaultTheme();
428 fake_theme_service_
->MarkClean();
431 syncer::SyncError error
=
433 ->MergeDataAndStartSyncing(
435 MakeThemeDataList(sync_pb::ThemeSpecifics()),
436 scoped_ptr
<syncer::SyncChangeProcessor
>(
437 new syncer::SyncChangeProcessorWrapperForTest(
438 fake_change_processor_
.get())),
439 scoped_ptr
<syncer::SyncErrorFactory
>(
440 new syncer::SyncErrorFactoryMock()))
442 EXPECT_FALSE(error
.IsSet()) << error
.message();
443 // Don't expect theme change initially because specifics are equal.
444 EXPECT_FALSE(fake_theme_service_
->is_dirty());
446 // Change specifics to use custom theme and update.
447 sync_pb::ThemeSpecifics theme_specifics
;
448 theme_specifics
.set_use_custom_theme(true);
449 theme_specifics
.set_custom_theme_id(theme_extension_
->id());
450 theme_specifics
.set_custom_theme_name(kCustomThemeName
);
451 theme_specifics
.set_custom_theme_name(kCustomThemeUrl
);
452 sync_pb::EntitySpecifics entity_specifics
;
453 entity_specifics
.mutable_theme()->CopyFrom(theme_specifics
);
454 syncer::SyncChangeList change_list
;
455 change_list
.push_back(
456 syncer::SyncChange(FROM_HERE
,
457 syncer::SyncChange::ACTION_UPDATE
,
458 syncer::SyncData::CreateRemoteData(
462 syncer::AttachmentIdList(),
463 syncer::AttachmentServiceProxyForTest::Create())));
464 error
= theme_sync_service_
->ProcessSyncChanges(FROM_HERE
, change_list
);
465 EXPECT_FALSE(error
.IsSet()) << error
.message();
466 EXPECT_EQ(fake_theme_service_
->theme_extension(), theme_extension_
.get());
469 TEST_F(ThemeSyncableServiceTest
, OnThemeChangeByUser
) {
470 // Set up theme service to use default theme.
471 fake_theme_service_
->UseDefaultTheme();
474 syncer::SyncError error
=
476 ->MergeDataAndStartSyncing(
478 MakeThemeDataList(sync_pb::ThemeSpecifics()),
479 scoped_ptr
<syncer::SyncChangeProcessor
>(
480 new syncer::SyncChangeProcessorWrapperForTest(
481 fake_change_processor_
.get())),
482 scoped_ptr
<syncer::SyncErrorFactory
>(
483 new syncer::SyncErrorFactoryMock()))
485 EXPECT_FALSE(error
.IsSet()) << error
.message();
486 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
487 EXPECT_EQ(0u, changes
.size());
489 // Change current theme to custom theme and notify theme_sync_service_.
490 fake_theme_service_
->SetTheme(theme_extension_
.get());
491 theme_sync_service_
->OnThemeChange();
492 EXPECT_EQ(1u, changes
.size());
493 const sync_pb::ThemeSpecifics
& change_specifics
=
494 changes
[0].sync_data().GetSpecifics().theme();
495 EXPECT_TRUE(change_specifics
.use_custom_theme());
496 EXPECT_EQ(theme_extension_
->id(), change_specifics
.custom_theme_id());
497 EXPECT_EQ(theme_extension_
->name(), change_specifics
.custom_theme_name());
499 extensions::ManifestURL::GetUpdateURL(theme_extension_
.get()).spec(),
500 change_specifics
.custom_theme_update_url());
503 TEST_F(ThemeSyncableServiceTest
, StopSync
) {
504 // Set up theme service to use default theme.
505 fake_theme_service_
->UseDefaultTheme();
508 syncer::SyncError error
=
510 ->MergeDataAndStartSyncing(
512 MakeThemeDataList(sync_pb::ThemeSpecifics()),
513 scoped_ptr
<syncer::SyncChangeProcessor
>(
514 new syncer::SyncChangeProcessorWrapperForTest(
515 fake_change_processor_
.get())),
516 scoped_ptr
<syncer::SyncErrorFactory
>(
517 new syncer::SyncErrorFactoryMock()))
519 EXPECT_FALSE(error
.IsSet()) << error
.message();
520 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
521 EXPECT_EQ(0u, changes
.size());
524 theme_sync_service_
->StopSyncing(syncer::THEMES
);
526 // Change current theme to custom theme and notify theme_sync_service_.
527 // No change is output because sync has stopped.
528 fake_theme_service_
->SetTheme(theme_extension_
.get());
529 theme_sync_service_
->OnThemeChange();
530 EXPECT_EQ(0u, changes
.size());
532 // ProcessSyncChanges() should return error when sync has stopped.
533 error
= theme_sync_service_
->ProcessSyncChanges(FROM_HERE
, changes
);
534 EXPECT_TRUE(error
.IsSet());
535 EXPECT_EQ(syncer::THEMES
, error
.model_type());
536 EXPECT_EQ("Theme syncable service is not started.", error
.message());
539 TEST_F(ThemeSyncableServiceTest
, RestoreSystemThemeBitWhenChangeToCustomTheme
) {
540 // Initialize to use system theme.
541 fake_theme_service_
->UseDefaultTheme();
542 sync_pb::ThemeSpecifics theme_specifics
;
543 theme_specifics
.set_use_system_theme_by_default(true);
544 syncer::SyncError error
=
546 ->MergeDataAndStartSyncing(
548 MakeThemeDataList(theme_specifics
),
549 scoped_ptr
<syncer::SyncChangeProcessor
>(
550 new syncer::SyncChangeProcessorWrapperForTest(
551 fake_change_processor_
.get())),
552 scoped_ptr
<syncer::SyncErrorFactory
>(
553 new syncer::SyncErrorFactoryMock()))
556 // Change to custom theme and notify theme_sync_service_.
557 // use_system_theme_by_default bit should be preserved.
558 fake_theme_service_
->SetTheme(theme_extension_
.get());
559 theme_sync_service_
->OnThemeChange();
560 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
561 EXPECT_EQ(1u, changes
.size());
562 const sync_pb::ThemeSpecifics
& change_specifics
=
563 changes
[0].sync_data().GetSpecifics().theme();
564 EXPECT_TRUE(change_specifics
.use_system_theme_by_default());
567 #if defined(TOOLKIT_GTK)
568 TEST_F(ThemeSyncableServiceTest
,
569 GtkUpdateSystemThemeBitWhenChangeBetweenSystemAndDefault
) {
570 // Initialize to use native theme.
571 fake_theme_service_
->UseSystemTheme();
572 fake_theme_service_
->MarkClean();
573 sync_pb::ThemeSpecifics theme_specifics
;
574 theme_specifics
.set_use_system_theme_by_default(true);
575 syncer::SyncError error
=
577 ->MergeDataAndStartSyncing(
579 MakeThemeDataList(theme_specifics
),
580 scoped_ptr
<syncer::SyncChangeProcessor
>(
581 new syncer::SyncChangeProcessorWrapperForTest(
582 fake_change_processor_
.get())),
583 scoped_ptr
<syncer::SyncErrorFactory
>(
584 new syncer::SyncErrorFactoryMock()))
586 EXPECT_FALSE(fake_theme_service_
->is_dirty());
588 // Change to default theme and notify theme_sync_service_.
589 // use_system_theme_by_default bit should be false.
590 fake_theme_service_
->UseDefaultTheme();
591 theme_sync_service_
->OnThemeChange();
592 syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
593 EXPECT_EQ(1u, changes
.size());
594 EXPECT_FALSE(changes
[0]
598 .use_system_theme_by_default());
600 // Change to native theme and notify theme_sync_service_.
601 // use_system_theme_by_default bit should be true.
603 fake_theme_service_
->UseSystemTheme();
604 theme_sync_service_
->OnThemeChange();
605 EXPECT_EQ(1u, changes
.size());
606 EXPECT_TRUE(changes
[0]
610 .use_system_theme_by_default());
615 TEST_F(ThemeSyncableServiceTest
,
616 NonGtkPreserveSystemThemeBitWhenChangeToDefaultTheme
) {
617 // Set up theme service to use default theme.
618 fake_theme_service_
->UseDefaultTheme();
620 // Initialize to use custom theme with use_system_theme_by_default set true.
621 sync_pb::ThemeSpecifics theme_specifics
;
622 theme_specifics
.set_use_custom_theme(true);
623 theme_specifics
.set_custom_theme_id(theme_extension_
->id());
624 theme_specifics
.set_custom_theme_name(kCustomThemeName
);
625 theme_specifics
.set_custom_theme_name(kCustomThemeUrl
);
626 theme_specifics
.set_use_system_theme_by_default(true);
627 syncer::SyncError error
=
629 ->MergeDataAndStartSyncing(
631 MakeThemeDataList(theme_specifics
),
632 scoped_ptr
<syncer::SyncChangeProcessor
>(
633 new syncer::SyncChangeProcessorWrapperForTest(
634 fake_change_processor_
.get())),
635 scoped_ptr
<syncer::SyncErrorFactory
>(
636 new syncer::SyncErrorFactoryMock()))
638 EXPECT_EQ(fake_theme_service_
->theme_extension(), theme_extension_
.get());
640 // Change to default theme and notify theme_sync_service_.
641 // use_system_theme_by_default bit should be preserved.
642 fake_theme_service_
->UseDefaultTheme();
643 theme_sync_service_
->OnThemeChange();
644 const syncer::SyncChangeList
& changes
= fake_change_processor_
->changes();
645 EXPECT_EQ(1u, changes
.size());
646 const sync_pb::ThemeSpecifics
& change_specifics
=
647 changes
[0].sync_data().GetSpecifics().theme();
648 EXPECT_FALSE(change_specifics
.use_custom_theme());
649 EXPECT_TRUE(change_specifics
.use_system_theme_by_default());
653 TEST_F(PolicyInstalledThemeTest
, InstallThemeByPolicy
) {
654 // Set up theme service to use custom theme that was installed by policy.
655 fake_theme_service_
->SetTheme(theme_extension_
.get());
657 syncer::SyncDataList data_list
=
658 theme_sync_service_
->GetAllSyncData(syncer::THEMES
);
660 ASSERT_EQ(0u, data_list
.size());