1 // Copyright 2013 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/ui/sync/profile_signin_confirmation_helper.h"
7 #include "base/basictypes.h"
9 #include "base/bind_helpers.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "base/compiler_specific.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/prefs/pref_notifier_impl.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/prefs/testing_pref_service.h"
18 #include "base/run_loop.h"
19 #include "base/strings/string16.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
23 #include "chrome/browser/extensions/extension_service.h"
24 #include "chrome/browser/extensions/test_extension_system.h"
25 #include "chrome/browser/history/history_service.h"
26 #include "chrome/browser/history/history_service_factory.h"
27 #include "chrome/browser/prefs/browser_prefs.h"
28 #include "chrome/common/extensions/extension_constants.h"
29 #include "chrome/test/base/testing_pref_service_syncable.h"
30 #include "chrome/test/base/testing_profile.h"
31 #include "components/bookmarks/core/browser/bookmark_model.h"
32 #include "components/bookmarks/core/test/bookmark_test_helpers.h"
33 #include "components/user_prefs/pref_registry_syncable.h"
34 #include "content/public/test/test_browser_thread_bundle.h"
35 #include "content/public/test/test_utils.h"
36 #include "extensions/browser/extension_prefs.h"
37 #include "extensions/common/extension.h"
38 #include "extensions/common/manifest_constants.h"
39 #include "extensions/common/permissions/permission_set.h"
40 #include "testing/gmock/include/gmock/gmock.h"
41 #include "testing/gtest/include/gtest/gtest.h"
43 #if defined(OS_CHROMEOS)
44 #include "chrome/browser/chromeos/login/user_manager.h"
45 #include "chrome/browser/chromeos/settings/cros_settings.h"
46 #include "chrome/browser/chromeos/settings/device_settings_service.h"
52 void GetValueAndQuit(T* result, const base::Closure& quit, T actual) {
59 const base::Callback<void(const base::Callback<void(T)>&)>& callback) {
62 callback.Run(base::Bind(&GetValueAndQuit<T>, &result, loop.QuitClosure()));
67 // A pref store that can have its read_error property changed for testing.
68 class TestingPrefStoreWithCustomReadError : public TestingPrefStore {
70 TestingPrefStoreWithCustomReadError()
71 : read_error_(PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
72 // By default the profile is "new" (NO_FILE means that the profile
73 // wasn't found on disk, so it was created).
75 virtual PrefReadError GetReadError() const OVERRIDE {
78 virtual bool IsInitializationComplete() const OVERRIDE {
81 void set_read_error(PrefReadError read_error) {
82 read_error_ = read_error;
85 virtual ~TestingPrefStoreWithCustomReadError() {}
86 PrefReadError read_error_;
90 const base::FilePath::CharType kExtensionFilePath[] =
91 FILE_PATH_LITERAL("c:\\foo");
92 #elif defined(OS_POSIX)
93 const base::FilePath::CharType kExtensionFilePath[] =
94 FILE_PATH_LITERAL("/oo");
97 static scoped_refptr<extensions::Extension> CreateExtension(
98 const std::string& name,
99 const std::string& id) {
100 base::DictionaryValue manifest;
101 manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0");
102 manifest.SetString(extensions::manifest_keys::kName, name);
104 scoped_refptr<extensions::Extension> extension =
105 extensions::Extension::Create(
106 base::FilePath(kExtensionFilePath).AppendASCII(name),
107 extensions::Manifest::INTERNAL,
109 extensions::Extension::NO_FLAGS,
117 class ProfileSigninConfirmationHelperTest : public testing::Test {
119 ProfileSigninConfirmationHelperTest()
124 virtual void SetUp() OVERRIDE {
125 // Create the profile.
126 TestingProfile::Builder builder;
127 user_prefs_ = new TestingPrefStoreWithCustomReadError;
128 TestingPrefServiceSyncable* pref_service = new TestingPrefServiceSyncable(
129 new TestingPrefStore(),
131 new TestingPrefStore(),
132 new user_prefs::PrefRegistrySyncable(),
133 new PrefNotifierImpl());
134 chrome::RegisterUserProfilePrefs(pref_service->registry());
135 builder.SetPrefService(make_scoped_ptr<PrefServiceSyncable>(pref_service));
136 profile_ = builder.Build();
138 // Initialize the services we check.
139 profile_->CreateBookmarkModel(true);
140 model_ = BookmarkModelFactory::GetForProfile(profile_.get());
141 test::WaitForBookmarkModelToLoad(model_);
142 ASSERT_TRUE(profile_->CreateHistoryService(true, false));
143 extensions::TestExtensionSystem* system =
144 static_cast<extensions::TestExtensionSystem*>(
145 extensions::ExtensionSystem::Get(profile_.get()));
146 CommandLine command_line(CommandLine::NO_PROGRAM);
147 system->CreateExtensionService(&command_line,
148 base::FilePath(kExtensionFilePath),
152 virtual void TearDown() OVERRIDE {
153 // TestExtensionSystem uses DeleteSoon, so we need to delete the profile
154 // and then run the message queue to clean up.
156 base::RunLoop().RunUntilIdle();
160 content::TestBrowserThreadBundle thread_bundle_;
161 scoped_ptr<TestingProfile> profile_;
162 TestingPrefStoreWithCustomReadError* user_prefs_;
163 BookmarkModel* model_;
165 #if defined OS_CHROMEOS
166 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
167 chromeos::ScopedTestCrosSettings test_cros_settings_;
168 chromeos::ScopedTestUserManager test_user_manager_;
172 TEST_F(ProfileSigninConfirmationHelperTest, DoNotPromptForNewProfile) {
173 // Profile is new and there's no profile data.
177 &ui::CheckShouldPromptForNewProfile,
181 TEST_F(ProfileSigninConfirmationHelperTest, PromptForNewProfile_Bookmarks) {
184 // Profile is new but has bookmarks.
185 model_->AddURL(model_->bookmark_bar_node(), 0,
186 base::string16(base::ASCIIToUTF16("foo")),
187 GURL("http://foo.com"));
191 &ui::CheckShouldPromptForNewProfile,
195 TEST_F(ProfileSigninConfirmationHelperTest, PromptForNewProfile_Extensions) {
196 ExtensionService* extensions =
197 extensions::ExtensionSystem::Get(profile_.get())->extension_service();
198 ASSERT_TRUE(extensions);
200 // Profile is new but has synced extensions.
202 // (The web store doesn't count.)
203 scoped_refptr<extensions::Extension> webstore =
204 CreateExtension("web store", extension_misc::kWebStoreAppId);
205 extensions::ExtensionPrefs::Get(profile_.get())->AddGrantedPermissions(
206 webstore->id(), make_scoped_refptr(new extensions::PermissionSet).get());
207 extensions->AddExtension(webstore.get());
208 EXPECT_FALSE(GetCallbackResult(
209 base::Bind(&ui::CheckShouldPromptForNewProfile, profile_.get())));
211 scoped_refptr<extensions::Extension> extension =
212 CreateExtension("foo", std::string());
213 extensions::ExtensionPrefs::Get(profile_.get())->AddGrantedPermissions(
214 extension->id(), make_scoped_refptr(new extensions::PermissionSet).get());
215 extensions->AddExtension(extension.get());
216 EXPECT_TRUE(GetCallbackResult(
217 base::Bind(&ui::CheckShouldPromptForNewProfile, profile_.get())));
220 TEST_F(ProfileSigninConfirmationHelperTest, PromptForNewProfile_History) {
221 HistoryService* history = HistoryServiceFactory::GetForProfile(
223 Profile::EXPLICIT_ACCESS);
224 ASSERT_TRUE(history);
226 // Profile is new but has more than $(kHistoryEntriesBeforeNewProfilePrompt)
229 for (int i = 0; i < 10; i++) {
230 base::snprintf(buf, arraysize(buf), "http://foo.com/%d", i);
232 GURL(std::string(buf)), base::Time::Now(), NULL, 1,
233 GURL(), history::RedirectList(), content::PAGE_TRANSITION_LINK,
234 history::SOURCE_BROWSED, false);
239 &ui::CheckShouldPromptForNewProfile,
243 TEST_F(ProfileSigninConfirmationHelperTest, PromptForNewProfile_TypedURLs) {
244 HistoryService* history = HistoryServiceFactory::GetForProfile(
246 Profile::EXPLICIT_ACCESS);
247 ASSERT_TRUE(history);
249 // Profile is new but has a typed URL.
251 GURL("http://example.com"), base::Time::Now(), NULL, 1,
252 GURL(), history::RedirectList(), content::PAGE_TRANSITION_TYPED,
253 history::SOURCE_BROWSED, false);
257 &ui::CheckShouldPromptForNewProfile,
261 TEST_F(ProfileSigninConfirmationHelperTest, PromptForNewProfile_Restarted) {
262 // Browser has been shut down since profile was created.
263 user_prefs_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NONE);
267 &ui::CheckShouldPromptForNewProfile,