Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / themes / theme_syncable_service_unittest.cc
blob67629be82642201447d6e9e17e37247af57c8448
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/chrome_switches.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "content/public/test/test_browser_thread.h"
20 #include "extensions/browser/extension_prefs.h"
21 #include "extensions/browser/extension_registry.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/common/manifest_constants.h"
24 #include "extensions/common/manifest_url_handlers.h"
25 #include "extensions/common/permissions/api_permission_set.h"
26 #include "extensions/common/permissions/permission_set.h"
27 #include "sync/api/attachments/attachment_id.h"
28 #include "sync/api/fake_sync_change_processor.h"
29 #include "sync/api/sync_change_processor_wrapper_for_test.h"
30 #include "sync/api/sync_error.h"
31 #include "sync/api/sync_error_factory_mock.h"
32 #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h"
33 #include "sync/protocol/sync.pb.h"
34 #include "sync/protocol/theme_specifics.pb.h"
35 #include "testing/gtest/include/gtest/gtest.h"
37 #if defined(OS_CHROMEOS)
38 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
39 #include "chrome/browser/chromeos/settings/cros_settings.h"
40 #include "chrome/browser/chromeos/settings/device_settings_service.h"
41 #endif
43 using std::string;
45 namespace {
47 static const char kCustomThemeName[] = "name";
48 static const char kCustomThemeUrl[] = "http://update.url/foo";
50 #if defined(OS_WIN)
51 const base::FilePath::CharType kExtensionFilePath[] =
52 FILE_PATH_LITERAL("c:\\foo");
53 #elif defined(OS_POSIX)
54 const base::FilePath::CharType kExtensionFilePath[] = FILE_PATH_LITERAL("/oo");
55 #endif
57 class FakeThemeService : public ThemeService {
58 public:
59 FakeThemeService() :
60 using_system_theme_(false),
61 using_default_theme_(false),
62 theme_extension_(NULL),
63 is_dirty_(false) {}
65 // ThemeService implementation
66 void SetTheme(const extensions::Extension* extension) override {
67 is_dirty_ = true;
68 theme_extension_ = extension;
69 using_system_theme_ = false;
70 using_default_theme_ = false;
73 void UseDefaultTheme() override {
74 is_dirty_ = true;
75 using_default_theme_ = true;
76 using_system_theme_ = false;
77 theme_extension_ = NULL;
80 void UseSystemTheme() override {
81 is_dirty_ = true;
82 using_system_theme_ = true;
83 using_default_theme_ = false;
84 theme_extension_ = NULL;
87 bool UsingDefaultTheme() const override { return using_default_theme_; }
89 bool UsingSystemTheme() const override { return using_system_theme_; }
91 string GetThemeID() const override {
92 if (theme_extension_.get())
93 return theme_extension_->id();
94 else
95 return std::string();
98 const extensions::Extension* theme_extension() const {
99 return theme_extension_.get();
102 bool is_dirty() const {
103 return is_dirty_;
106 void MarkClean() {
107 is_dirty_ = false;
110 private:
111 bool using_system_theme_;
112 bool using_default_theme_;
113 scoped_refptr<const extensions::Extension> theme_extension_;
114 bool is_dirty_;
117 scoped_ptr<KeyedService> BuildMockThemeService(
118 content::BrowserContext* profile) {
119 return make_scoped_ptr(new FakeThemeService);
122 scoped_refptr<extensions::Extension> MakeThemeExtension(
123 const base::FilePath& extension_path,
124 const string& name,
125 extensions::Manifest::Location location,
126 const string& update_url) {
127 base::DictionaryValue source;
128 source.SetString(extensions::manifest_keys::kName, name);
129 source.Set(extensions::manifest_keys::kTheme, new base::DictionaryValue());
130 source.SetString(extensions::manifest_keys::kUpdateURL, update_url);
131 source.SetString(extensions::manifest_keys::kVersion, "0.0.0.0");
132 string error;
133 scoped_refptr<extensions::Extension> extension =
134 extensions::Extension::Create(
135 extension_path, location, source,
136 extensions::Extension::NO_FLAGS, &error);
137 EXPECT_TRUE(extension.get());
138 EXPECT_EQ("", error);
139 return extension;
142 } // namespace
144 class ThemeSyncableServiceTest : public testing::Test {
145 protected:
146 ThemeSyncableServiceTest()
147 : ui_thread_(content::BrowserThread::UI, &loop_),
148 file_thread_(content::BrowserThread::FILE, &loop_),
149 fake_theme_service_(NULL) {}
151 ~ThemeSyncableServiceTest() override {}
153 void SetUp() override {
154 // Setting a matching update URL is necessary to make the test theme
155 // considered syncable.
156 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
157 switches::kAppsGalleryUpdateURL, kCustomThemeUrl);
159 profile_.reset(new TestingProfile);
160 fake_theme_service_ = BuildForProfile(profile_.get());
161 theme_sync_service_.reset(new ThemeSyncableService(profile_.get(),
162 fake_theme_service_));
163 fake_change_processor_.reset(new syncer::FakeSyncChangeProcessor);
164 SetUpExtension();
167 void TearDown() override {
168 profile_.reset();
169 loop_.RunUntilIdle();
172 void SetUpExtension() {
173 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
174 extensions::TestExtensionSystem* test_ext_system =
175 static_cast<extensions::TestExtensionSystem*>(
176 extensions::ExtensionSystem::Get(profile_.get()));
177 ExtensionService* service = test_ext_system->CreateExtensionService(
178 &command_line, base::FilePath(kExtensionFilePath), false);
179 EXPECT_TRUE(service->extensions_enabled());
180 service->Init();
181 loop_.RunUntilIdle();
183 // Create and add custom theme extension so the ThemeSyncableService can
184 // find it.
185 theme_extension_ = MakeThemeExtension(base::FilePath(kExtensionFilePath),
186 kCustomThemeName,
187 GetThemeLocation(),
188 kCustomThemeUrl);
189 extensions::APIPermissionSet empty_set;
190 extensions::ManifestPermissionSet empty_manifest_permissions;
191 extensions::URLPatternSet empty_extent;
192 scoped_refptr<extensions::PermissionSet> permissions =
193 new extensions::PermissionSet(empty_set, empty_manifest_permissions,
194 empty_extent, empty_extent);
195 extensions::ExtensionPrefs::Get(profile_.get())
196 ->AddGrantedPermissions(theme_extension_->id(), permissions.get());
197 service->AddExtension(theme_extension_.get());
198 extensions::ExtensionRegistry* registry =
199 extensions::ExtensionRegistry::Get(profile_.get());
200 ASSERT_EQ(1u, registry->enabled_extensions().size());
203 // Overridden in PolicyInstalledThemeTest below.
204 virtual extensions::Manifest::Location GetThemeLocation() {
205 return extensions::Manifest::INTERNAL;
208 FakeThemeService* BuildForProfile(Profile* profile) {
209 return static_cast<FakeThemeService*>(
210 ThemeServiceFactory::GetInstance()->SetTestingFactoryAndUse(
211 profile, &BuildMockThemeService));
214 syncer::SyncDataList MakeThemeDataList(
215 const sync_pb::ThemeSpecifics& theme_specifics) {
216 syncer::SyncDataList list;
217 sync_pb::EntitySpecifics entity_specifics;
218 entity_specifics.mutable_theme()->CopyFrom(theme_specifics);
219 list.push_back(syncer::SyncData::CreateLocalData(
220 ThemeSyncableService::kCurrentThemeClientTag,
221 ThemeSyncableService::kCurrentThemeNodeTitle,
222 entity_specifics));
223 return list;
226 // Needed for setting up extension service.
227 base::MessageLoop loop_;
228 content::TestBrowserThread ui_thread_;
229 content::TestBrowserThread file_thread_;
231 #if defined OS_CHROMEOS
232 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
233 chromeos::ScopedTestCrosSettings test_cros_settings_;
234 chromeos::ScopedTestUserManager test_user_manager_;
235 #endif
237 scoped_ptr<TestingProfile> profile_;
238 FakeThemeService* fake_theme_service_;
239 scoped_refptr<extensions::Extension> theme_extension_;
240 scoped_ptr<ThemeSyncableService> theme_sync_service_;
241 scoped_ptr<syncer::FakeSyncChangeProcessor> fake_change_processor_;
244 class PolicyInstalledThemeTest : public ThemeSyncableServiceTest {
245 extensions::Manifest::Location GetThemeLocation() override {
246 return extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD;
250 TEST_F(ThemeSyncableServiceTest, AreThemeSpecificsEqual) {
251 sync_pb::ThemeSpecifics a, b;
252 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
253 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
255 // Custom vs. non-custom.
257 a.set_use_custom_theme(true);
258 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
259 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
261 // Custom theme equality.
263 b.set_use_custom_theme(true);
264 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
265 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
267 a.set_custom_theme_id("id");
268 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
269 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
271 b.set_custom_theme_id("id");
272 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
273 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
275 a.set_custom_theme_update_url("http://update.url");
276 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
277 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
279 a.set_custom_theme_name("name");
280 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
281 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
283 // Non-custom theme equality.
285 a.set_use_custom_theme(false);
286 b.set_use_custom_theme(false);
287 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
288 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
290 a.set_use_system_theme_by_default(true);
291 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
292 EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
294 b.set_use_system_theme_by_default(true);
295 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
296 EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
299 TEST_F(ThemeSyncableServiceTest, SetCurrentThemeDefaultTheme) {
300 // Set up theme service to use custom theme.
301 fake_theme_service_->SetTheme(theme_extension_.get());
303 syncer::SyncError error =
304 theme_sync_service_
305 ->MergeDataAndStartSyncing(
306 syncer::THEMES,
307 MakeThemeDataList(sync_pb::ThemeSpecifics()),
308 scoped_ptr<syncer::SyncChangeProcessor>(
309 new syncer::SyncChangeProcessorWrapperForTest(
310 fake_change_processor_.get())),
311 scoped_ptr<syncer::SyncErrorFactory>(
312 new syncer::SyncErrorFactoryMock()))
313 .error();
314 EXPECT_FALSE(error.IsSet()) << error.message();
315 EXPECT_FALSE(fake_theme_service_->UsingDefaultTheme());
316 EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
319 TEST_F(ThemeSyncableServiceTest, SetCurrentThemeSystemTheme) {
320 sync_pb::ThemeSpecifics theme_specifics;
321 theme_specifics.set_use_system_theme_by_default(true);
323 // Set up theme service to use custom theme.
324 fake_theme_service_->SetTheme(theme_extension_.get());
325 syncer::SyncError error =
326 theme_sync_service_
327 ->MergeDataAndStartSyncing(
328 syncer::THEMES,
329 MakeThemeDataList(theme_specifics),
330 scoped_ptr<syncer::SyncChangeProcessor>(
331 new syncer::SyncChangeProcessorWrapperForTest(
332 fake_change_processor_.get())),
333 scoped_ptr<syncer::SyncErrorFactory>(
334 new syncer::SyncErrorFactoryMock()))
335 .error();
336 EXPECT_FALSE(error.IsSet()) << error.message();
337 EXPECT_FALSE(fake_theme_service_->UsingSystemTheme());
338 EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
341 TEST_F(ThemeSyncableServiceTest, SetCurrentThemeCustomTheme) {
342 sync_pb::ThemeSpecifics theme_specifics;
343 theme_specifics.set_use_custom_theme(true);
344 theme_specifics.set_custom_theme_id(theme_extension_->id());
345 theme_specifics.set_custom_theme_name(kCustomThemeName);
346 theme_specifics.set_custom_theme_name(kCustomThemeUrl);
348 // Set up theme service to use default theme.
349 fake_theme_service_->UseDefaultTheme();
350 syncer::SyncError error =
351 theme_sync_service_
352 ->MergeDataAndStartSyncing(
353 syncer::THEMES,
354 MakeThemeDataList(theme_specifics),
355 scoped_ptr<syncer::SyncChangeProcessor>(
356 new syncer::SyncChangeProcessorWrapperForTest(
357 fake_change_processor_.get())),
358 scoped_ptr<syncer::SyncErrorFactory>(
359 new syncer::SyncErrorFactoryMock()))
360 .error();
361 EXPECT_FALSE(error.IsSet()) << error.message();
362 EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
365 TEST_F(ThemeSyncableServiceTest, DontResetThemeWhenSpecificsAreEqual) {
366 // Set up theme service to use default theme and expect no changes.
367 fake_theme_service_->UseDefaultTheme();
368 fake_theme_service_->MarkClean();
369 syncer::SyncError error =
370 theme_sync_service_
371 ->MergeDataAndStartSyncing(
372 syncer::THEMES,
373 MakeThemeDataList(sync_pb::ThemeSpecifics()),
374 scoped_ptr<syncer::SyncChangeProcessor>(
375 new syncer::SyncChangeProcessorWrapperForTest(
376 fake_change_processor_.get())),
377 scoped_ptr<syncer::SyncErrorFactory>(
378 new syncer::SyncErrorFactoryMock()))
379 .error();
380 EXPECT_FALSE(error.IsSet()) << error.message();
381 EXPECT_FALSE(fake_theme_service_->is_dirty());
384 TEST_F(ThemeSyncableServiceTest, UpdateThemeSpecificsFromCurrentTheme) {
385 // Set up theme service to use custom theme.
386 fake_theme_service_->SetTheme(theme_extension_.get());
388 syncer::SyncError error =
389 theme_sync_service_
390 ->MergeDataAndStartSyncing(
391 syncer::THEMES,
392 syncer::SyncDataList(),
393 scoped_ptr<syncer::SyncChangeProcessor>(
394 new syncer::SyncChangeProcessorWrapperForTest(
395 fake_change_processor_.get())),
396 scoped_ptr<syncer::SyncErrorFactory>(
397 new syncer::SyncErrorFactoryMock()))
398 .error();
399 EXPECT_FALSE(error.IsSet()) << error.message();
400 const syncer::SyncChangeList& changes = fake_change_processor_->changes();
401 ASSERT_EQ(1u, changes.size());
402 EXPECT_TRUE(changes[0].IsValid());
403 EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
404 EXPECT_EQ(syncer::THEMES, changes[0].sync_data().GetDataType());
406 const sync_pb::ThemeSpecifics& theme_specifics =
407 changes[0].sync_data().GetSpecifics().theme();
408 EXPECT_TRUE(theme_specifics.use_custom_theme());
409 EXPECT_EQ(theme_extension_->id(), theme_specifics.custom_theme_id());
410 EXPECT_EQ(theme_extension_->name(), theme_specifics.custom_theme_name());
411 EXPECT_EQ(
412 extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(),
413 theme_specifics.custom_theme_update_url());
416 TEST_F(ThemeSyncableServiceTest, GetAllSyncData) {
417 // Set up theme service to use custom theme.
418 fake_theme_service_->SetTheme(theme_extension_.get());
420 syncer::SyncDataList data_list =
421 theme_sync_service_->GetAllSyncData(syncer::THEMES);
423 ASSERT_EQ(1u, data_list.size());
424 const sync_pb::ThemeSpecifics& theme_specifics =
425 data_list[0].GetSpecifics().theme();
426 EXPECT_TRUE(theme_specifics.use_custom_theme());
427 EXPECT_EQ(theme_extension_->id(), theme_specifics.custom_theme_id());
428 EXPECT_EQ(theme_extension_->name(), theme_specifics.custom_theme_name());
429 EXPECT_EQ(
430 extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(),
431 theme_specifics.custom_theme_update_url());
434 TEST_F(ThemeSyncableServiceTest, ProcessSyncThemeChange) {
435 // Set up theme service to use default theme.
436 fake_theme_service_->UseDefaultTheme();
437 fake_theme_service_->MarkClean();
439 // Start syncing.
440 syncer::SyncError error =
441 theme_sync_service_
442 ->MergeDataAndStartSyncing(
443 syncer::THEMES,
444 MakeThemeDataList(sync_pb::ThemeSpecifics()),
445 scoped_ptr<syncer::SyncChangeProcessor>(
446 new syncer::SyncChangeProcessorWrapperForTest(
447 fake_change_processor_.get())),
448 scoped_ptr<syncer::SyncErrorFactory>(
449 new syncer::SyncErrorFactoryMock()))
450 .error();
451 EXPECT_FALSE(error.IsSet()) << error.message();
452 // Don't expect theme change initially because specifics are equal.
453 EXPECT_FALSE(fake_theme_service_->is_dirty());
455 // Change specifics to use custom theme and update.
456 sync_pb::ThemeSpecifics theme_specifics;
457 theme_specifics.set_use_custom_theme(true);
458 theme_specifics.set_custom_theme_id(theme_extension_->id());
459 theme_specifics.set_custom_theme_name(kCustomThemeName);
460 theme_specifics.set_custom_theme_name(kCustomThemeUrl);
461 sync_pb::EntitySpecifics entity_specifics;
462 entity_specifics.mutable_theme()->CopyFrom(theme_specifics);
463 syncer::SyncChangeList change_list;
464 change_list.push_back(
465 syncer::SyncChange(FROM_HERE,
466 syncer::SyncChange::ACTION_UPDATE,
467 syncer::SyncData::CreateRemoteData(
469 entity_specifics,
470 base::Time(),
471 syncer::AttachmentIdList(),
472 syncer::AttachmentServiceProxyForTest::Create())));
473 error = theme_sync_service_->ProcessSyncChanges(FROM_HERE, change_list);
474 EXPECT_FALSE(error.IsSet()) << error.message();
475 EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
478 TEST_F(ThemeSyncableServiceTest, OnThemeChangeByUser) {
479 // Set up theme service to use default theme.
480 fake_theme_service_->UseDefaultTheme();
482 // Start syncing.
483 syncer::SyncError error =
484 theme_sync_service_
485 ->MergeDataAndStartSyncing(
486 syncer::THEMES,
487 MakeThemeDataList(sync_pb::ThemeSpecifics()),
488 scoped_ptr<syncer::SyncChangeProcessor>(
489 new syncer::SyncChangeProcessorWrapperForTest(
490 fake_change_processor_.get())),
491 scoped_ptr<syncer::SyncErrorFactory>(
492 new syncer::SyncErrorFactoryMock()))
493 .error();
494 EXPECT_FALSE(error.IsSet()) << error.message();
495 const syncer::SyncChangeList& changes = fake_change_processor_->changes();
496 EXPECT_EQ(0u, changes.size());
498 // Change current theme to custom theme and notify theme_sync_service_.
499 fake_theme_service_->SetTheme(theme_extension_.get());
500 theme_sync_service_->OnThemeChange();
501 EXPECT_EQ(1u, changes.size());
502 const sync_pb::ThemeSpecifics& change_specifics =
503 changes[0].sync_data().GetSpecifics().theme();
504 EXPECT_TRUE(change_specifics.use_custom_theme());
505 EXPECT_EQ(theme_extension_->id(), change_specifics.custom_theme_id());
506 EXPECT_EQ(theme_extension_->name(), change_specifics.custom_theme_name());
507 EXPECT_EQ(
508 extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(),
509 change_specifics.custom_theme_update_url());
512 TEST_F(ThemeSyncableServiceTest, StopSync) {
513 // Set up theme service to use default theme.
514 fake_theme_service_->UseDefaultTheme();
516 // Start syncing.
517 syncer::SyncError error =
518 theme_sync_service_
519 ->MergeDataAndStartSyncing(
520 syncer::THEMES,
521 MakeThemeDataList(sync_pb::ThemeSpecifics()),
522 scoped_ptr<syncer::SyncChangeProcessor>(
523 new syncer::SyncChangeProcessorWrapperForTest(
524 fake_change_processor_.get())),
525 scoped_ptr<syncer::SyncErrorFactory>(
526 new syncer::SyncErrorFactoryMock()))
527 .error();
528 EXPECT_FALSE(error.IsSet()) << error.message();
529 const syncer::SyncChangeList& changes = fake_change_processor_->changes();
530 EXPECT_EQ(0u, changes.size());
532 // Stop syncing.
533 theme_sync_service_->StopSyncing(syncer::THEMES);
535 // Change current theme to custom theme and notify theme_sync_service_.
536 // No change is output because sync has stopped.
537 fake_theme_service_->SetTheme(theme_extension_.get());
538 theme_sync_service_->OnThemeChange();
539 EXPECT_EQ(0u, changes.size());
541 // ProcessSyncChanges() should return error when sync has stopped.
542 error = theme_sync_service_->ProcessSyncChanges(FROM_HERE, changes);
543 EXPECT_TRUE(error.IsSet());
544 EXPECT_EQ(syncer::THEMES, error.model_type());
545 EXPECT_EQ("Theme syncable service is not started.", error.message());
548 TEST_F(ThemeSyncableServiceTest, RestoreSystemThemeBitWhenChangeToCustomTheme) {
549 // Initialize to use system theme.
550 fake_theme_service_->UseDefaultTheme();
551 sync_pb::ThemeSpecifics theme_specifics;
552 theme_specifics.set_use_system_theme_by_default(true);
553 syncer::SyncError error =
554 theme_sync_service_
555 ->MergeDataAndStartSyncing(
556 syncer::THEMES,
557 MakeThemeDataList(theme_specifics),
558 scoped_ptr<syncer::SyncChangeProcessor>(
559 new syncer::SyncChangeProcessorWrapperForTest(
560 fake_change_processor_.get())),
561 scoped_ptr<syncer::SyncErrorFactory>(
562 new syncer::SyncErrorFactoryMock()))
563 .error();
565 // Change to custom theme and notify theme_sync_service_.
566 // use_system_theme_by_default bit should be preserved.
567 fake_theme_service_->SetTheme(theme_extension_.get());
568 theme_sync_service_->OnThemeChange();
569 const syncer::SyncChangeList& changes = fake_change_processor_->changes();
570 EXPECT_EQ(1u, changes.size());
571 const sync_pb::ThemeSpecifics& change_specifics =
572 changes[0].sync_data().GetSpecifics().theme();
573 EXPECT_TRUE(change_specifics.use_system_theme_by_default());
576 #if defined(TOOLKIT_GTK)
577 TEST_F(ThemeSyncableServiceTest,
578 GtkUpdateSystemThemeBitWhenChangeBetweenSystemAndDefault) {
579 // Initialize to use native theme.
580 fake_theme_service_->UseSystemTheme();
581 fake_theme_service_->MarkClean();
582 sync_pb::ThemeSpecifics theme_specifics;
583 theme_specifics.set_use_system_theme_by_default(true);
584 syncer::SyncError error =
585 theme_sync_service_
586 ->MergeDataAndStartSyncing(
587 syncer::THEMES,
588 MakeThemeDataList(theme_specifics),
589 scoped_ptr<syncer::SyncChangeProcessor>(
590 new syncer::SyncChangeProcessorWrapperForTest(
591 fake_change_processor_.get())),
592 scoped_ptr<syncer::SyncErrorFactory>(
593 new syncer::SyncErrorFactoryMock()))
594 .error();
595 EXPECT_FALSE(fake_theme_service_->is_dirty());
597 // Change to default theme and notify theme_sync_service_.
598 // use_system_theme_by_default bit should be false.
599 fake_theme_service_->UseDefaultTheme();
600 theme_sync_service_->OnThemeChange();
601 syncer::SyncChangeList& changes = fake_change_processor_->changes();
602 EXPECT_EQ(1u, changes.size());
603 EXPECT_FALSE(changes[0]
604 .sync_data()
605 .GetSpecifics()
606 .theme()
607 .use_system_theme_by_default());
609 // Change to native theme and notify theme_sync_service_.
610 // use_system_theme_by_default bit should be true.
611 changes.clear();
612 fake_theme_service_->UseSystemTheme();
613 theme_sync_service_->OnThemeChange();
614 EXPECT_EQ(1u, changes.size());
615 EXPECT_TRUE(changes[0]
616 .sync_data()
617 .GetSpecifics()
618 .theme()
619 .use_system_theme_by_default());
621 #endif
623 #ifndef TOOLKIT_GTK
624 TEST_F(ThemeSyncableServiceTest,
625 NonGtkPreserveSystemThemeBitWhenChangeToDefaultTheme) {
626 // Set up theme service to use default theme.
627 fake_theme_service_->UseDefaultTheme();
629 // Initialize to use custom theme with use_system_theme_by_default set true.
630 sync_pb::ThemeSpecifics theme_specifics;
631 theme_specifics.set_use_custom_theme(true);
632 theme_specifics.set_custom_theme_id(theme_extension_->id());
633 theme_specifics.set_custom_theme_name(kCustomThemeName);
634 theme_specifics.set_custom_theme_name(kCustomThemeUrl);
635 theme_specifics.set_use_system_theme_by_default(true);
636 syncer::SyncError error =
637 theme_sync_service_
638 ->MergeDataAndStartSyncing(
639 syncer::THEMES,
640 MakeThemeDataList(theme_specifics),
641 scoped_ptr<syncer::SyncChangeProcessor>(
642 new syncer::SyncChangeProcessorWrapperForTest(
643 fake_change_processor_.get())),
644 scoped_ptr<syncer::SyncErrorFactory>(
645 new syncer::SyncErrorFactoryMock()))
646 .error();
647 EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
649 // Change to default theme and notify theme_sync_service_.
650 // use_system_theme_by_default bit should be preserved.
651 fake_theme_service_->UseDefaultTheme();
652 theme_sync_service_->OnThemeChange();
653 const syncer::SyncChangeList& changes = fake_change_processor_->changes();
654 EXPECT_EQ(1u, changes.size());
655 const sync_pb::ThemeSpecifics& change_specifics =
656 changes[0].sync_data().GetSpecifics().theme();
657 EXPECT_FALSE(change_specifics.use_custom_theme());
658 EXPECT_TRUE(change_specifics.use_system_theme_by_default());
660 #endif
662 TEST_F(PolicyInstalledThemeTest, InstallThemeByPolicy) {
663 // Set up theme service to use custom theme that was installed by policy.
664 fake_theme_service_->SetTheme(theme_extension_.get());
666 syncer::SyncDataList data_list =
667 theme_sync_service_->GetAllSyncData(syncer::THEMES);
669 ASSERT_EQ(0u, data_list.size());