Upstream version 7.36.149.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/common/extension.h"
21 #include "extensions/common/extension_messages.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/attachments/attachment_service_proxy_for_test.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/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/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_native_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_native_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_native_theme_ = false;
75     theme_extension_ = NULL;
76   }
77
78   virtual void SetNativeTheme() OVERRIDE {
79     is_dirty_ = true;
80     using_native_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 UsingNativeTheme() const OVERRIDE {
90     return using_native_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_native_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_->UsingNativeTheme());
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("datatype error was encountered: Theme syncable service is not "
538                 "started.",
539             error.message());
540 }
541
542 TEST_F(ThemeSyncableServiceTest, RestoreSystemThemeBitWhenChangeToCustomTheme) {
543   // Initialize to use system theme.
544   fake_theme_service_->UseDefaultTheme();
545   sync_pb::ThemeSpecifics theme_specifics;
546   theme_specifics.set_use_system_theme_by_default(true);
547   syncer::SyncError error =
548       theme_sync_service_
549           ->MergeDataAndStartSyncing(
550                 syncer::THEMES,
551                 MakeThemeDataList(theme_specifics),
552                 scoped_ptr<syncer::SyncChangeProcessor>(
553                     new syncer::SyncChangeProcessorWrapperForTest(
554                         fake_change_processor_.get())),
555                 scoped_ptr<syncer::SyncErrorFactory>(
556                     new syncer::SyncErrorFactoryMock()))
557           .error();
558
559   // Change to custom theme and notify theme_sync_service_.
560   // use_system_theme_by_default bit should be preserved.
561   fake_theme_service_->SetTheme(theme_extension_.get());
562   theme_sync_service_->OnThemeChange();
563   const syncer::SyncChangeList& changes = fake_change_processor_->changes();
564   EXPECT_EQ(1u, changes.size());
565   const sync_pb::ThemeSpecifics& change_specifics =
566       changes[0].sync_data().GetSpecifics().theme();
567   EXPECT_TRUE(change_specifics.use_system_theme_by_default());
568 }
569
570 #if defined(TOOLKIT_GTK)
571 TEST_F(ThemeSyncableServiceTest,
572        GtkUpdateSystemThemeBitWhenChangeBetweenSystemAndDefault) {
573   // Initialize to use native theme.
574   fake_theme_service_->SetNativeTheme();
575   fake_theme_service_->MarkClean();
576   sync_pb::ThemeSpecifics theme_specifics;
577   theme_specifics.set_use_system_theme_by_default(true);
578   syncer::SyncError error =
579       theme_sync_service_
580           ->MergeDataAndStartSyncing(
581                 syncer::THEMES,
582                 MakeThemeDataList(theme_specifics),
583                 scoped_ptr<syncer::SyncChangeProcessor>(
584                     new syncer::SyncChangeProcessorWrapperForTest(
585                         fake_change_processor_.get())),
586                 scoped_ptr<syncer::SyncErrorFactory>(
587                     new syncer::SyncErrorFactoryMock()))
588           .error();
589   EXPECT_FALSE(fake_theme_service_->is_dirty());
590
591   // Change to default theme and notify theme_sync_service_.
592   // use_system_theme_by_default bit should be false.
593   fake_theme_service_->UseDefaultTheme();
594   theme_sync_service_->OnThemeChange();
595   syncer::SyncChangeList& changes = fake_change_processor_->changes();
596   EXPECT_EQ(1u, changes.size());
597   EXPECT_FALSE(changes[0]
598                    .sync_data()
599                    .GetSpecifics()
600                    .theme()
601                    .use_system_theme_by_default());
602
603   // Change to native theme and notify theme_sync_service_.
604   // use_system_theme_by_default bit should be true.
605   changes.clear();
606   fake_theme_service_->SetNativeTheme();
607   theme_sync_service_->OnThemeChange();
608   EXPECT_EQ(1u, changes.size());
609   EXPECT_TRUE(changes[0]
610                   .sync_data()
611                   .GetSpecifics()
612                   .theme()
613                   .use_system_theme_by_default());
614 }
615 #endif
616
617 #ifndef TOOLKIT_GTK
618 TEST_F(ThemeSyncableServiceTest,
619        NonGtkPreserveSystemThemeBitWhenChangeToDefaultTheme) {
620   // Set up theme service to use default theme.
621   fake_theme_service_->UseDefaultTheme();
622
623   // Initialize to use custom theme with use_system_theme_by_default set true.
624   sync_pb::ThemeSpecifics theme_specifics;
625   theme_specifics.set_use_custom_theme(true);
626   theme_specifics.set_custom_theme_id(theme_extension_->id());
627   theme_specifics.set_custom_theme_name(kCustomThemeName);
628   theme_specifics.set_custom_theme_name(kCustomThemeUrl);
629   theme_specifics.set_use_system_theme_by_default(true);
630   syncer::SyncError error =
631       theme_sync_service_
632           ->MergeDataAndStartSyncing(
633                 syncer::THEMES,
634                 MakeThemeDataList(theme_specifics),
635                 scoped_ptr<syncer::SyncChangeProcessor>(
636                     new syncer::SyncChangeProcessorWrapperForTest(
637                         fake_change_processor_.get())),
638                 scoped_ptr<syncer::SyncErrorFactory>(
639                     new syncer::SyncErrorFactoryMock()))
640           .error();
641   EXPECT_EQ(fake_theme_service_->theme_extension(), theme_extension_.get());
642
643   // Change to default theme and notify theme_sync_service_.
644   // use_system_theme_by_default bit should be preserved.
645   fake_theme_service_->UseDefaultTheme();
646   theme_sync_service_->OnThemeChange();
647   const syncer::SyncChangeList& changes = fake_change_processor_->changes();
648   EXPECT_EQ(1u, changes.size());
649   const sync_pb::ThemeSpecifics& change_specifics =
650       changes[0].sync_data().GetSpecifics().theme();
651   EXPECT_FALSE(change_specifics.use_custom_theme());
652   EXPECT_TRUE(change_specifics.use_system_theme_by_default());
653 }
654 #endif
655
656 TEST_F(PolicyInstalledThemeTest, InstallThemeByPolicy) {
657   // Set up theme service to use custom theme that was installed by policy.
658   fake_theme_service_->SetTheme(theme_extension_.get());
659
660   syncer::SyncDataList data_list =
661       theme_sync_service_->GetAllSyncData(syncer::THEMES);
662
663   ASSERT_EQ(0u, data_list.size());
664 }