Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / themes / theme_syncable_service_unittest.cc
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.
4
5 #include "chrome/browser/themes/theme_syncable_service.h"
6
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/manifest_url_handler.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/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/attachments/attachment_id.h"
26 #include "sync/api/fake_sync_change_processor.h"
27 #include "sync/api/sync_change_processor_wrapper_for_test.h"
28 #include "sync/api/sync_error.h"
29 #include "sync/api/sync_error_factory_mock.h"
30 #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h"
31 #include "sync/protocol/sync.pb.h"
32 #include "sync/protocol/theme_specifics.pb.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34
35 #if defined(OS_CHROMEOS)
36 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
37 #include "chrome/browser/chromeos/settings/cros_settings.h"
38 #include "chrome/browser/chromeos/settings/device_settings_service.h"
39 #endif
40
41 using std::string;
42
43 namespace {
44
45 static const char kCustomThemeName[] = "name";
46 static const char kCustomThemeUrl[] = "http://update.url/foo";
47
48 #if defined(OS_WIN)
49 const base::FilePath::CharType kExtensionFilePath[] =
50     FILE_PATH_LITERAL("c:\\foo");
51 #elif defined(OS_POSIX)
52 const base::FilePath::CharType kExtensionFilePath[] = FILE_PATH_LITERAL("/oo");
53 #endif
54
55 class FakeThemeService : public ThemeService {
56  public:
57   FakeThemeService() :
58     using_system_theme_(false),
59     using_default_theme_(false),
60     theme_extension_(NULL),
61     is_dirty_(false) {}
62
63   // ThemeService implementation
64   virtual void SetTheme(const extensions::Extension* extension) OVERRIDE {
65     is_dirty_ = true;
66     theme_extension_ = extension;
67     using_system_theme_ = false;
68     using_default_theme_ = false;
69   }
70
71   virtual void UseDefaultTheme() OVERRIDE {
72     is_dirty_ = true;
73     using_default_theme_ = true;
74     using_system_theme_ = false;
75     theme_extension_ = NULL;
76   }
77
78   virtual void UseSystemTheme() OVERRIDE {
79     is_dirty_ = true;
80     using_system_theme_ = true;
81     using_default_theme_ = false;
82     theme_extension_ = NULL;
83   }
84
85   virtual bool UsingDefaultTheme() const OVERRIDE {
86     return using_default_theme_;
87   }
88
89   virtual bool UsingSystemTheme() const OVERRIDE {
90     return using_system_theme_;
91   }
92
93   virtual string GetThemeID() const OVERRIDE {
94     if (theme_extension_.get())
95       return theme_extension_->id();
96     else
97       return std::string();
98   }
99
100   const extensions::Extension* theme_extension() const {
101     return theme_extension_.get();
102   }
103
104   bool is_dirty() const {
105     return is_dirty_;
106   }
107
108   void MarkClean() {
109     is_dirty_ = false;
110   }
111
112  private:
113   bool using_system_theme_;
114   bool using_default_theme_;
115   scoped_refptr<const extensions::Extension> theme_extension_;
116   bool is_dirty_;
117 };
118
119 KeyedService* BuildMockThemeService(content::BrowserContext* profile) {
120   return new FakeThemeService;
121 }
122
123 scoped_refptr<extensions::Extension> MakeThemeExtension(
124     const base::FilePath& extension_path,
125     const string& name,
126     extensions::Manifest::Location location,
127     const string& update_url) {
128   base::DictionaryValue source;
129   source.SetString(extensions::manifest_keys::kName, name);
130   source.Set(extensions::manifest_keys::kTheme, new base::DictionaryValue());
131   source.SetString(extensions::manifest_keys::kUpdateURL, update_url);
132   source.SetString(extensions::manifest_keys::kVersion, "0.0.0.0");
133   string error;
134   scoped_refptr<extensions::Extension> extension =
135       extensions::Extension::Create(
136           extension_path, location, source,
137           extensions::Extension::NO_FLAGS, &error);
138   EXPECT_TRUE(extension.get());
139   EXPECT_EQ("", error);
140   return extension;
141 }
142
143 }  // namespace
144
145 class ThemeSyncableServiceTest : public testing::Test {
146  protected:
147   ThemeSyncableServiceTest()
148       : ui_thread_(content::BrowserThread::UI, &loop_),
149         file_thread_(content::BrowserThread::FILE, &loop_),
150         fake_theme_service_(NULL) {}
151
152   virtual ~ThemeSyncableServiceTest() {}
153
154   virtual void SetUp() {
155     profile_.reset(new TestingProfile);
156     fake_theme_service_ = BuildForProfile(profile_.get());
157     theme_sync_service_.reset(new ThemeSyncableService(profile_.get(),
158                                                        fake_theme_service_));
159     fake_change_processor_.reset(new syncer::FakeSyncChangeProcessor);
160     SetUpExtension();
161   }
162
163   virtual void TearDown() {
164     profile_.reset();
165     loop_.RunUntilIdle();
166   }
167
168   void SetUpExtension() {
169     CommandLine command_line(CommandLine::NO_PROGRAM);
170     extensions::TestExtensionSystem* test_ext_system =
171         static_cast<extensions::TestExtensionSystem*>(
172                 extensions::ExtensionSystem::Get(profile_.get()));
173     ExtensionService* service = test_ext_system->CreateExtensionService(
174         &command_line, base::FilePath(kExtensionFilePath), false);
175     EXPECT_TRUE(service->extensions_enabled());
176     service->Init();
177     loop_.RunUntilIdle();
178
179     // Create and add custom theme extension so the ThemeSyncableService can
180     // find it.
181     theme_extension_ = MakeThemeExtension(base::FilePath(kExtensionFilePath),
182                                           kCustomThemeName,
183                                           GetThemeLocation(),
184                                           kCustomThemeUrl);
185     extensions::APIPermissionSet empty_set;
186     extensions::ManifestPermissionSet empty_manifest_permissions;
187     extensions::URLPatternSet empty_extent;
188     scoped_refptr<extensions::PermissionSet> permissions =
189         new extensions::PermissionSet(empty_set, empty_manifest_permissions,
190                                       empty_extent, empty_extent);
191     extensions::ExtensionPrefs::Get(profile_.get())
192         ->AddGrantedPermissions(theme_extension_->id(), permissions.get());
193     service->AddExtension(theme_extension_.get());
194     ASSERT_EQ(1u, service->extensions()->size());
195   }
196
197   // Overridden in PolicyInstalledThemeTest below.
198   virtual extensions::Manifest::Location GetThemeLocation() {
199     return extensions::Manifest::INTERNAL;
200   }
201
202   FakeThemeService* BuildForProfile(Profile* profile) {
203     return static_cast<FakeThemeService*>(
204         ThemeServiceFactory::GetInstance()->SetTestingFactoryAndUse(
205             profile, &BuildMockThemeService));
206   }
207
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,
216         entity_specifics));
217     return list;
218   }
219
220   // Needed for setting up extension service.
221   base::MessageLoop loop_;
222   content::TestBrowserThread ui_thread_;
223   content::TestBrowserThread file_thread_;
224
225 #if defined OS_CHROMEOS
226   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
227   chromeos::ScopedTestCrosSettings test_cros_settings_;
228   chromeos::ScopedTestUserManager test_user_manager_;
229 #endif
230
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_;
236 };
237
238 class PolicyInstalledThemeTest : public ThemeSyncableServiceTest {
239   virtual extensions::Manifest::Location GetThemeLocation() OVERRIDE {
240     return extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD;
241   }
242 };
243
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));
248
249   // Custom vs. non-custom.
250
251   a.set_use_custom_theme(true);
252   EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
253   EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
254
255   // Custom theme equality.
256
257   b.set_use_custom_theme(true);
258   EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
259   EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
260
261   a.set_custom_theme_id("id");
262   EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
263   EXPECT_FALSE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
264
265   b.set_custom_theme_id("id");
266   EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
267   EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
268
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));
272
273   a.set_custom_theme_name("name");
274   EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, false));
275   EXPECT_TRUE(ThemeSyncableService::AreThemeSpecificsEqual(a, b, true));
276
277   // Non-custom theme equality.
278
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));
283
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));
287
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));
291 }
292
293 TEST_F(ThemeSyncableServiceTest, SetCurrentThemeDefaultTheme) {
294   // Set up theme service to use custom theme.
295   fake_theme_service_->SetTheme(theme_extension_.get());
296
297   syncer::SyncError error =
298       theme_sync_service_
299           ->MergeDataAndStartSyncing(
300                 syncer::THEMES,
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()))
307           .error();
308   EXPECT_FALSE(error.IsSet()) << error.message();
309   EXPECT_TRUE(fake_theme_service_->UsingDefaultTheme());
310 }
311
312 TEST_F(ThemeSyncableServiceTest, SetCurrentThemeSystemTheme) {
313   sync_pb::ThemeSpecifics theme_specifics;
314   theme_specifics.set_use_system_theme_by_default(true);
315
316   // Set up theme service to use custom theme.
317   fake_theme_service_->SetTheme(theme_extension_.get());
318   syncer::SyncError error =
319       theme_sync_service_
320           ->MergeDataAndStartSyncing(
321                 syncer::THEMES,
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()))
328           .error();
329   EXPECT_FALSE(error.IsSet()) << error.message();
330   EXPECT_TRUE(fake_theme_service_->UsingSystemTheme());
331 }
332
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);
339
340   // Set up theme service to use default theme.
341   fake_theme_service_->UseDefaultTheme();
342   syncer::SyncError error =
343       theme_sync_service_
344           ->MergeDataAndStartSyncing(
345                 syncer::THEMES,
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()))
352           .error();
353   EXPECT_FALSE(error.IsSet()) << error.message();
354   EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
355 }
356
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 =
362       theme_sync_service_
363           ->MergeDataAndStartSyncing(
364                 syncer::THEMES,
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()))
371           .error();
372   EXPECT_FALSE(error.IsSet()) << error.message();
373   EXPECT_FALSE(fake_theme_service_->is_dirty());
374 }
375
376 TEST_F(ThemeSyncableServiceTest, UpdateThemeSpecificsFromCurrentTheme) {
377   // Set up theme service to use custom theme.
378   fake_theme_service_->SetTheme(theme_extension_.get());
379
380   syncer::SyncError error =
381       theme_sync_service_
382           ->MergeDataAndStartSyncing(
383                 syncer::THEMES,
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()))
390           .error();
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());
397
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());
403   EXPECT_EQ(
404       extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(),
405       theme_specifics.custom_theme_update_url());
406 }
407
408 TEST_F(ThemeSyncableServiceTest, GetAllSyncData) {
409   // Set up theme service to use custom theme.
410   fake_theme_service_->SetTheme(theme_extension_.get());
411
412   syncer::SyncDataList data_list =
413       theme_sync_service_->GetAllSyncData(syncer::THEMES);
414
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());
421   EXPECT_EQ(
422       extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(),
423       theme_specifics.custom_theme_update_url());
424 }
425
426 TEST_F(ThemeSyncableServiceTest, ProcessSyncThemeChange) {
427   // Set up theme service to use default theme.
428   fake_theme_service_->UseDefaultTheme();
429   fake_theme_service_->MarkClean();
430
431   // Start syncing.
432   syncer::SyncError error =
433       theme_sync_service_
434           ->MergeDataAndStartSyncing(
435                 syncer::THEMES,
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()))
442           .error();
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());
446
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(
460                              1,
461                              entity_specifics,
462                              base::Time(),
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());
468 }
469
470 TEST_F(ThemeSyncableServiceTest, OnThemeChangeByUser) {
471   // Set up theme service to use default theme.
472   fake_theme_service_->UseDefaultTheme();
473
474   // Start syncing.
475   syncer::SyncError error =
476       theme_sync_service_
477           ->MergeDataAndStartSyncing(
478                 syncer::THEMES,
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()))
485           .error();
486   EXPECT_FALSE(error.IsSet()) << error.message();
487   const syncer::SyncChangeList& changes = fake_change_processor_->changes();
488   EXPECT_EQ(0u, changes.size());
489
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());
499   EXPECT_EQ(
500       extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(),
501       change_specifics.custom_theme_update_url());
502 }
503
504 TEST_F(ThemeSyncableServiceTest, StopSync) {
505   // Set up theme service to use default theme.
506   fake_theme_service_->UseDefaultTheme();
507
508   // Start syncing.
509   syncer::SyncError error =
510       theme_sync_service_
511           ->MergeDataAndStartSyncing(
512                 syncer::THEMES,
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()))
519           .error();
520   EXPECT_FALSE(error.IsSet()) << error.message();
521   const syncer::SyncChangeList& changes = fake_change_processor_->changes();
522   EXPECT_EQ(0u, changes.size());
523
524   // Stop syncing.
525   theme_sync_service_->StopSyncing(syncer::THEMES);
526
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());
532
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());
538 }
539
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 =
546       theme_sync_service_
547           ->MergeDataAndStartSyncing(
548                 syncer::THEMES,
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()))
555           .error();
556
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());
566 }
567
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 =
577       theme_sync_service_
578           ->MergeDataAndStartSyncing(
579                 syncer::THEMES,
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()))
586           .error();
587   EXPECT_FALSE(fake_theme_service_->is_dirty());
588
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]
596                    .sync_data()
597                    .GetSpecifics()
598                    .theme()
599                    .use_system_theme_by_default());
600
601   // Change to native theme and notify theme_sync_service_.
602   // use_system_theme_by_default bit should be true.
603   changes.clear();
604   fake_theme_service_->UseSystemTheme();
605   theme_sync_service_->OnThemeChange();
606   EXPECT_EQ(1u, changes.size());
607   EXPECT_TRUE(changes[0]
608                   .sync_data()
609                   .GetSpecifics()
610                   .theme()
611                   .use_system_theme_by_default());
612 }
613 #endif
614
615 #ifndef TOOLKIT_GTK
616 TEST_F(ThemeSyncableServiceTest,
617        NonGtkPreserveSystemThemeBitWhenChangeToDefaultTheme) {
618   // Set up theme service to use default theme.
619   fake_theme_service_->UseDefaultTheme();
620
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 =
629       theme_sync_service_
630           ->MergeDataAndStartSyncing(
631                 syncer::THEMES,
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()))
638           .error();
639   EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
640
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());
651 }
652 #endif
653
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());
657
658   syncer::SyncDataList data_list =
659       theme_sync_service_->GetAllSyncData(syncer::THEMES);
660
661   ASSERT_EQ(0u, data_list.size());
662 }