1// Copyright 2014 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 "base/basictypes.h"
6#include "base/bind.h"
7#include "base/bind_helpers.h"
8#include "base/files/file_path.h"
9#include "base/files/file_util.h"
10#include "base/memory/ref_counted.h"
11#include "base/message_loop/message_loop.h"
12#include "base/path_service.h"
13#include "base/values.h"
14#include "chrome/browser/browser_process.h"
15#include "chrome/browser/extensions/api/preferences_private/preferences_private_api.h"
16#include "chrome/browser/extensions/extension_apitest.h"
17#include "chrome/browser/extensions/extension_function_test_utils.h"
18#include "chrome/browser/profiles/profile.h"
19#include "chrome/browser/profiles/profile_manager.h"
20#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
21#include "chrome/browser/sync/profile_sync_components_factory_mock.h"
22#include "chrome/browser/sync/profile_sync_service.h"
23#include "chrome/browser/sync/profile_sync_service_factory.h"
24#include "chrome/browser/sync/supervised_user_signin_manager_wrapper.h"
25#include "chrome/browser/ui/browser.h"
26#include "chrome/common/chrome_constants.h"
27#include "chrome/common/chrome_paths.h"
28#include "chrome/test/base/testing_profile.h"
29#include "components/bookmarks/common/bookmark_constants.h"
30#include "components/sync_driver/sync_prefs.h"
31#include "content/public/browser/browser_context.h"
32#include "extensions/test/extension_test_message_listener.h"
33
34#if defined(OS_CHROMEOS)
35#include "chromeos/chromeos_switches.h"
36#endif
37
38using extensions::PreferencesPrivateGetSyncCategoriesWithoutPassphraseFunction;
39
40namespace {
41
42class FakeProfileSyncService : public ProfileSyncService {
43 public:
44  explicit FakeProfileSyncService(Profile* profile)
45      : ProfileSyncService(
46            scoped_ptr<ProfileSyncComponentsFactory>(
47                new ProfileSyncComponentsFactoryMock()),
48            profile,
49            make_scoped_ptr<SupervisedUserSigninManagerWrapper>(NULL),
50            ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
51            browser_sync::MANUAL_START),
52        sync_initialized_(true),
53        initialized_state_violation_(false) {}
54
55  virtual ~FakeProfileSyncService() {}
56
57  static KeyedService* BuildFakeProfileSyncService(
58      content::BrowserContext* context) {
59    return new FakeProfileSyncService(static_cast<Profile*>(context));
60  }
61
62  void set_sync_initialized(bool sync_initialized) {
63    sync_initialized_ = sync_initialized;
64  }
65
66  bool initialized_state_violation() { return initialized_state_violation_; }
67
68  // ProfileSyncService:
69  virtual bool sync_initialized() const OVERRIDE {
70    return sync_initialized_;
71  }
72
73  virtual void AddObserver(
74      ProfileSyncServiceBase::Observer* observer) OVERRIDE {
75    if (sync_initialized_)
76      initialized_state_violation_ = true;
77    // Set sync initialized state to true so the function will run after
78    // OnStateChanged is called.
79    sync_initialized_ = true;
80    base::MessageLoop::current()->PostTask(
81        FROM_HERE,
82        base::Bind(&ProfileSyncServiceBase::Observer::OnStateChanged,
83                   base::Unretained(observer)));
84  }
85
86  virtual syncer::ModelTypeSet GetEncryptedDataTypes() const OVERRIDE {
87    if (!sync_initialized_)
88      initialized_state_violation_ = true;
89    syncer::ModelTypeSet type_set;
90    type_set.Put(syncer::AUTOFILL);
91    return type_set;
92  }
93
94  virtual syncer::ModelTypeSet GetPreferredDataTypes() const OVERRIDE {
95    if (!sync_initialized_)
96      initialized_state_violation_ = true;
97    syncer::ModelTypeSet preferred_types =
98        syncer::UserSelectableTypes();
99    preferred_types.Remove(syncer::TYPED_URLS);
100    return preferred_types;
101  }
102
103 private:
104  bool sync_initialized_;
105  // Set to true if a function is called when sync_initialized is in an
106  // unexpected state.
107  mutable bool initialized_state_violation_;
108
109  DISALLOW_COPY_AND_ASSIGN(FakeProfileSyncService);
110};
111
112class PreferencesPrivateApiTest : public ExtensionApiTest {
113 public:
114  PreferencesPrivateApiTest() : browser_(NULL), service_(NULL) {}
115  virtual ~PreferencesPrivateApiTest() {}
116
117  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
118#if defined(OS_CHROMEOS)
119    command_line->AppendSwitch(
120        chromeos::switches::kIgnoreUserProfileMappingForTests);
121#endif
122  }
123
124  virtual void SetUpOnMainThread() OVERRIDE {
125    ExtensionApiTest::SetUpOnMainThread();
126
127    base::FilePath path;
128    PathService::Get(chrome::DIR_USER_DATA, &path);
129    path = path.AppendASCII("test_profile");
130    if (!base::PathExists(path))
131      CHECK(base::CreateDirectory(path));
132
133    Profile* profile =
134        Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
135    sync_driver::SyncPrefs sync_prefs(profile->GetPrefs());
136    sync_prefs.SetKeepEverythingSynced(false);
137
138    ProfileManager* profile_manager = g_browser_process->profile_manager();
139    profile_manager->RegisterTestingProfile(profile, true, false);
140
141    service_ = static_cast<FakeProfileSyncService*>(
142        ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
143        profile, &FakeProfileSyncService::BuildFakeProfileSyncService));
144
145    browser_ = new Browser(Browser::CreateParams(
146        profile, chrome::HOST_DESKTOP_TYPE_NATIVE));
147  }
148
149  // Calls GetSyncCategoriesWithoutPassphraseFunction and verifies that the
150  // results returned are the expected ones.
151  void TestGetSyncCategoriesWithoutPassphraseFunction();
152
153 protected:
154  Browser* browser_;
155  FakeProfileSyncService* service_;
156
157 private:
158  DISALLOW_COPY_AND_ASSIGN(PreferencesPrivateApiTest);
159};
160
161void
162PreferencesPrivateApiTest::TestGetSyncCategoriesWithoutPassphraseFunction() {
163  scoped_refptr<PreferencesPrivateGetSyncCategoriesWithoutPassphraseFunction>
164      function(
165          new PreferencesPrivateGetSyncCategoriesWithoutPassphraseFunction);
166  ASSERT_TRUE(extension_function_test_utils::RunFunction(
167      function.get(), "[]", browser_, extension_function_test_utils::NONE));
168  EXPECT_FALSE(service_->initialized_state_violation());
169
170  const base::ListValue* result = function->GetResultList();
171  EXPECT_EQ(1u, result->GetSize());
172
173  const base::ListValue* categories = NULL;
174  ASSERT_TRUE(result->GetList(0, &categories));
175  EXPECT_NE(categories->end(),
176            categories->Find(base::StringValue(bookmarks::kBookmarksFileName)));
177  EXPECT_NE(categories->end(),
178            categories->Find(base::StringValue(chrome::kPreferencesFilename)));
179  EXPECT_EQ(categories->end(),
180           categories->Find(base::StringValue("Autofill"))) <<
181               "Encrypted categories should not be present";
182  EXPECT_EQ(categories->end(),
183           categories->Find(base::StringValue("Typed URLs"))) <<
184               "Unsynced categories should not be present";
185}
186
187IN_PROC_BROWSER_TEST_F(PreferencesPrivateApiTest,
188                       GetSyncCategoriesWithoutPassphrase) {
189  TestGetSyncCategoriesWithoutPassphraseFunction();
190}
191
192// Verifies that we wait for the sync service to be ready before checking
193// encryption status.
194IN_PROC_BROWSER_TEST_F(PreferencesPrivateApiTest,
195                       GetSyncCategoriesWithoutPassphraseAsynchronous) {
196  service_->set_sync_initialized(false);
197  TestGetSyncCategoriesWithoutPassphraseFunction();
198}
199
200}  // namespace
201