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/common/extensions/extension_messages.h"
18 #include "chrome/common/extensions/manifest_url_handler.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "content/public/test/test_browser_thread.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/common/manifest_constants.h"
23 #include "extensions/common/permissions/api_permission_set.h"
24 #include "extensions/common/permissions/permission_set.h"
25 #include "sync/api/sync_error.h"
26 #include "sync/api/sync_error_factory_mock.h"
27 #include "sync/protocol/sync.pb.h"
28 #include "sync/protocol/theme_specifics.pb.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 #if defined(OS_CHROMEOS)
32 #include "chrome/browser/chromeos/login/user_manager.h"
33 #include "chrome/browser/chromeos/settings/cros_settings.h"
34 #include "chrome/browser/chromeos/settings/device_settings_service.h"
41 static const char kCustomThemeName
[] = "name";
42 static const char kCustomThemeUrl
[] = "http://update.url/foo";
45 const base::FilePath::CharType kExtensionFilePath
[] =
46 FILE_PATH_LITERAL("c:\\foo");
47 #elif defined(OS_POSIX)
48 const base::FilePath::CharType kExtensionFilePath
[] = FILE_PATH_LITERAL("/oo");
51 class FakeSyncChangeProcessor
: public syncer::SyncChangeProcessor
{
53 FakeSyncChangeProcessor() : change_output_(NULL
) {}
55 // syncer::SyncChangeProcessor implementation.
56 virtual syncer::SyncError
ProcessSyncChanges(
57 const tracked_objects::Location
& from_here
,
58 const syncer::SyncChangeList
& change_list
) OVERRIDE
{
59 change_output_
->insert(change_output_
->end(), change_list
.begin(),
61 return syncer::SyncError();
64 virtual syncer::SyncDataList
GetAllSyncData(syncer::ModelType type
) const
66 return syncer::SyncDataList();
69 void SetChangeOutput(syncer::SyncChangeList
*change_output
) {
70 change_output_
= change_output
;
74 syncer::SyncChangeList
*change_output_
;
77 class FakeThemeService
: public ThemeService
{
80 using_native_theme_(false),
81 using_default_theme_(false),
82 theme_extension_(NULL
),
85 // ThemeService implementation
86 virtual void SetTheme(const extensions::Extension
* extension
) OVERRIDE
{
88 theme_extension_
= extension
;
89 using_native_theme_
= false;
90 using_default_theme_
= false;
93 virtual void UseDefaultTheme() OVERRIDE
{
95 using_default_theme_
= true;
96 using_native_theme_
= false;
97 theme_extension_
= NULL
;
100 virtual void SetNativeTheme() OVERRIDE
{
102 using_native_theme_
= true;
103 using_default_theme_
= false;
104 theme_extension_
= NULL
;
107 virtual bool UsingDefaultTheme() const OVERRIDE
{
108 return using_default_theme_
;
111 virtual bool UsingNativeTheme() const OVERRIDE
{
112 return using_native_theme_
;
115 virtual string
GetThemeID() const OVERRIDE
{
116 if (theme_extension_
.get())
117 return theme_extension_
->id();
119 return std::string();
122 const extensions::Extension
* theme_extension() const {
123 return theme_extension_
.get();
126 bool is_dirty() const {
135 bool using_native_theme_
;
136 bool using_default_theme_
;
137 scoped_refptr
<const extensions::Extension
> theme_extension_
;
141 BrowserContextKeyedService
* BuildMockThemeService(
142 content::BrowserContext
* profile
) {
143 return new FakeThemeService
;
146 scoped_refptr
<extensions::Extension
> MakeThemeExtension(
147 const base::FilePath
& extension_path
,
149 extensions::Manifest::Location location
,
150 const string
& update_url
) {
151 base::DictionaryValue source
;
152 source
.SetString(extensions::manifest_keys::kName
, name
);
153 source
.Set(extensions::manifest_keys::kTheme
, new base::DictionaryValue());
154 source
.SetString(extensions::manifest_keys::kUpdateURL
, update_url
);
155 source
.SetString(extensions::manifest_keys::kVersion
, "0.0.0.0");
157 scoped_refptr
<extensions::Extension
> extension
=
158 extensions::Extension::Create(
159 extension_path
, location
, source
,
160 extensions::Extension::NO_FLAGS
, &error
);
161 EXPECT_TRUE(extension
.get());
162 EXPECT_EQ("", error
);
168 class ThemeSyncableServiceTest
: public testing::Test
{
170 ThemeSyncableServiceTest()
171 : ui_thread_(content::BrowserThread::UI
, &loop_
),
172 file_thread_(content::BrowserThread::FILE, &loop_
),
173 fake_theme_service_(NULL
) {}
175 virtual ~ThemeSyncableServiceTest() {}
177 virtual void SetUp() {
178 profile_
.reset(new TestingProfile
);
179 fake_theme_service_
= BuildForProfile(profile_
.get());
180 theme_sync_service_
.reset(new ThemeSyncableService(profile_
.get(),
181 fake_theme_service_
));
182 fake_change_processor_
.reset(new FakeSyncChangeProcessor
);
186 virtual void TearDown() {
188 loop_
.RunUntilIdle();
191 void SetUpExtension() {
192 CommandLine
command_line(CommandLine::NO_PROGRAM
);
193 extensions::TestExtensionSystem
* test_ext_system
=
194 static_cast<extensions::TestExtensionSystem
*>(
195 extensions::ExtensionSystem::Get(profile_
.get()));
196 ExtensionService
* service
= test_ext_system
->CreateExtensionService(
197 &command_line
, base::FilePath(kExtensionFilePath
), false);
198 EXPECT_TRUE(service
->extensions_enabled());
200 loop_
.RunUntilIdle();
202 // Create and add custom theme extension so the ThemeSyncableService can
204 theme_extension_
= MakeThemeExtension(base::FilePath(kExtensionFilePath
),
208 extensions::APIPermissionSet empty_set
;
209 extensions::ManifestPermissionSet empty_manifest_permissions
;
210 extensions::URLPatternSet empty_extent
;
211 scoped_refptr
<extensions::PermissionSet
> permissions
=
212 new extensions::PermissionSet(empty_set
, empty_manifest_permissions
,
213 empty_extent
, empty_extent
);
214 service
->extension_prefs()->AddGrantedPermissions(
215 theme_extension_
->id(), permissions
.get());
216 service
->AddExtension(theme_extension_
.get());
217 ASSERT_EQ(1u, service
->extensions()->size());
220 // Overridden in PolicyInstalledThemeTest below.
221 virtual extensions::Manifest::Location
GetThemeLocation() {
222 return extensions::Manifest::INTERNAL
;
225 FakeThemeService
* BuildForProfile(Profile
* profile
) {
226 return static_cast<FakeThemeService
*>(
227 ThemeServiceFactory::GetInstance()->SetTestingFactoryAndUse(
228 profile
, &BuildMockThemeService
));
231 syncer::SyncDataList
MakeThemeDataList(
232 const sync_pb::ThemeSpecifics
& theme_specifics
) {
233 syncer::SyncDataList list
;
234 sync_pb::EntitySpecifics entity_specifics
;
235 entity_specifics
.mutable_theme()->CopyFrom(theme_specifics
);
236 list
.push_back(syncer::SyncData::CreateLocalData(
237 ThemeSyncableService::kCurrentThemeClientTag
,
238 ThemeSyncableService::kCurrentThemeNodeTitle
,
243 // Needed for setting up extension service.
244 base::MessageLoop loop_
;
245 content::TestBrowserThread ui_thread_
;
246 content::TestBrowserThread file_thread_
;
248 #if defined OS_CHROMEOS
249 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_
;
250 chromeos::ScopedTestCrosSettings test_cros_settings_
;
251 chromeos::ScopedTestUserManager test_user_manager_
;
254 scoped_ptr
<TestingProfile
> profile_
;
255 FakeThemeService
* fake_theme_service_
;
256 scoped_refptr
<extensions::Extension
> theme_extension_
;
257 scoped_ptr
<ThemeSyncableService
> theme_sync_service_
;
258 scoped_ptr
<syncer::SyncChangeProcessor
> fake_change_processor_
;
261 class PolicyInstalledThemeTest
: public ThemeSyncableServiceTest
{
262 virtual extensions::Manifest::Location
GetThemeLocation() OVERRIDE
{
263 return extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD
;
267 TEST_F(ThemeSyncableServiceTest
, AreThemeSpecificsEqual
) {
268 sync_pb::ThemeSpecifics a
, b
;
269 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
270 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
272 // Custom vs. non-custom.
274 a
.set_use_custom_theme(true);
275 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
276 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
278 // Custom theme equality.
280 b
.set_use_custom_theme(true);
281 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
282 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
284 a
.set_custom_theme_id("id");
285 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
286 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
288 b
.set_custom_theme_id("id");
289 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
290 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
292 a
.set_custom_theme_update_url("http://update.url");
293 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
294 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
296 a
.set_custom_theme_name("name");
297 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
298 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
300 // Non-custom theme equality.
302 a
.set_use_custom_theme(false);
303 b
.set_use_custom_theme(false);
304 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
305 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
307 a
.set_use_system_theme_by_default(true);
308 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
309 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
311 b
.set_use_system_theme_by_default(true);
312 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, false));
313 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a
, b
, true));
316 TEST_F(ThemeSyncableServiceTest
, SetCurrentThemeDefaultTheme
) {
317 // Set up theme service to use custom theme.
318 fake_theme_service_
->SetTheme(theme_extension_
.get());
320 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
321 syncer::THEMES
, MakeThemeDataList(sync_pb::ThemeSpecifics()),
322 fake_change_processor_
.Pass(),
323 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
325 EXPECT_FALSE(error
.IsSet()) << error
.message();
326 EXPECT_TRUE(fake_theme_service_
->UsingDefaultTheme());
329 TEST_F(ThemeSyncableServiceTest
, SetCurrentThemeSystemTheme
) {
330 sync_pb::ThemeSpecifics theme_specifics
;
331 theme_specifics
.set_use_system_theme_by_default(true);
333 // Set up theme service to use custom theme.
334 fake_theme_service_
->SetTheme(theme_extension_
.get());
335 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
336 syncer::THEMES
, MakeThemeDataList(theme_specifics
),
337 fake_change_processor_
.Pass(),
338 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
340 EXPECT_FALSE(error
.IsSet()) << error
.message();
341 EXPECT_TRUE(fake_theme_service_
->UsingNativeTheme());
344 TEST_F(ThemeSyncableServiceTest
, SetCurrentThemeCustomTheme
) {
345 sync_pb::ThemeSpecifics theme_specifics
;
346 theme_specifics
.set_use_custom_theme(true);
347 theme_specifics
.set_custom_theme_id(theme_extension_
->id());
348 theme_specifics
.set_custom_theme_name(kCustomThemeName
);
349 theme_specifics
.set_custom_theme_name(kCustomThemeUrl
);
351 // Set up theme service to use default theme.
352 fake_theme_service_
->UseDefaultTheme();
353 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
354 syncer::THEMES
, MakeThemeDataList(theme_specifics
),
355 fake_change_processor_
.Pass(),
356 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
358 EXPECT_FALSE(error
.IsSet()) << error
.message();
359 EXPECT_EQ(fake_theme_service_
->theme_extension(), theme_extension_
.get());
362 TEST_F(ThemeSyncableServiceTest
, DontResetThemeWhenSpecificsAreEqual
) {
363 // Set up theme service to use default theme and expect no changes.
364 fake_theme_service_
->UseDefaultTheme();
365 fake_theme_service_
->MarkClean();
366 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
367 syncer::THEMES
, MakeThemeDataList(sync_pb::ThemeSpecifics()),
368 fake_change_processor_
.Pass(),
369 scoped_ptr
<syncer::SyncErrorFactory
>(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::SyncChangeList change_list
;
380 static_cast<FakeSyncChangeProcessor
*>(fake_change_processor_
.get())->
381 SetChangeOutput(&change_list
);
383 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
384 syncer::THEMES
, syncer::SyncDataList(), fake_change_processor_
.Pass(),
385 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
387 EXPECT_FALSE(error
.IsSet()) << error
.message();
389 ASSERT_EQ(1u, change_list
.size());
390 EXPECT_TRUE(change_list
[0].IsValid());
391 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, change_list
[0].change_type());
392 EXPECT_EQ(syncer::THEMES
, change_list
[0].sync_data().GetDataType());
394 const sync_pb::ThemeSpecifics
& theme_specifics
=
395 change_list
[0].sync_data().GetSpecifics().theme();
396 EXPECT_TRUE(theme_specifics
.use_custom_theme());
397 EXPECT_EQ(theme_extension_
->id(), theme_specifics
.custom_theme_id());
398 EXPECT_EQ(theme_extension_
->name(), theme_specifics
.custom_theme_name());
400 extensions::ManifestURL::GetUpdateURL(theme_extension_
.get()).spec(),
401 theme_specifics
.custom_theme_update_url());
404 TEST_F(ThemeSyncableServiceTest
, GetAllSyncData
) {
405 // Set up theme service to use custom theme.
406 fake_theme_service_
->SetTheme(theme_extension_
.get());
408 syncer::SyncDataList data_list
=
409 theme_sync_service_
->GetAllSyncData(syncer::THEMES
);
411 ASSERT_EQ(1u, data_list
.size());
412 const sync_pb::ThemeSpecifics
& theme_specifics
=
413 data_list
[0].GetSpecifics().theme();
414 EXPECT_TRUE(theme_specifics
.use_custom_theme());
415 EXPECT_EQ(theme_extension_
->id(), theme_specifics
.custom_theme_id());
416 EXPECT_EQ(theme_extension_
->name(), theme_specifics
.custom_theme_name());
418 extensions::ManifestURL::GetUpdateURL(theme_extension_
.get()).spec(),
419 theme_specifics
.custom_theme_update_url());
422 TEST_F(ThemeSyncableServiceTest
, ProcessSyncThemeChange
) {
423 // Set up theme service to use default theme.
424 fake_theme_service_
->UseDefaultTheme();
425 fake_theme_service_
->MarkClean();
428 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
429 syncer::THEMES
, MakeThemeDataList(sync_pb::ThemeSpecifics()),
430 fake_change_processor_
.Pass(),
431 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
433 EXPECT_FALSE(error
.IsSet()) << error
.message();
434 // Don't expect theme change initially because specifics are equal.
435 EXPECT_FALSE(fake_theme_service_
->is_dirty());
437 // Change specifics to use custom theme and update.
438 sync_pb::ThemeSpecifics theme_specifics
;
439 theme_specifics
.set_use_custom_theme(true);
440 theme_specifics
.set_custom_theme_id(theme_extension_
->id());
441 theme_specifics
.set_custom_theme_name(kCustomThemeName
);
442 theme_specifics
.set_custom_theme_name(kCustomThemeUrl
);
443 sync_pb::EntitySpecifics entity_specifics
;
444 entity_specifics
.mutable_theme()->CopyFrom(theme_specifics
);
445 syncer::SyncChangeList change_list
;
446 change_list
.push_back(syncer::SyncChange(
448 syncer::SyncChange::ACTION_UPDATE
,
449 syncer::SyncData::CreateRemoteData(
450 1, entity_specifics
, base::Time())));
451 error
= theme_sync_service_
->ProcessSyncChanges(FROM_HERE
, change_list
);
452 EXPECT_FALSE(error
.IsSet()) << error
.message();
453 EXPECT_EQ(fake_theme_service_
->theme_extension(), theme_extension_
.get());
456 TEST_F(ThemeSyncableServiceTest
, OnThemeChangeByUser
) {
457 syncer::SyncChangeList change_list
;
458 static_cast<FakeSyncChangeProcessor
*>(fake_change_processor_
.get())->
459 SetChangeOutput(&change_list
);
461 // Set up theme service to use default theme.
462 fake_theme_service_
->UseDefaultTheme();
465 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
466 syncer::THEMES
, MakeThemeDataList(sync_pb::ThemeSpecifics()),
467 fake_change_processor_
.Pass(),
468 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
470 EXPECT_FALSE(error
.IsSet()) << error
.message();
471 EXPECT_EQ(0u, change_list
.size());
473 // Change current theme to custom theme and notify theme_sync_service_.
474 fake_theme_service_
->SetTheme(theme_extension_
.get());
475 theme_sync_service_
->OnThemeChange();
476 EXPECT_EQ(1u, change_list
.size());
477 const sync_pb::ThemeSpecifics
& change_specifics
=
478 change_list
[0].sync_data().GetSpecifics().theme();
479 EXPECT_TRUE(change_specifics
.use_custom_theme());
480 EXPECT_EQ(theme_extension_
->id(), change_specifics
.custom_theme_id());
481 EXPECT_EQ(theme_extension_
->name(), change_specifics
.custom_theme_name());
483 extensions::ManifestURL::GetUpdateURL(theme_extension_
.get()).spec(),
484 change_specifics
.custom_theme_update_url());
487 TEST_F(ThemeSyncableServiceTest
, StopSync
) {
488 syncer::SyncChangeList change_list
;
489 static_cast<FakeSyncChangeProcessor
*>(fake_change_processor_
.get())->
490 SetChangeOutput(&change_list
);
492 // Set up theme service to use default theme.
493 fake_theme_service_
->UseDefaultTheme();
496 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
497 syncer::THEMES
, MakeThemeDataList(sync_pb::ThemeSpecifics()),
498 fake_change_processor_
.Pass(),
499 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
501 EXPECT_FALSE(error
.IsSet()) << error
.message();
502 EXPECT_EQ(0u, change_list
.size());
505 theme_sync_service_
->StopSyncing(syncer::THEMES
);
507 // Change current theme to custom theme and notify theme_sync_service_.
508 // No change is output because sync has stopped.
509 fake_theme_service_
->SetTheme(theme_extension_
.get());
510 theme_sync_service_
->OnThemeChange();
511 EXPECT_EQ(0u, change_list
.size());
513 // ProcessSyncChanges() should return error when sync has stopped.
514 error
= theme_sync_service_
->ProcessSyncChanges(FROM_HERE
, change_list
);
515 EXPECT_TRUE(error
.IsSet());
516 EXPECT_EQ(syncer::THEMES
, error
.model_type());
517 EXPECT_EQ("datatype error was encountered: Theme syncable service is not "
522 TEST_F(ThemeSyncableServiceTest
, RestoreSystemThemeBitWhenChangeToCustomTheme
) {
523 syncer::SyncChangeList change_list
;
524 static_cast<FakeSyncChangeProcessor
*>(fake_change_processor_
.get())->
525 SetChangeOutput(&change_list
);
527 // Initialize to use system theme.
528 fake_theme_service_
->UseDefaultTheme();
529 sync_pb::ThemeSpecifics theme_specifics
;
530 theme_specifics
.set_use_system_theme_by_default(true);
531 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
532 syncer::THEMES
, MakeThemeDataList(theme_specifics
),
533 fake_change_processor_
.Pass(),
534 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
537 // Change to custom theme and notify theme_sync_service_.
538 // use_system_theme_by_default bit should be preserved.
539 fake_theme_service_
->SetTheme(theme_extension_
.get());
540 theme_sync_service_
->OnThemeChange();
541 EXPECT_EQ(1u, change_list
.size());
542 const sync_pb::ThemeSpecifics
& change_specifics
=
543 change_list
[0].sync_data().GetSpecifics().theme();
544 EXPECT_TRUE(change_specifics
.use_system_theme_by_default());
547 #if defined(TOOLKIT_GTK)
548 TEST_F(ThemeSyncableServiceTest
,
549 GtkUpdateSystemThemeBitWhenChangeBetweenSystemAndDefault
) {
550 syncer::SyncChangeList change_list
;
551 static_cast<FakeSyncChangeProcessor
*>(fake_change_processor_
.get())->
552 SetChangeOutput(&change_list
);
554 // Initialize to use native theme.
555 fake_theme_service_
->SetNativeTheme();
556 fake_theme_service_
->MarkClean();
557 sync_pb::ThemeSpecifics theme_specifics
;
558 theme_specifics
.set_use_system_theme_by_default(true);
559 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
560 syncer::THEMES
, MakeThemeDataList(theme_specifics
),
561 fake_change_processor_
.Pass(),
562 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
564 EXPECT_FALSE(fake_theme_service_
->is_dirty());
566 // Change to default theme and notify theme_sync_service_.
567 // use_system_theme_by_default bit should be false.
568 fake_theme_service_
->UseDefaultTheme();
569 theme_sync_service_
->OnThemeChange();
570 EXPECT_EQ(1u, change_list
.size());
571 EXPECT_FALSE(change_list
[0].sync_data().GetSpecifics().theme()
572 .use_system_theme_by_default());
574 // Change to native theme and notify theme_sync_service_.
575 // use_system_theme_by_default bit should be true.
577 fake_theme_service_
->SetNativeTheme();
578 theme_sync_service_
->OnThemeChange();
579 EXPECT_EQ(1u, change_list
.size());
580 EXPECT_TRUE(change_list
[0].sync_data().GetSpecifics().theme()
581 .use_system_theme_by_default());
586 TEST_F(ThemeSyncableServiceTest
,
587 NonGtkPreserveSystemThemeBitWhenChangeToDefaultTheme
) {
588 syncer::SyncChangeList change_list
;
589 static_cast<FakeSyncChangeProcessor
*>(fake_change_processor_
.get())->
590 SetChangeOutput(&change_list
);
592 // Set up theme service to use default theme.
593 fake_theme_service_
->UseDefaultTheme();
595 // Initialize to use custom theme with use_system_theme_by_default set true.
596 sync_pb::ThemeSpecifics theme_specifics
;
597 theme_specifics
.set_use_custom_theme(true);
598 theme_specifics
.set_custom_theme_id(theme_extension_
->id());
599 theme_specifics
.set_custom_theme_name(kCustomThemeName
);
600 theme_specifics
.set_custom_theme_name(kCustomThemeUrl
);
601 theme_specifics
.set_use_system_theme_by_default(true);
602 syncer::SyncError error
= theme_sync_service_
->MergeDataAndStartSyncing(
603 syncer::THEMES
, MakeThemeDataList(theme_specifics
),
604 fake_change_processor_
.Pass(),
605 scoped_ptr
<syncer::SyncErrorFactory
>(new syncer::SyncErrorFactoryMock())).
607 EXPECT_EQ(fake_theme_service_
->theme_extension(), theme_extension_
.get());
609 // Change to default theme and notify theme_sync_service_.
610 // use_system_theme_by_default bit should be preserved.
611 fake_theme_service_
->UseDefaultTheme();
612 theme_sync_service_
->OnThemeChange();
613 EXPECT_EQ(1u, change_list
.size());
614 const sync_pb::ThemeSpecifics
& change_specifics
=
615 change_list
[0].sync_data().GetSpecifics().theme();
616 EXPECT_FALSE(change_specifics
.use_custom_theme());
617 EXPECT_TRUE(change_specifics
.use_system_theme_by_default());
621 TEST_F(PolicyInstalledThemeTest
, InstallThemeByPolicy
) {
622 // Set up theme service to use custom theme that was installed by policy.
623 fake_theme_service_
->SetTheme(theme_extension_
.get());
625 syncer::SyncDataList data_list
=
626 theme_sync_service_
->GetAllSyncData(syncer::THEMES
);
628 ASSERT_EQ(0u, data_list
.size());